From 60c1050f97b7d12a8915e69370c91367acb4463a Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Oct 2019 15:40:59 +0100 Subject: [PATCH 001/114] Updated Makefile for compatibility & optimisations --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 8f63e21..b51e977 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ -CPP = g++ - +CPP = g++-4.8 ARCHFLAG = -m32 -METAMOD_SRCDIR = ./dependencies/metamod-hl1/metamod -HLSDK_BASEDIR = ./dependencies/hlsdk +META_DIR = ./dependencies/metamod-hl1/metamod +HLSDK_DIR = ./dependencies/hlsdk BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/common" -I"${HLSDK_BASEDIR}/dlls" -I"${HLSDK_BASEDIR}/engine" -I"${HLSDK_BASEDIR}/pm_shared" -I"${HLSDK_BASEDIR}/public" +CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -w -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe -I"${META_DIR}" \ + -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" OBJ = NodeMachine.o \ bot.o \ @@ -30,7 +30,7 @@ ifeq ($(UNAME_S),Darwin) SO_SUFFIX = dylib endif -realbot_mm_i386.${SO_SUFFIX}: ${OBJ} +realbot_mm.${SO_SUFFIX}: ${OBJ} ${CPP} ${ARCHFLAG} -fPIC -shared -o $@ ${OBJ} -ldl mkdir -p Release mv $@ ${OBJ} Release From c3df046a91005be22c5beae80e8afee828a9feac Mon Sep 17 00:00:00 2001 From: Stefan Hendriks Date: Wed, 2 Oct 2019 06:14:40 +0200 Subject: [PATCH 002/114] Removing danger costs makes bots less weird in their navigation. So at this point bots ignore experience - it probably should be redone. --- NodeMachine.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index b65362e..4c6ead2 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2441,10 +2441,10 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou float cost = gCost + hCost; if (botTeam > -1) { - double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; +// double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; // double contactCost = InfoNodes[neighbourNode].fContact[botTeam] * cost; - cost += dangerCost; +// cost += dangerCost; // cost += contactCost; } @@ -3573,10 +3573,11 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->vip) { score = 0; // do not chase yourself } else { - // if distance is too big, go to it. (guard the VIP) - int maxDistanceWeKeepToVIP = 500; - float goalScore = maxDistanceWeKeepToVIP / fDistanceToGoal; - score = (score + goalScore) / 2.0; + score = 0; // don't care about VIP +// // if distance is too big, go to it. (guard the VIP) +// int maxDistanceWeKeepToVIP = 500; +// float goalScore = maxDistanceWeKeepToVIP / fDistanceToGoal; +// score = (score + goalScore) / 2.0; } } } From b64b86d30730708544cf14723fb45fda0e278c92 Mon Sep 17 00:00:00 2001 From: Stefan Hendriks Date: Wed, 2 Oct 2019 07:02:27 +0200 Subject: [PATCH 003/114] More logging with radio --- bot.cpp | 16 ++++++++++++---- bot_func.cpp | 9 +++++++-- engine.cpp | 8 ++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/bot.cpp b/bot.cpp index 714e380..2684298 100644 --- a/bot.cpp +++ b/bot.cpp @@ -3693,12 +3693,14 @@ bool BotRadioAction() { } // Enemy Down! if (strstr(message, "#Enemy_down") != NULL) { + BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); unstood = true; can_do_negative = false; } // Stick together team! if (strstr(message, "#Stick_together_team") != NULL) { + BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); unstood = true; // TODO: Find someone to follow. (to stick with) } @@ -3706,6 +3708,7 @@ bool BotRadioAction() { // Need backup / taking fire... if (strstr(message, "#Need_backup") != NULL || strstr(message, "#Taking_fire") != NULL) { + BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); unstood = true; @@ -3713,7 +3716,7 @@ bool BotRadioAction() { int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); if (iBackupNode > -1) { - BotPointer->rprint("Setting goal for backup"); + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); BotPointer->setGoalNode(iBackupNode); BotPointer->forgetPath(); BotPointer->f_camp_time = gpGlobals->time - 1; @@ -3727,11 +3730,15 @@ bool BotRadioAction() { // unstood = true; } // Team fall back! - if (strstr(message, "#Team_fall_back") != NULL) {} + if (strstr(message, "#Team_fall_back") != NULL) { + + } // Go GO Go, stop camping, stop following, get the heck out of there! if (strstr(message, "#Go_go_go") != NULL) { + BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); unstood = true; BotPointer->f_camp_time = gpGlobals->time - 30; + BotPointer->f_walk_time = gpGlobals->time; BotPointer->f_cover_time = gpGlobals->time - 10; BotPointer->f_hold_duck = gpGlobals->time - 10; BotPointer->f_jump_time = gpGlobals->time - 10; @@ -3740,8 +3747,9 @@ bool BotRadioAction() { } if ((FUNC_DoRadio(BotPointer)) && (unstood)) { - if (BotPointer->console_nr == 0 - && radios < (gpGlobals->maxClients / 4)) { + int maxAllowedRadios = gpGlobals->maxClients / 4; + if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { + if (!report_back) { UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! } else { diff --git a/bot_func.cpp b/bot_func.cpp index 86de85e..c71dabf 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -565,14 +565,19 @@ bool BotShouldDuck(cBot *pBot) { return true; } +/** + * Returns if a bot can and wants to do radio. Wanting is based on personality flag. + * @param pBot + * @return + */ bool FUNC_DoRadio(cBot *pBot) { - if (pBot->fDoRadio > gpGlobals->time) + if (pBot->fDoRadio > gpGlobals->time) // allowed? return false; int iRadio = pBot->ipCreateRadio; - return RANDOM_LONG(0, 100) < iRadio; + return RANDOM_LONG(0, 100) < iRadio; // want? } // DECIDE: Take cover or not diff --git a/engine.cpp b/engine.cpp index 5010e51..cc15bca 100644 --- a/engine.cpp +++ b/engine.cpp @@ -386,14 +386,12 @@ void pfnWriteCoord(float flValue) { } void pfnWriteString(const char *sz) { - if (Game.bEngineDebug) { char msg[256]; sprintf(msg, "ENGINE: pfnWriteByte() - '%s'\n", sz); rblog(msg); } - if (gpGlobals->deathmatch) { // Ditlew's Radio if ((strstr(sz, "(RADIO):") != NULL) && !radio_message) { @@ -508,8 +506,9 @@ void pfnWriteString(const char *sz) { strcpy(message, sz); // copy message and handle at bot.cpp radio routine. radio_message = true; radio_message_from = false; - } else if (strcmp(sz, "#Game_radio") == 0) + } else if (strcmp(sz, "#Game_radio") == 0) { radio_message_start = true; + } // End Ditlew's Radio @@ -519,8 +518,9 @@ void pfnWriteString(const char *sz) { // if this message is for a bot, call the client message function... - if (botMsgFunction) + if (botMsgFunction) { (*botMsgFunction)((void *) sz, botMsgIndex); + } } RETURN_META(MRES_IGNORED); From f0b7e0f62356c0a9f186cf1b6cb6727acd636964 Mon Sep 17 00:00:00 2001 From: Stefan Hendriks Date: Wed, 2 Oct 2019 07:02:40 +0200 Subject: [PATCH 004/114] Take walking into account for reaching destination - so we won't consider stuck when we move slower, we give the bot a bit more time (just like ducking) - Also when a bot has another bot in front of him, he will try to unstuck (strafe right) for only the time given to move to the node, after that the 'normal' unstuck logic also kicks in. Else the bots will remain stuck at each other forever... :/ --- NodeMachine.cpp | 10 ++++++++-- bot.cpp | 8 ++++++++ bot.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 4c6ead2..4a46104 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2903,8 +2903,13 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (strcmp(STRING(pEntityHit->v.classname), "player") == 0) { pBot->rprint_trace("cNodeMachine::path_walk", "Another player between me and next node."); - pBot->strafeRight(0.2); - return; + if (pBot->hasTimeToMoveToNode()) { + pBot->strafeRight(0.2); + pBot->rprint_trace("cNodeMachine::path_walk", "Time left to move to node, so lets try strafing to unstuck."); + return; + } else { + pBot->rprint_trace("cNodeMachine::path_walk", "No time left to move to node, so we continue and let stuck logic kick in"); + } } pBot->rprint_trace("cNodeMachine::path_walk", "Finished - entity hit end block"); @@ -2922,6 +2927,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; double expectedMoveDistance = speedInOneTenthOfASecond; if (pBot->isFreezeTime()) expectedMoveDistance = 0; + if (pBot->isWalking()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; if (pBot->isDucking()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; if (pBot->isJumping()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; // no need for 'is walking' because walking time influence `f_move_speed` hence it is already taken care of diff --git a/bot.cpp b/bot.cpp index 2684298..d2c49f4 100644 --- a/bot.cpp +++ b/bot.cpp @@ -4278,6 +4278,14 @@ bool cBot::isDucking() { return b; } +bool cBot::isWalking() { + bool b = !keyPressed(IN_RUN) || this->f_walk_time > gpGlobals->time; + if (b) { + rprint_trace("isWalking", "Yes I am walking"); + } + return b; +} + void cBot::doJump(Vector &vector) { rprint_trace("doJump", "With vector"); // stay focussed with body and head to this vector diff --git a/bot.h b/bot.h index b3a6ec9..fd1796c 100644 --- a/bot.h +++ b/bot.h @@ -576,6 +576,7 @@ class cBot { void doDuck(); bool isDucking(); + bool isWalking(); bool isFreezeTime() const; From 8613aa67aac4eb0eb4f5472a96e94a18590c7a0c Mon Sep 17 00:00:00 2001 From: Stefan Hendriks Date: Wed, 2 Oct 2019 07:03:43 +0200 Subject: [PATCH 005/114] Started testing on as_oilrig again --- makeAndCopyAndRun.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/makeAndCopyAndRun.sh b/makeAndCopyAndRun.sh index c64178c..817fda1 100755 --- a/makeAndCopyAndRun.sh +++ b/makeAndCopyAndRun.sh @@ -17,7 +17,9 @@ touch "/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half- # run #"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map cs_italy +maxplayers 32 #"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map de_prodigy +maxplayers 32 -"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map de_dust +maxplayers 32 -#"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map as_oilrig +maxplayers 32 +#"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map de_dust +maxplayers 32 + +"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map as_oilrig +maxplayers 32 + #"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map fy_iceworld +maxplayers 32 #"/Users/shendriks/Library/Application Support/Steam/SteamApps/common/Half-Life/hl.sh" -game cstrike --listen +map cs_assault +maxplayers 32 From a6649c826ce39912a2670d755671954242ccfaa3 Mon Sep 17 00:00:00 2001 From: Stefan Hendriks Date: Wed, 2 Oct 2019 08:01:58 +0200 Subject: [PATCH 006/114] Re-enable danger cost - it looked like the testing on as_oilrig showed other causes for the weird navigation: reason being that from CT spawn to the slope downwards there are connections and bots did not know they couldnt get over/under the bar between. - I ran test with a single bot, it learned the connections where bad, then re-adding multiple bots and the behavior was good again. - With the other changes where bots getting stuck will still kick off (after a certain time) the unstuck mechanism also helped a lot - Another thing: the mechanism creating connections should be smarter so instead of 'unlearning' it should also prevent creating bad connections in the first place. --- NodeMachine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 4a46104..a34f093 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2441,10 +2441,10 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou float cost = gCost + hCost; if (botTeam > -1) { -// double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; + double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; // double contactCost = InfoNodes[neighbourNode].fContact[botTeam] * cost; -// cost += dangerCost; + cost += dangerCost; // cost += contactCost; } From 2ca07161768cc5c311bbef416ab3a2b28b57e5d7 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 20 Feb 2021 02:27:53 +0000 Subject: [PATCH 007/114] Optimisation, reduced redundancy and add missing parameters --- ChatEngine.cpp | 26 +-- IniParser.cpp | 48 ++--- Makefile | 12 +- NodeMachine.cpp | 516 ++++++++++++++++++++++----------------------- NodeMachine.h | 54 ++--- bot.cpp | 374 ++++++++++++++++++-------------- bot.h | 116 +++++----- bot_buycode.cpp | 12 +- bot_client.cpp | 36 ++-- bot_func.cpp | 54 ++--- bot_navigate.cpp | 16 +- dll.cpp | 93 ++++---- engine.cpp | 16 +- engine.h | 21 +- game.cpp | 95 ++++----- game.h | 26 +-- realbot_mm.vcxproj | 6 +- util.cpp | 90 +++----- 18 files changed, 783 insertions(+), 828 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 984113d..b7895c8 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -28,8 +28,8 @@ **/ // Chatting Engine -#include -#include +#include +#include // Some tests by EVYNCKE #include #include @@ -97,8 +97,7 @@ void cChatEngine::think() { // 29/08/2019 Stefan: by using string compare on the name of the sender (ie sender[] is the name) we retrieve // the edict pointer edict_t *pSender = NULL; - int i; - for (i = 1; i <= gpGlobals->maxClients; i++) { + for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); if (pPlayer && (!pPlayer->free)) { @@ -126,7 +125,7 @@ void cChatEngine::think() { int c = 0; int wc = 0; - int sentenceLength = strlen(sentence); + const int sentenceLength = strlen(sentence); // When length is not valid, get out. // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? @@ -244,13 +243,8 @@ void cChatEngine::think() { // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free) && pSender != pPlayer) { - - // only reply to the living when alive, and otherwise - bool bSenderAlive = false; - bool bPlayerAlive = false; - - bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here - bPlayerAlive = IsAlive(pPlayer); + bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here + bool bPlayerAlive = IsAlive(pPlayer); if (bSenderAlive != bPlayerAlive) continue; @@ -315,20 +309,16 @@ void cChatEngine::think() { // copy senders name to chSentence strcat(temp, sender); - // From here us 'tc' to keep track of chSentence and use - // nC to keep reading from ReplyBlock - int tc = nC; - // Skip %n part in ReplyBlock nC = name_offset + 3; // we just copied a name to chSentence // set our cursor after the name now (name length + 1) - tc = strlen(temp); + int tc = strlen(temp); // now finish the sentence // get entire length of ReplyBlock and go until we reach the end - int length = + const int length = strlen(ReplyBlock[iTheBlock]. sentence[the_c]); diff --git a/IniParser.cpp b/IniParser.cpp index 0f4bc4c..59c6652 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -32,7 +32,7 @@ * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 **/ -#include +#include #include #include #include @@ -46,7 +46,7 @@ #include "NodeMachine.h" #include "ChatEngine.h" -#include +#include extern int mod_id; extern edict_t *pHostEdict; @@ -61,9 +61,7 @@ extern cChatEngine ChatEngine; // with the chars in between. So : [MAP] -> section = 'MAP'. Use function INI_SectionType(..) // to get the correct ID for that. void INI_Section(char input[80], char section[30]) { - - int pos = 0; - int end_pos = -1; + int end_pos = -1; // clear out entire string for (int i = 0; i < 30; i++) @@ -71,7 +69,7 @@ void INI_Section(char input[80], char section[30]) { // check if the first character is a '[' if (input[0] == '[') { - pos = 1; // Begin at character 1 + int pos = 1; // Begin at character 1 while (pos < 79) { if (input[pos] == ']') { @@ -120,7 +118,7 @@ void INI_Word(char input[80], char word[25]) { // Reads out word[], does a string compare and returns type id int INI_WordType(char word[25], int section) { - if (strlen(word) > 0) { + if (word[0] != '\0') { if (strcmp(word, "Word") == 0) return WORD_WORD; @@ -550,7 +548,6 @@ void INI_PARSE_CHATFILE() { FILE *stream; int section = INI_NONE; - int wordtype = WORD_NONE; // Set Directory name + file @@ -584,8 +581,6 @@ void INI_PARSE_CHATFILE() { linefeed[0] == '\n' || linefeed[0] == '\0') continue; // Skip - wordtype = WORD_NONE; - // Every line is checked for a new section. INI_Section(linefeed, linesection); @@ -620,7 +615,7 @@ void INI_PARSE_CHATFILE() { if (iBlockId > -1) { INI_Word(linefeed, lineword); - wordtype = INI_WordType(lineword, section); + int wordtype = INI_WordType(lineword, section); // We load in words if (wordtype == WORD_WORD) { @@ -685,7 +680,6 @@ void INI_PARSE_IAD() { FILE *stream; int section = INI_NONE; - int wordtype = WORD_NONE; // Set Directory name strcpy(dirname, "data/cstrike/ini/"); @@ -699,8 +693,8 @@ void INI_PARSE_IAD() { SERVER_PRINT(filename); SERVER_PRINT("\n"); - float AreaX, AreaY, AreaZ; - AreaX = AreaY = AreaZ = 9999; + float AreaY, AreaZ; + float AreaX = AreaY = AreaZ = 9999; if ((stream = fopen(filename, "r+t")) != NULL) { char linefeed[80]; @@ -718,8 +712,6 @@ void INI_PARSE_IAD() { linefeed[0] == '\n' || linefeed[0] == '\0') continue; // Skip - wordtype = WORD_NONE; - // Every line is checked for a new section. INI_Section(linefeed, linesection); @@ -731,7 +723,7 @@ void INI_PARSE_IAD() { // Check word only when in a section if (section != INI_NONE) { INI_Word(linefeed, lineword); - wordtype = INI_WordType(lineword, section); + int wordtype = INI_WordType(lineword, section); if (section == INI_AREA) { if (wordtype == WORD_AREAX) @@ -770,7 +762,6 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { FILE *stream; int section = INI_NONE; - int wordtype = WORD_NONE; char dirname[256]; char filename[256]; @@ -804,8 +795,6 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { linefeed[0] == '\n' || linefeed[0] == '\0') continue; // Skip - wordtype = WORD_NONE; - // Every line is checked for a new section. INI_Section(linefeed, linesection); @@ -816,7 +805,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Check word only when in a section if (section != INI_NONE) { INI_Word(linefeed, lineword); - wordtype = INI_WordType(lineword, section); + int wordtype = INI_WordType(lineword, section); // WEAPON if (section == INI_WEAPON) { @@ -937,7 +926,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Skill, everything but botskill can change. // Determine reaction time based upon botskill here - float fMinReact = 0.0, fMaxReact; + float fMinReact = 0.0; if (pBot->bot_skill == 0) fMinReact = 0.0; else @@ -947,7 +936,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { RANDOM_FLOAT((pBot->bot_skill / 20) + 0.05, (pBot->bot_skill / 5) + 0.05); - fMaxReact = fMinReact + RANDOM_FLOAT(0.05, 0.2); + float fMaxReact = fMinReact + RANDOM_FLOAT(0.05, 0.2); // SET them pBot->fpMinReactTime = fMinReact; @@ -956,8 +945,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Set Offsets (note, they are extra upon current aiming code) // 30.8.04 redefined by frashman // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); - float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5) + 0.05, - (pBot->bot_skill / 2) + 0.05); + const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5) + 0.05, + (pBot->bot_skill / 2) + 0.05); // SET pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; @@ -995,10 +984,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE *rbl; - // Only save if lock type is < 1 - rbl = fopen(filename, "w+t"); + FILE* rbl = fopen(filename, "w+t"); // Created file if (rbl != NULL) { @@ -1076,7 +1063,6 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { void INI_PARSE_BUYTABLE() { FILE *stream; int section = INI_NONE; - int wordtype = WORD_NONE; int prev_section = section; int weapon_id = -1; @@ -1117,8 +1103,6 @@ void INI_PARSE_BUYTABLE() { linefeed[0] == '\n' || linefeed[0] == '\0') continue; // Skip - wordtype = WORD_NONE; - // Every line is checked for a new section. INI_Section(linefeed, linesection); @@ -1145,7 +1129,7 @@ void INI_PARSE_BUYTABLE() { // Check word only when in a section if (section != INI_NONE) { INI_Word(linefeed, lineword); - wordtype = INI_WordType(lineword, section); + int wordtype = INI_WordType(lineword, section); if (wordtype != WORD_NONE) { if (wordtype == WORD_PRICE) { //BotDebug("Loading price\n"); diff --git a/Makefile b/Makefile index 8f63e21..7c2407d 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ CPP = g++ - ARCHFLAG = -m32 -METAMOD_SRCDIR = ./dependencies/metamod-hl1/metamod -HLSDK_BASEDIR = ./dependencies/hlsdk +META_DIR = ./dependencies/metamod-hl1/metamod +HLSDK_DIR = ./dependencies/hlsdk BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/common" -I"${HLSDK_BASEDIR}/dlls" -I"${HLSDK_BASEDIR}/engine" -I"${HLSDK_BASEDIR}/pm_shared" -I"${HLSDK_BASEDIR}/public" +CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -w -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe -I"${META_DIR}" \ + -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" OBJ = NodeMachine.o \ bot.o \ @@ -30,7 +30,7 @@ ifeq ($(UNAME_S),Darwin) SO_SUFFIX = dylib endif -realbot_mm_i386.${SO_SUFFIX}: ${OBJ} +realbot_mm.${SO_SUFFIX}: ${OBJ} ${CPP} ${ARCHFLAG} -fPIC -shared -o $@ ${OBJ} -ldl mkdir -p Release mv $@ ${OBJ} Release @@ -51,4 +51,4 @@ distclean: ${CPP} ${CPPFLAGS} -c $< -o $@ %.o: %.c - ${CPP} ${CPPFLAGS} -c $< -o $@ + ${CPP} ${CPPFLAGS} -c $< -o $@ \ No newline at end of file diff --git a/NodeMachine.cpp b/NodeMachine.cpp index a34f093..18a94c8 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -32,14 +32,14 @@ * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 **/ -#include +#include #include #include #include #include // malloc stuff? -#include "stdlib.h" +#include // --- #include "bot.h" @@ -76,10 +76,10 @@ cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) { // was int // work out the position - long iPosition = (iFrom * MAX_NODES) + iTo; + const long iPosition = (iFrom * MAX_NODES) + iTo; - long iByte = (int) (iPosition / 8); - unsigned int iBit = iPosition % 8; + const long iByte = (int) (iPosition / 8); + const unsigned int iBit = iPosition % 8; if (iByte < g_iMaxVisibilityByte) { // Get the Byte that this is in @@ -103,10 +103,10 @@ cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { // -- END -- // was int - long iPosition = (iFrom * MAX_NODES) + iTo; + const long iPosition = (iFrom * MAX_NODES) + iTo; - long iByte = (int) (iPosition / 8); - unsigned int iBit = iPosition % 8; + const long iByte = (int) (iPosition / 8); + const unsigned int iBit = iPosition % 8; if (iByte < g_iMaxVisibilityByte) { unsigned char *ToChange = (cVisTable + iByte); @@ -118,13 +118,15 @@ cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { } } -void cNodeMachine::ClearVisibilityTable(void) { +void cNodeMachine::ClearVisibilityTable() const +{ if (cVisTable) { memset(cVisTable, 0, g_iMaxVisibilityByte); } } -void cNodeMachine::FreeVisibilityTable(void) { +void cNodeMachine::FreeVisibilityTable() const +{ if (cVisTable) { free(cVisTable); } @@ -171,7 +173,7 @@ void cNodeMachine::init() { } // CODE: From cheesemonster - unsigned long iSize = g_iMaxVisibilityByte; + const unsigned long iSize = g_iMaxVisibilityByte; //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first @@ -206,7 +208,8 @@ void cNodeMachine::initGoal(int g) { memset(Goals[g].name, 0, sizeof(Goals[g].name)); } -int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) { +int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const +{ char msg[255]; // sprintf(msg, "GetTroubleIndexForConnection | from %d to %d\n", iFrom, iTo); // rblog(msg); @@ -220,9 +223,7 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) { return -1; } - // seems to be valid, look for troubled connections - int index; - for (index = 0; index < MAX_TROUBLE; index++) { + for (int index = 0; index < MAX_TROUBLE; index++) { if (Troubles[index].iFrom == iFrom && Troubles[index].iTo == iTo) { memset(msg, 0, sizeof(msg)); @@ -245,14 +246,13 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) { * @return index of newly created index */ int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) { - int existingIndex = GetTroubleIndexForConnection(iFrom, iTo); + const int existingIndex = GetTroubleIndexForConnection(iFrom, iTo); if (existingIndex > -1) return existingIndex; // already exists int iNew = -1; - int t; - for (t = 0; t < MAX_TROUBLE; t++) + for (int t = 0; t < MAX_TROUBLE; t++) if (Troubles[t].iFrom < 0 || Troubles[t].iTo < 0) { iNew = t; @@ -299,7 +299,7 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) { * @return */ bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int iFrom, int iTo) { - int index = AddTroubledConnection(iFrom, iTo); + const int index = AddTroubledConnection(iFrom, iTo); IncreaseAttemptsForTroubledConnection(index); if (hasAttemptedConnectionTooManyTimes(index)) { rblog("(trouble) IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded | a troubled connection - tried too many times!\n"); @@ -339,7 +339,7 @@ bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) { sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); rblog(msg); - int index = GetTroubleIndexForConnection(iFrom, iTo); + const int index = GetTroubleIndexForConnection(iFrom, iTo); memset(msg, 0, sizeof(msg)); sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d has index %d\n", iFrom, iTo, index); @@ -365,7 +365,8 @@ void cNodeMachine::path_clear(int botIndex) { } // Return -Vector cNodeMachine::node_vector(int iNode) { +Vector cNodeMachine::node_vector(int iNode) const +{ if (iNode > -1) { return Nodes[iNode].origin; } @@ -374,7 +375,7 @@ Vector cNodeMachine::node_vector(int iNode) { } // Input: Vector, Output X and Y Meredians -void cNodeMachine::VectorToMeredian(Vector vOrigin, int *iX, int *iY) { +void cNodeMachine::VectorToMeredian(const Vector vOrigin, int *iX, int *iY) { // Called for lookupt and for storing float iCoordX = vOrigin.x + 8192.0; // map height (converts from - to +) float iCoordY = vOrigin.y + 8192.0; // map width (converts from - to +) @@ -402,9 +403,9 @@ void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { } // Does the node float? -bool cNodeMachine::node_float(Vector vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_float(const Vector vOrigin, edict_t *pEdict) { TraceResult tr; - Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); + const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) //UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -434,9 +435,9 @@ bool cNodeMachine::node_float(Vector vOrigin, edict_t *pEdict) { } // Does the node stand on a crate? or a steep slope? -bool cNodeMachine::node_on_crate(Vector vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_on_crate(const Vector vOrigin, edict_t *pEdict) { TraceResult tr; - Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); + const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) if (pEdict) @@ -471,7 +472,7 @@ bool cNodeMachine::node_on_crate(Vector vOrigin, edict_t *pEdict) { * @param pEdict * @return */ -int cNodeMachine::getClosestNode(Vector vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getClosestNode(const Vector vOrigin, float fDist, edict_t *pEdict) { // REDO: Need faster method to find a node // TOADD: For secure results all nodes should be checked to figure out the real // 'closest' node. @@ -494,11 +495,11 @@ int cNodeMachine::getClosestNode(Vector vOrigin, float fDist, edict_t *pEdict) { for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) { if (Meredians[iX][iY].iNodes[i] < 0) continue; // skip invalid node indexes - int iNode = Meredians[iX][iY].iNodes[i]; + const int iNode = Meredians[iX][iY].iNodes[i]; // if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us - float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); + const float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); if (distanceFromTo < dist) { dist = distanceFromTo; @@ -541,7 +542,7 @@ int cNodeMachine::getClosestNode(Vector vOrigin, float fDist, edict_t *pEdict) { * @param pEdict * @return */ -int cNodeMachine::getFurthestNode(Vector vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getFurthestNode(const Vector vOrigin, float fDist, edict_t *pEdict) { // Use Meredians to search for nodes // TODO: we should take care in the situation where we're at the 'edge' of such a meridian (subspace). So we should // basicly take edging meridians as well when too close to the edge. @@ -560,11 +561,11 @@ int cNodeMachine::getFurthestNode(Vector vOrigin, float fDist, edict_t *pEdict) for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) { if (Meredians[iX][iY].iNodes[i] < 0) continue; // skip invalid node indexes - int iNode = Meredians[iX][iY].iNodes[i]; + const int iNode = Meredians[iX][iY].iNodes[i]; // if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us - float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); + const float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); if (distanceFromTo < fDist && // within range distanceFromTo > dist) { // but furthest so far dist = distanceFromTo; @@ -607,7 +608,7 @@ bool cNodeMachine::add_neighbour_node(int iNode, int iToNode) { return false; tNode *node = getNode(iNode); - int iNeighbourId = freeNeighbourNodeIndex(node); + const int iNeighbourId = freeNeighbourNodeIndex(node); if (iNeighbourId > -1) { node->iNeighbour[iNeighbourId] = iToNode; return true; @@ -640,10 +641,8 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { bool removedOneOrMoreNeighbours = false; - // Find the connection and remove it - int i = 0; - for (i = 0; i < MAX_NEIGHBOURS; i++) { - int neighbourNode = node->iNeighbour[i]; + for (int i = 0; i < MAX_NEIGHBOURS; i++) { + const int neighbourNode = node->iNeighbour[i]; sprintf(msg, "(trouble) removeConnection(from->%d, to->%d), evaluating neighbour [%d] = node %d\n", @@ -673,8 +672,7 @@ bool cNodeMachine::remove_neighbour_nodes(int iNode) { if (iNode < 0) return false; - int i = 0; - for (i = 0; i < MAX_NEIGHBOURS; i++) + for (int i = 0; i < MAX_NEIGHBOURS; i++) Nodes[iNode].iNeighbour[i] = -1; return true; @@ -702,7 +700,7 @@ int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) { } // Compute the horizontal distance between A and B (ignoring z coordinate) -static float horizontal_distance(Vector a, Vector b) { +static float horizontal_distance(const Vector a, const Vector b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } @@ -710,18 +708,16 @@ static float horizontal_distance(Vector a, Vector b) { // Return the floor below V // TO BE IMPROVED use pEntityCOntaining -static Vector FloorBelow(Vector V) { +static Vector FloorBelow(const Vector V) { static TraceResult tr; // Keep it available even outside of the call - Vector ReallyDown, UpALittle; - int HullNumber, HullHeight; // First use this hull - HullNumber = human_hull; - HullHeight = 36; + int HullNumber = human_hull; + int HullHeight = 36; // Bump V a little higher (to allow for a steep climb) - UpALittle = V + Vector(0, 0, HullHeight); - ReallyDown = V + Vector(0, 0, -500); + Vector UpALittle = V + Vector(0, 0, HullHeight); + Vector ReallyDown = V + Vector(0, 0, -500); UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, NULL, &tr); //printf(" Floor %.0f -> %.0f, TraceHull fraction = %.2f, vecEndPos.z=%.0f %s %s\n", //UpALittle.z,ReallyDown.z,tr.flFraction,tr.vecEndPos.z, @@ -763,13 +759,14 @@ static Vector FloorBelow(Vector V) { // to a point in water or a point in the air // - ducking and walking (assuming flat ground) // - swimming -int cNodeMachine::Reachable(const int iStart, const int iEnd) { - Vector IncMove, Check, Floor, Start, End; +int cNodeMachine::Reachable(const int iStart, const int iEnd) const +{ + Vector IncMove, Check, Floor; float Dist, Height, PreviousHeight; TraceResult tr; - Start = Nodes[iStart].origin; - End = Nodes[iEnd].origin; + Vector Start = Nodes[iStart].origin; + Vector End = Nodes[iEnd].origin; #ifdef DEBUG_REACHABLE printf("Reachable %d(%.0f,%.0f,%.0f)%s", iStart, Start.x, Start.y, Start.z, @@ -881,12 +878,12 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) { } // Adding a node: another way... -int cNodeMachine::add2(Vector vOrigin, int iType, edict_t *pEntity) { +int cNodeMachine::add2(const Vector vOrigin, int iType, edict_t *pEntity) { // Do not add a node when there is already one close if (getClosestNode(vOrigin, NODE_ZONE, pEntity) > -1) return -1; - int newNodeIndex = getFreeNodeIndex(); + const int newNodeIndex = getFreeNodeIndex(); if (newNodeIndex >= MAX_NODES || newNodeIndex < 0) { return -1; @@ -944,7 +941,7 @@ int cNodeMachine::add2(Vector vOrigin, int iType, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling, the distance will be bigger. - int maxDistance = 3 * NODE_ZONE; + const int maxDistance = 3 * NODE_ZONE; if (horizontal_distance(Nodes[newNodeIndex].origin, Nodes[j].origin) > maxDistance) continue; @@ -969,9 +966,9 @@ int cNodeMachine::add2(Vector vOrigin, int iType, edict_t *pEntity) { * Returns a free node index, this is not bound to a meredian (subcluster)! * @return */ -int cNodeMachine::getFreeNodeIndex() { - int i = 0; - for (i = 0; i < MAX_NODES; i++) { +int cNodeMachine::getFreeNodeIndex() const +{ + for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin == INVALID_VECTOR) { return i; break; @@ -981,13 +978,13 @@ int cNodeMachine::getFreeNodeIndex() { } // Adding a node -int cNodeMachine::addNode(Vector vOrigin, edict_t *pEntity) { +int cNodeMachine::addNode(const Vector vOrigin, edict_t *pEntity) { // Do not add a node when there is already one close if (getClosestNode(vOrigin, NODE_ZONE, pEntity) > -1) return -1; - int currentIndex = getFreeNodeIndex(); + const int currentIndex = getFreeNodeIndex(); // failed to find free node, bail if (currentIndex < 0) { @@ -1065,7 +1062,7 @@ int cNodeMachine::addNode(Vector vOrigin, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling (or walking a slope), the distance will be bigger. - float distanceBetweenVectorsWithoutZAxis = func_distance(vNormalizedOrigin, vNormalizedIndex); + const float distanceBetweenVectorsWithoutZAxis = func_distance(vNormalizedOrigin, vNormalizedIndex); if (distanceBetweenVectorsWithoutZAxis > (NODE_ZONE * 3)) { // allow up to 3 times the boundary we use normally continue; } @@ -1076,7 +1073,7 @@ int cNodeMachine::addNode(Vector vOrigin, edict_t *pEntity) { // Traceline from nodeIndex to index bool bNeighbourFloats = node_float(Nodes[nodeIndex].origin, pEntity); - bool bNeighOnCrate = node_on_crate(Nodes[nodeIndex].origin, pEntity); + const bool bNeighOnCrate = node_on_crate(Nodes[nodeIndex].origin, pEntity); bool bNeighbourWater = false; // when pEntity is on ladder, it is NOT floating! @@ -1094,13 +1091,13 @@ int cNodeMachine::addNode(Vector vOrigin, edict_t *pEntity) { // // // 14/06/04 - fix: Some slopes are not counted in here..., de_dust jump from crates connects now - bool nodeIsHigherThanOrigin = Nodes[nodeIndex].origin.z > Nodes[currentIndex].origin.z; + const bool nodeIsHigherThanOrigin = Nodes[nodeIndex].origin.z > Nodes[currentIndex].origin.z; // this assumes 'our' position is lower, this determines 'slope' distance - vec_t slopeDistance = Nodes[nodeIndex].origin.z - Nodes[currentIndex].origin.z; + const vec_t slopeDistance = Nodes[nodeIndex].origin.z - Nodes[currentIndex].origin.z; // this assumes 'our' position is higher, so we can determine fall distance - vec_t fallDistance = Nodes[currentIndex].origin.z - Nodes[nodeIndex].origin.z; + const vec_t fallDistance = Nodes[currentIndex].origin.z - Nodes[nodeIndex].origin.z; if (indexNodeFloats && (fallDistance > MAX_FALLHEIGHT) @@ -1201,7 +1198,7 @@ int cNodeMachine::addNode(Vector vOrigin, edict_t *pEntity) { bCanConnect = true; if (bCanConnect) { - int jNeigh = freeNeighbourNodeIndex(&Nodes[nodeIndex]); + const int jNeigh = freeNeighbourNodeIndex(&Nodes[nodeIndex]); if (jNeigh > -1) Nodes[nodeIndex].iNeighbour[jNeigh] = currentIndex; // reversed also possible } @@ -1266,7 +1263,7 @@ void cNodeMachine::addNodesForPlayers() { if (pPlayer->free) continue; if (!IsAlive(pPlayer)) continue; - int iPlayerIndex = index - 1; + const int iPlayerIndex = index - 1; // within a certain distance no node found? add one if (func_distance(pPlayer->v.origin, Players[iPlayerIndex].vPrevPos) > NODE_ZONE) { @@ -1312,20 +1309,20 @@ void cNodeMachine::connections(edict_t *pEntity) { if (closeNode > -1) { for (int j = 0; j < MAX_NEIGHBOURS; j++) { tNode &node = Nodes[closeNode]; - int neighbourNode = node.iNeighbour[j]; + const int neighbourNode = node.iNeighbour[j]; if (neighbourNode > -1) { - Vector start = node.origin; - Vector end = Nodes[neighbourNode].origin; + const Vector start = node.origin; + const Vector end = Nodes[neighbourNode].origin; int red = 0; int green = 255; int blue = 0; - int troubleIndex = GetTroubleIndexForConnection(closeNode, neighbourNode); + const int troubleIndex = GetTroubleIndexForConnection(closeNode, neighbourNode); if (troubleIndex > -1) { - int tries = Troubles[troubleIndex].iTries; + const int tries = Troubles[troubleIndex].iTries; if (tries <= 1) { red = 255; green = 255; @@ -1357,22 +1354,22 @@ void cNodeMachine::connections(edict_t *pEntity) { // Draw void cNodeMachine::draw(edict_t *pEntity) { //DebugOut("waypoint: waypoint_draw()\n"); - int i = 0, max_drawn = 0; + int max_drawn = 0; - for (i = 0; i < MAX_NODES; i++) { + for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin != Vector(9999, 9999, 9999)) { - Vector start = Nodes[i].origin - Vector(0, 0, 36); + const Vector start = Nodes[i].origin - Vector(0, 0, 36); Vector end = Nodes[i].origin; - bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); + const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); - int angle_to_waypoint = + const int angle_to_waypoint = FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); if (good && angle_to_waypoint < 65) { - int r, g, b, l; - r = g = b = l = 250; + int g, b, l; + int r = g = b = l = 250; l = 250; //l = 250; // Normally light is 250 @@ -1395,7 +1392,7 @@ void cNodeMachine::draw(edict_t *pEntity) { } } // for } - int iNodeClose = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); + const int iNodeClose = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); char msg[50]; char Flags[10]; @@ -1426,7 +1423,6 @@ void cNodeMachine::draw(edict_t *pEntity) { void cNodeMachine::experience_save() { char dirname[256]; char filename[256]; - int i; // Set Directory name strcpy(dirname, "data/cstrike/exp/"); @@ -1436,15 +1432,14 @@ void cNodeMachine::experience_save() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE *rbl; // Only save if lock type is < 1 - rbl = fopen(filename, "wb"); + FILE* rbl = fopen(filename, "wb"); if (rbl != NULL) { int iVersion = FILE_EXP_VER2; fwrite(&iVersion, sizeof(int), 1, rbl); - for (i = 0; i < MAX_NODES; i++) { + for (int i = 0; i < MAX_NODES; i++) { fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); fwrite(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); @@ -1456,7 +1451,7 @@ void cNodeMachine::experience_save() { iMaxUsedNodes = MAX_NODES; // Here write down the MAX amounts of nodes used from vis table! - unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; fwrite(&iMaxUsedNodes, sizeof(int), 1, rbl); @@ -1509,8 +1504,7 @@ void cNodeMachine::experience_load() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE *rbl; - rbl = fopen(filename, "rb"); + FILE* rbl = fopen(filename, "rb"); if (rbl != NULL) { int iVersion = FILE_EXP_VER1; @@ -1531,7 +1525,7 @@ void cNodeMachine::experience_load() { if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; - unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; // Read table from what we know fread(cVisTable, iSize, 1, rbl); @@ -1551,7 +1545,7 @@ void cNodeMachine::experience_load() { if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; - unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; // Now read the cVisTable from what we know ClearVisibilityTable(); // clear first @@ -1587,10 +1581,10 @@ void cNodeMachine::experience_load() { } // Save -void cNodeMachine::save() { +void cNodeMachine::save() const +{ char dirname[256]; char filename[256]; - int i, n; // Set Directory name strcpy(dirname, "data/cstrike/maps/"); @@ -1600,17 +1594,16 @@ void cNodeMachine::save() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE *rbl; // Only save if lock type is < 1 - rbl = fopen(filename, "wb"); + FILE* rbl = fopen(filename, "wb"); if (rbl != NULL) { // Write down version number int iVersion = FILE_NODE_VER1; fwrite(&iVersion, sizeof(int), 1, rbl); - for (i = 0; i < MAX_NODES; i++) { + for (int i = 0; i < MAX_NODES; i++) { fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); - for (n = 0; n < MAX_NEIGHBOURS; n++) + for (int n = 0; n < MAX_NEIGHBOURS; n++) fwrite(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); // save bit flags @@ -1621,7 +1614,8 @@ void cNodeMachine::save() { fprintf(stderr, "Cannot write file %s\n", filename); } -void cNodeMachine::save_important() { +void cNodeMachine::save_important() const +{ char dirname[256]; char filename[256]; @@ -1645,7 +1639,7 @@ void cNodeMachine::save_important() { if (Goals[iGn].iType == GOAL_IMPORTANT) { // save this area fprintf(rbl, "[AREA]\n"); - Vector iGoalVector = node_vector(Goals[iGn].iNode); + const Vector iGoalVector = node_vector(Goals[iGn].iNode); fprintf(rbl, "X=%f\n", iGoalVector.x); fprintf(rbl, "Y=%f\n", iGoalVector.y); fprintf(rbl, "Z=%f\n\n", iGoalVector.z); @@ -1662,7 +1656,7 @@ void cNodeMachine::save_important() { void cNodeMachine::load() { char dirname[256]; char filename[256]; - int i, n; + int i; // Set Directory name strcpy(dirname, "data/cstrike/maps/"); @@ -1673,8 +1667,7 @@ void cNodeMachine::load() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE *rbl; - rbl = fopen(filename, "rb"); + FILE* rbl = fopen(filename, "rb"); if (rbl != NULL) { int iVersion = FILE_NODE_VER1; @@ -1684,7 +1677,7 @@ void cNodeMachine::load() { if (iVersion == FILE_NODE_VER1) { for (i = 0; i < MAX_NODES; i++) { fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); - for (n = 0; n < MAX_NEIGHBOURS; n++) { + for (int n = 0; n < MAX_NEIGHBOURS; n++) { fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); } @@ -1739,22 +1732,22 @@ void cNodeMachine::ClearImportantGoals() { // Draw path 0 (user) void cNodeMachine::path_draw(edict_t *pEntity) { //DebugOut("waypoint: waypoint_draw()\n"); - int i = 0, max_drawn = 0; + int max_drawn = 0; - for (i = 0; i < MAX_NODES; i++) { - int iNode = iPath[draw_nodepath][i]; - int iNextNode = iPath[draw_nodepath][(i + 1)]; + for (int i = 0; i < MAX_NODES; i++) { + const int iNode = iPath[draw_nodepath][i]; + const int iNextNode = iPath[draw_nodepath][(i + 1)]; if (iNode > -1 && iNextNode > -1) { - Vector start = Nodes[iNode].origin; + const Vector start = Nodes[iNode].origin; Vector end = Nodes[iNextNode].origin; - bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); - int angle_to_waypoint = + const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); + const int angle_to_waypoint = FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); if (max_drawn < 39 && good && angle_to_waypoint < 50) { - int red = 255; + const int red = 255; int green = 0; int blue = 255; int width = 15; @@ -1801,7 +1794,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { // Go through all valid nodes, except iNode, and increase danger if needed. for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin != Vector(9999, 9999, 9999) && i != iNode) { - float fDist = func_distance(Nodes[i].origin, Nodes[iNode].origin); + const float fDist = func_distance(Nodes[i].origin, Nodes[iNode].origin); if (fDist < NODE_CONTACT_DIST) { //Using TraceHull to detect de_aztec bridge and other entities. TraceResult tr; @@ -1812,7 +1805,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { // within distance and 'reachable' if (tr.flFraction >= 1.0) { - double costIncrease = (fDist / NODE_CONTACT_DIST) * NODE_CONTACT_STEP; + const double costIncrease = (fDist / NODE_CONTACT_DIST) * NODE_CONTACT_STEP; InfoNodes[i].fContact[iTeam] += costIncrease; } } @@ -1842,7 +1835,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { // Go through all valid nodes, except iNode, and increase danger if needed. for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin != Vector(9999, 9999, 9999) && i != iNode) { - float fDist = func_distance(Nodes[i].origin, Nodes[iNode].origin); + const float fDist = func_distance(Nodes[i].origin, Nodes[iNode].origin); if (fDist < NODE_DANGER_DIST) { //Using TraceHull to detect de_aztec bridge and other entities. TraceResult tr; @@ -1851,7 +1844,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { // within distance and reachable if (tr.flFraction >= 1.0) { - double costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; + const double costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; InfoNodes[i].fDanger[iTeam] += costIncrease; } } @@ -1860,7 +1853,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { } // Adds a new goal to the array -void cNodeMachine::addGoal(edict_t *pEdict, int goalType, Vector vVec) { +void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector vVec) { // // 14/06/04 // Be carefull with adding SERVER_PRINT messages here @@ -1873,7 +1866,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, Vector vVec) { return; // do not add goal that is already in our list } - int index = getFreeGoalIndex(); + const int index = getFreeGoalIndex(); if (index < 0) { return; } @@ -1934,8 +1927,7 @@ tGoal *cNodeMachine::getGoal(int index) { */ int cNodeMachine::getFreeGoalIndex() const { int index = -1; - int g = 0; // <-- ADDED BY PMB ELSE LINUX COMPILER COMPLAINS (ISO COMPLIANCE) - for (g = 0; g < MAX_GOALS; g++) { + for (int g = 0; g < MAX_GOALS; g++) { if (Goals[g].iType == GOAL_NONE) { index = g; break; @@ -1951,7 +1943,8 @@ int cNodeMachine::getFreeGoalIndex() const { * @param pEdict * @return */ -bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) { +bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const +{ if (pEdict == NULL) return false; // no edict == by default no for (int g = 0; g < MAX_GOALS; g++) { @@ -1972,7 +1965,8 @@ void cNodeMachine::resetCheckedValuesForGoals() { } // returns goal type from node, -1 for unknown -int cNodeMachine::getGoalIndexFromNode(int iNode) { +int cNodeMachine::getGoalIndexFromNode(int iNode) const +{ for (int g = 0; g < MAX_GOALS; g++) if (Goals[g].iNode == iNode) return Goals[g].iType; @@ -2126,7 +2120,7 @@ tGoal *cNodeMachine::getRandomGoalByType(int goalType) { return NULL; // nothing found :( // we have an amount of goals, pick one randomly - int randomGoalIndex = RANDOM_LONG(0, (possibleCandidateIndex - 1)); + const int randomGoalIndex = RANDOM_LONG(0, (possibleCandidateIndex - 1)); char msg[255]; sprintf(msg, "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", @@ -2153,7 +2147,7 @@ void cNodeMachine::scale_contact() { continue; // no need to rescale } // Check how much we passed the limit - float fLimit = 1.0 / fHighest; + const float fLimit = 1.0 / fHighest; // Now rescale all for (i = 0; i < MAX_NODES; i++) @@ -2183,7 +2177,7 @@ void cNodeMachine::scale_danger() { continue; // no need to rescale } // Check how much we passed the limit - float fLimit = 0.7 / fHighest; + const float fLimit = 0.7 / fHighest; // Now rescale all for (i = 0; i < MAX_NODES; i++) @@ -2213,9 +2207,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn if (nodeStartIndex > iMaxUsedNodes || nodeTargetIndex > iMaxUsedNodes) return false; // do not create a path when invalid params given - int botTeam = -1; if (pBot) { - botTeam = UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based + int botTeam = UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based } const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); @@ -2227,7 +2220,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn return false; } - int path_index = 0, nodeIndex; + int nodeIndex; path_clear(botIndex); @@ -2235,10 +2228,10 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn makeAllWaypointsAvailable(); // Our start waypoint is open - float gCost = 0.0f; // distance from starting node - float hCost = func_distance(Nodes[nodeStartIndex].origin, - Nodes[nodeTargetIndex].origin); // distance from end node to node - float cost = gCost + hCost; + const float gCost = 0.0f; // distance from starting node + const float hCost = func_distance(Nodes[nodeStartIndex].origin, + Nodes[nodeTargetIndex].origin); // distance from end node to node + const float cost = gCost + hCost; closeNode(nodeStartIndex, nodeStartIndex, cost); openNeighbourNodes(nodeStartIndex, nodeStartIndex, nodeTargetIndex, -1); @@ -2366,12 +2359,12 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn } // INIT: Start - path_index = 0; // done above, but done again to be sure + int path_index = 0; // done above, but done again to be sure // INIT: End // Now set the path up correctly for (nodeIndex = (MAX_NODES - 1); nodeIndex > -1; nodeIndex--) { - int node = temp_path[nodeIndex]; + const int node = temp_path[nodeIndex]; if (node < 0) continue; @@ -2421,6 +2414,10 @@ void cNodeMachine::closeNode(int nodeIndex, int parent, float cost) { /** * Open all neighbouring nodes, calculate costs for each neighbouring node + * @param startNodeIndex + * @param nodeToOpenNeighboursFrom + * @param destinationNodeIndex + * @param botTeam * @param nodeStartIndex * @param parent * @param cost @@ -2432,16 +2429,16 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou tNode &node = Nodes[nodeToOpenNeighboursFrom]; // node evaluating neighbours for (int i = 0; i < MAX_NEIGHBOURS; i++) { - int neighbourNode = node.iNeighbour[i]; + const int neighbourNode = node.iNeighbour[i]; if (neighbourNode < 0) continue; // skip invalid nodes if (Nodes[neighbourNode].origin == INVALID_VECTOR) continue; // skip nodes with invalid vector - float gCost = func_distance(startNode.origin, destNode.origin); // distance from starting node - float hCost = func_distance(node.origin, destNode.origin); // distance from end node to node + const float gCost = func_distance(startNode.origin, destNode.origin); // distance from starting node + const float hCost = func_distance(node.origin, destNode.origin); // distance from end node to node float cost = gCost + hCost; if (botTeam > -1) { - double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; + const double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; // double contactCost = InfoNodes[neighbourNode].fContact[botTeam] * cost; cost += dangerCost; @@ -2474,9 +2471,9 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou * This marks all waypoints to be available to be evaluated again * @param nodeIndex */ -void cNodeMachine::makeAllWaypointsAvailable() const { - int nodeIndex = 0; - for (nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { +void cNodeMachine::makeAllWaypointsAvailable() +{ + for (int nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { astar_list[nodeIndex].cost = 0; astar_list[nodeIndex].parent = -1; astar_list[nodeIndex].state = AVAILABLE; @@ -2485,7 +2482,7 @@ void cNodeMachine::makeAllWaypointsAvailable() const { } // Find a node which has almost no danger! -int cNodeMachine::node_camp(Vector vOrigin, int iTeam) { +int cNodeMachine::node_camp(const Vector vOrigin, int iTeam) { // Use Meredians to search for nodes int iX, iY; VectorToMeredian(vOrigin, &iX, &iY); @@ -2502,7 +2499,7 @@ int cNodeMachine::node_camp(Vector vOrigin, int iTeam) { // Search in this meredian for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) if (Meredians[iX][iY].iNodes[i] > -1) { - int iNode = Meredians[iX][iY].iNodes[i]; + const int iNode = Meredians[iX][iY].iNodes[i]; if (Nodes[iNode].iNodeBits & BIT_WATER) continue; // next node, do not camp under water! @@ -2537,10 +2534,10 @@ int cNodeMachine::node_camp(Vector vOrigin, int iTeam) { // Check if iFrom is visible from other nodes (and opposite) void cNodeMachine::vis_calculate(int iFrom) { // Check around your area to see what is visible - float fClosest = 1024; + const float fClosest = 1024; for (int i = 0; i < MAX_NODES; i++) if ((i != iFrom) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { - float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); + const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { TraceResult tr; @@ -2562,7 +2559,7 @@ void cNodeMachine::vis_calculate(int iFrom) { } // Find a node to look at when camping -int cNodeMachine::node_look_camp(Vector vOrigin, int iTeam, +int cNodeMachine::node_look_camp(const Vector vOrigin, int iTeam, edict_t *pEdict) { rblog("node_look_camp - start\n"); @@ -2572,10 +2569,10 @@ int cNodeMachine::node_look_camp(Vector vOrigin, int iTeam, // Theory: // Find a node, far, and a lot danger... - int iFrom = getClosestNode(vOrigin, 75, pEdict); + const int iFrom = getClosestNode(vOrigin, 75, pEdict); // Search in this meredian for (int i = 0; i < MAX_NODES; i++) { - int iNode = i; + const int iNode = i; if (InfoNodes[iNode].fDanger[iTeam] > fDanger) if (func_distance(vOrigin, Nodes[iNode].origin) > fDistance) { // all nodes within this range may be tracelined @@ -2627,7 +2624,7 @@ int cNodeMachine::node_look_camp(Vector vOrigin, int iTeam, */ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->rprint("cNodeMachine::path_walk", "START"); - int BotIndex = pBot->iBotIndex; + const int BotIndex = pBot->iBotIndex; // Check if path is valid if (iPath[BotIndex][0] < 0) { @@ -2656,7 +2653,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->setMoveSpeed(pBot->f_max_speed); // Walk the path - int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); // Node we are heading for + const int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); // Node we are heading for // possibly end of path reached, overshoot destination? if (currentNodeToHeadFor < 0) { @@ -2669,7 +2666,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // when pButtonEdict is filled in, we check if we are close! if (pBot->pButtonEdict) { pBot->rprint("cNodeMachine::path_walk", "Interacting with button logic"); - Vector vButtonVector = VecBModelOrigin(pBot->pButtonEdict); + const Vector vButtonVector = VecBModelOrigin(pBot->pButtonEdict); float fDistance = 90; bool bTrigger = false; @@ -2811,7 +2808,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } } - bool shouldDrawWaypointBeamsFromBot = false; + const bool shouldDrawWaypointBeamsFromBot = false; if (shouldDrawWaypointBeamsFromBot) { tNode *nodeHeadingFor = this->getNode(currentNodeToHeadFor); @@ -2831,7 +2828,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { 255, 255, 255 ); - int currentNode = pBot->determineCurrentNodeWithTwoAttempts(); + const int currentNode = pBot->determineCurrentNodeWithTwoAttempts(); if (currentNode > -1) { tNode *node = getNode(currentNode); @@ -2862,7 +2859,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // TODO TODO TODO Water Navigation - int nextNodeToHeadFor = pBot->getNextPathNode(); // the node we will head for after reaching currentNode + const int nextNodeToHeadFor = pBot->getNextPathNode(); // the node we will head for after reaching currentNode // NO ENEMY, CHECK AROUND AREA // This determines where to look at, no enemy == look at next node @@ -2920,11 +2917,11 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - unstuck // - go back in path... - float timeEvaluatingMoveSpeed = 0.1; - bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; + const float timeEvaluatingMoveSpeed = 0.1; + const bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; - double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. Else it would trigger stuck logic too soon, too often. - double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; + const double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. Else it would trigger stuck logic too soon, too often. + const double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; double expectedMoveDistance = speedInOneTenthOfASecond; if (pBot->isFreezeTime()) expectedMoveDistance = 0; if (pBot->isWalking()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; @@ -2937,7 +2934,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, expectedMoveDistance, notStuckForAWhile); pBot->rprint_trace("cNodeMachine::path_walk", msg); - bool isStuck = distanceMoved < expectedMoveDistance && pBot->shouldBeAbleToMove() && notStuckForAWhile; // also did not evaluate this logic for 0.5 second + const bool isStuck = distanceMoved < expectedMoveDistance && pBot->shouldBeAbleToMove() && notStuckForAWhile; // also did not evaluate this logic for 0.5 second Vector &vector = Nodes[currentNodeToHeadFor].origin; if (isStuck) { @@ -2950,8 +2947,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (pBot->getMoveToNodeTimeRemaining() < 0) { pBot->rprint_trace("cNodeMachine::path_walk/timeRemaining", "Time is up!"); - int iFrom = pBot->getPreviousPathNodeToHeadFor(); - int iTo = currentNodeToHeadFor; + const int iFrom = pBot->getPreviousPathNodeToHeadFor(); + const int iTo = currentNodeToHeadFor; IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(iFrom, iTo); @@ -2967,8 +2964,8 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "START"); pBot->fNotStuckTime = gpGlobals->time + 0.25; // give some time to unstuck - int iFrom = pBot->getPreviousPathNodeToHeadFor(); - int iTo = currentNodeToHeadFor; + const int iFrom = pBot->getPreviousPathNodeToHeadFor(); + const int iTo = currentNodeToHeadFor; // JUMP & DUCK tNode ¤tNode = Nodes[currentNodeToHeadFor]; @@ -2999,7 +2996,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec char msg[255]; memset(msg, 0, sizeof(msg)); - float timeRemaining = pBot->getMoveToNodeTimeRemaining(); + const float timeRemaining = pBot->getMoveToNodeTimeRemaining(); sprintf(msg, "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); @@ -3075,7 +3072,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec // check if the connection we want is going up // - when going up // - when we should move - bool nodeToHeadForIsHigher = currentNode.origin.z > pBot->pEdict->v.origin.z; + const bool nodeToHeadForIsHigher = currentNode.origin.z > pBot->pEdict->v.origin.z; if (nodeToHeadForIsHigher) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Node to head for is higher than me"); // check if the next node is floating (skip self) @@ -3123,10 +3120,10 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { pBot->rprint_trace("cNodeMachine::ExecuteNearNodeLogic", "Start"); - int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); + const int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); // first determine if we where heading for a goal node - bool isHeadingForGoalNode = pBot->isHeadingForGoalNode(); + const bool isHeadingForGoalNode = pBot->isHeadingForGoalNode(); // increase index on path, so we will go to next node pBot->nextPathIndex(); @@ -3142,10 +3139,10 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { char msg[255]; memset(msg, 0, sizeof(msg)); - int currentPathNode = pBot->getCurrentPathNodeToHeadFor(); + const int currentPathNode = pBot->getCurrentPathNodeToHeadFor(); if (currentPathNode > -1) { - int troubleIndex = GetTroubleIndexForConnection(pBot->getPreviousPathNodeToHeadFor(), currentNodeToHeadFor); + const int troubleIndex = GetTroubleIndexForConnection(pBot->getPreviousPathNodeToHeadFor(), currentNodeToHeadFor); if (troubleIndex > -1) { tTrouble &trouble = Troubles[troubleIndex]; sprintf(msg, "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); @@ -3205,7 +3202,7 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { // At destination, bomb is planted and we have not discovered the C4 yet... // TODO: Remember which goals/bomb spots have been visited so bots won't visit this bomb spot again? - int iGoalType = getGoalIndexFromNode(pBot->getGoalNode()); + const int iGoalType = getGoalIndexFromNode(pBot->getGoalNode()); if (pBot->isCounterTerrorist()) { if (Game.bBombPlanted && !Game.isPlantedC4Discovered()) { @@ -3234,22 +3231,26 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { * @param pEntityHit * @return */ -bool cNodeMachine::isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHit) const { +bool cNodeMachine::isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHit) +{ return FBitSet(pEntityHit->v.spawnflags, SF_DOOR_USE_ONLY) && !(FBitSet(pEntityHit->v.spawnflags, SF_DOOR_NO_AUTO_RETURN)); } -bool cNodeMachine::isEntityDoor(const edict_t *pEntityHit) const { +bool cNodeMachine::isEntityDoor(const edict_t *pEntityHit) +{ return strcmp(STRING(pEntityHit->v.classname), "func_door") == 0 || // normal door (can be used as an elevator) strcmp(STRING(pEntityHit->v.classname), "func_wall") == 0 || // I am not 100% sure about func_wall, but include it anyway strcmp(STRING(pEntityHit->v.classname), "func_door_rotating") == 0; // rotating door } -bool cNodeMachine::isEntityHostage(const edict_t *pEntityHit) const { +bool cNodeMachine::isEntityHostage(const edict_t *pEntityHit) +{ return strcmp(STRING(pEntityHit->v.classname), "hostage_entity") == 0; // hostage } -bool cNodeMachine::isEntityWorldspawn(const edict_t *pEntityHit) const { +bool cNodeMachine::isEntityWorldspawn(const edict_t *pEntityHit) +{ return strcmp(STRING(pEntityHit->v.classname), "worldspawn") == 0; // the world } @@ -3259,7 +3260,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->shouldBeWandering()) { int currentNode = -1; for (int attempts = 1; attempts < 5; attempts++) { - float distance = NODE_ZONE + (attempts * NODE_ZONE); + const float distance = NODE_ZONE + (attempts * NODE_ZONE); currentNode = pBot->determineCurrentNode(distance); // this also sets current node in bot state if (currentNode > -1) break; } @@ -3291,7 +3292,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint("cNodeMachine::path_think", "Time to camp"); if (!pBot->hasGoal()) { pBot->rprint("cNodeMachine::path_think", "Setting goal to look for camping"); - int noteToLookAt = node_look_camp(pBot->pEdict->v.origin, UTIL_GetTeam(pBot->pEdict), pBot->pEdict); + const int noteToLookAt = node_look_camp(pBot->pEdict->v.origin, UTIL_GetTeam(pBot->pEdict), pBot->pEdict); pBot->setGoalNode(noteToLookAt); } return; @@ -3312,14 +3313,14 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_think", "I am not walking a path."); - int thisBotIndex = pBot->iBotIndex; + const int thisBotIndex = pBot->iBotIndex; // No path pBot->stopMoving(); if (pBot->hasGoal()) { // there is no path, but there is a goal to work to - int iCurrentNode = pBot->determineCurrentNodeWithTwoAttempts(); + const int iCurrentNode = pBot->determineCurrentNodeWithTwoAttempts(); if (iCurrentNode < 0) { pBot->forgetGoal(); @@ -3365,35 +3366,31 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { int iFinalGoalNode = -1; int iFinalGoalIndex = -1; - int goalIndex = 0; - - float MAX_DISTANCE = 16384.0; // theoretical max distance - float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0; + const float MAX_DISTANCE = 16384.0; // theoretical max distance + const float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0; // 01-07-2008; Instead of using 'scores', use a normalized score. // We do: // (current score + gained score) / 2.0; // Since both scores can be max 1.0, meaning we keep it between 0.0 and 1.0 // A score of 1.0 is max. - int maxCheckedScore = 5; + const int maxCheckedScore = 5; pBot->rprint_normal("cNodeMachine::path_think", "going to choose goal"); - for (goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { + for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { // Make sure this goal is valid if (Goals[goalIndex].iNode < 0) { continue; } - float score = 0.0f; // start with 0 - - float fDistanceToGoal = func_distance( + const float fDistanceToGoal = func_distance( pBot->pEdict->v.origin, node_vector(Goals[goalIndex].iNode) ); // First score is distance, so just set it: - score = fDistanceToGoal / MAX_GOAL_DISTANCE; + float score = fDistanceToGoal / MAX_GOAL_DISTANCE; if (Goals[goalIndex].iChecked > maxCheckedScore) { // it has been very popular, reset @@ -3438,10 +3435,10 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { score = (score + (1.0 - (goalAlreadyUsedScore / teamMembers))) / 2.0; // Goals regardless of map/game type - int goalType = Goals[goalIndex].iType; + const int goalType = Goals[goalIndex].iType; if (goalType == GOAL_SPAWNCT || goalType == GOAL_SPAWNT) { - float goalscore = fDistanceToGoal / MAX_GOAL_DISTANCE; + const float goalscore = fDistanceToGoal / MAX_GOAL_DISTANCE; score = (score + goalscore) / 2.0; } @@ -3468,7 +3465,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { // always go to the most furthest hostage spot, and add some randomness here, else // all bots go to there. - float mul = MAX_GOAL_DISTANCE / fDistanceToGoal; + const float mul = MAX_GOAL_DISTANCE / fDistanceToGoal; goalscore = 1 + mul; } } else { @@ -3501,7 +3498,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->hasBomb()) { goalscore = 2.0; // plant it! } else { - float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; + const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; goalscore = (0.7 * mul); } @@ -3515,21 +3512,21 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint_trace("path_think/determine goal", msg); // find a node close to the C4 - int nodeCloseToC4 = getClosestNode(Game.vPlantedC4, NODE_ZONE * 2, NULL); + const int nodeCloseToC4 = getClosestNode(Game.vPlantedC4, NODE_ZONE * 2, NULL); if (nodeCloseToC4 > -1) { // measure distance compared to goal node we are evaluating - float distanceToC4FromCloseNode = func_distance( + const float distanceToC4FromCloseNode = func_distance( Game.vPlantedC4, node_vector(Goals[nodeCloseToC4].iNode) ); // the distance from this goal node - float distanceToC4FromThisGoalNode = func_distance( + const float distanceToC4FromThisGoalNode = func_distance( Game.vPlantedC4, node_vector(Goals[goalIndex].iNode) ); - float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; + const float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; goalscore = 1.5 + score; memset(msg, 0, sizeof(msg)); sprintf(msg, "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", @@ -3548,7 +3545,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } } else { pBot->rprint_trace("path_think/determine goal", "Bomb is not planted"); - float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; + const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; goalscore = (0.7 * mul); } } @@ -3729,7 +3726,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // } // create path - bool success = createPath(iCurrentNode, pBot->getGoalNode(), thisBotIndex, pBot, pBot->iPathFlags); + const bool success = createPath(iCurrentNode, pBot->getGoalNode(), thisBotIndex, pBot, pBot->iPathFlags); // If we still did not find a path, we set wander time // for 1 second we wait before a new attempt to find a goal and create a path. @@ -3738,7 +3735,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint("cNodeMachine::path_think()", "Finding node nearby to move to"); pBot->setGoalNode(getClosestNode(pBot->pEdict->v.origin, NODE_ZONE * 5, pBot->pEdict)); - bool successToAlternative = createPath(iCurrentNode, pBot->getGoalNode(), thisBotIndex, pBot, pBot->iPathFlags); + const bool successToAlternative = createPath(iCurrentNode, pBot->getGoalNode(), thisBotIndex, pBot, pBot->iPathFlags); if (!successToAlternative) { pBot->rprint("cNodeMachine::path_think()", "Unable to create path to node nearby."); @@ -3754,7 +3751,8 @@ tNode *cNodeMachine::getNode(int index) { return &Nodes[index]; } -char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) const { +char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) +{ char typeAsText[32]; memset(typeAsText, 0, sizeof(typeAsText)); @@ -3836,7 +3834,7 @@ int cNodeMachine::node_cover(int iFrom, int iTo, edict_t *pEdict) { int iClosest = -1; for (int i = 0; i < MAX_NODES; i++) if ((i != iTo) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { - float fDistance = + const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { // all nodes within this range may be tracelined @@ -3950,14 +3948,13 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, return iClosest; } -void cNodeMachine::dump_goals(void) { - int i; - char buffer[100]; - Vector v; +void cNodeMachine::dump_goals() const +{ + char buffer[100]; - rblog("Dump of all goals\n"); - for (i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { - v = Nodes[Goals[i].iNode].origin; + rblog("Dump of all goals\n"); + for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { + Vector v = Nodes[Goals[i].iNode].origin; sprintf(buffer, "Goal#%d is at node %d (%.0f, %.0f, %.0f), iChecked= %d, ", i + 1, Goals[i].iNode, v.x, v.y, v.z, Goals[i].iChecked); @@ -4013,8 +4010,7 @@ void cNodeMachine::dump_goals(void) { // EVY: another dump void cNodeMachine::dump_path(int iBot, int CurrentPath) { char buffer[80]; - int i, j, CurrentNode; - Vector v; + int i, CurrentNode; if (CurrentPath >= 0) CurrentNode = iPath[iBot][CurrentPath]; @@ -4034,8 +4030,8 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { rblog(" Current direct neighbours are:\n"); for (i = 0; i < MAX_NEIGHBOURS; i++) if (Nodes[CurrentNode].iNeighbour[i] >= 0) { - j = Nodes[CurrentNode].iNeighbour[i]; - v = Nodes[j].origin; + int j = Nodes[CurrentNode].iNeighbour[i]; + Vector v = Nodes[j].origin; sprintf(buffer, " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, v.z); rblog(buffer); @@ -4054,10 +4050,10 @@ static char *bmp_buffer; static float maxx, maxy, minx, miny; static float scale; -static void InitDebugBitmap(void) { +static void InitDebugBitmap() { // this function allocates memory and clears the debug bitmap buffer - if (bmp_buffer) +// if (bmp_buffer) free(bmp_buffer); // reliability check, free BMP buffer if already allocated bmp_buffer = NULL; @@ -4074,18 +4070,16 @@ static void InitDebugBitmap(void) { // Draw a small cross static void DrawPoint(const Vector v, unsigned char color) { - int offset, x0, y0; - - if (bmp_buffer == NULL) { + if (bmp_buffer == NULL) { fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates - x0 = (int) ((v.x - minx) / scale); - y0 = (int) ((v.y - miny) / scale); + int x0 = (int)((v.x - minx) / scale); + int y0 = (int)((v.y - miny) / scale); - offset = y0 * DEBUG_BMP_WIDTH + x0; + int offset = y0 * DEBUG_BMP_WIDTH + x0; if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", @@ -4112,9 +4106,8 @@ static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsign // assumed to be DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT pixels (currently 2000 * 2000 to fit with // the size of the universe, with an adaptative unit scale, up to 1 pixel = 10 vector units). - int x0, y0, x1, y1; - int dx, stepx, dy, stepy; - int offset, fraction; + int stepx, stepy; + int fraction; if (bmp_buffer == NULL) { fprintf(stderr, @@ -4122,13 +4115,13 @@ static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsign return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates - x0 = (int) ((v_from.x - minx) / scale); - y0 = (int) ((v_from.y - miny) / scale); - x1 = (int) ((v_to.x - minx) / scale); - y1 = (int) ((v_to.y - miny) / scale); + int x0 = (int)((v_from.x - minx) / scale); + int y0 = (int)((v_from.y - miny) / scale); + int x1 = (int)((v_to.x - minx) / scale); + int y1 = (int)((v_to.y - miny) / scale); - dx = (x1 - x0) * 2; - dy = (y1 - y0) * 2; + int dx = (x1 - x0) * 2; + int dy = (y1 - y0) * 2; if (dx < 0) { dx = -dx; stepx = -1; @@ -4140,7 +4133,7 @@ static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsign } else stepy = 1; - offset = y0 * DEBUG_BMP_WIDTH + x0; + int offset = y0 * DEBUG_BMP_WIDTH + x0; if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", @@ -4213,12 +4206,7 @@ static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsign // from PMB & Botman code static void WriteDebugBitmap(const char *filename) { - // this function writes the debug bitmap image buffer in a .BMP file to disk. The format is - // 256 color and 2000 * 2000 pixels. The center of the world being roughly the center of the - // bitmap. The bitmap is stored in the file specified by 'filename' (which can be a relative - // path from the Half-Life base directory). - FILE *fp; - int data_start, file_size; + int data_start, file_size; unsigned long dummy; if (bmp_buffer == NULL) { @@ -4227,10 +4215,10 @@ static void WriteDebugBitmap(const char *filename) { return; // reliability check: cancel if bmp buffer unallocated } // open (or create) the .bmp file for writing in binary mode... - fp = fopen(filename, "wb"); + FILE* fp = fopen(filename, "wb"); if (fp == NULL) { fprintf(stderr, "WriteDebugBitmap(): unable to open BMP file!\n"); - if (bmp_buffer) +// if (bmp_buffer) free(bmp_buffer); // cannot open file, free DXF buffer bmp_buffer = NULL; return; // cancel if error creating file @@ -4370,7 +4358,7 @@ static void WriteDebugBitmap(const char *filename) { fclose(fp); // finished, close the BMP file - if (bmp_buffer) +// if (bmp_buffer) free(bmp_buffer); // and free the BMP buffer bmp_buffer = NULL; @@ -4380,13 +4368,11 @@ static void WriteDebugBitmap(const char *filename) { // Find the border of all nodes to scale the bitmap -void cNodeMachine::FindMinMax(void) { - int i; - float scalex, scaley; - - minx = miny = 9999.0; +void cNodeMachine::FindMinMax() const +{ + minx = miny = 9999.0; maxx = maxy = -9999.0; - for (i = 0; + for (int i = 0; (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); i++) { if (Nodes[i].origin.x > maxx) @@ -4406,8 +4392,8 @@ void cNodeMachine::FindMinMax(void) { miny -= NODE_ZONE; // first compute the X and Y divider scale, and take the greatest of both - scalex = (1 + maxx - minx) / DEBUG_BMP_WIDTH; - scaley = (1 + maxy - miny) / DEBUG_BMP_WIDTH; + float scalex = (1 + maxx - minx) / DEBUG_BMP_WIDTH; + float scaley = (1 + maxy - miny) / DEBUG_BMP_WIDTH; if (scalex > scaley) scale = scalex + scalex / 100; // add a little offset (margin) for safety else @@ -4420,26 +4406,24 @@ void cNodeMachine::FindMinMax(void) { // Makes a slightly darker dark void cNodeMachine::MarkAxis(void) { - int x, y, x0, y0; - - x0 = (int) ((0 - minx) / scale); - y0 = (int) ((0 - miny) / scale); + int x0 = (int)((0 - minx) / scale); + int y0 = (int)((0 - miny) / scale); // Mark X axis by keeping X to 0 and varying Y if ((minx < 0) && (0 < maxx)) - for (y = 0; y < DEBUG_BMP_HEIGHT; y++) + for (int y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x0] += 2; // Mark Y axis by keeping Y to 0 and varying X if ((miny < 0) && (0 < maxy)) - for (x = 0; x < DEBUG_BMP_WIDTH; x++) + for (int x = 0; x < DEBUG_BMP_WIDTH; x++) bmp_buffer[y0 * DEBUG_BMP_WIDTH + x] += 2; } // 05/07/04 // Mark each meredians (default 256 units) of alternating color -void cNodeMachine::MarkMeredians(void) { +void cNodeMachine::MarkMeredians() { int x, y; int Meredian; @@ -4469,13 +4453,13 @@ void cNodeMachine::MarkMeredians(void) { // Put a cross on all nodes in RBN + draw lines to all neighbours void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) { - int i, j; + int i; // Draw all neighbours for (i = 0; (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); i++) - for (j = 0; (j < MAX_NEIGHBOURS) && (Nodes[i].iNeighbour[j] >= 0); + for (int j = 0; (j < MAX_NEIGHBOURS) && (Nodes[i].iNeighbour[j] >= 0); j++) DrawLineInDebugBitmap(Nodes[i].origin, Nodes[Nodes[i].iNeighbour[j]].origin, @@ -4489,28 +4473,24 @@ void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) { // Put a small cross at all goal points -void cNodeMachine::PlotGoals(int color) { - int i; - Vector v; - - for (i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { - v = Nodes[Goals[i].iNode].origin; +void cNodeMachine::PlotGoals(int color) const +{ + for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { + Vector v = Nodes[Goals[i].iNode].origin; DrawPoint(v, color); } } // Plot the computed paths for all life bots void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) { - int i, iBot, From, To; - - for (iBot = 0; (iBot < 32); iBot++) { + for (int iBot = 0; (iBot < 32); iBot++) { if (bots[iBot].bIsUsed) { - From = iPath[iBot][0]; + int From = iPath[iBot][0]; if (From < 0) continue; // This bot has not path - for (i = 1; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { - To = iPath[iBot][i]; + for (int i = 1; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { + int To = iPath[iBot][i]; DrawLineInDebugBitmap(Nodes[From].origin, Nodes[To].origin, (bots[iBot].iTeam == 1) ? Tcolor : CTcolor); @@ -4526,7 +4506,7 @@ void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) { // 05/07/04 // Marking Axis, Meredians, other colors, other filenames (linked to map names) -void cNodeMachine::Draw(void) { +void cNodeMachine::Draw() { static int Count = 0; // Static to create filenames like cs_siege0000.bmp, cs_siege0001.bmp, ... char Filename[80]; @@ -4652,7 +4632,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // Somehow the button is not detectable. Find a node, that is close to it. // then retry the traceline. It should NOT hit a thing now. // On success, it is still our button - int iClose = getClosestNode(vPentVector, NODE_ZONE, pent); + const int iClose = getClosestNode(vPentVector, NODE_ZONE, pent); if (iClose > -1) { // retry the tracehull @@ -4679,10 +4659,10 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) if (pButtonEdict) { memset(msg, 0, sizeof(msg)); // Get its vector - Vector vButtonVector = VecBModelOrigin(pButtonEdict); + const Vector vButtonVector = VecBModelOrigin(pButtonEdict); // Search a node close to it - int iButtonNode = getClosestNode(vButtonVector, NODE_ZONE, pButtonEdict); + const int iButtonNode = getClosestNode(vButtonVector, NODE_ZONE, pButtonEdict); // When node found, create path to it if (pBot->createPath(iButtonNode, PATH_NONE)) { diff --git a/NodeMachine.h b/NodeMachine.h index 18e3a0e..47efc13 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -45,13 +45,13 @@ class cNodeMachine { // ----------------- int addNode(Vector vOrigin, edict_t *pEntity); - int Reachable(const int iStart, const int iEnd); + int Reachable(const int iStart, const int iEnd) const; int add2(Vector vOrigin, int iType, edict_t *pEntity); int getClosestNode(Vector vOrigin, float fDist, edict_t *pEdict); // returns a close node int getFurthestNode(Vector vOrigin, float fDist, edict_t *pEdict); // returns a node within dist, but most far away - int getFreeNodeIndex(); + int getFreeNodeIndex() const; // ----------------- bool add_neighbour_node(int iNode, int iToNode); @@ -60,21 +60,21 @@ class cNodeMachine { bool remove_neighbour_nodes(int iNode); - int freeNeighbourNodeIndex(tNode *Node); + static int freeNeighbourNodeIndex(tNode *Node); int is_neighbour_node(tNode node, int iNode); // ----------------- void init(); // Init (info)nodes - void save(); // Save nodes on disk + void save() const; // Save nodes on disk void load(); // Load nodes on disk - void save_important(); + void save_important() const; // ----------------- - Vector node_vector(int iNode); + Vector node_vector(int iNode) const; // ----------------- - int GetTroubleIndexForConnection(int iFrom, int iTo); + int GetTroubleIndexForConnection(int iFrom, int iTo) const; int AddTroubledConnection(int iFrom, int iTo); @@ -90,20 +90,20 @@ class cNodeMachine { void setUpInitialGoals(); // find new goals and attach them to the nodes void updateGoals(); // update moving goals (ie hostages) - int getGoalIndexFromNode(int iNode); + int getGoalIndexFromNode(int iNode) const; void resetCheckedValuesForGoals(); void ClearImportantGoals(); - bool hasGoalWithEdict(edict_t *pEdict); + bool hasGoalWithEdict(edict_t *pEdict) const; void addGoal(edict_t *pEdict, int goalType, Vector vVec); tGoal * getRandomGoalByType(int goalType); // return a node close to a iType goal (random) - bool node_float(Vector vOrigin, edict_t *pEdict); + static bool node_float(Vector vOrigin, edict_t *pEdict); - bool node_on_crate(Vector vOrigin, edict_t *pEdict); + static bool node_on_crate(Vector vOrigin, edict_t *pEdict); int node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance); @@ -143,7 +143,7 @@ class cNodeMachine { int getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex); // ----------------- - void VectorToMeredian(Vector vOrigin, int *iX, int *iY); // Input: origin, output X and Y Meredians + static void VectorToMeredian(Vector vOrigin, int *iX, int *iY); // Input: origin, output X and Y Meredians void AddToMeredian(int iX, int iY, int iNode); // ----------------- @@ -158,18 +158,18 @@ class cNodeMachine { // ------------------- // From cheesemonster: int GetVisibilityFromTo(int iFrom, int iTo); // BERKED - void ClearVisibilityTable(void); + void ClearVisibilityTable() const; void SetVisibilityFromTo(int iFrom, int iTo, bool bVisible); - void FreeVisibilityTable(void); + void FreeVisibilityTable() const; // Some debugging by EVY - void dump_goals(void); + void dump_goals() const; void dump_path(int iBot, int ThisNode); - void Draw(void); + void Draw(); tNode *getNode(int index); @@ -190,24 +190,24 @@ class cNodeMachine { unsigned char *cVisTable; tTrouble Troubles[MAX_TROUBLE]; - void FindMinMax(void); + void FindMinMax() const; - void MarkAxis(void); + static void MarkAxis(); - void MarkMeredians(void); + static void MarkMeredians(); void PlotNodes(int NeighbourColor, int NodeColor); void PlotPaths(int Tcolor, int CTcolor); - void PlotGoals(int GoalColor); + void PlotGoals(int GoalColor) const; - void makeAllWaypointsAvailable() const; + static void makeAllWaypointsAvailable(); - void closeNode(int nodeIndex, int parent, float cost); + static void closeNode(int nodeIndex, int parent, float cost); void openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam); - char *getGoalTypeAsText(const tGoal &goal) const; + static char *getGoalTypeAsText(const tGoal &goal); int getFreeGoalIndex() const; @@ -215,11 +215,11 @@ class cNodeMachine { void initGoal(int g); - bool isEntityDoor(const edict_t *pEntityHit) const; - bool isEntityHostage(const edict_t *pEntityHit) const; - bool isEntityWorldspawn(const edict_t *pEntityHit) const; + static bool isEntityDoor(const edict_t *pEntityHit); + static bool isEntityHostage(const edict_t *pEntityHit); + static bool isEntityWorldspawn(const edict_t *pEntityHit); - bool isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHit) const; + static bool isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHit); void ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vector &vector); diff --git a/bot.cpp b/bot.cpp index d2c49f4..7d14b11 100644 --- a/bot.cpp +++ b/bot.cpp @@ -72,7 +72,7 @@ bool CBaseBot::IsShootableThruObstacle(Vector vecDest) */ -#include +#include #include #include #include @@ -138,7 +138,7 @@ void cBot::SpawnInit() { fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5, 5); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; - float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; f_shoot_wait_time = gpGlobals->time; f_goback_time = gpGlobals->time; @@ -311,7 +311,7 @@ void cBot::NewRound() { fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5, 5); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; - float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; f_shoot_wait_time = gpGlobals->time; f_goback_time = gpGlobals->time; @@ -462,7 +462,7 @@ void cBot::NewRound() { iMax++; } - int the_c = RANDOM_LONG(0, iMax); + const int the_c = RANDOM_LONG(0, iMax); if (the_c > -1 && iMax > -1) { char chSentence[80]; @@ -496,7 +496,7 @@ void cBot::PrepareChat(char sentence[128]) { Function purpose: Return reaction time based upon skill ******************************************************************************/ float cBot::ReactionTime(int iSkill) { - float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); + const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); if (Game.messageVerbosity > 1) { char msg[255]; sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); @@ -534,13 +534,13 @@ int cBot::FindEnemy() { // if bot can see the player... if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) { - int player_team = UTIL_GetTeam(pPlayer); - int bot_team = UTIL_GetTeam(pEdict); + const int player_team = UTIL_GetTeam(pPlayer); + const int bot_team = UTIL_GetTeam(pEdict); if (player_team == bot_team) continue; // do not target teammates // Its not a friend, track enemy - float fDistance = + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); bool bCanSee = true; @@ -560,7 +560,7 @@ int cBot::FindEnemy() { // We found a new enemy & the new enemy is different then previous pointer if (pNewEnemy && pNewEnemy != pEnemyEdict) { - int iCurrentNode = determineCurrentNode(); + const int iCurrentNode = determineCurrentNode(); // Add 'contact' data if (iCurrentNode > -1) { @@ -601,15 +601,16 @@ void cBot::rememberEnemyFound() { /****************************************************************************** Function purpose: Sets vHead to aim at vector ******************************************************************************/ -void cBot::setHeadAiming(Vector vTarget) { +void cBot::setHeadAiming(const Vector vTarget) { vHead = vTarget; } /** - * Returns true / false wether enemy is alive. + * Returns true / false whether enemy is alive. * @return */ -bool cBot::isEnemyAlive() { +bool cBot::isEnemyAlive() const +{ return IsAlive(pEnemyEdict); } @@ -626,8 +627,8 @@ bool cBot::isSeeingEnemy() { Vector vBody = pEnemyEdict->v.origin; Vector vHead = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs; - bool bodyInFOV = FInViewCone(&vBody, pEdict) && FVisible(vBody, pEdict); - bool headInFOV = FInViewCone(&vHead, pEdict) && FVisible(vHead, pEdict); + const bool bodyInFOV = FInViewCone(&vBody, pEdict) && FVisible(vBody, pEdict); + const bool headInFOV = FInViewCone(&vHead, pEdict) && FVisible(vHead, pEdict); if (bodyInFOV || headInFOV) { return true; } @@ -647,14 +648,11 @@ void cBot::AimAtEnemy() { return; } - // ------------------------ we can see enemy ------------------------- - float fDistance; - // Distance to enemy - fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero + float fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero // factor in distance, the further away the more deviation - which is based on skill - int skillReversed = (10 - bot_skill) + 1; + const int skillReversed = (10 - bot_skill) + 1; float fScale = 0.5 + (fDistance / (64 * skillReversed)); // a good skilled bot is less impacted by distance than a bad skilled bot @@ -671,8 +669,8 @@ void cBot::AimAtEnemy() { vTarget = pEnemyEdict->v.origin; // aim for body // Based upon how far, we make this fuzzy - float fDx, fDy, fDz; - fDx = fDy = fDz = ((bot_skill + 1) * fScale); + float fDy, fDz; + float fDx = fDy = fDz = ((bot_skill + 1) * fScale); // Example 1: // Super skilled bot (bot_skill 1), with enemy of 2048 units away. Results into: @@ -797,7 +795,7 @@ void cBot::FightEnemy() { if (!bFirstOutOfSight) { rprint_trace("FightEnemy()", "Enemy out of sight, calculating path towards it."); // Only change path when we update our information here - int iGoal = NodeMachine.getClosestNode(lastSeenEnemyVector, NODE_ZONE, pEdict); + const int iGoal = NodeMachine.getClosestNode(lastSeenEnemyVector, NODE_ZONE, pEdict); if (iGoal > -1) { setGoalNode(iGoal); forgetPath(); @@ -821,11 +819,13 @@ void cBot::pickWeapon(int weaponId) { f_update_weapon_time = gpGlobals->time + 0.7; } -bool cBot::ownsFavoritePrimaryWeapon() { +bool cBot::ownsFavoritePrimaryWeapon() const +{ return hasFavoritePrimaryWeaponPreference() && isOwningWeapon(ipFavoPriWeapon); } -bool cBot::ownsFavoriteSecondaryWeapon() { +bool cBot::ownsFavoriteSecondaryWeapon() const +{ return hasFavoriteSecondaryWeaponPreference() && isOwningWeapon(ipFavoSecWeapon); } @@ -834,7 +834,8 @@ bool cBot::ownsFavoriteSecondaryWeapon() { * @param weaponId * @return */ -bool cBot::isOwningWeapon(int weaponId) { +bool cBot::isOwningWeapon(int weaponId) const +{ return bot_weapons & (1 << weaponId); } @@ -843,19 +844,23 @@ bool cBot::isOwningWeapon(int weaponId) { * @param weaponId * @return */ -bool cBot::isHoldingWeapon(int weaponId) { +bool cBot::isHoldingWeapon(int weaponId) const +{ return (current_weapon.iId == weaponId); } -bool cBot::hasFavoritePrimaryWeaponPreference() { +bool cBot::hasFavoritePrimaryWeaponPreference() const +{ return ipFavoPriWeapon > -1; } -bool cBot::hasFavoriteSecondaryWeaponPreference() { +bool cBot::hasFavoriteSecondaryWeaponPreference() const +{ return ipFavoSecWeapon > -1; } -bool cBot::canAfford(int price) { +bool cBot::canAfford(int price) const +{ return this->bot_money > price; } @@ -868,9 +873,9 @@ void cBot::PickBestWeapon() { return; // Distance to enemy - float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); + const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - float knifeDistance = 300; + const float knifeDistance = 300; // ---------------------------- // In this function all we do is decide what weapon to pick @@ -932,8 +937,8 @@ void cBot::PickBestWeapon() { // ---------------------------------------- // More complex bad things that can happen: // ---------------------------------------- - int iTotalAmmo = current_weapon.iAmmo1; - int iCurrentAmmo = current_weapon.iClip; + const int iTotalAmmo = current_weapon.iAmmo1; + const int iCurrentAmmo = current_weapon.iClip; //char msg[80]; //sprintf(msg, "BOT: ICLIP %d, TOTALAMMO %d\n", iCurrentAmmo, iTotalAmmo); @@ -1024,8 +1029,7 @@ void cBot::FireWeapon() { if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) || CarryWeapon(CS_WEAPON_AUG)) && (bot_skill < 3)) { - float f_burst = 0.1; - f_burst = (2048 / fDistance) + 0.1; + float f_burst = (2048 / fDistance) + 0.1; if (f_burst < 0.1) f_burst = 0.1; if (f_burst > 0.4) @@ -1149,9 +1153,9 @@ void cBot::Combat() { if (Game.iDeathsBroadcasting != BROADCAST_DEATHS_NONE) { // This is a human, we will tell this human he has been killed // by a bot. - int r = RANDOM_LONG(150, 255); - int g = RANDOM_LONG(30, 155); - int b = RANDOM_LONG(30, 155); + const int r = RANDOM_LONG(150, 255); + const int g = RANDOM_LONG(30, 155); + const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); @@ -1209,20 +1213,16 @@ void cBot::Combat() { ******************************************************************************/ void cBot::FindCover() { TraceResult tr; - Vector dest = lastSeenEnemyVector; + const Vector dest = lastSeenEnemyVector; // Vector start = pEdict->v.origin; // Vector end; Vector cover_vect = Vector(9999, 9999, 9999); - // When vector is visible, then look from that vector to the threat, if then NOT - // Visible, then its cover. - Vector v_src, v_right, v_left; - // TraceLines in 2 directions to find which way to go... UTIL_MakeVectors(pEdict->v.v_angle); - v_src = pEdict->v.origin + pEdict->v.view_ofs; - v_right = v_src + gpGlobals->v_right * 90; - v_left = v_src + gpGlobals->v_right * -90; + Vector v_src = pEdict->v.origin + pEdict->v.view_ofs; + Vector v_right = v_src + gpGlobals->v_right * 90; + Vector v_left = v_src + gpGlobals->v_right * -90; // We have now our first 'left' and 'right' @@ -1304,13 +1304,13 @@ void cBot::FindCover() { } } - int iNodeEnemy = NodeMachine.getClosestNode(pEnemyEdict->v.origin, 60, pEnemyEdict); - int iNodeFrom = NodeMachine.getClosestNode(pEdict->v.origin, NODE_ZONE, pEdict); + const int iNodeEnemy = NodeMachine.getClosestNode(pEnemyEdict->v.origin, 60, pEnemyEdict); + const int iNodeFrom = NodeMachine.getClosestNode(pEdict->v.origin, NODE_ZONE, pEdict); // -------------- // TEST TEST TEST // -------------- - int iCoverNode = NodeMachine.node_cover(iNodeFrom, iNodeEnemy, pEdict); + const int iCoverNode = NodeMachine.node_cover(iNodeFrom, iNodeEnemy, pEdict); bool bTakenCover = false; if (iCoverNode > -1) { @@ -1329,7 +1329,7 @@ void cBot::FindCover() { // -------------------------------------------------- if (cover_vect != Vector(9999, 9999, 9999)) { rprint("FindCover()", "cover node found (cover_vect based)"); - int iNodeCover = NodeMachine.getClosestNode(cover_vect, 60, pEdict); + const int iNodeCover = NodeMachine.getClosestNode(cover_vect, 60, pEdict); if (iNodeCover > -1) { setGoalNode(iNodeCover); forgetPath(); @@ -1430,7 +1430,7 @@ void cBot::InteractWithPlayers() { // friends are important, we are a team dudes! InteractWithFriends(); - int result = FindEnemy(); + const int result = FindEnemy(); // ------------------------------- // RESULT < 0; NO ENEMY FOUND @@ -1544,7 +1544,7 @@ void cBot::InteractWithPlayers() { } // INITIALIZATION: - int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); + const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); if (iGoal > -1) { rprint_trace("InteractWithPlayers()", "Found a new enemy, setting goal and forgetting path"); setGoalNode(iGoal); @@ -1590,7 +1590,7 @@ void cBot::InteractWithPlayers() { // // INITIALIZATION: - int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); + const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); if (iGoal > -1) { rprint_trace("InteractWithPlayers()", "Found a *newer* enemy, so picking goal node to that"); @@ -1704,13 +1704,12 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { // how? we save the values here, andc alculate the new value. // this part is copied from botchangeyaw/pitch so it SHOULD work :) float current_180; // current +/- 180 degrees - float diff; // turn from the current v_angle pitch to the idealpitch by selecting // the quickest way to turn to face that direction // find the difference in the current and ideal angle - diff = fabs(current - ideal); + float diff = fabs(current - ideal); // check if the bot is already facing the idealpitch direction... if (diff <= 1.0) @@ -1796,11 +1795,11 @@ bool cBot::Defuse() { // Remember, pent=c4 now! // Calculate the distance between our position to the c4 - Vector vC4 = pent->v.origin; - float distance = func_distance(pEdict->v.origin, vC4); + const Vector vC4 = pent->v.origin; + const float distance = func_distance(pEdict->v.origin, vC4); // can see C4 - bool canSeeC4 = canSeeVector(vC4); + const bool canSeeC4 = canSeeVector(vC4); if (!canSeeC4) { rprint_trace("Defuse()", "Cannot see planted C4 - bailing"); @@ -1816,13 +1815,13 @@ bool cBot::Defuse() { // We can do 2 things now // - If we are not close, we check if we can walk to it, and if so we face to the c4 // - If we are close, we face it and (begin) defuse the bomb. - int distanceForC4ToBeInReach = 70; + const int distanceForC4ToBeInReach = 70; if (distance < distanceForC4ToBeInReach) { vHead = vC4; vBody = vC4; setTimeToMoveToNode(3); // we are going to do non-path-follow stuff, so keep timer updated - int angle_to_c4 = FUNC_InFieldOfView(pEdict, (vC4 - pEdict->v.origin)); + const int angle_to_c4 = FUNC_InFieldOfView(pEdict, (vC4 - pEdict->v.origin)); // if defusion timer has not been set (ie, the bot is not yet going to defuse the bomb) if (f_defuse < gpGlobals->time && angle_to_c4 < 35) { @@ -1852,7 +1851,7 @@ bool cBot::Defuse() { } else { rprint_trace("Defuse()", "I can see C4, but it is out of reach."); - int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, NULL); + const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, NULL); if (iGoalNode < 0) { rprint_normal("Defuse()", "No node close, so just look at it/body face at it and move towards it."); vHead = vC4; @@ -2080,7 +2079,8 @@ bool cBot::shouldActWithC4() const { } // BOT: On ladder? -bool cBot::isOnLadder() { +bool cBot::isOnLadder() const +{ return FUNC_IsOnLadder(pEdict); } @@ -2099,42 +2099,41 @@ void cBot::CheckAround() { // Note: we use TRACEHULL instead of TRACELINE, because TRACEHULL detects // the famous 'undetectable' func_walls. TraceResult tr; - Vector v_source, v_left, v_right, v_forward, v_forwardleft, v_forwardright; -// v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); - v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); + // v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); + Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); // Go forward first - float distance = 90; - v_forward = v_source + gpGlobals->v_forward * distance; + const float distance = 90; + Vector v_forward = v_source + gpGlobals->v_forward * distance; // now really go left/right - v_right = v_source + gpGlobals->v_right * distance; - v_left = v_source + gpGlobals->v_right * -distance; + Vector v_right = v_source + gpGlobals->v_right * distance; + Vector v_left = v_source + gpGlobals->v_right * -distance; // now really go left/right - v_forwardright = v_right + gpGlobals->v_forward * distance; - v_forwardleft = v_left + gpGlobals->v_forward * -distance; + Vector v_forwardright = v_right + gpGlobals->v_forward * distance; + Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; // TRACELINE: forward UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - bool bHitForward = tr.flFraction < 1.0; + const bool bHitForward = tr.flFraction < 1.0; // TRACELINE: Left UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - bool bHitLeft = tr.flFraction < 1.0; + const bool bHitLeft = tr.flFraction < 1.0; // TRACELINE: Right UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - bool bHitRight = tr.flFraction < 1.0; + const bool bHitRight = tr.flFraction < 1.0; // TRACELINE: Forward left UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - bool bHitForwardLeft = tr.flFraction < 1.0; + const bool bHitForwardLeft = tr.flFraction < 1.0; // TRACELINE: Forward right UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - bool bHitForwardRight = tr.flFraction < 1.0; + const bool bHitForwardRight = tr.flFraction < 1.0; char msg[255]; @@ -2181,7 +2180,7 @@ void cBot::CheckAround() { if (strcmp("func_breakable", item_name) == 0) { // Found a func_breakable - Vector vBreakableOrigin = VecBModelOrigin(pent); + const Vector vBreakableOrigin = VecBModelOrigin(pent); // Shoot if ((pent->v.flags & FL_WORLDBRUSH) == 0) // can it be broken? @@ -2205,7 +2204,8 @@ void cBot::CheckAround() { } // BOT: Should be taking cover? -bool cBot::TakeCover() { +bool cBot::TakeCover() const +{ // Its time based. if (f_cover_time < gpGlobals->time) @@ -2234,17 +2234,20 @@ void cBot::prevPathIndex() { } // Returns true if bot has a path to follow -bool cBot::isWalkingPath() { +bool cBot::isWalkingPath() const +{ return this->pathIndex > -1; } // Returns true if bot has goal node -bool cBot::hasGoal() { +bool cBot::hasGoal() const +{ return this->iGoalNode > -1; } // Returns true if bot has goal node index (ie referring to Goals[]) -bool cBot::hasGoalIndex() { +bool cBot::hasGoalIndex() const +{ return this->goalIndex > -1; } @@ -2252,7 +2255,8 @@ bool cBot::hasGoalIndex() { * Returns goal data , if goal data exists * @return */ -tGoal *cBot::getGoalData() { +tGoal *cBot::getGoalData() const +{ if (!hasGoalIndex()) return NULL; tGoal *ptr = NodeMachine.getGoal(this->goalIndex); if (ptr == NULL) return NULL; @@ -2265,7 +2269,8 @@ tGoal *cBot::getGoalData() { } // Returns true if bot has an enemy edict -bool cBot::hasEnemy() { +bool cBot::hasEnemy() const +{ return this->pEnemyEdict != NULL; } @@ -2274,7 +2279,8 @@ bool cBot::hasEnemy() { * @param pEdict * @return */ -bool cBot::hasEnemy(edict_t * pEdict) { +bool cBot::hasEnemy(edict_t * pEdict) const +{ return this->pEnemyEdict == pEdict; } @@ -2336,11 +2342,13 @@ void cBot::forgetGoal() { this->goalIndex = -1; } -int cBot::getPathIndex() { +int cBot::getPathIndex() const +{ return this->pathIndex; } -int cBot::getPreviousPathIndex() { +int cBot::getPreviousPathIndex() const +{ return this->pathIndex - 1; } @@ -2354,11 +2362,13 @@ void cBot::forgetEnemy() { this->pEnemyEdict = NULL; } -edict_t * cBot::getEnemyEdict() { +edict_t * cBot::getEnemyEdict() const +{ return this->pEnemyEdict; } -int cBot::getGoalNode() { +int cBot::getGoalNode() const +{ return this->iGoalNode; } @@ -2440,27 +2450,33 @@ void cBot::rprint_trace(const char *msg) { rprint_trace("rprint()", msg); } -bool cBot::hasBomb() { +bool cBot::hasBomb() const +{ return isOwningWeapon(CS_WEAPON_C4); } -bool cBot::isCounterTerrorist() { +bool cBot::isCounterTerrorist() const +{ return iTeam == 2; } -bool cBot::isTerrorist() { +bool cBot::isTerrorist() const +{ return iTeam == 1; } -bool cBot::hasPrimaryWeaponEquiped() { +bool cBot::hasPrimaryWeaponEquiped() const +{ return iPrimaryWeapon > -1; } -bool cBot::hasSecondaryWeaponEquiped() { +bool cBot::hasSecondaryWeaponEquiped() const +{ return iSecondaryWeapon > -1; } -bool cBot::hasSecondaryWeapon(int weaponId) { +bool cBot::hasSecondaryWeapon(int weaponId) const +{ return isOwningWeapon(weaponId); } @@ -2745,7 +2761,7 @@ void cBot::Memory() { // check if its running if (FUNC_PlayerRuns(FUNC_PlayerSpeed(pPlayer))) { // check distance - float fDistance = + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody @@ -2774,7 +2790,7 @@ void cBot::Memory() { && FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_SMOKEGRENADE)) { // check distance - float fDistance = + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody @@ -2798,7 +2814,7 @@ void cBot::Memory() { // zooming of a sniper rifle if (pPlayer->v.button & IN_ATTACK2) { // check distance - float fDistance = + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody @@ -2856,7 +2872,7 @@ void cBot::Memory() { } // we go to the destination - float fTime = 5 + (ipFearRate / 7); + const float fTime = 5 + (ipFearRate / 7); if (RANDOM_LONG(0, 100) < ipFearRate && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk @@ -2929,16 +2945,18 @@ void cBot::Memory() { // BOT: Do i carry weapon # now? -bool cBot::CarryWeapon(int iType) { +bool cBot::CarryWeapon(int iType) const +{ if (current_weapon.iId == iType) return true; return false; } // BOT: Do i carry weapon TYPE # now? -int cBot::CarryWeaponType() { +int cBot::CarryWeaponType() const +{ int kind = PRIMARY; - int weapon_id = current_weapon.iId; + const int weapon_id = current_weapon.iId; // Check 1. Is it a knife? if (weapon_id == CS_WEAPON_KNIFE) @@ -3011,7 +3029,8 @@ void cBot::rememberWhichHostageToRescue(edict_t *pHostage) { this->pBotHostage = pHostage; } -edict_t * cBot::getHostageToRescue() { +edict_t * cBot::getHostageToRescue() const +{ return pBotHostage; } @@ -3034,11 +3053,13 @@ edict_t * cBot::findHostageToRescue() { return NULL; } -bool cBot::isDefusing() { +bool cBot::isDefusing() const +{ return f_defuse > gpGlobals->time; } -bool cBot::hasTimeToMoveToNode() { +bool cBot::hasTimeToMoveToNode() const +{ return fMoveToNodeTime > -1 && getMoveToNodeTimeRemaining() > 0; } /** @@ -3065,7 +3086,8 @@ int cBot::determineCurrentNodeWithTwoAttempts() { /** Find node close to bot, given range. Does not cache result. **/ -int cBot::determineCurrentNode(float range) { +int cBot::determineCurrentNode(float range) const +{ return NodeMachine.getClosestNode(pEdict->v.origin, range, pEdict); } @@ -3085,7 +3107,8 @@ int cBot::getCurrentNode() { /** * Aka, the node we are heading for. */ -int cBot::getCurrentPathNodeToHeadFor() { +int cBot::getCurrentPathNodeToHeadFor() const +{ return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex); } @@ -3093,23 +3116,27 @@ int cBot::getCurrentPathNodeToHeadFor() { * Aka, the node we were coming from. In case the index is < 0 (ie, there is no previous node yet), this will * return -1; */ -int cBot::getPreviousPathNodeToHeadFor() { +int cBot::getPreviousPathNodeToHeadFor() const +{ return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, getPreviousPathIndex()); } -bool cBot::isHeadingForGoalNode() { +bool cBot::isHeadingForGoalNode() const +{ return getCurrentPathNodeToHeadFor() == getGoalNode(); } /** * Aka, the next node after we have arrived at the current path node. */ -int cBot::getNextPathNode() { +int cBot::getNextPathNode() const +{ return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex + 1); } // Is this bot dead? -bool cBot::isDead() { +bool cBot::isDead() const +{ return (pEdict->v.health < 1) || (pEdict->v.deadflag != DEAD_NO); } @@ -3147,9 +3174,9 @@ void cBot::Think() { && killer_edict != NULL) { // This is a human, we will tell this human he has been killed // by a bot. - int r = RANDOM_LONG(150, 255); - int g = RANDOM_LONG(30, 155); - int b = RANDOM_LONG(30, 155); + const int r = RANDOM_LONG(150, 255); + const int g = RANDOM_LONG(30, 155); + const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) sprintf(msg, @@ -3191,7 +3218,7 @@ void cBot::Think() { if (ChatEngine.ReplyBlock[99].sentence[tc][0] != '\0') iMax++; } - int the_c = RANDOM_LONG(0, iMax); + const int the_c = RANDOM_LONG(0, iMax); if (the_c > -1 && iMax > -1) { char chSentence[80]; @@ -3241,9 +3268,9 @@ void cBot::Think() { // Move speed... moved_distance. if (distanceMovedTimer <= gpGlobals->time) { // see how far bot has moved since the previous position... - Vector v_diff = prevOrigin - pEdict->v.origin; + const Vector v_diff = prevOrigin - pEdict->v.origin; // make distanceMoved an average of this moment and the previous one. - float movedTwoTimes = distanceMoved + v_diff.Length(); + const float movedTwoTimes = distanceMoved + v_diff.Length(); // prevent division by zero if (movedTwoTimes > 0.0f) { @@ -3270,7 +3297,7 @@ void cBot::Think() { // -------------------------------- // IMPORTANT THINKING GOING ON HERE // -------------------------------- - int healthChange = prev_health - bot_health; + const int healthChange = prev_health - bot_health; // handle damage taken if (prev_health > bot_health @@ -3308,8 +3335,8 @@ void cBot::Think() { // NEW: When round time is over and still busy playing, kill bots - float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60; - float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60; + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); if (Game.getRoundStartedTime() + 10.0 + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { end_round = true; // round is ended @@ -3439,7 +3466,7 @@ bool cBot::isFreezeTime() const { Return true if one of the pointers is not NULL **/ bool cBot::isEscortingHostages() { - bool result = getAmountOfHostagesBeingRescued() > 0; + const bool result = getAmountOfHostagesBeingRescued() > 0; if (result) { rprint("I am escorting hostages!"); } @@ -3618,10 +3645,9 @@ bool BotRadioAction() { if (BotPointer == NULL) continue; // somehow this fucked up, bail out - bool want_to_answer = false; // want to answer radio call - bool report_back = false; // for reporting in - float distance = func_distance(plr->v.origin, - BotPointer->pEdict->v.origin); // distance between the 2 + const bool report_back = false; // for reporting in + const float distance = func_distance(plr->v.origin, + BotPointer->pEdict->v.origin); // distance between the 2 // Same team, randomly, do we even listen to the radio? // the more further away, the more chance it will not listen @@ -3634,7 +3660,7 @@ bool BotRadioAction() { // Hearrate (personality setting) if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && bWantToListen) - want_to_answer = true; + bool want_to_answer = true; bool can_do_negative = true; // On some radio commands we can't say negative, thats stupid @@ -3676,7 +3702,7 @@ bool BotRadioAction() { can_do_negative = false; // Find player who issues this message and go to it - int iBackupNode = + const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); // Help this player @@ -3713,7 +3739,7 @@ bool BotRadioAction() { unstood = true; // get source of backup - int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); if (iBackupNode > -1) { BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); @@ -3747,7 +3773,7 @@ bool BotRadioAction() { } if ((FUNC_DoRadio(BotPointer)) && (unstood)) { - int maxAllowedRadios = gpGlobals->maxClients / 4; + const int maxAllowedRadios = gpGlobals->maxClients / 4; if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { if (!report_back) { @@ -3802,7 +3828,7 @@ bool BotRadioAction() { } // Is entity visible? (from Entity view) -bool EntityIsVisible(edict_t *pEntity, Vector dest) { +bool EntityIsVisible(edict_t *pEntity, const Vector dest) { //DebugOut("bot: EntityIsVisible()\n"); TraceResult tr; @@ -3820,12 +3846,13 @@ bool EntityIsVisible(edict_t *pEntity, Vector dest) { } // Can see Edict? -bool cBot::canSeeEntity(edict_t *pEntity) { +bool cBot::canSeeEntity(edict_t *pEntity) const +{ if (pEntity == NULL) return false; TraceResult tr; - Vector start = pEdict->v.origin + pEdict->v.view_ofs; - Vector vDest = pEntity->v.origin; + const Vector start = pEdict->v.origin + pEdict->v.view_ofs; + const Vector vDest = pEntity->v.origin; // trace a line from bot's eyes to destination... UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); @@ -3859,7 +3886,8 @@ float cBot::getDistanceTo(int nodeIndex) { * @param vDest * @return */ -float cBot::getDistanceTo(Vector vDest) { +float cBot::getDistanceTo(const Vector vDest) const +{ return func_distance(pEdict->v.origin, vDest); } @@ -3917,7 +3945,8 @@ void cBot::forgetHostage(edict_t *pHostage) { } } -int cBot::getAmountOfHostagesBeingRescued() { +int cBot::getAmountOfHostagesBeingRescued() const +{ int count = 0; if (hostage1 != NULL) count++; @@ -3931,9 +3960,10 @@ int cBot::getAmountOfHostagesBeingRescued() { // Will return true when the vector is visible. // TODO: Make this function more flexible, ie able to hit an entity that it searches // and return true on that as well. (mix it with the above function) -bool cBot::canSeeVector(Vector vDest) { +bool cBot::canSeeVector(const Vector vDest) const +{ TraceResult tr; - Vector start = pEdict->v.origin + pEdict->v.view_ofs; + const Vector start = pEdict->v.origin + pEdict->v.view_ofs; // trace a line from bot's eyes to destination... UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); @@ -3947,12 +3977,14 @@ bool cBot::canSeeVector(Vector vDest) { // The coming 2 shield functions where originaly created by Whistler; // i got them from the JoeBot source though. But... in the end, thank you // Whistler! -bool cBot::hasShield() { +bool cBot::hasShield() const +{ // Adapted from Wei Mingzhi's YAPB return (strncmp(STRING(pEdict->v.viewmodel), "models/shield/v_shield_", 23) == 0); } -bool cBot::hasShieldDrawn() { +bool cBot::hasShieldDrawn() const +{ // Adapted from Wei Mingzhi's YAPB if (!hasShield()) return false; @@ -3980,10 +4012,10 @@ void BotThink(cBot *pBot) { // PASS THROUGH ENGINE // float frameInterval = m_lastCommandTime - gpGlobals->time; - float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; + const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; pBot->fLastRunPlayerMoveTime = gpGlobals->time; - double upMove = 0.0; + const double upMove = 0.0; char msg[255]; sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); @@ -3996,7 +4028,7 @@ void BotThink(cBot *pBot) { 0, msecval); - float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps + const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; } @@ -4004,9 +4036,9 @@ void BotThink(cBot *pBot) { // log important variables of the bot (it will be called from dll.cpp once per active bot) // they are logged into reallog.txt file -void cBot::Dump(void) { +void cBot::Dump() { char buffer[181]; - int iCurrentNode = + const int iCurrentNode = NodeMachine.getClosestNode(pEdict->v.origin, (NODE_ZONE * 2), pEdict); _snprintf(buffer, 180, @@ -4047,11 +4079,13 @@ void cBot::beginWalkingPath() { this->pathIndex = 0; } -bool cBot::hasHostageToRescue() { +bool cBot::hasHostageToRescue() const +{ return pBotHostage != NULL; } -bool cBot::canSeeHostageToRescue() { +bool cBot::canSeeHostageToRescue() const +{ return canSeeEntity(pBotHostage); } @@ -4087,12 +4121,14 @@ void cBot::checkIfHostagesAreRescued() { if (isHostageRescued(this, hostage4)) forgetHostage(hostage4); } -bool cBot::isOnSameTeamAs(cBot *pBot) { +bool cBot::isOnSameTeamAs(cBot *pBot) const +{ if (pBot == NULL) return false; return pBot->iTeam == this->iTeam; } -bool cBot::wantsToBuyStuff() { +bool cBot::wantsToBuyStuff() const +{ return buy_secondary == true || buy_primary == true || buy_ammo_primary == true || @@ -4103,11 +4139,13 @@ bool cBot::wantsToBuyStuff() { buy_flashbang > 0; } -bool cBot::isUsingConsole() { +bool cBot::isUsingConsole() const +{ return console_nr > 0; } -bool cBot::shouldBeAbleToMove() { +bool cBot::shouldBeAbleToMove() const +{ return !isDead() && !isFreezeTime() && !shouldCamp() && @@ -4117,9 +4155,10 @@ bool cBot::shouldBeAbleToMove() { // !isJumping(); } -edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() { +edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const +{ TraceResult tr; - Vector vOrigin = pEdict->v.origin; + const Vector vOrigin = pEdict->v.origin; tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); @@ -4143,7 +4182,8 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() { * Get distance to the next node we're heading for * @return */ -float cBot::getDistanceToNextNode() { +float cBot::getDistanceToNextNode() const +{ tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); if (node) { return getDistanceTo(node->origin); @@ -4172,7 +4212,7 @@ void cBot::lookAtNode(int nodeIndex) { */ void cBot::setTimeToMoveToNode(float timeInSeconds) { char msg[255]; - float endTime = gpGlobals->time + timeInSeconds; + const float endTime = gpGlobals->time + timeInSeconds; sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); rprint_trace("setTimeToMoveToNode", msg); @@ -4188,7 +4228,7 @@ void cBot::increaseTimeToMoveToNode(float timeInSeconds) { if (nodeTimeIncreasedAmount < 2) { nodeTimeIncreasedAmount++; this->fMoveToNodeTime += timeInSeconds; - float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); + const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); char msg[255]; memset(msg, 0, sizeof(msg)); sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); @@ -4198,15 +4238,18 @@ void cBot::increaseTimeToMoveToNode(float timeInSeconds) { } } -float cBot::getMoveToNodeTimeRemaining() { +float cBot::getMoveToNodeTimeRemaining() const +{ return fMoveToNodeTime - gpGlobals->time; } -bool cBot::shouldCamp() { +bool cBot::shouldCamp() const +{ return f_camp_time > gpGlobals->time; } -bool cBot::shouldWait() { +bool cBot::shouldWait() const +{ return f_wait_time > gpGlobals->time; } @@ -4214,15 +4257,18 @@ void cBot::setTimeToWait(float timeInSeconds) { this->f_wait_time = gpGlobals->time + timeInSeconds; } -bool cBot::shouldBeAbleToInteractWithButton() { +bool cBot::shouldBeAbleToInteractWithButton() const +{ return fButtonTime < gpGlobals->time; } -bool cBot::hasButtonToInteractWith() { +bool cBot::hasButtonToInteractWith() const +{ return pButtonEdict != NULL; } -bool cBot::hasCurrentNode() { +bool cBot::hasCurrentNode() const +{ return iCloseNode > -1; } @@ -4247,7 +4293,7 @@ bool cBot::createPath(int destinationNode, int flags) { return false; } - int currentNode = getCurrentNode(); + const int currentNode = getCurrentNode(); if (currentNode < 0) { rprint("createPath()", "Unable to create path to destination because I am not close to a start node"); return false; @@ -4271,7 +4317,7 @@ void cBot::doDuck() { } bool cBot::isDucking() { - bool b = keyPressed(IN_DUCK) || this->f_hold_duck > gpGlobals->time; + const bool b = keyPressed(IN_DUCK) || this->f_hold_duck > gpGlobals->time; if (b) { rprint_trace("isDucking", "Yes I am ducking"); } @@ -4279,7 +4325,7 @@ bool cBot::isDucking() { } bool cBot::isWalking() { - bool b = !keyPressed(IN_RUN) || this->f_walk_time > gpGlobals->time; + const bool b = !keyPressed(IN_RUN) || this->f_walk_time > gpGlobals->time; if (b) { rprint_trace("isWalking", "Yes I am walking"); } @@ -4308,7 +4354,7 @@ void cBot::doJump() { } bool cBot::isJumping() { - bool b = keyPressed(IN_JUMP) || f_jump_time > gpGlobals->time; + const bool b = keyPressed(IN_JUMP) || f_jump_time > gpGlobals->time; if (b) { rprint_trace("isJumping", "Yes I am jumping"); } diff --git a/bot.h b/bot.h index fd1796c..f1bdb18 100644 --- a/bot.h +++ b/bot.h @@ -187,14 +187,14 @@ class cBot { void rememberHostageIsFollowingMe(edict_t *pHostage); void rememberWhichHostageToRescue(edict_t *pHostage); void clearHostageToRescueTarget(); - int getAmountOfHostagesBeingRescued(); + int getAmountOfHostagesBeingRescued() const; edict_t * findHostageToRescue(); // finds a hostage to rescue - edict_t * getHostageToRescue(); // returns hostage state pointer + edict_t * getHostageToRescue() const; // returns hostage state pointer bool isEscortingHostages(); // Does the bot has used any hostages yet? void checkOfHostagesStillFollowMe(); - bool hasTimeToMoveToNode(); - bool isDefusing(); + bool hasTimeToMoveToNode() const; + bool isDefusing() const; // ------------------------ // TIMERS @@ -394,11 +394,11 @@ class cBot { void CheckGear(); void ThinkAboutGoals(); // Think about goals - bool TakeCover(); + bool TakeCover() const; - bool CarryWeapon(int iType); + bool CarryWeapon(int iType) const; - int CarryWeaponType(); + int CarryWeaponType() const; void setHeadAiming(Vector vTarget); // Aim at vector void AimAtEnemy(); @@ -407,16 +407,16 @@ class cBot { void FireWeapon(); - int ReturnTurnedAngle(float speed, float current, float ideal); + static int ReturnTurnedAngle(float speed, float current, float ideal); int FindEnemy(); float ReactionTime(int iSkill); // Reaction time based upon skill void FindCover(); - bool canSeeVector(Vector vDest); + bool canSeeVector(Vector vDest) const; - bool canSeeEntity(edict_t *pEntity); + bool canSeeEntity(edict_t *pEntity) const; void InteractWithFriends(); @@ -427,40 +427,40 @@ class cBot { // Set methods int determineCurrentNode(); int determineCurrentNodeWithTwoAttempts(); - int determineCurrentNode(float range); + int determineCurrentNode(float range) const; // Get methods float getDistanceTo(int nodeIndex); - float getDistanceTo(Vector vDest); + float getDistanceTo(Vector vDest) const; // "is" Methods (booleans, statements, etc) - bool isDead(); - bool isHeadingForGoalNode(); - bool isEnemyAlive(); // If enemy set, is it alive? (else returns false) - bool isOnLadder(); // Bot on ladder or not? + bool isDead() const; + bool isHeadingForGoalNode() const; + bool isEnemyAlive() const; // If enemy set, is it alive? (else returns false) + bool isOnLadder() const; // Bot on ladder or not? bool isSeeingEnemy(); // If enemy set, can we see it? (takes blinded by flashbang into account) - bool isCounterTerrorist(); - bool isTerrorist(); + bool isCounterTerrorist() const; + bool isTerrorist() const; // "is" methods, related to weapons - bool wantsToBuyStuff(); - bool isUsingConsole(); - bool isOwningWeapon(int weaponId); - bool isHoldingWeapon(int weaponId); - bool ownsFavoritePrimaryWeapon(); - bool ownsFavoriteSecondaryWeapon(); - bool hasFavoritePrimaryWeaponPreference(); - bool hasFavoriteSecondaryWeaponPreference(); - bool hasPrimaryWeaponEquiped(); - bool hasSecondaryWeaponEquiped(); + bool wantsToBuyStuff() const; + bool isUsingConsole() const; + bool isOwningWeapon(int weaponId) const; + bool isHoldingWeapon(int weaponId) const; + bool ownsFavoritePrimaryWeapon() const; + bool ownsFavoriteSecondaryWeapon() const; + bool hasFavoritePrimaryWeaponPreference() const; + bool hasFavoriteSecondaryWeaponPreference() const; + bool hasPrimaryWeaponEquiped() const; + bool hasSecondaryWeaponEquiped() const; bool hasPrimaryWeapon(int weaponId); - bool hasSecondaryWeapon(int weaponId); - bool canAfford(int weaponId); + bool hasSecondaryWeapon(int weaponId) const; + bool canAfford(int weaponId) const; // ------------------- // 20/06/04 - CS 1.6 shield functions - bool hasShield(); - bool hasShieldDrawn(); + bool hasShield() const; + bool hasShieldDrawn() const; bool isHoldingGrenadeOrFlashbang() const; bool isBlindedByFlashbang() const; @@ -476,18 +476,18 @@ class cBot { // ------------------- // - bool hasEnemy(); - bool hasEnemy(edict_t * pEdict); - edict_t * getEnemyEdict(); + bool hasEnemy() const; + bool hasEnemy(edict_t * pEdict) const; + edict_t * getEnemyEdict() const; - bool hasGoal(); - bool hasGoalIndex(); - tGoal *getGoalData(); + bool hasGoal() const; + bool hasGoalIndex() const; + tGoal *getGoalData() const; bool shouldBeWandering(); - bool hasBomb(); + bool hasBomb() const; // ------------ - bool isWalkingPath(); + bool isWalkingPath() const; void beginWalkingPath(); void nextPathIndex(); // increases index so we know which node to walk on path @@ -501,13 +501,13 @@ class cBot { void setGoalNode(int nodeIndex, int iGoalIndex); int getCurrentNode(); // the current (closest) node we are at - int getCurrentPathNodeToHeadFor(); // get Node from path - int getPreviousPathNodeToHeadFor(); // get previous Node from path - int getNextPathNode(); // get next Node from path - int getPathIndex(); - int getPreviousPathIndex(); + int getCurrentPathNodeToHeadFor() const; // get Node from path + int getPreviousPathNodeToHeadFor() const; // get previous Node from path + int getNextPathNode() const; // get next Node from path + int getPathIndex() const; + int getPreviousPathIndex() const; - int getGoalNode(); + int getGoalNode() const; @@ -531,19 +531,19 @@ class cBot { void rprint_trace(const char *msg); void Dump(); - bool hasHostageToRescue(); + bool hasHostageToRescue() const; - bool canSeeHostageToRescue(); + bool canSeeHostageToRescue() const; void checkIfHostagesAreRescued(); - bool isOnSameTeamAs(cBot *pBot); + bool isOnSameTeamAs(cBot *pBot) const; - bool shouldBeAbleToMove(); + bool shouldBeAbleToMove() const; - edict_t *getEntityBetweenMeAndCurrentPathNodeToHeadFor(); + edict_t *getEntityBetweenMeAndCurrentPathNodeToHeadFor() const; - float getDistanceToNextNode(); + float getDistanceToNextNode() const; void setBodyToNode(int nodeIndex); @@ -552,20 +552,20 @@ class cBot { void setTimeToMoveToNode(float timeInSeconds); void increaseTimeToMoveToNode(float timeInSeconds); - float getMoveToNodeTimeRemaining(); + float getMoveToNodeTimeRemaining() const; bool shouldActWithC4() const; int keyPressed(int key) const; - bool shouldCamp(); - bool shouldWait(); + bool shouldCamp() const; + bool shouldWait() const; void setTimeToWait(float timeInSeconds); - bool shouldBeAbleToInteractWithButton(); + bool shouldBeAbleToInteractWithButton() const; - bool hasButtonToInteractWith(); - bool hasCurrentNode(); + bool hasButtonToInteractWith() const; + bool hasCurrentNode() const; bool createPath(int destinationNode, int flags); bool createPath(int destinationNode); diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 4f2934c..e3fa0a9 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -27,7 +27,7 @@ * **/ -#include +#include #include #include #include @@ -186,8 +186,8 @@ void BotDecideWhatToBuy(cBot *pBot) { * In other words, it needs refactoring... * */ - int money = pBot->bot_money; // Money - int team = pBot->iTeam; // Team + const int money = pBot->bot_money; // Money + const int team = pBot->iTeam; // Team int buy_weapon = -1; @@ -279,7 +279,7 @@ void BotDecideWhatToBuy(cBot *pBot) { pBot->rprint("BotDecideWhatToBuy()", "Found a primary weapon to buy"); // depending on amount of money we have left buy *also* secondary weapon - int iMoneyLeft = money - PriceWeapon(buy_weapon); + const int iMoneyLeft = money - PriceWeapon(buy_weapon); // TODO: this should be dependant on something else... not only money // 01.09.04 Frashman if buyed a Shield, try to buy a good Pistol @@ -341,7 +341,7 @@ void BotDecideWhatToBuy(cBot *pBot) { if (weapons_table[i].price <= money) { if (pBot->iSecondaryWeapon > -1) { - int index = + const int index = weapons_table[pBot->iSecondaryWeapon].iIdIndex; // 31.08.04 Frashman > corrected to >= , // else the bot will buy another weapon with the same priority @@ -442,7 +442,7 @@ void ConsoleThink(cBot *pBot) { // buy time is in minutes, we need // gpGlobals->time is in seconds, so we need to translate the minutes into seconds - float buyTime = CVAR_GET_FLOAT("mp_buytime") * 60; + const float buyTime = CVAR_GET_FLOAT("mp_buytime") * 60; if (Game.getRoundStartedTime() + buyTime > gpGlobals->time && pBot->wantsToBuyStuff()) { BotDecideWhatToBuy(pBot); diff --git a/bot_client.cpp b/bot_client.cpp index 3bc1c71..3b72057 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -28,7 +28,7 @@ **/ -#include +#include #include #include #include @@ -232,7 +232,6 @@ void BotClient_Valve_AmmoX(void *p, int bot_index) { static int state = 0; // current state machine state static int index; static int ammount; - int ammo_index; if (state == 0) { state++; @@ -244,7 +243,7 @@ void BotClient_Valve_AmmoX(void *p, int bot_index) { bots[bot_index].m_rgAmmo[index] = ammount; // store it away - ammo_index = bots[bot_index].current_weapon.iId; + int ammo_index = bots[bot_index].current_weapon.iId; // update the ammo counts for this weapon... bots[bot_index].current_weapon.iAmmo1 = @@ -283,7 +282,6 @@ void BotClient_Valve_AmmoPickup(void *p, int bot_index) { static int state = 0; // current state machine state static int index; static int ammount; - int ammo_index; if (state == 0) { state++; @@ -295,7 +293,7 @@ void BotClient_Valve_AmmoPickup(void *p, int bot_index) { bots[bot_index].m_rgAmmo[index] = ammount; - ammo_index = bots[bot_index].current_weapon.iId; + int ammo_index = bots[bot_index].current_weapon.iId; // update the ammo counts for this weapon... bots[bot_index].current_weapon.iAmmo1 = @@ -325,10 +323,7 @@ void BotClient_FLF_AmmoPickup(void *p, int bot_index) { // This message gets sent when the bot picks up a weapon. void BotClient_Valve_WeaponPickup(void *p, int bot_index) { - //DebugOut("bot_client: BotClient_Valve_WeaponPickup()\n"); - int index; - - index = *(int *) p; + int index = *(int*)p; // set this weapon bit to indicate that we are carrying this weapon bots[bot_index].bot_weapons |= (1 << index); @@ -462,13 +457,13 @@ void BotClient_Valve_Damage(void *p, int bot_index) { if (damage_bits & (DMG_FALL | DMG_CRUSH)) { pBot->rprint_trace("BotClient_Valve_Damage", "Taken fall damage!"); if (pBot->getPathIndex() > 0) { // was one node further, so we can use previous node! - int iNode = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, pBot->getPreviousPathIndex()); + const int iNode = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, pBot->getPreviousPathIndex()); - float fDist = fabs(damage_origin.z - NodeMachine.node_vector(iNode).z); + const float fDist = fabs(damage_origin.z - NodeMachine.node_vector(iNode).z); if (fDist > 90) { // we know where we came from, and we know where we went to - int iNodeTo = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, - pBot->getPathIndex()); + const int iNodeTo = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, + pBot->getPathIndex()); // remove connection? @@ -587,9 +582,9 @@ void BotClient_CS_SayText(void *p, int bot_index) { if (strstr(sentence, " : ")) length = strlen(sentence) - strlen(strstr(sentence, " : ")); - int tc = 0, c; + int tc = 0; - for (c = length; c < MAX_SENTENCE_LENGTH; c++) { + for (int c = length; c < MAX_SENTENCE_LENGTH; c++) { chSentence[tc] = sentence[c]; tc++; } @@ -814,7 +809,6 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { static int duration; static int hold_time; static int fade_flags; - float length; if (state == 0) { state++; @@ -828,7 +822,7 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { } else if (state == 6) { state = 0; - length = (duration + hold_time) / 4096.0; + float length = (duration + hold_time) / 4096.0; int iDevide = bots[bot_index].bot_skill; if (iDevide < 1) iDevide = 1; @@ -837,12 +831,10 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { bots[bot_index].fBlindedTime = gpGlobals->time + length; - // Get pointer and do some radio stuff here - Added by Stefan - cBot *pBot; - pBot = &bots[bot_index]; + cBot* pBot = &bots[bot_index]; - int iCurrentNode = NodeMachine.getClosestNode(pBot->pEdict->v.origin, NODE_ZONE, pBot->pEdict); - int iCoverNode = NodeMachine.node_cover(iCurrentNode, iCurrentNode, pBot->pEdict); + const int iCurrentNode = NodeMachine.getClosestNode(pBot->pEdict->v.origin, NODE_ZONE, pBot->pEdict); + const int iCoverNode = NodeMachine.node_cover(iCurrentNode, iCurrentNode, pBot->pEdict); if (iCoverNode > -1) { // pBot->forgetPath(); diff --git a/bot_func.cpp b/bot_func.cpp index c71dabf..4bdcb82 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -28,7 +28,7 @@ **/ -#include +#include #include #include #include @@ -55,10 +55,10 @@ extern cNodeMachine NodeMachine; #define TOTAL_SCORE 16300 // 16000 money + 100 health + 100 fear + 100 camp desire bool -VectorIsVisibleWithEdict(edict_t *pEdict, Vector dest, char *checkname) { +VectorIsVisibleWithEdict(edict_t *pEdict, const Vector dest, char *checkname) { TraceResult tr; - Vector start = pEdict->v.origin + pEdict->v.view_ofs; + const Vector start = pEdict->v.origin + pEdict->v.view_ofs; // trace a line from bot's eyes to destination... UTIL_TraceLine(start, dest, ignore_monsters, @@ -89,7 +89,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, Vector dest, char *checkname) { } -bool VectorIsVisible(Vector start, Vector dest, char *checkname) { +bool VectorIsVisible(const Vector start, const Vector dest, char *checkname) { TraceResult tr; // trace a line from bot's eyes to destination... @@ -135,7 +135,7 @@ float func_distance(Vector v1, Vector v2) { * @param dest * @return */ -int FUNC_InFieldOfView(edict_t *pEntity, Vector dest) { +int FUNC_InFieldOfView(edict_t *pEntity, const Vector dest) { // NOTE: Copy from Botman's BotInFieldOfView() routine. // find angles from source to destination... Vector entity_angles = UTIL_VecToAngles(dest); @@ -171,7 +171,7 @@ int FUNC_InFieldOfView(edict_t *pEntity, Vector dest) { * @param start * @param end */ -void DrawBeam(edict_t *visibleForWho, Vector start, Vector end) { +void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end) { DrawBeam(visibleForWho, start, end, 25, 1, 255, 255, 255, 255, 1); } @@ -180,8 +180,11 @@ void DrawBeam(edict_t *visibleForWho, Vector start, Vector end) { * @param visibleForWho * @param start * @param end + * @param r + * @param g + * @param b */ -void DrawBeam(edict_t *visibleForWho, Vector start, Vector end, int r, int g, int b) { +void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int r, int g, int b) { DrawBeam(visibleForWho, start, end, 25, 1, r, g, b, 255, 1); } @@ -198,7 +201,7 @@ void DrawBeam(edict_t *visibleForWho, Vector start, Vector end, int r, int g, in * @param brightness * @param speed */ -void DrawBeam(edict_t *visibleForWho, Vector start, Vector end, int width, +void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int width, int noise, int red, int green, int blue, int brightness, int speed) { MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, visibleForWho); @@ -265,7 +268,7 @@ cBot *getCloseFellowBot(cBot *pBot) { */ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { edict_t *pEdict = pBot->pEdict; - int FOV = 90; // TODO: use server var "default_fov" ? + const int FOV = 90; // TODO: use server var "default_fov" ? for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); @@ -281,9 +284,9 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { || (pPlayer->v.flags & FL_CLIENT))) continue; - int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); + const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - int distance = NODE_ZONE; + const int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < FOV) { return pPlayer; } @@ -337,7 +340,7 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - int distance = NODE_ZONE; + const int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { return true; } @@ -367,7 +370,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { return false; } - bool result = BotShouldJump(pBot); + const bool result = BotShouldJump(pBot); if (result) { pBot->rprint_trace("BotShouldJumpIfStuck", "BotShouldJump returns true, so returning that"); return true; @@ -406,12 +409,11 @@ bool BotShouldJump(cBot *pBot) { if (pBot->isJumping()) return false; // already jumping TraceResult tr; - Vector v_jump, v_source, v_dest; edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... - v_jump = FUNC_CalculateAngles(pBot); + Vector v_jump = FUNC_CalculateAngles(pBot); v_jump.x = 0; // reset pitch to 0 (level horizontally) v_jump.z = 0; // reset roll to 0 (straight up and down) @@ -419,8 +421,8 @@ bool BotShouldJump(cBot *pBot) { // Check if we can jump onto something with maximum jump height: // maximum jump height, so check one unit above that (MAX_JUMPHEIGHT) - v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); - v_dest = v_source + gpGlobals->v_forward * 90; + Vector v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); + Vector v_dest = v_source + gpGlobals->v_forward * 90; // trace a line forward at maximum jump height... UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -493,7 +495,7 @@ bool BotShouldJump(cBot *pBot) { // FUNCTION: Calculates angles as pEdict->v.v_angle should be when checking for body Vector FUNC_CalculateAngles(cBot *pBot) { // aim for the head and/or body - Vector v_target = pBot->vBody - pBot->pEdict->v.origin; + const Vector v_target = pBot->vBody - pBot->pEdict->v.origin; Vector v_body = UTIL_VecToAngles(v_target); if (v_body.y > 180) @@ -575,7 +577,7 @@ bool FUNC_DoRadio(cBot *pBot) { if (pBot->fDoRadio > gpGlobals->time) // allowed? return false; - int iRadio = pBot->ipCreateRadio; + const int iRadio = pBot->ipCreateRadio; return RANDOM_LONG(0, 100) < iRadio; // want? } @@ -593,13 +595,13 @@ bool FUNC_ShouldTakeCover(cBot *pBot) { pBot->f_cover_time = gpGlobals->time; // MONEY: The less we have, the more we want to take cover - int vMoney = 16000 - pBot->bot_money; + const int vMoney = 16000 - pBot->bot_money; // HEALTH: The less we have, the more we want to take cover - int vHealth = 100 - pBot->bot_health; + const int vHealth = 100 - pBot->bot_health; // CAMP: The more we want, the more we want to take cover - int vCamp = pBot->ipCampRate; + const int vCamp = pBot->ipCampRate; return RANDOM_LONG(0, TOTAL_SCORE) < (vMoney + vHealth + vCamp); } @@ -674,7 +676,7 @@ void FUNC_HearingTodo(cBot *pBot) { // I HEAR SOMETHING // More chance on getting to true - int health = pBot->bot_health; + const int health = pBot->bot_health; int action = 0; int etime = 0; @@ -817,7 +819,7 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { } // Whenever we have a hostage to go after, verify it is still rescueable - bool isRescueable = isHostageRescueable(pBot, pHostage); + const bool isRescueable = isHostageRescueable(pBot, pHostage); if (!isRescueable) { pBot->rprint_trace("TryToGetHostageTargetToFollowMe", "Hostage found, but not rescueable, forgetting..."); @@ -829,7 +831,7 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { } // Prevent bots getting to close here - float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); + const float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); // From here, we should get the hostage when still visible if (pBot->canSeeEntity(pHostage)) { @@ -844,7 +846,7 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { pBot->setMoveSpeed(0.0f); // too close, do not move // only use hostage when facing - int angle_to_hostage = FUNC_InFieldOfView(pBot->pEdict, (pBot->vBody - pBot->pEdict->v.origin)); + const int angle_to_hostage = FUNC_InFieldOfView(pBot->pEdict, (pBot->vBody - pBot->pEdict->v.origin)); if (angle_to_hostage <= 30 && (pBot->f_use_timer < gpGlobals->time)) { diff --git a/bot_navigate.cpp b/bot_navigate.cpp index c98386c..f644f38 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -28,7 +28,7 @@ **/ -#include +#include #include #include #include @@ -77,12 +77,11 @@ bool BotCanJumpUp(cBot * pBot) { // that the bot can not get onto. TraceResult tr; - Vector v_jump, v_source, v_dest; edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... - v_jump = pEdict->v.v_angle; + Vector v_jump = pEdict->v.v_angle; v_jump.x = 0; // reset pitch to 0 (level horizontally) v_jump.z = 0; // reset roll to 0 (straight up and down) @@ -91,8 +90,8 @@ bool BotCanJumpUp(cBot * pBot) { // use center of the body first... // maximum jump height is 45, so check one unit above that (46) - v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT); - v_dest = v_source + gpGlobals->v_forward * 24; + Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT); + Vector v_dest = v_source + gpGlobals->v_forward * 24; // trace a line forward at maximum jump height... UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, @@ -197,12 +196,11 @@ bool BotCanDuckUnder(cBot * pBot) { // we can duck under it. TraceResult tr; - Vector v_duck, v_source, v_dest; edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... - v_duck = pEdict->v.v_angle; + Vector v_duck = pEdict->v.v_angle; v_duck.x = 0; // reset pitch to 0 (level horizontally) v_duck.z = 0; // reset roll to 0 (straight up and down) @@ -211,8 +209,8 @@ bool BotCanDuckUnder(cBot * pBot) { // use center of the body first... // duck height is 36, so check one unit above that (37) - v_source = pEdict->v.origin + Vector(0, 0, -36 + 37); - v_dest = v_source + gpGlobals->v_forward * 24; + Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + 37); + Vector v_dest = v_source + gpGlobals->v_forward * 24; // trace a line forward at duck height... UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, diff --git a/dll.cpp b/dll.cpp index 5cca9f7..b7ac175 100644 --- a/dll.cpp +++ b/dll.cpp @@ -27,7 +27,7 @@ * **/ -#include +#include #include #include #include @@ -102,7 +102,7 @@ int counterstrike = 0; // Default 1.5 void UpdateClientData(const struct edict_s *ent, int sendweapons, struct clientdata_s *cd); -void ProcessBotCfgFile(void); +void ProcessBotCfgFile(); // External added variables bool end_round = false; @@ -119,7 +119,7 @@ bool internet_addbot = false; // Add a bot? float add_timer = -1; // Timer for adding bots bool internet_play = false; -void RealBot_ServerCommand(void); +void RealBot_ServerCommand(); // START of Metamod stuff enginefuncs_t meta_engfuncs; @@ -271,10 +271,8 @@ GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, // @PMB -> Yes so far it does ;) working on this MOD-GAME independent structure... grmbl } -void GameDLLInit(void) { - // clear log.txt - FILE *fplog; - fplog = fopen("reallog.txt", "wt"); +void GameDLLInit() { + FILE* fplog = fopen("reallog.txt", "wt"); if (fplog) { fprintf(fplog, "Realbot Logbook\n"); @@ -297,9 +295,8 @@ void GameDLLInit(void) { rblog("Verifying realbot is installed correctly.."); - FILE *fp; - bool bInstalledCorrectly = false; - fp = fopen("realbot/dll/realbot_mm.dll", "rb"); + bool bInstalledCorrectly = false; + FILE* fp = fopen("realbot/dll/realbot_mm.dll", "rb"); if (fp != NULL) { bInstalledCorrectly = true; fclose(fp); @@ -465,9 +462,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, void ClientDisconnect(edict_t *pEntity) { if (gpGlobals->deathmatch) { - int i; - - i = 0; + int i = 0; while ((i < 32) && (clients[i] != pEntity)) i++; @@ -529,7 +524,7 @@ void ClientCommand(edict_t *pEntity) { // TODO: Revise this method -void StartFrame(void) { +void StartFrame() { if (!gpGlobals->deathmatch) return; // bots only work in 'deathmatch mode' // REALBOT_PRINT("StartFrame", "BEGIN"); @@ -1047,12 +1042,10 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { isFakeClientCommand = FALSE; } -void ProcessBotCfgFile(void) { - int ch; - char cmd_line[256]; - int cmd_index; - static char server_cmd[80]; - char *cmd, *arg1, *arg2, *arg3, *arg4; +void ProcessBotCfgFile() { + char cmd_line[256]; + static char server_cmd[80]; + char *arg2, *arg3, *arg4; char msg[80]; if (bot_cfg_pause_time > gpGlobals->time) @@ -1061,10 +1054,10 @@ void ProcessBotCfgFile(void) { if (bot_cfg_fp == NULL) return; - cmd_index = 0; + int cmd_index = 0; cmd_line[cmd_index] = 0; - ch = fgetc(bot_cfg_fp); + int ch = fgetc(bot_cfg_fp); // skip any leading blanks while (ch == ' ') @@ -1105,8 +1098,8 @@ void ProcessBotCfgFile(void) { strcat(server_cmd, "\n"); cmd_index = 0; - cmd = cmd_line; - arg1 = arg2 = arg3 = arg4 = NULL; + char* cmd = cmd_line; + char* arg1 = arg2 = arg3 = arg4 = NULL; // skip to blank or end of string... while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0)) @@ -1168,7 +1161,7 @@ void ProcessBotCfgFile(void) { // REALBOT COMMAND // SERVER Command: RealBot -void RealBot_ServerCommand(void) { +void RealBot_ServerCommand() { const char *pcmd = CMD_ARGV(1); const char *arg1 = CMD_ARGV(2); const char *arg2 = CMD_ARGV(3); @@ -1177,7 +1170,6 @@ void RealBot_ServerCommand(void) { char cMessage[256]; bool bSendMessage = true; - bool bValidCommand = true; // When we need an edict to send messages to, we do that to the pHostEdict edict_t *pEntity = pHostEdict; @@ -1218,7 +1210,7 @@ void RealBot_ServerCommand(void) { EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "misc/imgood12.wav", 1.0, ATTN_NORM, 0, 100); } else if (FStrEq(pcmd, "add")) { - int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); + const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); bot_check_time = gpGlobals->time + 5.0; if (iStatus == GAME_MSG_SUCCESS) sprintf(cMessage, "REALBOT: Successfully created bot."); @@ -1231,7 +1223,7 @@ void RealBot_ServerCommand(void) { "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { if ((arg1 != NULL) && (*arg1 != 0)) { - float fVar = atof(arg1); + const float fVar = atof(arg1); // Only set when valid if (fVar < 0) @@ -1293,7 +1285,7 @@ void RealBot_ServerCommand(void) { end_round = true; } else if (FStrEq(pcmd, "csversion")) { if ((arg1 != NULL) && (*arg1 != 0)) { - int temp = atoi(arg1); + const int temp = atoi(arg1); if (temp <= 0) counterstrike = 0; // cs 1.5 else @@ -1318,7 +1310,7 @@ void RealBot_ServerCommand(void) { if ((arg1 != NULL) && (*arg1 != 0)) { // switch on/off internet mode - int temp = atoi(arg1); + const int temp = atoi(arg1); if (temp == 0) internet_play = false; @@ -1365,7 +1357,7 @@ void RealBot_ServerCommand(void) { if ((arg1 != NULL) && (*arg1 != 0)) { // get amount - int temp = atoi(arg1); + const int temp = atoi(arg1); kick_amount_bots = temp; if (kick_amount_bots > 31) kick_amount_bots = 31; @@ -1377,7 +1369,7 @@ void RealBot_ServerCommand(void) { // get team int team = 0; - int temp = atoi(arg2); + const int temp = atoi(arg2); if (temp == 1) team = 1; if (temp == 2) @@ -1456,7 +1448,7 @@ void RealBot_ServerCommand(void) { } } else if (FStrEq(pcmd, "autoskill")) { if ((arg1 != NULL) && (*arg1 != 0)) { - int temp = atoi(arg1); + const int temp = atoi(arg1); if (temp == 1) autoskill = true; @@ -1470,7 +1462,7 @@ void RealBot_ServerCommand(void) { sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { if ((arg1 != NULL) && (*arg1 != 0)) { - int temp = atoi(arg1); + const int temp = atoi(arg1); if (temp == 1) Game.iOverrideBotSkill = GAME_YES; @@ -1486,7 +1478,7 @@ void RealBot_ServerCommand(void) { "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { if ((arg1 != NULL) && (*arg1 != 0)) { - int temp = atoi(arg1); + const int temp = atoi(arg1); if ((temp < -1) || (temp > 10)) { sprintf(cMessage, "REALBOT: Invalid argument given - default skill = %d.", @@ -1648,11 +1640,11 @@ void RealBot_ServerCommand(void) { // check for valid argument if ((arg2 != NULL) && (*arg2 != 0)) { - int iTo = atoi(arg2); // add connection TO + const int iTo = atoi(arg2); // add connection TO // Add this connection if (iTo > -1) { - bool bSuccess = + const bool bSuccess = NodeMachine.add_neighbour_node(iOnNode, iTo); if (bSuccess) @@ -1676,11 +1668,11 @@ void RealBot_ServerCommand(void) { // check for valid argument if ((arg2 != NULL) && (*arg2 != 0)) { - int iTo = atoi(arg2); // remove connection TO + const int iTo = atoi(arg2); // remove connection TO // remove this connection if (iTo > -1) { - bool bSuccess = + const bool bSuccess = NodeMachine.removeConnection(iOnNode, iTo); if (bSuccess) @@ -1700,7 +1692,7 @@ void RealBot_ServerCommand(void) { "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeall")) { - bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); + const bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); if (bSuccess) sprintf(cMessage, @@ -1787,8 +1779,8 @@ void RealBot_ServerCommand(void) { // check for valid argument if ((arg2 != NULL) && (*arg2 != 0) && (arg3 != NULL) && (*arg3 != 0)) { - int Node1 = atoi(arg2); // add connection TO - int Node2 = atoi(arg3); // add connection TO + const int Node1 = atoi(arg2); // add connection TO + const int Node2 = atoi(arg3); // add connection TO if ((Node1 >= 0) && (Node2 >= 0) && NodeMachine.add_neighbour_node(Node1, Node2)) sprintf(cMessage, @@ -1804,8 +1796,8 @@ void RealBot_ServerCommand(void) { // check for valid argument if ((arg2 != NULL) && (*arg2 != 0) && (arg3 != NULL) && (*arg3 != 0)) { - int Node1 = atoi(arg2); - int Node2 = atoi(arg3); + const int Node1 = atoi(arg2); + const int Node2 = atoi(arg3); if ((Node1 >= 0) && (Node2 >= 0) && NodeMachine.removeConnection(Node1, Node2)) sprintf(cMessage, @@ -1828,7 +1820,7 @@ void RealBot_ServerCommand(void) { if (FStrEq(arg1, "dontshoot")) { // realbot debug dontshoot [1/0] // check for valid argument if ((arg2 != NULL) && (*arg2 != 0)) { - int temp = atoi(arg2); + const int temp = atoi(arg2); if (temp) Game.bDoNotShoot = true; else @@ -1843,7 +1835,7 @@ void RealBot_ServerCommand(void) { // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] if ((arg2 != NULL) && (*arg2 != 0)) { - int temp = atoi(arg2); + const int temp = atoi(arg2); if (temp) Game.bPistols = true; else @@ -1861,9 +1853,8 @@ void RealBot_ServerCommand(void) { } else if (FStrEq(arg1, "bots")) // realbot debug bots // Print information about all current bots { - int iBot; - rblog("Dumping information about all bots:\n"); - for (iBot = 0; (iBot < 32) && (bots[iBot].bIsUsed == true); iBot++) { + rblog("Dumping information about all bots:\n"); + for (int iBot = 0; (iBot < 32) && (bots[iBot].bIsUsed == true); iBot++) { bots[iBot].Dump(); } @@ -1875,7 +1866,7 @@ void RealBot_ServerCommand(void) { sprintf(cMessage, "RBDEBUG: Debug messages off."); } else { if ((arg2 != NULL) && (*arg2 != 0)) { - int temp = atoi(arg2); + const int temp = atoi(arg2); Game.bDebug = temp; sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); } else { @@ -1968,7 +1959,7 @@ void RealBot_ServerCommand(void) { // Not a valid command sprintf(cMessage, "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); - bValidCommand = false; + bool bValidCommand = false; } // Send message diff --git a/engine.cpp b/engine.cpp index cc15bca..50a2729 100644 --- a/engine.cpp +++ b/engine.cpp @@ -27,7 +27,7 @@ * **/ -#include +#include #include #include #include @@ -150,15 +150,13 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict } if (gpGlobals->deathmatch) { - int index = -1; - - // Fix this up for CS 1.6 weaponlists + // Fix this up for CS 1.6 weaponlists // 01/07/04 - Stefan - Thanks to Whistler for pointing this out! if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", NULL)) botMsgFunction = BotClient_CS_WeaponList; if (edict) { - index = UTIL_GetBotIndex(edict); + int index = UTIL_GetBotIndex(edict); // is this message for a bot? if (index != -1) { @@ -271,7 +269,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict RETURN_META(MRES_IGNORED); } -void pfnMessageEnd(void) { +void pfnMessageEnd() { if (gpGlobals->deathmatch) { if (botMsgEndFunction) (*botMsgEndFunction)(NULL, botMsgIndex); // NULL indicated msg end @@ -399,7 +397,7 @@ void pfnWriteString(const char *sz) { radio_message = true; // we found a radio message // Thank god Ditlew you already coded this... - int length = strlen(sz) - strlen(strstr(sz, " (RADIO)")); + const int length = strlen(sz) - strlen(strstr(sz, " (RADIO)")); strncpy(radio_messenger, sz, length); // Now search for any compatible radio command (old string). @@ -543,7 +541,7 @@ void pfnClientPrintf(edict_t *pEdict, PRINT_TYPE ptype, const char *szMsg) { RETURN_META(MRES_IGNORED); } -const char *pfnCmd_Args(void) { +const char *pfnCmd_Args() { if (isFakeClientCommand) RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[0]); RETURN_META_VALUE(MRES_IGNORED, NULL); @@ -566,7 +564,7 @@ const char *pfnCmd_Argv(int argc) { RETURN_META_VALUE(MRES_IGNORED, NULL); } -int pfnCmd_Argc(void) { +int pfnCmd_Argc() { if (isFakeClientCommand) RETURN_META_VALUE(MRES_SUPERCEDE, fake_arg_count); RETURN_META_VALUE(MRES_IGNORED, 0); diff --git a/engine.h b/engine.h index 4733976..d400272 100644 --- a/engine.h +++ b/engine.h @@ -30,6 +30,9 @@ #ifndef ENGINE_H #define ENGINE_H +#include +#include + // engine prototypes (from engine\eiface.h)... int pfnPrecacheModel(char *s); int pfnPrecacheSound(char *s); @@ -56,7 +59,7 @@ edict_t *pfnEntitiesInPVS(edict_t * pplayer); void pfnMakeVectors(const float *rgflVector); void pfnAngleVectors(const float *rgflVector, float *forward, float *right, float *up); -edict_t *pfnCreateEntity(void); +edict_t *pfnCreateEntity(); void pfnRemoveEntity(edict_t * e); edict_t *pfnCreateNamedEntity(int className); void pfnMakeStatic(edict_t * ent); @@ -86,7 +89,7 @@ void pfnTraceSphere(const float *v1, const float *v2, int fNoMonsters, float radius, edict_t * pentToSkip, TraceResult * ptr); void pfnGetAimVector(edict_t * ent, float speed, float *rgflReturn); void pfnServerCommand(char *str); -void pfnServerExecute(void); +void pfnServerExecute(); void pfnClientCommand(edict_t * pEdict, const char *szFmt, ...); void pfnParticleEffect(const float *org, const float *dir, float color, float count); @@ -95,7 +98,7 @@ int pfnDecalIndex(const char *name); int pfnPointContents(const float *rgflVector); void pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t * edict); -void pfnMessageEnd(void); +void pfnMessageEnd(); void pfnWriteByte(int iValue); void pfnWriteChar(int iValue); void pfnWriteShort(int iValue); @@ -136,9 +139,9 @@ const char *pfnNameForFunction(uint32 function); void pfnClientPrintf(edict_t * pEdict, PRINT_TYPE ptype, const char *szMsg); void pfnServerPrint(const char *szMsg); -const char *pfnCmd_Args(void); +const char *pfnCmd_Args(); const char *pfnCmd_Argv(int argc); -int pfnCmd_Argc(void); +int pfnCmd_Argc(); void pfnGetAttachment(const edict_t * pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles); void pfnCRC32_Init(CRC32_t * pulCRC); @@ -148,7 +151,7 @@ CRC32_t pfnCRC32_Final(CRC32_t pulCRC); int32 pfnRandomLong(int32 lLow, int32 lHigh); float pfnRandomFloat(float flLow, float flHigh); void pfnSetView(const edict_t * pClient, const edict_t * pViewent); -float pfnTime(void); +float pfnTime(); void pfnCrosshairAngle(const edict_t * pClient, float pitch, float yaw); byte *pfnLoadFileForMe(char *filename, int *pLength); void pfnFreeFile(void *buffer); @@ -164,7 +167,7 @@ edict_t *pfnCreateFakeClient(const char *netname); void pfnRunPlayerMove(edict_t * fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec); -int pfnNumberOfEntities(void); +int pfnNumberOfEntities(); char *pfnGetInfoKeyBuffer(edict_t * e); char *pfnInfoKeyValue(char *infobuffer, char *key); void pfnSetKeyValue(char *infobuffer, char *key, char *value); @@ -179,7 +182,7 @@ void pfnBuildSoundMsg(edict_t * entity, int channel, const char *sample, /*int */ float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t * ed); -int pfnIsDedicatedServer(void); +int pfnIsDedicatedServer(); cvar_t *pfnCVarGetPointer(const char *szVarName); unsigned int pfnGetPlayerWONId(edict_t * e); const char *pfnGetPlayerAuthId(edict_t * e); // new @@ -208,7 +211,7 @@ void pfnDeltaAddEncoder(char *name, *from, const unsigned char *to)); -int pfnGetCurrentPlayer(void); +int pfnGetCurrentPlayer(); int pfnCanSkipPlayer(const edict_t * player); int pfnDeltaFindField(struct delta_s *pFields, const char *fieldname); void pfnDeltaSetFieldByIndex(struct delta_s *pFields, int fieldNumber); diff --git a/game.cpp b/game.cpp index baeae4e..4180d67 100644 --- a/game.cpp +++ b/game.cpp @@ -27,7 +27,7 @@ * **/ -#include +#include #include #include #include @@ -141,7 +141,8 @@ void cGame::InitNewRound() { * If the c4 is dropped (not planted), then return true. * @return */ -bool cGame::isC4Dropped() { +bool cGame::isC4Dropped() const +{ return vDroppedC4 != Vector(9999, 9999, 9999); } @@ -149,7 +150,8 @@ bool cGame::isC4Dropped() { * Is the C4 - when planted - discovered? * @return */ -bool cGame::isPlantedC4Discovered() { +bool cGame::isPlantedC4Discovered() const +{ return vPlantedC4 != Vector(9999, 9999, 9999); } @@ -158,7 +160,8 @@ char *cGame::RandomSentence() { return cSpeechSentences[RANDOM_LONG(0, 15)]; } -void cGame::DetermineMapGoal() { +void cGame::DetermineMapGoal() const +{ rblog("DetermineMapGoal called\n"); edict_t *pEnt = NULL; @@ -218,11 +221,13 @@ void cGame::SetRoundTime(float fTime) { // GAME: Get round time // NOTE: This is the time when a round has just started! -float cGame::getRoundStartedTime() { +float cGame::getRoundStartedTime() const +{ return fRoundTime; } -float cGame::getRoundTimeElapsed() { +float cGame::getRoundTimeElapsed() const +{ if (getRoundStartedTime() > -1) { return gpGlobals->time - getRoundStartedTime(); } else { @@ -236,7 +241,8 @@ void cGame::SetNewRound(bool bState) { } // GAME: Get new round status -bool cGame::NewRound() { +bool cGame::NewRound() const +{ return bNewRound; } @@ -261,12 +267,14 @@ void cGame::SetPlayingRounds(int iMin, int iMax) { } // SetPlayingRounds() // GAME: GET Max playing rounds -int cGame::GetMaxPlayRounds() { +int cGame::GetMaxPlayRounds() const +{ return iMaxPlayRounds; } // GAME: GET Min playing rounds -int cGame::GetMinPlayRounds() { +int cGame::GetMinPlayRounds() const +{ return iMinPlayRounds; } @@ -280,27 +288,24 @@ void cGame::LoadCFG() { // NOTE: This function is just a copy/paste stuff from Botmans template, nothing more, nothing less // TODO: Rewrite this, can be done much cleaner. void cGame::LoadNames() { - FILE *bot_name_fp; - int str_index; - char name_buffer[80]; - int length, index; - char filename[256]; + char name_buffer[80]; + char filename[256]; UTIL_BuildFileNameRB("rb_names.txt", filename); - bot_name_fp = fopen(filename, "r"); + FILE* bot_name_fp = fopen(filename, "r"); if (bot_name_fp != NULL) { while ((iAmountNames < MAX_BOT_NAMES) && (fgets(name_buffer, 80, bot_name_fp) != NULL)) { - length = strlen(name_buffer); + int length = strlen(name_buffer); if (name_buffer[length - 1] == '\n') { name_buffer[length - 1] = 0; // remove '\n' length--; } - str_index = 0; + int str_index = 0; while (str_index < length) { if ((name_buffer[str_index] < ' ') || (name_buffer[str_index] > '~') || (name_buffer[str_index] == '"')) - for (index = str_index; index < length; index++) + for (int index = str_index; index < length; index++) name_buffer[index] = name_buffer[index + 1]; str_index++; } @@ -315,7 +320,8 @@ void cGame::LoadNames() { } // LoadNames() // Any names available? -bool cGame::NamesAvailable() { +bool cGame::NamesAvailable() const +{ if (iAmountNames > 0) return true; @@ -325,11 +331,9 @@ bool cGame::NamesAvailable() { // Picks a random name // rewritten on april 10th 2004 -void cGame::SelectName(char *name) { - int iNameIndex, iIndex; - bool bUsed; - edict_t *pPlayer; - iNameIndex = 0; // zero based (RANDOM_LONG (0, iAmountNames-1)) +void cGame::SelectName(char *name) const +{ + int iNameIndex = 0; // zero based (RANDOM_LONG (0, iAmountNames-1)) bool iNameUsed[MAX_BOT_NAMES]; for (int i = 0; i < MAX_BOT_NAMES; i++) { @@ -337,10 +341,10 @@ void cGame::SelectName(char *name) { } // check make sure this name isn't used - bUsed = true; + bool bUsed = true; while (bUsed) { iNameIndex = RANDOM_LONG(0, iAmountNames - 1); // pick random one - int iLimit = iNameIndex; // remember this. + const int iLimit = iNameIndex; // remember this. // make sure it is not checked yet while (iNameUsed[iNameIndex]) { @@ -366,8 +370,8 @@ void cGame::SelectName(char *name) { bUsed = false; // check if this name is used - for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - pPlayer = INDEXENT(iIndex); + for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { + edict_t* pPlayer = INDEXENT(iIndex); if (pPlayer && !pPlayer->free) { if (strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) == 0) { @@ -394,9 +398,7 @@ void cGame::LoadBuyTable() { // GAME: Update global vars (called by StartFrame) void cGame::UpdateGameStatus() { - // Used variables - edict_t *pEnt; - pEnt = NULL; + edict_t* pEnt = NULL; // ------------------ // Update: Dropped C4 @@ -432,9 +434,7 @@ void cGame::UpdateGameStatus() { if (bPlanted && // found a planted bomb bPlanted != bBombPlanted // and previously we didn't know that ) { - - int i; - for (i = 1; i <= gpGlobals->maxClients; i++) { + for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); cBot *bot = UTIL_GetBotPointer(pPlayer); @@ -474,7 +474,8 @@ void cGame::UpdateGameStatus() { * @param nameArg * @return */ -int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg, const char *modelArg, const char *nameArg) { +int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg, const char *modelArg, const char *nameArg) const +{ // NAME char botName[BOT_NAME_LEN + 1]; @@ -494,12 +495,10 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // length of name int lengthOfBotName = strlen(botName); - // remove any illegal characters from name... - int i, j; - for (i = 0; i < lengthOfBotName; i++) { + for (int i = 0; i < lengthOfBotName; i++) { if ((botName[i] <= ' ') || (botName[i] > '~') || (botName[i] == '"')) { // move chars to the left (and null) - for (j = i; j < lengthOfBotName; j++) { + for (int j = i; j < lengthOfBotName; j++) { botName[j] = botName[j + 1]; } lengthOfBotName--; @@ -532,12 +531,8 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg char ptr[128]; // allocate space for message from ClientConnect - char *infobuffer; - int clientIndex; - // find empty bot index - int freeBotIndex; - freeBotIndex = 0; + int freeBotIndex = 0; while ((bots[freeBotIndex].bIsUsed) && (freeBotIndex < MAX_BOTS)) freeBotIndex++; @@ -557,8 +552,8 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // END OF FIX: --- score resetted CALL_GAME_ENTITY(PLID, "player", VARS(pBotEdict)); - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pBotEdict); - clientIndex = ENTINDEX(pBotEdict); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pBotEdict); + int clientIndex = ENTINDEX(pBotEdict); (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, "model", ""); (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, "rate", "3500.000000"); @@ -707,10 +702,10 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { float roundTimeInMinutes = CVAR_GET_FLOAT("mp_roundtime"); if (roundTimeInMinutes < 0) roundTimeInMinutes = 4; // sensible default - float roundTimeInSeconds = roundTimeInMinutes * 60; - float roundTimeRemaining = roundTimeInSeconds - roundElapsedTimeInSeconds; - int minutesLeft = roundTimeRemaining / 60; - int secondsLeft = (int)roundTimeRemaining % 60; + const float roundTimeInSeconds = roundTimeInMinutes * 60; + const float roundTimeRemaining = roundTimeInSeconds - roundElapsedTimeInSeconds; + const int minutesLeft = roundTimeRemaining / 60; + const int secondsLeft = (int)roundTimeRemaining % 60; sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); diff --git a/game.h b/game.h index 53befe7..6c47021 100644 --- a/game.h +++ b/game.h @@ -71,36 +71,36 @@ class cGame { // --------------------- void LoadNames(); - void LoadCFG(); - void LoadBuyTable(); + static void LoadCFG(); + static void LoadBuyTable(); // --------------------- - void SelectName(char *name); - bool NamesAvailable(); + void SelectName(char *name) const; + bool NamesAvailable() const; void SetPlayingRounds(int iMin, int iMax); void SetNewRound(bool bState); void resetRoundTime(); void SetRoundTime(float fTime); - void DetermineMapGoal(); + void DetermineMapGoal() const; // --------------------- char *RandomSentence(); // --------------------- - int GetMinPlayRounds(); - int GetMaxPlayRounds(); + int GetMinPlayRounds() const; + int GetMaxPlayRounds() const; - bool NewRound(); // New round? - float getRoundStartedTime(); // When did the round start? (time) - float getRoundTimeElapsed(); // difference between now and round started time + bool NewRound() const; // New round? + float getRoundStartedTime() const; // When did the round start? (time) + float getRoundTimeElapsed() const; // difference between now and round started time int createBot(edict_t * pPlayer, const char *teamArg, const char *skillArg, - const char *modelArg, const char *nameArg); + const char *modelArg, const char *nameArg) const; // --------------------- void UpdateGameStatus(); // Updates global game variables - bool isC4Dropped(); - bool isPlantedC4Discovered(); + bool isC4Dropped() const; + bool isPlantedC4Discovered() const; // --------------------- // public variables diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 288bf2d..f97f3c2 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -8,12 +8,12 @@ {0AE0F290-F98C-402E-9F35-329A88708328} - 8.1 + 10.0 DynamicLibrary - v140 + v142 false MultiByte @@ -50,7 +50,7 @@ MaxSpeed OnlyExplicitInline - C:\projects\RealBot\dependencies\hlsdk\dlls;C:\projects\RealBot\dependencies\hlsdk\common;C:\projects\RealBot\dependencies\hlsdk\pm_shared;C:\projects\RealBot\dependencies\hlsdk\engine;C:\projects\RealBot\dependencies\hlsdk\public;C:\projects\RealBot\dependencies\metamod-hl1\metamod;%(AdditionalIncludeDirectories) + .\dependencies\hlsdk\dlls;.\dependencies\hlsdk\common;.\dependencies\hlsdk\pm_shared;.\dependencies\hlsdk\engine;.\dependencies\hlsdk\public;.\dependencies\metamod-hl1\metamod;%(AdditionalIncludeDirectories) NDEBUG;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true MultiThreaded diff --git a/util.cpp b/util.cpp index 55fa17b..1bb8af4 100644 --- a/util.cpp +++ b/util.cpp @@ -42,7 +42,7 @@ * **/ -#include +#include #include #include #include @@ -54,7 +54,7 @@ #include "game.h" #include "ChatEngine.h" -#include +#include #ifndef _WIN32 #define _snprintf snprintf @@ -107,9 +107,7 @@ void UTIL_MakeVectors(const Vector &vecAngles) { edict_t *UTIL_FindEntityInSphere(edict_t *pentStart, const Vector &vecCenter, float flRadius) { - edict_t *pentEntity; - - pentEntity = FIND_ENTITY_IN_SPHERE(pentStart, vecCenter, flRadius); + edict_t* pentEntity = FIND_ENTITY_IN_SPHERE(pentStart, vecCenter, flRadius); if (!FNullEnt(pentEntity)) return pentEntity; @@ -120,9 +118,7 @@ edict_t *UTIL_FindEntityInSphere(edict_t *pentStart, edict_t *UTIL_FindEntityByString(edict_t *pentStart, const char *szKeyword, const char *szValue) { - edict_t *pentEntity; - - pentEntity = FIND_ENTITY_BY_STRING(pentStart, szKeyword, szValue); + edict_t* pentEntity = FIND_ENTITY_BY_STRING(pentStart, szKeyword, szValue); if (!FNullEnt(pentEntity)) return pentEntity; @@ -200,13 +196,10 @@ void UTIL_SayText(const char *pText, edict_t *pEdict) { } void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { - int j; - char text[128]; + char text[128]; char *pc; - int sender_team, player_team; - edict_t *client; - // make sure the text has content + // make sure the text has content for (pc = message; pc != NULL && *pc != 0; pc++) { if (isprint(*pc) && !isspace(*pc)) { pc = NULL; // we've found an alphanumeric character, so text is valid @@ -223,7 +216,7 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { else sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); - j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator + int j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator if ((int) strlen(message) > j) message[j] = 0; @@ -238,15 +231,15 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { if (gmsgSayText == 0) gmsgSayText = REG_USER_MSG("SayText", -1); - sender_team = UTIL_GetTeam(pEntity); + int sender_team = UTIL_GetTeam(pEntity); - client = NULL; + edict_t* client = NULL; while (((client = UTIL_FindEntityByClassname(client, "player")) != NULL) && (!FNullEnt(client))) { if (client == pEntity) // skip sender of message continue; - player_team = UTIL_GetTeam(client); + int player_team = UTIL_GetTeam(client); if (teamonly && (sender_team != player_team)) continue; @@ -291,10 +284,9 @@ bool UTIL_IsVip(edict_t *pEntity) { if (mod_id != CSTRIKE_DLL) return false; else { - char *infobuffer; - char model_name[32]; + char model_name[32]; - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); if (strcmp(model_name, "vip") == 0) // VIP @@ -307,10 +299,9 @@ bool UTIL_IsVip(edict_t *pEntity) { // return team number 0 through 3 based what MOD uses for team numbers int UTIL_GetTeam(edict_t *pEntity) { if (mod_id == CSTRIKE_DLL) { - char *infobuffer; - char model_name[32]; + char model_name[32]; - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); @@ -340,19 +331,16 @@ int UTIL_GetTeam(edict_t *pEntity) { // return class number 0 through N int UTIL_GetClass(edict_t *pEntity) { - char *infobuffer; - char model_name[32]; + char model_name[32]; - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); return 0; } int UTIL_GetBotIndex(edict_t *pEdict) { - int index; - - for (index = 0; index < 32; index++) { + for (int index = 0; index < 32; index++) { if (bots[index].pEdict == pEdict) { return index; } @@ -367,9 +355,7 @@ int UTIL_GetBotIndex(edict_t *pEdict) { * @return */ cBot *UTIL_GetBotPointer(edict_t *pEdict) { - int index; - - for (index = 0; index < 32; index++) { + for (int index = 0; index < 32; index++) { if (bots[index].pEdict == pEdict) { return (&bots[index]); } @@ -388,15 +374,12 @@ bool IsAlive(edict_t *pEdict) { } bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { - Vector2D vec2LOS; - float flDot; + UTIL_MakeVectors(pEdict->v.angles); - UTIL_MakeVectors(pEdict->v.angles); - - vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); + Vector2D vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); vec2LOS = vec2LOS.Normalize(); - flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); + float flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); if (flDot > 0.50) // 60 degree field of view { @@ -409,13 +392,12 @@ bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { // FVisible() bool FVisible(const Vector &vecOrigin, edict_t *pEdict) { TraceResult tr; - Vector vecLookerOrigin; // look through caller's eyes - vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; + Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; - int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); - int bLookerInWater = + const int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); + const int bLookerInWater = (UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER); // don't look through water @@ -498,7 +480,7 @@ void UTIL_BuildFileNameRB(char *subdir, char *filename) { strcpy(filename, "realbot/"); strcat(filename, subdir); while (*filename) { - if ((*filename == '/') && (*filename == '\\')) + if ((*filename == '/') || (*filename == '\\')) *filename = S; filename++; } @@ -799,16 +781,14 @@ char *UTIL_GiveWeaponName(int id) { // Thanks Botman for this code (from forum). void UTIL_BotSprayLogo(edict_t *pEntity, char *logo_name) { - int index; - TraceResult pTrace; - Vector v_src, v_dest; - UTIL_MakeVectors(pEntity->v.v_angle); - v_src = pEntity->v.origin + pEntity->v.view_ofs; - v_dest = v_src + gpGlobals->v_forward * 80; + TraceResult pTrace; + UTIL_MakeVectors(pEntity->v.v_angle); + Vector v_src = pEntity->v.origin + pEntity->v.view_ofs; + Vector v_dest = v_src + gpGlobals->v_forward * 80; UTIL_TraceLine(v_src, v_dest, ignore_monsters, pEntity->v.pContainingEntity, &pTrace); - index = DECAL_INDEX(logo_name); + int index = DECAL_INDEX(logo_name); if (index < 0) return; @@ -899,9 +879,7 @@ int UTIL_GetGrenadeType(edict_t *pEntity) { // 2 functions from podbot source unsigned short FixedUnsigned16(float value, float scale) { - int output; - - output = (int) value * scale; + int output = (int)value * scale; if (output < 0) output = 0; if (output > 0xFFFF) @@ -911,9 +889,7 @@ unsigned short FixedUnsigned16(float value, float scale) { } short FixedSigned16(float value, float scale) { - int output; - - output = (int) value * scale; + int output = (int)value * scale; if (output > 32767) output = 32767; @@ -979,7 +955,7 @@ void UTIL_SayTextBot(const char *pText, cBot *pBot) { // init szTemp[0] = 2; - int entind = ENTINDEX(pBot->pEdict); + const int entind = ENTINDEX(pBot->pEdict); if (IsAlive(pBot->pEdict)) { strcpy(szName, pBot->name); From 70da662558068bdba77734a9de5a60501322689e Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 20 Feb 2021 03:17:55 +0000 Subject: [PATCH 008/114] Linux Build prefers older GCC --- .gitignore | 1 + Makefile | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2efd4e6..cc5b3f4 100644 --- a/.gitignore +++ b/.gitignore @@ -216,3 +216,4 @@ CMakeLists.txt cmake-build-debug/ *.o +realbot_mm.so diff --git a/Makefile b/Makefile index ccfba66..b51e977 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,4 @@ -CPP = g++ - +CPP = g++-4.8 ARCHFLAG = -m32 META_DIR = ./dependencies/metamod-hl1/metamod @@ -52,4 +51,4 @@ distclean: ${CPP} ${CPPFLAGS} -c $< -o $@ %.o: %.c - ${CPP} ${CPPFLAGS} -c $< -o $@ \ No newline at end of file + ${CPP} ${CPPFLAGS} -c $< -o $@ From 3929979f5d687d6af01661ed65eb09511f98899e Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 20 Feb 2021 23:45:07 +0000 Subject: [PATCH 009/114] Update Makefile --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b51e977..633a4a6 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,9 @@ META_DIR = ./dependencies/metamod-hl1/metamod HLSDK_DIR = ./dependencies/hlsdk BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -w -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe -I"${META_DIR}" \ - -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" +CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe \ + -Wno-write-strings -I"${META_DIR}" -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" \ + -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" OBJ = NodeMachine.o \ bot.o \ From 4d3efa1d389fdc4db245cdd9900f15dbdb25a9d7 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 21 Feb 2021 03:21:19 +0000 Subject: [PATCH 010/114] UMP45 Fix by TokusyuSAT700 https://github.com/AoiKagase/RealBot/commit/fd9bb5ac6fb54a8905b11d08d1f1f469b13c6f37 --- bot.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bot.cpp b/bot.cpp index 7d14b11..7724f1e 100644 --- a/bot.cpp +++ b/bot.cpp @@ -2969,9 +2969,8 @@ int cBot::CarryWeaponType() const // Check 3, is it a secondary gun? if (weapon_id == CS_WEAPON_P228 || weapon_id == CS_WEAPON_ELITE - || weapon_id == CS_WEAPON_UMP45 || weapon_id == CS_WEAPON_USP - || weapon_id == CS_WEAPON_GLOCK18 || weapon_id == CS_WEAPON_DEAGLE - || weapon_id == CS_WEAPON_FIVESEVEN) + || weapon_id == CS_WEAPON_USP || weapon_id == CS_WEAPON_GLOCK18 + || weapon_id == CS_WEAPON_DEAGLE || weapon_id == CS_WEAPON_FIVESEVEN) kind = SECONDARY; // Check 4, is it a sniper gun? @@ -3534,13 +3533,13 @@ void cBot::CheckGear() { if (isOwningWeapon(UTIL_GiveWeaponId("weapon_scout"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_scout"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_mac10"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_mac10"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_g3sg1"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_g3sg1"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ump45"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_ump45"); // Counter-Strike 1.6 weapon FAMAS/GALIL if (isOwningWeapon(UTIL_GiveWeaponId("weapon_famas"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_famas"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_galil"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_galil"); // SECONDARY - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ump45"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_ump45"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_elite"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_elite"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_fiveseven"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_fiveseven"); if (isOwningWeapon(UTIL_GiveWeaponId("weapon_p228"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_p228"); From b2498cf6eddcf275c4220ba5647548cb93fc9ea1 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 21 Feb 2021 03:28:56 +0000 Subject: [PATCH 011/114] AMBuild support from AoiKagase https://github.com/AoiKagase/RealBot/commit/2f9d5c77c0418f64fe0aef6dcc6fa33654d34728 --- AMBuildScript | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++ configure.py | 24 ++++++++ 2 files changed, 190 insertions(+) create mode 100644 AMBuildScript create mode 100644 configure.py diff --git a/AMBuildScript b/AMBuildScript new file mode 100644 index 0000000..f70134f --- /dev/null +++ b/AMBuildScript @@ -0,0 +1,166 @@ +import os + +# +# Detect Metamod and HLSDK +# + +def detectMetamod(): + metamod_path = builder.options.metamod_path + if not len(metamod_path): + metamod_path = os.getenv('METAMOD', '') + + if len(metamod_path): + metamod_path = os.path.join(builder.originalCwd, metamod_path) + if not os.path.exists(os.path.join(metamod_path, 'metamod')): + raise Exception('Metamod path does not exist: {0}'.format(metamod_path)) + else: + try_paths = [ + os.path.join(builder.sourcePath, '..', 'metamod'), + os.path.join(builder.sourcePath, '..', 'metamod-am'), + os.path.join(builder.sourcePath, '..', 'metamod-hl1'), + ] + for try_path in try_paths: + if os.path.exists(os.path.join(try_path, 'metamod')): + metamod_path = os.path.normpath(try_path) + break + if not metamod_path: + raise Exception('Could not find the source code to Metamod! Try passing --metamod to configure.py.') + + return metamod_path + +def detectHlsdk(): + hlsdk_path = builder.options.hlsdk_path + if not len(hlsdk_path): + hlsdk_path = os.getenv('HLSDK', '') + + if len(hlsdk_path): + hlsdk_path = os.path.join(builder.originalCwd, hlsdk_path) + if not os.path.exists(hlsdk_path): + raise Exception('Metamod path does not exist: {0}'.format(hlsdk_path)) + else: + try_paths = [ + os.path.join(builder.sourcePath, '..', 'hlsdk'), + ] + for try_path in try_paths: + if os.path.exists(try_path): + hlsdk_path = os.path.normpath(try_path) + break + if not hlsdk_path: + raise Exception('Could not find the HLSDK! Try passing --hlsdk to configure.py.') + + return hlsdk_path + + +metamod_path = detectMetamod() +hlsdk_path = detectHlsdk() + +# +# Compiler settings +# +cxx = builder.DetectCompilers() + +cxx.defines += [ + 'HAVE_STDINT_H' + ] + +if cxx.like('gcc'): + cxx.cflags += [ + '-Wall', + '-Werror', + '-Wno-error=unused-result', + '-Wno-error=unused-variable', + '-Wno-unused-value', + '-fno-strict-aliasing', + '-fPIC', + '-m32' + ] + + cxx.cxxflags += [ + '-std=gnu++14', + '-fno-exceptions', + '-fno-rtti' + ] + + cxx.linkflags += [ + '-m32' + ] + + if builder.options.opt == '1': + cxx.cflags += ['-O2'] + +elif cxx.like('msvc'): + cxx.cflags += [ + '/W3' + ] + + cxx.cxxflags += [ + '/EHsc' + ] + + cxx.linkflags += [ + '/MACHINE:X86', + '/SUBSYSTEM:WINDOWS', + '/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1', + 'kernel32.lib' + ] + + if builder.options.opt == '1': + cxx.cflags += ['/Ox'] + cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + + if builder.options.debug == '1': + cxx.cflags += ['/MTd', '/Od', '/RTC1'] + cxx.linkflags += ['/NODEFAULTLIB:libcmt'] + else: + cxx.cflags += ['/MT'] + + + +# Optimization +if builder.options.opt == '1': + cxx.defines += ['NDEBUG'] + +# Debugging +if builder.options.debug == '1': + cxx.defines += ['DEBUG', '_DEBUG'] + + +cxx.includes += [ + os.path.join(metamod_path, 'metamod'), + os.path.join(hlsdk_path, 'common'), + os.path.join(hlsdk_path, 'public'), + os.path.join(hlsdk_path, 'engine'), + os.path.join(hlsdk_path, 'dlls'), + os.path.join(hlsdk_path, 'game_shared'), + os.path.join(hlsdk_path, 'pm_shared'), +] + + +#name = 'realbot_mm' +#if builder.target_platform == 'linux': +# name += '_i386' + +binary = cxx.Library(name) +binary.sources += [ + 'bot.cpp', + 'bot_buycode.cpp', + 'bot_client.cpp', + 'bot_func.cpp', + 'bot_navigate.cpp', + 'build.cpp', + 'ChatEngine.cpp', + 'dll.cpp', + 'engine.cpp', + 'game.cpp', + 'IniParser.cpp', + 'NodeMachine.cpp', + 'util.cpp', +] + + +# +# Run scripts, add binaries +# + +builder.Add(binary) + diff --git a/configure.py b/configure.py new file mode 100644 index 0000000..efb9c06 --- /dev/null +++ b/configure.py @@ -0,0 +1,24 @@ +API_VERSION = '2.1' + +import sys +try: + from ambuild2 import run + if not run.HasAPI(API_VERSION): + raise Exception() +except: + sys.stderr.write('AMBuild {0} must be installed to build this project.\n'.format(API_VERSION)) + sys.stderr.write('http://www.alliedmods.net/ambuild\n') + sys.exit(1) + +prep = run.PrepareBuild(sourcePath=sys.path[0]) +prep.default_build_folder = 'obj-' + prep.target_platform +prep.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', + help='Enable debugging symbols') +prep.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', + help='Enable optimization') +prep.options.add_option('--metamod', type='string', dest='metamod_path', default='', + help='Path to Metamod source code') +prep.options.add_option('--hlsdk', type='string', dest='hlsdk_path', default='', + help='Path to the HLSDK') + +prep.Configure() \ No newline at end of file From c01f767114012a02c1e37cd175cd7c5380d18d07 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 21 Feb 2021 16:10:19 +0000 Subject: [PATCH 012/114] Bug fix for newer GCC --- AMBuildScript | 9 +++++---- ChatEngine.cpp | 2 +- Makefile | 2 +- NodeMachine.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index f70134f..4042ec8 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -66,7 +66,8 @@ cxx.defines += [ if cxx.like('gcc'): cxx.cflags += [ '-Wall', - '-Werror', + #'-Werror', + '-Wno-write-strings', '-Wno-error=unused-result', '-Wno-error=unused-variable', '-Wno-unused-value', @@ -136,9 +137,9 @@ cxx.includes += [ ] -#name = 'realbot_mm' -#if builder.target_platform == 'linux': -# name += '_i386' +name = 'realbot_mm' +if builder.target_platform == 'linux': + name += '' binary = cxx.Library(name) binary.sources += [ diff --git a/ChatEngine.cpp b/ChatEngine.cpp index b7895c8..d99df8a 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -184,7 +184,7 @@ void cChatEngine::think() { // 03/07/04 // add score to matching word (evy: ignoring case) - if (strcmpi(ReplyBlock[iB].word[iBw], word) == 0) + if (strcmp(ReplyBlock[iB].word[iBw], word) == 0) WordBlockScore[iB]++; } // all words in this block } // any used block diff --git a/Makefile b/Makefile index 633a4a6..386def3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CPP = g++-4.8 +CPP = g++ ARCHFLAG = -m32 META_DIR = ./dependencies/metamod-hl1/metamod diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 18a94c8..5e38def 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -1901,7 +1901,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector vVec) { goal->index = index; goal->pGoalEdict = pEdict; goal->iType = goalType; - strcpy(goal->name, getGoalTypeAsText(*goal)); + //strcpy(goal->name, getGoalTypeAsText(*goal)); //That appears to trigger crash [APG]RoboCop[CL] char msg[255]; memset(msg, 0, sizeof(msg)); From 9ea778894884452b1dc3dfa6921f4ade49369921 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 22 Feb 2021 14:58:50 +0000 Subject: [PATCH 013/114] Update todo.txt --- todo.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/todo.txt b/todo.txt index 396be67..ca1d62a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,10 @@ - Bots may not camp when last in team (or second last?) - Bots should know when others are near its waypoint, so it won't run into each other -- Bots should have better knowledge about goals +- Bots should have better knowledge about goals (mainly for invesitigating which bomb site got the live C4 in) - Improve pathfinder - Chat rate should be lower @ default - Improve code in overall, ugly! - - -- improve the way bots walk path and decide it is a bad connection - - improve 'unstucking'... when not stuck by other players. +- Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples +- Improve the way bots walk path and decide it is a bad connection +- improve 'unstucking'... when not stuck by other players. \ No newline at end of file From 54b94b44217a4792cf2e07742deffe7ddec9ef58 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 22 Feb 2021 15:04:52 +0000 Subject: [PATCH 014/114] Update todo.txt --- todo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo.txt b/todo.txt index ca1d62a..adc7632 100644 --- a/todo.txt +++ b/todo.txt @@ -7,4 +7,4 @@ - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. - \ No newline at end of file +- Allow bots to autovacate for human players \ No newline at end of file From 67833b14b0bedec668765c9657d04281c0fffccb Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 22 Feb 2021 22:32:22 +0000 Subject: [PATCH 015/114] Update todo.txt --- todo.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/todo.txt b/todo.txt index adc7632..e6382b5 100644 --- a/todo.txt +++ b/todo.txt @@ -7,4 +7,5 @@ - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. -- Allow bots to autovacate for human players \ No newline at end of file +- Allow bots to autovacate for human players +- Prevent bots from Team Killing when a player switches sides \ No newline at end of file From b72f9c9ae5b187ea124d5274e4e0f85d6b4caba6 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 22 Feb 2021 22:37:51 +0000 Subject: [PATCH 016/114] Update todo.txt --- todo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo.txt b/todo.txt index e6382b5..65546df 100644 --- a/todo.txt +++ b/todo.txt @@ -8,4 +8,4 @@ - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. - Allow bots to autovacate for human players -- Prevent bots from Team Killing when a player switches sides \ No newline at end of file +- Prevent bots from Team Killing when a player joins T in CZ \ No newline at end of file From 097bf8653249651eb44d48cb4f6a05063c4806eb Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 5 Aug 2021 14:55:37 +0100 Subject: [PATCH 017/114] Reduced redundancy --- Bsp2Rbn/Makefile | 8 ++++---- Bsp2Rbn/dummy.cpp | 2 +- NodeMachine.cpp | 2 +- NodeMachine.h | 2 +- dependencies/hlsdk/linux/vgui.so | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) delete mode 120000 dependencies/hlsdk/linux/vgui.so diff --git a/Bsp2Rbn/Makefile b/Bsp2Rbn/Makefile index 4037829..16f37b6 100644 --- a/Bsp2Rbn/Makefile +++ b/Bsp2Rbn/Makefile @@ -1,11 +1,11 @@ # CPP must be g++ on Linux CPP = g++ -ARCHFLAG = i586 +ARCHFLAG = i686 -METAMOD_SRCDIR = ../../metamod-1.17/metamod +METAMOD_SRCDIR = ../../metamod-p/metamod -HLSDK_BASEDIR = ../../HLSDK +HLSDK_BASEDIR = ../../hlsdk-2.3-p4 BASEFLAGS = -g -Wall CPPFLAGS = ${BASEFLAGS} -march=${ARCHFLAG} -O2 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/multiplayer/common" -I"${HLSDK_BASEDIR}/multiplayer/dlls" -I"${HLSDK_BASEDIR}/multiplayer/engine" -I"${HLSDK_BASEDIR}/multiplayer/pm_shared" @@ -34,4 +34,4 @@ clean: %.o: %.c ${CPP} ${CPPFLAGS} -c $< -o $@ - + diff --git a/Bsp2Rbn/dummy.cpp b/Bsp2Rbn/dummy.cpp index 349ed67..911cf58 100644 --- a/Bsp2Rbn/dummy.cpp +++ b/Bsp2Rbn/dummy.cpp @@ -94,7 +94,7 @@ void cChatEngine::set_sentence(char csender[30], char csentence[128]) // From bot.cpp // Can see Edict? -bool cBot::canSeeEntity (edict_t * pEntity) +bool cBot::canSeeEntity (edict_t * pEntity) const { TraceResult tr; Vector start = pEdict->v.origin + pEdict->v.view_ofs; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 5e38def..7d82e29 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -4405,7 +4405,7 @@ void cNodeMachine::FindMinMax() const // Palette is defined such that increasing the palette index // Makes a slightly darker dark -void cNodeMachine::MarkAxis(void) { +void cNodeMachine::MarkAxis() { int x0 = (int)((0 - minx) / scale); int y0 = (int)((0 - miny) / scale); diff --git a/NodeMachine.h b/NodeMachine.h index 47efc13..fbe2a15 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -45,7 +45,7 @@ class cNodeMachine { // ----------------- int addNode(Vector vOrigin, edict_t *pEntity); - int Reachable(const int iStart, const int iEnd) const; + int Reachable(int iStart, int iEnd) const; int add2(Vector vOrigin, int iType, edict_t *pEntity); diff --git a/dependencies/hlsdk/linux/vgui.so b/dependencies/hlsdk/linux/vgui.so deleted file mode 120000 index 3b3dc1b..0000000 --- a/dependencies/hlsdk/linux/vgui.so +++ /dev/null @@ -1 +0,0 @@ -release/vgui.so \ No newline at end of file From b40564d9b45f6077ea4a5e137279851e8f4551ff Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 26 Aug 2021 20:05:21 +0100 Subject: [PATCH 018/114] Modernised code --- ChatEngine.cpp | 10 +- IniParser.cpp | 75 +++++++------ NodeMachine.cpp | 276 +++++++++++++++++++++++------------------------ bot.cpp | 242 ++++++++++++++++++++--------------------- bot_buycode.cpp | 12 +-- bot_client.cpp | 144 ++++++++++++------------- bot_func.cpp | 54 +++++----- bot_navigate.cpp | 4 +- dll.cpp | 167 ++++++++++++++-------------- engine.cpp | 114 ++++++++++---------- game.cpp | 48 ++++----- util.cpp | 62 +++++------ 12 files changed, 604 insertions(+), 604 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index d99df8a..e2912e2 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -96,7 +96,7 @@ void cChatEngine::think() { // 29/08/2019 Stefan: by using string compare on the name of the sender (ie sender[] is the name) we retrieve // the edict pointer - edict_t *pSender = NULL; + edict_t *pSender = nullptr; for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); @@ -243,15 +243,15 @@ void cChatEngine::think() { // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free) && pSender != pPlayer) { - bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here - bool bPlayerAlive = IsAlive(pPlayer); + const bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here + const bool bPlayerAlive = IsAlive(pPlayer); if (bSenderAlive != bPlayerAlive) continue; cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); - if (pBotPointer != NULL) + if (pBotPointer != nullptr) if (RANDOM_LONG(0, 100) < (pBotPointer->ipChatRate + 25)) { // When we have at least 1 sentence... @@ -288,7 +288,7 @@ void cChatEngine::think() { sentence[the_c], "%n"); // when name_pos var is found, fill it in. - if (name_pos != NULL) { + if (name_pos != nullptr) { // when name is in this one: int name_offset = name_pos - diff --git a/IniParser.cpp b/IniParser.cpp index 59c6652..79a7bd2 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -557,21 +557,20 @@ void INI_PARSE_CHATFILE() { UTIL_BuildFileNameRB(dirname, filename); // make sure the engine knows... - REALBOT_PRINT(NULL, "INI_PARSE_CHATFILE", "Loading CHAT.INI\n"); + REALBOT_PRINT(nullptr, "INI_PARSE_CHATFILE", "Loading CHAT.INI\n"); int iBlockId = -1; int iBlockWord = -1; int iBlockSentence = -1; // load it - if ((stream = fopen(filename, "r+t")) != NULL) { - char linefeed[80]; - char lineword[25]; - char linesection[30]; + if ((stream = fopen(filename, "r+t")) != nullptr) { - // infinite loop baby - while (!feof(stream)) { - INI_Sentence(stream, linefeed); + // infinite loop baby + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary // character (which is "//", ";" or "#"), or an empty line, then skip it @@ -614,8 +613,9 @@ void INI_PARSE_CHATFILE() { } if (iBlockId > -1) { - INI_Word(linefeed, lineword); - int wordtype = INI_WordType(lineword, section); + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); // We load in words if (wordtype == WORD_WORD) { @@ -696,13 +696,12 @@ void INI_PARSE_IAD() { float AreaY, AreaZ; float AreaX = AreaY = AreaZ = 9999; - if ((stream = fopen(filename, "r+t")) != NULL) { - char linefeed[80]; - char lineword[25]; - char linesection[30]; + if ((stream = fopen(filename, "r+t")) != nullptr) { - while (!feof(stream)) { - INI_Sentence(stream, linefeed); + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary // character (which is "//", ";" or "#"), or an empty line, then skip it @@ -722,8 +721,9 @@ void INI_PARSE_IAD() { // Check word only when in a section if (section != INI_NONE) { - INI_Word(linefeed, lineword); - int wordtype = INI_WordType(lineword, section); + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); if (section == INI_AREA) { if (wordtype == WORD_AREAX) @@ -737,7 +737,7 @@ void INI_PARSE_IAD() { if (AreaX != 9999 && AreaY != 9999 && AreaZ != 9999) { // add this to goal rblog("IAD: Adding an important area/goal\n"); - NodeMachine.addGoal(NULL, GOAL_IMPORTANT, Vector(AreaX, AreaY, AreaZ)); + NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, Vector(AreaX, AreaY, AreaZ)); AreaX = AreaY = AreaZ = 9999; } @@ -778,14 +778,13 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { UTIL_BuildFileNameRB(dirname, filename); // we open the file here! - if ((stream = fopen(filename, "r+t")) != NULL) { - char linefeed[80]; - char lineword[25]; - char linesection[30]; + if ((stream = fopen(filename, "r+t")) != nullptr) { - // infinite loop baby + // infinite loop baby while (!feof(stream)) { - INI_Sentence(stream, linefeed); + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary // character (which is "//", ";" or "#"), or an empty line, then skip it @@ -804,8 +803,9 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { } // Check word only when in a section if (section != INI_NONE) { - INI_Word(linefeed, lineword); - int wordtype = INI_WordType(lineword, section); + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); // WEAPON if (section == INI_WEAPON) { @@ -936,7 +936,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { RANDOM_FLOAT((pBot->bot_skill / 20) + 0.05, (pBot->bot_skill / 5) + 0.05); - float fMaxReact = fMinReact + RANDOM_FLOAT(0.05, 0.2); + const float fMaxReact = fMinReact + RANDOM_FLOAT(0.05, 0.2); // SET them pBot->fpMinReactTime = fMinReact; @@ -988,7 +988,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { FILE* rbl = fopen(filename, "w+t"); // Created file - if (rbl != NULL) { + if (rbl != nullptr) { fprintf(rbl, "; RealBot\n"); fprintf(rbl, "; \n"); fprintf(rbl, @@ -1087,13 +1087,11 @@ void INI_PARSE_BUYTABLE() { weapons_table[cl].iIdIndex = -1; } - if ((stream = fopen(filename, "r+t")) != NULL) { - char linefeed[80]; - char lineword[25]; - char linesection[30]; - - while (!feof(stream)) { - INI_Sentence(stream, linefeed); + if ((stream = fopen(filename, "r+t")) != nullptr) { + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary // character (which is "//", ";" or "#"), or an empty line, then skip it @@ -1128,8 +1126,9 @@ void INI_PARSE_BUYTABLE() { // Check word only when in a section if (section != INI_NONE) { - INI_Word(linefeed, lineword); - int wordtype = INI_WordType(lineword, section); + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); if (wordtype != WORD_NONE) { if (wordtype == WORD_PRICE) { //BotDebug("Loading price\n"); diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 7d82e29..ded5a55 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -78,7 +78,7 @@ cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) { // work out the position const long iPosition = (iFrom * MAX_NODES) + iTo; - const long iByte = (int) (iPosition / 8); + const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; if (iByte < g_iMaxVisibilityByte) { @@ -105,7 +105,7 @@ cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { // was int const long iPosition = (iFrom * MAX_NODES) + iTo; - const long iByte = (int) (iPosition / 8); + const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; if (iByte < g_iMaxVisibilityByte) { @@ -173,11 +173,11 @@ void cNodeMachine::init() { } // CODE: From cheesemonster - const unsigned long iSize = g_iMaxVisibilityByte; + constexpr unsigned long iSize = g_iMaxVisibilityByte; //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first - cVisTable = (unsigned char *) malloc(iSize); + cVisTable = static_cast(malloc(iSize)); memset(cVisTable, 0, iSize); ClearVisibilityTable(); // END: @@ -200,7 +200,7 @@ void cNodeMachine::initGoals() { void cNodeMachine::initGoal(int g) { Goals[g].iNode = -1; - Goals[g].pGoalEdict = NULL; + Goals[g].pGoalEdict = nullptr; Goals[g].iType = GOAL_NONE; Goals[g].index = g; Goals[g].iChecked = 0; @@ -210,9 +210,8 @@ void cNodeMachine::initGoal(int g) { int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const { - char msg[255]; -// sprintf(msg, "GetTroubleIndexForConnection | from %d to %d\n", iFrom, iTo); -// rblog(msg); + // sprintf(msg, "GetTroubleIndexForConnection | from %d to %d\n", iFrom, iTo); + // rblog(msg); // in case of invalid values, return -1 - no need to loop if (iFrom < -1 || iFrom >= MAX_NODES) { rblog("GetTroubleIndexForConnection | invalid iFrom\n"); @@ -226,7 +225,8 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const for (int index = 0; index < MAX_TROUBLE; index++) { if (Troubles[index].iFrom == iFrom && Troubles[index].iTo == iTo) { - memset(msg, 0, sizeof(msg)); + char msg[255]; + memset(msg, 0, sizeof(msg)); sprintf(msg, "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); rblog(msg); // found troubled connection, return its index @@ -277,7 +277,7 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) { return false; } - tTrouble &trouble = Troubles[index]; + const tTrouble &trouble = Troubles[index]; char msg[255]; sprintf(msg, "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); @@ -328,7 +328,7 @@ void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) { Troubles[index].iTries++; - tTrouble &trouble = Troubles[index]; + const tTrouble &trouble = Troubles[index]; memset(msg, 0, sizeof(msg)); sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); @@ -384,8 +384,8 @@ void cNodeMachine::VectorToMeredian(const Vector vOrigin, int *iX, int *iY) { iCoordX = iCoordX / SIZE_MEREDIAN; iCoordY = iCoordY / SIZE_MEREDIAN; - *iX = (int) iCoordX; - *iY = (int) iCoordY; + *iX = static_cast(iCoordX); + *iY = static_cast(iCoordY); } void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { @@ -413,7 +413,7 @@ bool cNodeMachine::node_float(const Vector vOrigin, edict_t *pEdict) { UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, pEdict->v.pContainingEntity, &tr); else - UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, NULL, + UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, nullptr, &tr); // if nothing hit: floating too high, return false @@ -444,7 +444,7 @@ bool cNodeMachine::node_on_crate(const Vector vOrigin, edict_t *pEdict) { UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, pEdict->v.pContainingEntity, &tr); else - UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, NULL, + UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, human_hull, nullptr, &tr); // if nothing hit: floating too high, return false @@ -516,12 +516,12 @@ int cNodeMachine::getClosestNode(const Vector vOrigin, float fDist, edict_t *pEd &tr); } else { UTIL_TraceHull(vOrigin, nodeVector, dont_ignore_monsters, - head_hull, NULL, &tr); + head_hull, nullptr, &tr); } // if nothing hit: if (tr.flFraction >= 1.0) { - if (pEdict != NULL) { + if (pEdict != nullptr) { if (FInViewCone(&nodeVector, pEdict) // in FOV && FVisible(nodeVector, pEdict)) { iCloseNode = iNode; @@ -583,12 +583,12 @@ int cNodeMachine::getFurthestNode(const Vector vOrigin, float fDist, edict_t *pE &tr); } else { UTIL_TraceHull(vOrigin, nodeVector, dont_ignore_monsters, - head_hull, NULL, &tr); + head_hull, nullptr, &tr); } // if nothing hit: if (tr.flFraction >= 1.0) { - if (pEdict != NULL) { + if (pEdict != nullptr) { if (FInViewCone(&nodeVector, pEdict) // in FOV && FVisible(nodeVector, pEdict)) { iFarNode = iNode; @@ -718,7 +718,7 @@ static Vector FloorBelow(const Vector V) { // Bump V a little higher (to allow for a steep climb) Vector UpALittle = V + Vector(0, 0, HullHeight); Vector ReallyDown = V + Vector(0, 0, -500); - UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, NULL, &tr); + UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, nullptr, &tr); //printf(" Floor %.0f -> %.0f, TraceHull fraction = %.2f, vecEndPos.z=%.0f %s %s\n", //UpALittle.z,ReallyDown.z,tr.flFraction,tr.vecEndPos.z, //(tr.fAllSolid) ? "AllSolid" : "", @@ -726,7 +726,7 @@ static Vector FloorBelow(const Vector V) { if (tr.fStartSolid) { // Perhaps we where too high and hit the ceiling UpALittle = V + Vector(0, 0, 0); ReallyDown = V + Vector(0, 0, -500); - UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, NULL, &tr); + UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, nullptr, &tr); //printf(" Floor without raising %.0f -> %.0f, TraceHull fraction = %.2f, vecEndPos.z=%.0f %s %s\n", //UpALittle.z,ReallyDown.z,tr.flFraction,tr.vecEndPos.z, //(tr.fAllSolid) ? "AllSolid" : "", @@ -736,7 +736,7 @@ static Vector FloorBelow(const Vector V) { HullHeight = 0; UpALittle = V + Vector(0, 0, STEP); ReallyDown = V + Vector(0, 0, -500); - UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, NULL, &tr); + UTIL_TraceHull(UpALittle, ReallyDown, ignore_monsters, HullNumber, nullptr, &tr); //printf(" Floor with point hull %.0f -> %.0f, TraceHull fraction = %.2f, vecEndPos.z=%.0f %s %s\n", //UpALittle.z,ReallyDown.z,tr.flFraction,tr.vecEndPos.z, //(tr.fAllSolid) ? "AllSolid" : "", @@ -765,8 +765,8 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const float Dist, Height, PreviousHeight; TraceResult tr; - Vector Start = Nodes[iStart].origin; - Vector End = Nodes[iEnd].origin; + const Vector Start = Nodes[iStart].origin; + const Vector End = Nodes[iEnd].origin; #ifdef DEBUG_REACHABLE printf("Reachable %d(%.0f,%.0f,%.0f)%s", iStart, Start.x, Start.y, Start.z, @@ -780,7 +780,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const // Quick & dirty check whether we can go through... // This is simply to quickly decide whether the move is impossible - UTIL_TraceHull(Start, End, ignore_monsters, point_hull, NULL, &tr); + UTIL_TraceHull(Start, End, ignore_monsters, point_hull, nullptr, &tr); #ifdef DEBUG_REACHABLE printf("TraceHull --> tr.flFraction = %.2f\n", tr.flFraction); @@ -794,7 +794,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const if ((Nodes[iStart].iNodeBits & BIT_LADDER) || (Nodes[iEnd].iNodeBits & BIT_LADDER)) { - UTIL_TraceHull(Start, End, ignore_monsters, human_hull, NULL, &tr); + UTIL_TraceHull(Start, End, ignore_monsters, human_hull, nullptr, &tr); return tr.flFraction >= 1.0; } @@ -941,7 +941,7 @@ int cNodeMachine::add2(const Vector vOrigin, int iType, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling, the distance will be bigger. - const int maxDistance = 3 * NODE_ZONE; + constexpr int maxDistance = 3 * NODE_ZONE; if (horizontal_distance(Nodes[newNodeIndex].origin, Nodes[j].origin) > maxDistance) continue; @@ -1028,8 +1028,8 @@ int cNodeMachine::addNode(const Vector vOrigin, edict_t *pEntity) { } // do only check pEntity when its not NULL else { // Does this thing float? - indexNodeFloats = node_float(Nodes[currentIndex].origin, NULL); - bIndexOnCrate = node_on_crate(Nodes[currentIndex].origin, NULL); + indexNodeFloats = node_float(Nodes[currentIndex].origin, nullptr); + bIndexOnCrate = node_on_crate(Nodes[currentIndex].origin, nullptr); } // add to subcluster @@ -1285,7 +1285,7 @@ void cNodeMachine::connections(edict_t *pEntity) { if (botPointer.bIsUsed) { closeNode = botPointer.determineCurrentNodeWithTwoAttempts(); if (closeNode > -1) { - Vector &vector = Nodes[closeNode].origin; + const Vector &vector = Nodes[closeNode].origin; sprintf(msg, "Bot [%s|%d] is at node %d (%f,%f,%f)\n", botPointer.name, draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { sprintf(msg, "Bot [%s|%d] is at node %d\n", botPointer.name, draw_nodepath, closeNode); @@ -1293,7 +1293,7 @@ void cNodeMachine::connections(edict_t *pEntity) { } else { closeNode = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); if (closeNode > -1) { - Vector &vector = Nodes[closeNode].origin; + const Vector &vector = Nodes[closeNode].origin; sprintf(msg, "No bot used for slot [%d], YOU are at node %d (%f,%f,%f)\n", draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { sprintf(msg, "No bot used for slot [%d], YOU are at node %d\n", draw_nodepath, closeNode); @@ -1308,7 +1308,7 @@ void cNodeMachine::connections(edict_t *pEntity) { if (closeNode > -1) { for (int j = 0; j < MAX_NEIGHBOURS; j++) { - tNode &node = Nodes[closeNode]; + const tNode &node = Nodes[closeNode]; const int neighbourNode = node.iNeighbour[j]; if (neighbourNode > -1) { @@ -1435,8 +1435,8 @@ void cNodeMachine::experience_save() { // Only save if lock type is < 1 FILE* rbl = fopen(filename, "wb"); - if (rbl != NULL) { - int iVersion = FILE_EXP_VER2; + if (rbl != nullptr) { + constexpr int iVersion = FILE_EXP_VER2; fwrite(&iVersion, sizeof(int), 1, rbl); for (int i = 0; i < MAX_NODES; i++) { @@ -1494,7 +1494,6 @@ void cNodeMachine::experience_save() { void cNodeMachine::experience_load() { char dirname[256]; char filename[256]; - int i; // Set Directory name strcpy(dirname, "data/cstrike/exp/"); @@ -1506,8 +1505,9 @@ void cNodeMachine::experience_load() { FILE* rbl = fopen(filename, "rb"); - if (rbl != NULL) { - int iVersion = FILE_EXP_VER1; + if (rbl != nullptr) { + int i; + int iVersion = FILE_EXP_VER1; fread(&iVersion, sizeof(int), 1, rbl); if (iVersion == FILE_EXP_VER1) { @@ -1597,9 +1597,9 @@ void cNodeMachine::save() const // Only save if lock type is < 1 FILE* rbl = fopen(filename, "wb"); - if (rbl != NULL) { + if (rbl != nullptr) { // Write down version number - int iVersion = FILE_NODE_VER1; + constexpr int iVersion = FILE_NODE_VER1; fwrite(&iVersion, sizeof(int), 1, rbl); for (int i = 0; i < MAX_NODES; i++) { fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); @@ -1656,7 +1656,6 @@ void cNodeMachine::save_important() const void cNodeMachine::load() { char dirname[256]; char filename[256]; - int i; // Set Directory name strcpy(dirname, "data/cstrike/maps/"); @@ -1669,8 +1668,9 @@ void cNodeMachine::load() { FILE* rbl = fopen(filename, "rb"); - if (rbl != NULL) { - int iVersion = FILE_NODE_VER1; + if (rbl != nullptr) { + int i; + int iVersion = FILE_NODE_VER1; fread(&iVersion, sizeof(int), 1, rbl); // Version 1.0 @@ -1723,7 +1723,7 @@ void cNodeMachine::ClearImportantGoals() { if (Goals[iGn].iType == GOAL_IMPORTANT && Goals[iGn].iNode > -1) { Goals[iGn].iType = -1; Goals[iGn].iNode = -1; - Goals[iGn].pGoalEdict = NULL; + Goals[iGn].pGoalEdict = nullptr; memset(Goals[iGn].name, 0, sizeof(Goals[iGn].name)); } } @@ -1747,7 +1747,7 @@ void cNodeMachine::path_draw(edict_t *pEntity) { FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); if (max_drawn < 39 && good && angle_to_waypoint < 50) { - const int red = 255; + constexpr int red = 255; int green = 0; int blue = 255; int width = 15; @@ -1801,7 +1801,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { //UTIL_TraceHull(Nodes[iNode].origin, Nodes[i].origin, ignore_monsters, human_hull, NULL, &tr); UTIL_TraceHull(Nodes[iNode].origin, Nodes[i].origin, - ignore_monsters, point_hull, NULL, &tr); + ignore_monsters, point_hull, nullptr, &tr); // within distance and 'reachable' if (tr.flFraction >= 1.0) { @@ -1840,7 +1840,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { //Using TraceHull to detect de_aztec bridge and other entities. TraceResult tr; UTIL_TraceHull(Nodes[iNode].origin, Nodes[i].origin, - ignore_monsters, point_hull, NULL, &tr); + ignore_monsters, point_hull, nullptr, &tr); // within distance and reachable if (tr.flFraction >= 1.0) { @@ -1893,7 +1893,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector vVec) { } tGoal *goal = getGoal(index); - if (goal == NULL) { + if (goal == nullptr) { rblog("No valid goal index found - bailing\n"); return; } @@ -1912,7 +1912,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector vVec) { tGoal *cNodeMachine::getGoal(int index) { if (index < 0 || index >= MAX_GOALS) { rblog("ERROR: Asking to retrieve goal with invalid index! Returning goal NULL\n"); - return NULL; + return nullptr; } // char msg[255]; // sprintf(msg, "Getting goal by index [%d]\n", index); @@ -1945,7 +1945,7 @@ int cNodeMachine::getFreeGoalIndex() const { */ bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const { - if (pEdict == NULL) return false; // no edict == by default no + if (pEdict == nullptr) return false; // no edict == by default no for (int g = 0; g < MAX_GOALS; g++) { if (Goals[g].pGoalEdict == pEdict) { @@ -1978,7 +1978,7 @@ void cNodeMachine::updateGoals() { rblog("cNodeMachine::updateGoals - START\n"); for (int i = 0; i < MAX_GOALS; i++) { tGoal *goal = getGoal(i); - if (goal == NULL || goal->iNode < 0) continue; + if (goal == nullptr || goal->iNode < 0) continue; if (goal->iType == GOAL_HOSTAGE) { initGoal(i); @@ -1989,13 +1989,13 @@ void cNodeMachine::updateGoals() { } } - edict_t *pent = NULL; + edict_t *pent = nullptr; // re-add goals for hostages so we have the latest information about them // GOAL #5 - Hostages (this is the 'starting' position): - while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { // verify hostage is still rescueable - if (isHostageRescued(NULL, pent) || !FUNC_EdictIsAlive(pent)) { + if (isHostageRescued(nullptr, pent) || !FUNC_EdictIsAlive(pent)) { continue; // skip dead or already rescued hostages } @@ -2033,61 +2033,61 @@ void cNodeMachine::setUpInitialGoals() { // because Nodes get expanded all the time the bot should eventually learn // how to reach other goals. - edict_t *pent = NULL; + edict_t *pent = nullptr; // GOAL #1 - Counter Terrorist Spawn points. - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != nullptr) { addGoal(pent, GOAL_SPAWNCT, pent->v.origin); } // GOAL #2 - Terrorist Spawn points. - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { addGoal(pent, GOAL_SPAWNT, pent->v.origin); } // GOAL #3 - Hostage rescue zone - while ((pent = UTIL_FindEntityByClassname(pent, "func_hostage_rescue")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "func_hostage_rescue")) != nullptr) { addGoal(pent, GOAL_RESCUEZONE, VecBModelOrigin(pent)); } // rescue zone can also be an entity of info_hostage_rescue - while ((pent = UTIL_FindEntityByClassname(pent, "info_hostage_rescue")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_hostage_rescue")) != nullptr) { addGoal(pent, GOAL_RESCUEZONE, VecBModelOrigin(pent)); } // GOAL #4 - Bombspot zone // Bomb spot - while ((pent = UTIL_FindEntityByClassname(pent, "func_bomb_target")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "func_bomb_target")) != nullptr) { addGoal(pent, GOAL_BOMBSPOT, VecBModelOrigin(pent)); } - while ((pent = UTIL_FindEntityByClassname(pent, "info_bomb_target")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_bomb_target")) != nullptr) { addGoal(pent, GOAL_BOMBSPOT, VecBModelOrigin(pent)); } // GOAL #5 - Hostages (this is the 'starting' position): - while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { addGoal(pent, GOAL_HOSTAGE, pent->v.origin + Vector(0,0,32)); } // GOAL #6 - VIP (this is the 'starting' position) (EVY) - while ((pent = UTIL_FindEntityByClassname(pent, "info_vip_start")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_vip_start")) != nullptr) { addGoal(pent, GOAL_VIP, VecBModelOrigin(pent)); } // GOAL #7 - VIP safety (this is the 'rescue' position) (EVY) - while ((pent = UTIL_FindEntityByClassname(pent, "func_vip_safetyzone")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "func_vip_safetyzone")) != nullptr) { addGoal(pent, GOAL_VIPSAFETY, VecBModelOrigin(pent)); } // GOAL #8 - Escape zone for es_ (EVY) - while ((pent = UTIL_FindEntityByClassname(pent, "func_escapezone")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "func_escapezone")) != nullptr) { addGoal(pent, GOAL_ESCAPEZONE, VecBModelOrigin(pent)); } // 05/07/04 // GOAL #9 - Free weapons on the ground EVY - while ((pent = UTIL_FindEntityByClassname(pent, "armoury_entity")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "armoury_entity")) != nullptr) { addGoal(pent, GOAL_WEAPON, VecBModelOrigin(pent)); } @@ -2099,7 +2099,7 @@ void cNodeMachine::setUpInitialGoals() { // Find a goal, and return the node close to it tGoal *cNodeMachine::getRandomGoalByType(int goalType) { if (goalType == GOAL_NONE) - return NULL; + return nullptr; int possibleGoalNodes[MAX_GOALS]; for (int c = 0; c < MAX_GOALS; c++) { @@ -2117,7 +2117,7 @@ tGoal *cNodeMachine::getRandomGoalByType(int goalType) { } if (possibleCandidateIndex == 0) - return NULL; // nothing found :( + return nullptr; // nothing found :( // we have an amount of goals, pick one randomly const int randomGoalIndex = RANDOM_LONG(0, (possibleCandidateIndex - 1)); @@ -2228,7 +2228,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn makeAllWaypointsAvailable(); // Our start waypoint is open - const float gCost = 0.0f; // distance from starting node + constexpr float gCost = 0.0f; // distance from starting node const float hCost = func_distance(Nodes[nodeStartIndex].origin, Nodes[nodeTargetIndex].origin); // distance from end node to node const float cost = gCost + hCost; @@ -2301,8 +2301,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn } for (nodeIndex = 0; nodeIndex < MAX_PATH_NODES; nodeIndex++) { - - tNodestar &nodeStar = astar_list[nodeIndex]; + const tNodestar &nodeStar = astar_list[nodeIndex]; if (nodeStar.state == AVAILABLE) continue; // char msg[255]; @@ -2371,7 +2370,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn iPath[botIndex][path_index] = node; // print out full path so we know what the order is - if (pBot != NULL) { + if (pBot != nullptr) { char pathMsg[255]; memset(pathMsg, 0, sizeof(pathMsg)); sprintf(pathMsg, "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); @@ -2389,7 +2388,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn iPath[botIndex][path_index] = -1; // And set bot in motion - if (pBot != NULL) { + if (pBot != nullptr) { pBot->beginWalkingPath(); pBot->setTimeToMoveToNode(2); // set timer (how much time do we allow ourselves to reach the following node) pBot->rprint("cNodeMachine::createPath", "Path creation finished successfully"); @@ -2423,10 +2422,10 @@ void cNodeMachine::closeNode(int nodeIndex, int parent, float cost) { * @param cost */ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) { - tNode &startNode = Nodes[startNodeIndex]; // very start of path - tNode &destNode = Nodes[destinationNodeIndex]; // destination for path + const tNode &startNode = Nodes[startNodeIndex]; // very start of path + const tNode &destNode = Nodes[destinationNodeIndex]; // destination for path - tNode &node = Nodes[nodeToOpenNeighboursFrom]; // node evaluating neighbours + const tNode &node = Nodes[nodeToOpenNeighboursFrom]; // node evaluating neighbours for (int i = 0; i < MAX_NEIGHBOURS; i++) { const int neighbourNode = node.iNeighbour[i]; @@ -2486,17 +2485,18 @@ int cNodeMachine::node_camp(const Vector vOrigin, int iTeam) { // Use Meredians to search for nodes int iX, iY; VectorToMeredian(vOrigin, &iX, &iY); - float fDanger = 2.0; - float fDistance = 9999; - int iVisibility = 9999; int iBestNode = -1; // Theory: // Find a node, close, and less danger... // and with less visibility - if (iX > -1 && iY > -1) { - // Search in this meredian + if (iX > -1 && iY > -1) + { + int iVisibility = 9999; + float fDistance = 9999; + float fDanger = 2.0; + // Search in this meredian for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) if (Meredians[iX][iY].iNodes[i] > -1) { const int iNode = Meredians[iX][iY].iNodes[i]; @@ -2534,9 +2534,10 @@ int cNodeMachine::node_camp(const Vector vOrigin, int iTeam) { // Check if iFrom is visible from other nodes (and opposite) void cNodeMachine::vis_calculate(int iFrom) { // Check around your area to see what is visible - const float fClosest = 1024; + for (int i = 0; i < MAX_NODES; i++) if ((i != iFrom) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { + constexpr float fClosest = 1024; const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { TraceResult tr; @@ -2544,7 +2545,7 @@ void cNodeMachine::vis_calculate(int iFrom) { // Visibility is not yet calculated, so determine now if (GetVisibilityFromTo(iFrom, i) == VIS_UNKNOWN) // BERKED { - UTIL_TraceHull(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, point_hull, NULL, &tr); + UTIL_TraceHull(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, point_hull, nullptr, &tr); if (tr.flFraction < 1.0) { SetVisibilityFromTo(iFrom, i, false); @@ -2705,7 +2706,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->vBody = pBot->vHead; // kill edict in memory - pBot->pButtonEdict = NULL; + pBot->pButtonEdict = nullptr; // press use if (!bTrigger) @@ -2808,7 +2809,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } } - const bool shouldDrawWaypointBeamsFromBot = false; + constexpr bool shouldDrawWaypointBeamsFromBot = false; if (shouldDrawWaypointBeamsFromBot) { tNode *nodeHeadingFor = this->getNode(currentNodeToHeadFor); @@ -2917,10 +2918,10 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - unstuck // - go back in path... - const float timeEvaluatingMoveSpeed = 0.1; + constexpr float timeEvaluatingMoveSpeed = 0.1; const bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; - const double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. Else it would trigger stuck logic too soon, too often. + constexpr double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. Else it would trigger stuck logic too soon, too often. const double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; double expectedMoveDistance = speedInOneTenthOfASecond; if (pBot->isFreezeTime()) expectedMoveDistance = 0; @@ -3004,8 +3005,8 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec // edict_t *playerNearbyInFOV = getPlayerNearbyBotInFOV(pBot); edict_t *entityNearbyInFOV = getEntityNearbyBotInFOV(pBot); - edict_t *playerNearbyInFOV = NULL; - edict_t *hostageNearbyInFOV = NULL; + edict_t *playerNearbyInFOV = nullptr; + edict_t *hostageNearbyInFOV = nullptr; if (entityNearbyInFOV) { if (strcmp(STRING(entityNearbyInFOV->v.classname), "player") == 0) { @@ -3020,11 +3021,11 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec } memset(msg, 0, sizeof(msg)); - sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", playerNearbyInFOV != NULL, hostageNearbyInFOV != NULL, pBotStuck != NULL, timeRemaining); + sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", playerNearbyInFOV != nullptr, hostageNearbyInFOV != nullptr, pBotStuck != nullptr, timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); if (playerNearbyInFOV) { - if (pBotStuck != NULL) { + if (pBotStuck != nullptr) { if (pBotStuck->pEdict == playerNearbyInFOV) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "The player nearby in FOV is the close bot as well: it is a fellow bot that blocks me"); } else { @@ -3066,7 +3067,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec // should move, but no nearby bot found that could cause us to get stuck // - when no players are close (could be blocked by them, do not learn stupid things) - if (pBotStuck == NULL) { + if (pBotStuck == nullptr) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "There is no other BOT around making me go stuck"); // check if the connection we want is going up @@ -3144,7 +3145,7 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { if (currentPathNode > -1) { const int troubleIndex = GetTroubleIndexForConnection(pBot->getPreviousPathNodeToHeadFor(), currentNodeToHeadFor); if (troubleIndex > -1) { - tTrouble &trouble = Troubles[troubleIndex]; + const tTrouble &trouble = Troubles[troubleIndex]; sprintf(msg, "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); } else { sprintf(msg, "Heading to next node: %d - with no trouble", currentPathNode); @@ -3366,8 +3367,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { int iFinalGoalNode = -1; int iFinalGoalIndex = -1; - const float MAX_DISTANCE = 16384.0; // theoretical max distance - const float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0; + constexpr float MAX_DISTANCE = 16384.0; // theoretical max distance + constexpr float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0; // 01-07-2008; Instead of using 'scores', use a normalized score. // We do: @@ -3416,7 +3417,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { // not a bot cBot *botPointer = &bots[botIndex]; - if (botPointer == NULL || + if (botPointer == nullptr || !botPointer->bIsUsed || botPointer == pBot) { // skip self continue; @@ -3512,7 +3513,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint_trace("path_think/determine goal", msg); // find a node close to the C4 - const int nodeCloseToC4 = getClosestNode(Game.vPlantedC4, NODE_ZONE * 2, NULL); + const int nodeCloseToC4 = getClosestNode(Game.vPlantedC4, NODE_ZONE * 2, nullptr); if (nodeCloseToC4 > -1) { // measure distance compared to goal node we are evaluating const float distanceToC4FromCloseNode = func_distance( @@ -3655,11 +3656,11 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // Well it looks like we override the 'final' goal node (not so final after all huh?) to the dropped c4 if (Game.vDroppedC4 != Vector(9999, 9999, 9999) && // c4 dropped somewhere - pBot->pButtonEdict == NULL) { // not using button + pBot->pButtonEdict == nullptr) { // not using button // randomly, if we 'feel like picking up the bomb' just override the 'final' goal node if (RANDOM_LONG(0, 100) < pBot->ipDroppedBomb) { - iFinalGoalNode = getClosestNode(Game.vDroppedC4, 75, NULL); + iFinalGoalNode = getClosestNode(Game.vDroppedC4, 75, nullptr); } } @@ -3692,7 +3693,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { char msg[255]; memset(msg, 0, sizeof(msg)); - if (goalData != NULL) { + if (goalData != nullptr) { sprintf(msg, "I have chosen a goal: Node [%d], Goal type [%s], checked [%d], score [%f], distance [%f]", iFinalGoalNode, goalData->name, @@ -3747,7 +3748,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { tNode *cNodeMachine::getNode(int index) { // safe-guard - if (index < 0 || index >= MAX_NODES) return NULL; + if (index < 0 || index >= MAX_NODES) return nullptr; return &Nodes[index]; } @@ -3950,11 +3951,10 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, void cNodeMachine::dump_goals() const { - char buffer[100]; - rblog("Dump of all goals\n"); for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { - Vector v = Nodes[Goals[i].iNode].origin; + char buffer[100]; + const Vector v = Nodes[Goals[i].iNode].origin; sprintf(buffer, "Goal#%d is at node %d (%.0f, %.0f, %.0f), iChecked= %d, ", i + 1, Goals[i].iNode, v.x, v.y, v.z, Goals[i].iChecked); @@ -4030,8 +4030,8 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { rblog(" Current direct neighbours are:\n"); for (i = 0; i < MAX_NEIGHBOURS; i++) if (Nodes[CurrentNode].iNeighbour[i] >= 0) { - int j = Nodes[CurrentNode].iNeighbour[i]; - Vector v = Nodes[j].origin; + const int j = Nodes[CurrentNode].iNeighbour[i]; + const Vector v = Nodes[j].origin; sprintf(buffer, " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, v.z); rblog(buffer); @@ -4056,9 +4056,9 @@ static void InitDebugBitmap() { // if (bmp_buffer) free(bmp_buffer); // reliability check, free BMP buffer if already allocated - bmp_buffer = NULL; - bmp_buffer = (char *) malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // allocate memory - if (bmp_buffer == NULL) { + bmp_buffer = nullptr; + bmp_buffer = static_cast(malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)); // allocate memory + if (bmp_buffer == nullptr) { fprintf(stderr, "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024); @@ -4070,16 +4070,16 @@ static void InitDebugBitmap() { // Draw a small cross static void DrawPoint(const Vector v, unsigned char color) { - if (bmp_buffer == NULL) { + if (bmp_buffer == nullptr) { fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates - int x0 = (int)((v.x - minx) / scale); - int y0 = (int)((v.y - miny) / scale); + const int x0 = static_cast((v.x - minx) / scale); + const int y0 = static_cast((v.y - miny) / scale); - int offset = y0 * DEBUG_BMP_WIDTH + x0; + const int offset = y0 * DEBUG_BMP_WIDTH + x0; if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", @@ -4109,16 +4109,16 @@ static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsign int stepx, stepy; int fraction; - if (bmp_buffer == NULL) { + if (bmp_buffer == nullptr) { fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates - int x0 = (int)((v_from.x - minx) / scale); - int y0 = (int)((v_from.y - miny) / scale); - int x1 = (int)((v_to.x - minx) / scale); - int y1 = (int)((v_to.y - miny) / scale); + int x0 = static_cast((v_from.x - minx) / scale); + int y0 = static_cast((v_from.y - miny) / scale); + const int x1 = static_cast((v_to.x - minx) / scale); + const int y1 = static_cast((v_to.y - miny) / scale); int dx = (x1 - x0) * 2; int dy = (y1 - y0) * 2; @@ -4209,18 +4209,18 @@ static void WriteDebugBitmap(const char *filename) { int data_start, file_size; unsigned long dummy; - if (bmp_buffer == NULL) { + if (bmp_buffer == nullptr) { fprintf(stderr, "WriteDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // open (or create) the .bmp file for writing in binary mode... FILE* fp = fopen(filename, "wb"); - if (fp == NULL) { + if (fp == nullptr) { fprintf(stderr, "WriteDebugBitmap(): unable to open BMP file!\n"); // if (bmp_buffer) free(bmp_buffer); // cannot open file, free DXF buffer - bmp_buffer = NULL; + bmp_buffer = nullptr; return; // cancel if error creating file } // write the BMP header @@ -4360,7 +4360,7 @@ static void WriteDebugBitmap(const char *filename) { // if (bmp_buffer) free(bmp_buffer); // and free the BMP buffer - bmp_buffer = NULL; + bmp_buffer = nullptr; return; // and return } @@ -4392,8 +4392,8 @@ void cNodeMachine::FindMinMax() const miny -= NODE_ZONE; // first compute the X and Y divider scale, and take the greatest of both - float scalex = (1 + maxx - minx) / DEBUG_BMP_WIDTH; - float scaley = (1 + maxy - miny) / DEBUG_BMP_WIDTH; + const float scalex = (1 + maxx - minx) / DEBUG_BMP_WIDTH; + const float scaley = (1 + maxy - miny) / DEBUG_BMP_WIDTH; if (scalex > scaley) scale = scalex + scalex / 100; // add a little offset (margin) for safety else @@ -4406,8 +4406,8 @@ void cNodeMachine::FindMinMax() const // Makes a slightly darker dark void cNodeMachine::MarkAxis() { - int x0 = (int)((0 - minx) / scale); - int y0 = (int)((0 - miny) / scale); + const int x0 = static_cast((0 - minx) / scale); + const int y0 = static_cast((0 - miny) / scale); // Mark X axis by keeping X to 0 and varying Y if ((minx < 0) && (0 < maxx)) @@ -4430,8 +4430,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (x = 0; x < DEBUG_BMP_WIDTH; x++) { Meredian = - (int) ((float) x * scale + minx + - 8192.0) / (float) SIZE_MEREDIAN; + static_cast((float)x * scale + minx + + 8192.0) / static_cast(SIZE_MEREDIAN); if (Meredian & 0x01) { for (y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4441,8 +4441,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (y = 0; y < DEBUG_BMP_HEIGHT; y++) { Meredian = - (int) ((float) y * scale + miny + - 8192.0) / (float) SIZE_MEREDIAN; + static_cast((float)y * scale + miny + + 8192.0) / static_cast(SIZE_MEREDIAN); if (Meredian & 0x01) { for (x = 0; x < DEBUG_BMP_HEIGHT; x++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4476,7 +4476,7 @@ void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) { void cNodeMachine::PlotGoals(int color) const { for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { - Vector v = Nodes[Goals[i].iNode].origin; + const Vector v = Nodes[Goals[i].iNode].origin; DrawPoint(v, color); } } @@ -4490,7 +4490,7 @@ void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) { continue; // This bot has not path for (int i = 1; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { - int To = iPath[iBot][i]; + const int To = iPath[iBot][i]; DrawLineInDebugBitmap(Nodes[From].origin, Nodes[To].origin, (bots[iBot].iTeam == 1) ? Tcolor : CTcolor); @@ -4535,7 +4535,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) UTIL_BotPressKey(pBot, IN_USE); pBot->setTimeToWait(0.5); pBot->fButtonTime = gpGlobals->time + 5; - pBot->pButtonEdict = NULL; + pBot->pButtonEdict = nullptr; pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", "I have pressed USE to open a door - finished"); // TODO: when this door is opened by a trigger_multiple (on touch) @@ -4553,12 +4553,12 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", msg); // find this entity - edict_t *pButtonEdict = NULL; - edict_t *pent = NULL; + edict_t *pButtonEdict = nullptr; + edict_t *pent = nullptr; TraceResult trb; // search for all buttons - while ((pent = UTIL_FindEntityByClassname(pent, "func_button")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "func_button")) != nullptr) { // skip anything that could be 'self' (unlikely) if (pent == pEntityHit) continue; @@ -4587,12 +4587,12 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) } // while (func_button) // still nothing found - if (pButtonEdict == NULL) { + if (pButtonEdict == nullptr) { // TOUCH buttons (are not func_button!) - pent = NULL; + pent = nullptr; // search for all buttons - while ((pent = UTIL_FindEntityByClassname(pent, "trigger_multiple")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "trigger_multiple")) != nullptr) { // skip anything that could be 'self' (unlikely) if (pent == pEntityHit) continue; diff --git a/bot.cpp b/bot.cpp index 7724f1e..2afe2da 100644 --- a/bot.cpp +++ b/bot.cpp @@ -102,7 +102,7 @@ extern bool autoskill; /* Radio issue Credit by Ditlew (NNBOT - Rest In Peace) */ bool radio_message = false; -char *message = (char *) malloc(64 * sizeof(char)); +char *message = static_cast(malloc(64 * sizeof(char))); char radio_messenger[30]; // random boundries @@ -118,7 +118,7 @@ extern bool end_round; // End round #endif cBot::cBot() { - pBotHostage = NULL; + pBotHostage = nullptr; fMoveToNodeTime = -1; clearHostages(); } @@ -184,10 +184,10 @@ void cBot::SpawnInit() { // ------------------------ // POINTERS // ------------------------ - pButtonEdict = NULL; - pBotHostage = NULL; + pButtonEdict = nullptr; + pBotHostage = nullptr; clearHostages(); - pEnemyEdict = NULL; + pEnemyEdict = nullptr; // chat memset(chChatSentence, 0, sizeof(chChatSentence)); @@ -349,10 +349,10 @@ void cBot::NewRound() { // ------------------------ // POINTERS // ------------------------ - pButtonEdict = NULL; - pBotHostage = NULL; + pButtonEdict = nullptr; + pBotHostage = nullptr; clearHostages(); - pEnemyEdict = NULL; + pEnemyEdict = nullptr; // ------------------------ // INTEGERS @@ -517,7 +517,7 @@ int cBot::FindEnemy() { if (fBlindedTime > gpGlobals->time) return -1; float fNearestDistance = 9999; // Nearest distance - edict_t *pNewEnemy = NULL; // New enemy found + edict_t *pNewEnemy = nullptr; // New enemy found // SEARCH PLAYERS FOR ENEMIES for (int i = 1; i <= gpGlobals->maxClients; i++) { @@ -573,7 +573,7 @@ int cBot::FindEnemy() { pEnemyEdict = pNewEnemy; // Update pointer // We did not have an enemy before - if (pEnemyEdict == NULL) { + if (pEnemyEdict == nullptr) { rprint_trace("FindEnemy()", "Found new enemy"); // RADIO: When we found a NEW enemy but NOT via a friend @@ -649,7 +649,7 @@ void cBot::AimAtEnemy() { } // Distance to enemy - float fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero + const float fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero // factor in distance, the further away the more deviation - which is based on skill const int skillReversed = (10 - bot_skill) + 1; @@ -783,7 +783,7 @@ void cBot::FightEnemy() { else // ---- CANNOT SEE ENEMY { if (f_bot_find_enemy_time < gpGlobals->time) { - pEnemyEdict = NULL; + pEnemyEdict = nullptr; lastSeenEnemyVector = Vector(0, 0, 0); rprint_trace("FightEnemy()", "Lost enemy out of sight, forgetting path and goal"); forgetPath(); @@ -875,7 +875,7 @@ void cBot::PickBestWeapon() { // Distance to enemy const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - const float knifeDistance = 300; + constexpr float knifeDistance = 300; // ---------------------------- // In this function all we do is decide what weapon to pick @@ -1143,7 +1143,7 @@ void cBot::Combat() { cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); // This bot killed a human; adjust skill when 'autoskill' is on. - if (checkpointer == NULL) { + if (checkpointer == nullptr) { // increase bot_skill value when autoskill enabled (making bot weaker) if (autoskill && bot_skill < 10) { @@ -1220,7 +1220,7 @@ void cBot::FindCover() { // TraceLines in 2 directions to find which way to go... UTIL_MakeVectors(pEdict->v.v_angle); - Vector v_src = pEdict->v.origin + pEdict->v.view_ofs; + const Vector v_src = pEdict->v.origin + pEdict->v.view_ofs; Vector v_right = v_src + gpGlobals->v_right * 90; Vector v_left = v_src + gpGlobals->v_right * -90; @@ -1392,11 +1392,11 @@ void cBot::InteractWithFriends() { cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); // It is a fellow bot - if (pBotPointer != NULL) { + if (pBotPointer != nullptr) { if (bClose) { if (pBotPointer->f_camp_time > gpGlobals->time && pBotPointer->f_camp_time - 10 < gpGlobals->time - && pBotPointer->pEnemyEdict == NULL + && pBotPointer->pEnemyEdict == nullptr && (RANDOM_LONG(0, 100) < ipCampRate && FUNC_DoRadio(this))) { // issue go go go @@ -1414,7 +1414,7 @@ void cBot::InteractWithFriends() { // any player: if (bClose) { // some one is close, need backup? - if (RANDOM_LONG(0, 100) < ipFearRate && pEnemyEdict != NULL) + if (RANDOM_LONG(0, 100) < ipFearRate && pEnemyEdict != nullptr) if (FUNC_DoRadio(this)) { UTIL_BotRadioMessage(this, 3, "3", ""); // need backup } @@ -1605,12 +1605,12 @@ void cBot::JoinTeam() { if (mod_id != CSTRIKE_DLL) return; // When bot plays Counter-Strike (only Counter-Strike is supported) - char c_team[32]; char c_class[32]; // Choose team first if (start_action == MSG_CS_TEAM_SELECT) { - start_action = MSG_CS_IDLE; // switch back to idle + char c_team[32]; + start_action = MSG_CS_IDLE; // switch back to idle // in case of bad state/input fall-back to 'pick one for me' if ((iTeam != 1) && (iTeam != 2) && (iTeam != 5)) { @@ -1627,7 +1627,7 @@ void cBot::JoinTeam() { } // choose - FakeClientCommand(this->pEdict, "menuselect", c_team, NULL); + FakeClientCommand(this->pEdict, "menuselect", c_team, nullptr); return; } @@ -1657,7 +1657,7 @@ void cBot::JoinTeam() { else strcpy(c_class, "5"); // random - FakeClientCommand(this->pEdict, "menuselect", c_class, NULL); + FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); // bot has now joined a team hasJoinedTeam = true; @@ -1689,7 +1689,7 @@ void cBot::JoinTeam() { else strcpy(c_class, "5"); // random - FakeClientCommand(this->pEdict, "menuselect", c_class, NULL); + FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); // bot has now joined the game (doesn't need to be started) hasJoinedTeam = true; @@ -1709,11 +1709,11 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { // the quickest way to turn to face that direction // find the difference in the current and ideal angle - float diff = fabs(current - ideal); + const float diff = fabs(current - ideal); // check if the bot is already facing the idealpitch direction... if (diff <= 1.0) - return (int) current; // return number of degrees turned + return static_cast(current); // return number of degrees turned // check if difference is less than the max degrees per turn if (diff < speed) @@ -1757,7 +1757,7 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { current -= 360; if (current < -180) current += 360; - return (int) current; // return what it should be + return static_cast(current); // return what it should be } // BOT: sub-function (DEFUSE) for ACT() @@ -1775,9 +1775,9 @@ bool cBot::Defuse() { // if this bot is close. If so, the bot should be defusing the bomb // if the timers are set. The above check makes sure that no other // bot will be defusing the bomb. - edict_t *pent = NULL; + edict_t *pent = nullptr; bool c4Found = false; - while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != nullptr) { if (UTIL_GetGrenadeType(pent) == 4) { // It is a C4 c4Found = true; break; @@ -1815,7 +1815,7 @@ bool cBot::Defuse() { // We can do 2 things now // - If we are not close, we check if we can walk to it, and if so we face to the c4 // - If we are close, we face it and (begin) defuse the bomb. - const int distanceForC4ToBeInReach = 70; + constexpr int distanceForC4ToBeInReach = 70; if (distance < distanceForC4ToBeInReach) { vHead = vC4; vBody = vC4; @@ -1851,7 +1851,7 @@ bool cBot::Defuse() { } else { rprint_trace("Defuse()", "I can see C4, but it is out of reach."); - const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, NULL); + const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); if (iGoalNode < 0) { rprint_normal("Defuse()", "No node close, so just look at it/body face at it and move towards it."); vHead = vC4; @@ -1971,7 +1971,7 @@ void cBot::Act() { pEdict->v.button &= (~IN_RUN); // release IN_RUN rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed((float) (((int) f_max_speed) / 2 + ((int) f_max_speed) / 50)); + setMoveSpeed(static_cast(((int)f_max_speed) / 2 + ((int)f_max_speed) / 50)); } // When we are at max speed, press IN_RUN to get a running animation @@ -2101,19 +2101,19 @@ void cBot::CheckAround() { TraceResult tr; // v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); - Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); + const Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); // Go forward first - const float distance = 90; - Vector v_forward = v_source + gpGlobals->v_forward * distance; + constexpr float distance = 90; + const Vector v_forward = v_source + gpGlobals->v_forward * distance; // now really go left/right - Vector v_right = v_source + gpGlobals->v_right * distance; - Vector v_left = v_source + gpGlobals->v_right * -distance; + const Vector v_right = v_source + gpGlobals->v_right * distance; + const Vector v_left = v_source + gpGlobals->v_right * -distance; // now really go left/right - Vector v_forwardright = v_right + gpGlobals->v_forward * distance; - Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; + const Vector v_forwardright = v_right + gpGlobals->v_forward * distance; + const Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; // TRACELINE: forward UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -2171,10 +2171,11 @@ void cBot::CheckAround() { // ------------------------------------------------------------- // When checking around a bot also handles breakable stuff. // ------------------------------------------------------------- - char item_name[40]; - edict_t *pent = NULL; - while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60)) != NULL) { - strcpy(item_name, STRING(pent->v.classname)); + + edict_t *pent = nullptr; + while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60)) != nullptr) { + char item_name[40]; + strcpy(item_name, STRING(pent->v.classname)); // See if it matches our object name if (strcmp("func_breakable", item_name) == 0) { @@ -2257,21 +2258,21 @@ bool cBot::hasGoalIndex() const */ tGoal *cBot::getGoalData() const { - if (!hasGoalIndex()) return NULL; + if (!hasGoalIndex()) return nullptr; tGoal *ptr = NodeMachine.getGoal(this->goalIndex); - if (ptr == NULL) return NULL; + if (ptr == nullptr) return nullptr; // only goals with a node are valid if (ptr->iNode > -1) return ptr; // else not - return NULL; + return nullptr; } // Returns true if bot has an enemy edict bool cBot::hasEnemy() const { - return this->pEnemyEdict != NULL; + return this->pEnemyEdict != nullptr; } /** @@ -2359,7 +2360,7 @@ void cBot::forgetPath() { } void cBot::forgetEnemy() { - this->pEnemyEdict = NULL; + this->pEnemyEdict = nullptr; } edict_t * cBot::getEnemyEdict() const @@ -2383,7 +2384,7 @@ void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { char msg[255]; memset(msg, 0, sizeof(msg)); - if (goalPtr != NULL) { + if (goalPtr != nullptr) { sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", nodeIndex, goalIndex, @@ -2401,7 +2402,7 @@ void cBot::setGoalNode(int nodeIndex) { } void cBot::setGoalNode(tGoal *goal) { - if (goal != NULL && goal->iNode > -1) { + if (goal != nullptr && goal->iNode > -1) { rprint("setGoalNode with goal pointer\n"); this->setGoalNode(goal->iNode, goal->index); } @@ -2491,7 +2492,7 @@ void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { strcpy(this->arg1, "buy"); strcpy(this->arg2, menuItem); - if (subMenuItem != NULL) strcpy(this->arg3, subMenuItem); + if (subMenuItem != nullptr) strcpy(this->arg3, subMenuItem); this->console_nr = 1; // start console command sequence } @@ -2739,9 +2740,9 @@ void cBot::Memory() { // Hear players: (loop through all players, determine if they are running and if // we can hear them (estimated distance)). - if (pEnemyEdict == NULL) { + if (pEnemyEdict == nullptr) { Vector vHear = Vector(9999, 9999, 9999); - edict_t *pHearPlayer = NULL; + edict_t *pHearPlayer = nullptr; //f_walk_time = gpGlobals->time + 1; @@ -2840,13 +2841,13 @@ void cBot::Memory() { } // Fill in hearing vectory if any: - if (pHearPlayer != NULL) { + if (pHearPlayer != nullptr) { if (RANDOM_LONG(0, 100) < (ipFearRate + 10)) { // determine fuzzyness by distance: int iFuzz = - (int) (func_distance(pEdict->v.origin, vHear) / - BOT_HEARDISTANCE) * 250; + static_cast(func_distance(pEdict->v.origin, vHear) / + BOT_HEARDISTANCE) * 250; // skill depended iFuzz /= (bot_skill + 1); @@ -3034,10 +3035,10 @@ edict_t * cBot::getHostageToRescue() const } edict_t * cBot::findHostageToRescue() { - edict_t *pent = NULL; + edict_t *pent = nullptr; // Search for all hostages in the game - while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { if (!isHostageRescueable(this, pent)) continue; if (!canSeeEntity(pent)) continue; // skip too far hostages, leave it up to the goal picking to get closer @@ -3049,7 +3050,7 @@ edict_t * cBot::findHostageToRescue() { return pent; } - return NULL; + return nullptr; } bool cBot::isDefusing() const @@ -3162,7 +3163,7 @@ void cBot::Think() { cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); // not killed by a fellow bot, presumably a human player - if (botPointerOfKiller == NULL) { + if (botPointerOfKiller == nullptr) { if (autoskill) { bot_skill--; if (bot_skill < 0) @@ -3170,7 +3171,7 @@ void cBot::Think() { } if (Game.iKillsBroadcasting != BROADCAST_KILLS_NONE - && killer_edict != NULL) { + && killer_edict != nullptr) { // This is a human, we will tell this human he has been killed // by a bot. const int r = RANDOM_LONG(150, 255); @@ -3361,17 +3362,17 @@ void cBot::Think() { vHead = vBody = pEdict->v.origin; // find any spawnpoint to look at: - edict_t *pent = NULL; + edict_t *pent = nullptr; if (isCounterTerrorist()) { - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != nullptr) { if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && func_distance(pent->v.origin, pEdict->v.origin) > 50) { break; } } } else { - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != NULL) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && func_distance(pent->v.origin, pEdict->v.origin) > 50) { break; @@ -3380,7 +3381,7 @@ void cBot::Think() { } // when pent is filled, look at it - if (pent != NULL) { + if (pent != nullptr) { vBody = vHead = pent->v.origin; } @@ -3507,11 +3508,11 @@ void cBot::checkOfHostagesStillFollowMe() { void cBot::clearHostages() { rprint_trace("clearHostages"); - hostage1 = NULL; - hostage2 = NULL; - hostage3 = NULL; - hostage4 = NULL; - pBotHostage = NULL; + hostage1 = nullptr; + hostage2 = nullptr; + hostage3 = nullptr; + hostage4 = nullptr; + pBotHostage = nullptr; } // BOT: CheckGear, part of UpdateStatus() @@ -3589,8 +3590,8 @@ void cBot::UpdateStatus() { // char msg[255]; // sprintf(msg, "f_max_speed set to %f", f_max_speed); // rprint_trace("UpdateStatus", msg); - bot_health = (int) pEdict->v.health; - bot_armor = (int) pEdict->v.armorvalue; + bot_health = static_cast(pEdict->v.health); + bot_armor = static_cast(pEdict->v.armorvalue); } } @@ -3604,7 +3605,7 @@ void cBot::UpdateStatus() { bool BotRadioAction() { char name[64]; bool unstood = false; - edict_t *plr = NULL; + edict_t *plr = nullptr; int team = -1; int i; int radios = 0; // Hold amount of replies here, so we don't flood :) @@ -3613,10 +3614,10 @@ bool BotRadioAction() { // First find the team messager name for (i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); // Get pEdict - char netname[64]; if (pPlayer) // If player exists { - strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname + char netname[64]; + strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname if (strcmp(netname, name) == 0) // If { plr = pPlayer; @@ -3628,23 +3629,22 @@ bool BotRadioAction() { // Check players and check if radio message applies to them for (i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); - char netname[64]; if (pPlayer) { + char netname[64]; - strcpy(netname, STRING(pPlayer->v.netname)); + strcpy(netname, STRING(pPlayer->v.netname)); if ((strcmp(netname, name) != 0) && // When not the same name (team == UTIL_GetTeam(pPlayer)) && // .. the same team... (pPlayer->v.deadflag == DEAD_NO) && // .. not dead .. - ((UTIL_GetBotPointer(pPlayer) != NULL))) // and a RealBot + ((UTIL_GetBotPointer(pPlayer) != nullptr))) // and a RealBot { // here are all bots cBot *BotPointer = UTIL_GetBotPointer(pPlayer); - if (BotPointer == NULL) + if (BotPointer == nullptr) continue; // somehow this fucked up, bail out - const bool report_back = false; // for reporting in const float distance = func_distance(plr->v.origin, BotPointer->pEdict->v.origin); // distance between the 2 @@ -3661,18 +3661,17 @@ bool BotRadioAction() { bWantToListen) bool want_to_answer = true; - bool can_do_negative = true; // On some radio commands we can't say negative, thats stupid - // If we want to listen to the radio... then handle it! if (bWantToListen) { + bool can_do_negative = true; - // Report in team! - if (strstr(message, "#Report_in_team") != NULL) { + // Report in team! + if (strstr(message, "#Report_in_team") != nullptr) { // gives human knowledge who is on his team } // Regroup team! - if (strstr(message, "#Regroup_team") != NULL) { + if (strstr(message, "#Regroup_team") != nullptr) { // regroup now! unstood = true; @@ -3683,21 +3682,21 @@ bool BotRadioAction() { } // Hold this position - if (strstr(message, "#Hold_this_position") != NULL || - strstr(message, "#Get_in_position_and_wait") != NULL) { + if (strstr(message, "#Hold_this_position") != nullptr || + strstr(message, "#Get_in_position_and_wait") != nullptr) { // do nothing } // Follow me!! - if (strstr(message, "#Follow_me") != NULL) {} + if (strstr(message, "#Follow_me") != nullptr) {} // You take the point! // 23/06/04 - Stefan - Here the leader should break up his position? // ie, the leader will be assigned to the bot this human/bot is facing? - if (strstr(message, "#You_take_the_point") != NULL) { + if (strstr(message, "#You_take_the_point") != nullptr) { can_do_negative = false; } // Enemy Sotted! - if (strstr(message, "#Enemy_spotted") != NULL) { + if (strstr(message, "#Enemy_spotted") != nullptr) { can_do_negative = false; // Find player who issues this message and go to it @@ -3717,14 +3716,14 @@ bool BotRadioAction() { } } // Enemy Down! - if (strstr(message, "#Enemy_down") != NULL) { + if (strstr(message, "#Enemy_down") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); unstood = true; can_do_negative = false; } // Stick together team! - if (strstr(message, "#Stick_together_team") != NULL) { + if (strstr(message, "#Stick_together_team") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); unstood = true; // TODO: Find someone to follow. (to stick with) @@ -3732,7 +3731,7 @@ bool BotRadioAction() { // cover me|| strstr (message, "#Cover_me") != NULL // Need backup / taking fire... - if (strstr(message, "#Need_backup") != NULL || strstr(message, "#Taking_fire") != NULL) { + if (strstr(message, "#Need_backup") != nullptr || strstr(message, "#Taking_fire") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); unstood = true; @@ -3750,16 +3749,16 @@ bool BotRadioAction() { } // Taking fire! - if (strstr(message, "#Taking_fire") != NULL) { + if (strstr(message, "#Taking_fire") != nullptr) { // todo todo todo backup our friend // unstood = true; } // Team fall back! - if (strstr(message, "#Team_fall_back") != NULL) { + if (strstr(message, "#Team_fall_back") != nullptr) { } // Go GO Go, stop camping, stop following, get the heck out of there! - if (strstr(message, "#Go_go_go") != NULL) { + if (strstr(message, "#Go_go_go") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); unstood = true; BotPointer->f_camp_time = gpGlobals->time - 30; @@ -3774,8 +3773,9 @@ bool BotRadioAction() { if ((FUNC_DoRadio(BotPointer)) && (unstood)) { const int maxAllowedRadios = gpGlobals->maxClients / 4; if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { + const bool report_back = false; - if (!report_back) { + if (!report_back) { UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! } else { UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! @@ -3847,7 +3847,7 @@ bool EntityIsVisible(edict_t *pEntity, const Vector dest) { // Can see Edict? bool cBot::canSeeEntity(edict_t *pEntity) const { - if (pEntity == NULL) return false; + if (pEntity == nullptr) return false; TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -3873,7 +3873,7 @@ bool cBot::canSeeEntity(edict_t *pEntity) const */ float cBot::getDistanceTo(int nodeIndex) { tNode *nodePtr = NodeMachine.getNode(nodeIndex); - if (nodePtr != NULL) { + if (nodePtr != nullptr) { return getDistanceTo(nodePtr->origin); } rprint("getDistanceTo(int nodeIndex)", "The given nodeIndex was invalid, returning 9999 distance"); @@ -3891,7 +3891,7 @@ float cBot::getDistanceTo(const Vector vDest) const } bool cBot::isUsingHostage(edict_t *pHostage) { - if (pHostage == NULL) return false; + if (pHostage == nullptr) return false; // checks if the current pEdict is already 'in use' // note: time check only when we have an hostage pointer assigned @@ -3922,25 +3922,25 @@ void cBot::forgetHostage(edict_t *pHostage) { // these are the hostages we are rescueing (ie, they are following this bot) if (hostage1 == pHostage) { rprint("forgetHostage", "hostage1"); - hostage1 = NULL; + hostage1 = nullptr; } if (hostage2 == pHostage) { rprint("forgetHostage", "hostage2"); - hostage2 = NULL; + hostage2 = nullptr; } if (hostage3 == pHostage) { rprint("forgetHostage", "hostage3"); - hostage3 = NULL; + hostage3 = nullptr; } if (hostage4 == pHostage) { rprint("forgetHostage", "hostage4"); - hostage4 = NULL; + hostage4 = nullptr; } // this is the hostage we have taken interest in if (pBotHostage == pHostage) { rprint("forgetHostage", "pBotHostage"); - pBotHostage = NULL; + pBotHostage = nullptr; } } @@ -3948,10 +3948,10 @@ int cBot::getAmountOfHostagesBeingRescued() const { int count = 0; - if (hostage1 != NULL) count++; - if (hostage2 != NULL) count++; - if (hostage3 != NULL) count++; - if (hostage4 != NULL) count++; + if (hostage1 != nullptr) count++; + if (hostage2 != nullptr) count++; + if (hostage3 != nullptr) count++; + if (hostage4 != nullptr) count++; return count; } @@ -4014,7 +4014,7 @@ void BotThink(cBot *pBot) { const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; pBot->fLastRunPlayerMoveTime = gpGlobals->time; - const double upMove = 0.0; + constexpr double upMove = 0.0; char msg[255]; sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); @@ -4027,7 +4027,7 @@ void BotThink(cBot *pBot) { 0, msecval); - const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps + constexpr float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; } @@ -4080,7 +4080,7 @@ void cBot::beginWalkingPath() { bool cBot::hasHostageToRescue() const { - return pBotHostage != NULL; + return pBotHostage != nullptr; } bool cBot::canSeeHostageToRescue() const @@ -4090,24 +4090,24 @@ bool cBot::canSeeHostageToRescue() const void cBot::clearHostageToRescueTarget() { rprint_trace("clearHostageToRescueTarget", "clearing pBotHostage pointer"); - this->pBotHostage = NULL; + this->pBotHostage = nullptr; } // Finds a free hostage pointer and assigns it. void cBot::rememberHostageIsFollowingMe(edict_t *pHostage) { - if (pHostage == NULL) { + if (pHostage == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "ERROR assigning NULL pHostage pointer!?"); } - if (hostage1 == NULL) { + if (hostage1 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage1 slot is free."); hostage1 = pHostage; - } else if (hostage2 == NULL) { + } else if (hostage2 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage2 slot is free."); hostage2 = pHostage; - } else if (hostage3 == NULL) { + } else if (hostage3 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage3 slot is free."); hostage3 = pHostage; - } else if (hostage4 == NULL) { + } else if (hostage4 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage4 slot is free."); hostage4 = pHostage; } @@ -4122,7 +4122,7 @@ void cBot::checkIfHostagesAreRescued() { bool cBot::isOnSameTeamAs(cBot *pBot) const { - if (pBot == NULL) return false; + if (pBot == nullptr) return false; return pBot->iTeam == this->iTeam; } @@ -4159,7 +4159,7 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const TraceResult tr; const Vector vOrigin = pEdict->v.origin; - tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); //Using TraceHull to detect de_aztec bridge and other entities. //DONT_IGNORE_MONSTERS, we reached it only when there are no other bots standing in our way! @@ -4174,7 +4174,7 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const } } - return NULL; + return nullptr; } /** @@ -4263,7 +4263,7 @@ bool cBot::shouldBeAbleToInteractWithButton() const bool cBot::hasButtonToInteractWith() const { - return pButtonEdict != NULL; + return pButtonEdict != nullptr; } bool cBot::hasCurrentNode() const diff --git a/bot_buycode.cpp b/bot_buycode.cpp index e3fa0a9..858ad0b 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -74,7 +74,7 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const ch strcpy(pBot->arg2, arg1); // add argument - if (arg2 != NULL) + if (arg2 != nullptr) strcpy(pBot->arg3, arg2); pBot->console_nr = 1; // start console command sequence @@ -371,14 +371,14 @@ void BotDecideWhatToBuy(cBot *pBot) { } else if (pBot->buy_ammo_primary == true) { pBot->rprint("BotDecideWhatToBuy()", "buy_ammo_primary"); // Buy primary ammo - BotPrepareConsoleCommandsToBuyWeapon(pBot, "6", NULL); + BotPrepareConsoleCommandsToBuyWeapon(pBot, "6", nullptr); pBot->buy_ammo_primary = false; return; } else if (pBot->buy_ammo_secondary == true) { pBot->rprint("BotDecideWhatToBuy()", "buy_ammo_secondary"); // Buy secondary ammo - BotPrepareConsoleCommandsToBuyWeapon(pBot, "7", NULL); + BotPrepareConsoleCommandsToBuyWeapon(pBot, "7", nullptr); pBot->buy_ammo_secondary = false; return; } else if (pBot->buy_defusekit) { @@ -472,18 +472,18 @@ void BotConsole(cBot *pBot) { // issue command (buy/radio) if (pBot->console_nr == 1) - FakeClientCommand(pBot->pEdict, pBot->arg1, NULL, NULL); + FakeClientCommand(pBot->pEdict, pBot->arg1, nullptr, nullptr); // do menuselect if (pBot->console_nr == 2) - FakeClientCommand(pBot->pEdict, "menuselect", pBot->arg2, NULL); + FakeClientCommand(pBot->pEdict, "menuselect", pBot->arg2, nullptr); // do menuselect if (pBot->console_nr == 3) { // When the last parameter is not null, we will perform that action. if (pBot->arg3[0] != 0) FakeClientCommand(pBot->pEdict, "menuselect", pBot->arg3, - NULL); + nullptr); // reset pBot->console_nr = -1; diff --git a/bot_client.cpp b/bot_client.cpp index 3b72057..641bb3b 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -58,11 +58,11 @@ static FILE *fp; // This message is sent when the Counter-Strike VGUI menu is displayed. void BotClient_CS_VGUI(void *p, int bot_index) { //DebugOut("bot_client: BotClient_CS_VGUI()\n"); - if ((*(int *) p) == 2) // is it a team select menu? + if ((*static_cast(p)) == 2) // is it a team select menu? bots[bot_index].start_action = MSG_CS_TEAM_SELECT; - else if ((*(int *) p) == 26) // is is a terrorist model select menu? + else if ((*static_cast(p)) == 26) // is is a terrorist model select menu? bots[bot_index].start_action = MSG_CS_T_SELECT; - else if ((*(int *) p) == 27) // is is a counter-terrorist model select menu? + else if ((*static_cast(p)) == 27) // is is a counter-terrorist model select menu? bots[bot_index].start_action = MSG_CS_CT_SELECT; } @@ -76,18 +76,18 @@ void BotClient_CS_ShowMenu(void *p, int bot_index) { return; } - if (strcmp((char *) p, "#Team_Select") == 0 || - strcmp((char *) p, "#Team_Select_Spect") == 0 || - strcmp((char *) p, "#IG_Team_Select_Spect") == 0 || - strcmp((char *) p, "#IG_Team_Select") == 0 || - strcmp((char *) p, "#IG_VIP_Team_Select") == 0 || - strcmp((char *) p, "#IG_VIP_Team_Select_Spect") == 0) { + if (strcmp(static_cast(p), "#Team_Select") == 0 || + strcmp(static_cast(p), "#Team_Select_Spect") == 0 || + strcmp(static_cast(p), "#IG_Team_Select_Spect") == 0 || + strcmp(static_cast(p), "#IG_Team_Select") == 0 || + strcmp(static_cast(p), "#IG_VIP_Team_Select") == 0 || + strcmp(static_cast(p), "#IG_VIP_Team_Select_Spect") == 0) { // team select menu? bots[bot_index].start_action = MSG_CS_TEAM_SELECT; - } else if (strcmp((char *) p, "#Terrorist_Select") == 0) { + } else if (strcmp(static_cast(p), "#Terrorist_Select") == 0) { // T model select? bots[bot_index].start_action = MSG_CS_T_SELECT; - } else if (strcmp((char *) p, "#CT_Select") == 0) { + } else if (strcmp(static_cast(p), "#CT_Select") == 0) { // CT model select menu? bots[bot_index].start_action = MSG_CS_CT_SELECT; } @@ -104,32 +104,32 @@ void BotClient_Valve_WeaponList(void *p, int bot_index) { if (state == 0) { state++; - strcpy(bot_weapon.szClassname, (char *) p); + strcpy(bot_weapon.szClassname, static_cast(p)); } else if (state == 1) { state++; - bot_weapon.iAmmo1 = *(int *) p; // ammo index 1 + bot_weapon.iAmmo1 = *static_cast(p); // ammo index 1 } else if (state == 2) { state++; - bot_weapon.iAmmo1Max = *(int *) p; // max ammo1 + bot_weapon.iAmmo1Max = *static_cast(p); // max ammo1 } else if (state == 3) { state++; - bot_weapon.iAmmo2 = *(int *) p; // ammo index 2 + bot_weapon.iAmmo2 = *static_cast(p); // ammo index 2 } else if (state == 4) { state++; - bot_weapon.iAmmo2Max = *(int *) p; // max ammo2 + bot_weapon.iAmmo2Max = *static_cast(p); // max ammo2 } else if (state == 5) { state++; - bot_weapon.iSlot = *(int *) p; // slot for this weapon + bot_weapon.iSlot = *static_cast(p); // slot for this weapon } else if (state == 6) { state++; - bot_weapon.iPosition = *(int *) p; // position in slot + bot_weapon.iPosition = *static_cast(p); // position in slot } else if (state == 7) { state++; - bot_weapon.iId = *(int *) p; // weapon ID + bot_weapon.iId = *static_cast(p); // weapon ID } else if (state == 8) { state = 0; - bot_weapon.iFlags = *(int *) p; // flags for weapon (WTF???) + bot_weapon.iFlags = *static_cast(p); // flags for weapon (WTF???) // store away this weapon with it's ammo information... weapon_defs[bot_weapon.iId] = bot_weapon; @@ -174,18 +174,18 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { static int state = 0; // current state machine state static int iState; static int iId; - static int iClip; if (state == 0) { state++; - iState = *(int *) p; // state of the current weapon + iState = *static_cast(p); // state of the current weapon } else if (state == 1) { state++; - iId = *(int *) p; // weapon ID of current weapon + iId = *static_cast(p); // weapon ID of current weapon } else if (state == 2) { - state = 0; + static int iClip; + state = 0; - iClip = *(int *) p; // ammo currently in the clip for this weapon + iClip = *static_cast(p); // ammo currently in the clip for this weapon if (iId <= 31) { bots[bot_index].bot_weapons |= (1 << iId); // set this weapon bit @@ -231,19 +231,19 @@ void BotClient_Valve_AmmoX(void *p, int bot_index) { //DebugOut("bot_client: BotClient_Valve_AmmoX()\n"); static int state = 0; // current state machine state static int index; - static int ammount; if (state == 0) { state++; - index = *(int *) p; // ammo index (for type of ammo) + index = *static_cast(p); // ammo index (for type of ammo) } else if (state == 1) { - state = 0; + static int ammount; + state = 0; - ammount = *(int *) p; // the ammount of ammo currently available + ammount = *static_cast(p); // the ammount of ammo currently available bots[bot_index].m_rgAmmo[index] = ammount; // store it away - int ammo_index = bots[bot_index].current_weapon.iId; + const int ammo_index = bots[bot_index].current_weapon.iId; // update the ammo counts for this weapon... bots[bot_index].current_weapon.iAmmo1 = @@ -281,19 +281,19 @@ void BotClient_Valve_AmmoPickup(void *p, int bot_index) { //DebugOut("bot_client: BotClient_Valve_AmmoPickup()\n"); static int state = 0; // current state machine state static int index; - static int ammount; if (state == 0) { state++; - index = *(int *) p; + index = *static_cast(p); } else if (state == 1) { - state = 0; + static int ammount; + state = 0; - ammount = *(int *) p; + ammount = *static_cast(p); bots[bot_index].m_rgAmmo[index] = ammount; - int ammo_index = bots[bot_index].current_weapon.iId; + const int ammo_index = bots[bot_index].current_weapon.iId; // update the ammo counts for this weapon... bots[bot_index].current_weapon.iAmmo1 = @@ -323,7 +323,7 @@ void BotClient_FLF_AmmoPickup(void *p, int bot_index) { // This message gets sent when the bot picks up a weapon. void BotClient_Valve_WeaponPickup(void *p, int bot_index) { - int index = *(int*)p; + const int index = *static_cast(p); // set this weapon bit to indicate that we are carrying this weapon bots[bot_index].bot_weapons |= (1 << index); @@ -374,7 +374,7 @@ void BotClient_FLF_ItemPickup(void *p, int bot_index) { // This message gets sent when the bots health changes. void BotClient_Valve_Health(void *p, int bot_index) { //DebugOut("bot_client: BotClient_Valve_Health()\n"); - bots[bot_index].bot_health = *(int *) p; // health ammount + bots[bot_index].bot_health = *static_cast(p); // health ammount } void BotClient_CS_Health(void *p, int bot_index) { @@ -398,7 +398,7 @@ void BotClient_FLF_Health(void *p, int bot_index) { // This message gets sent when the bots armor changes. void BotClient_Valve_Battery(void *p, int bot_index) { //DebugOut("bot_client: BotClient_Valve_Battery()\n"); - bots[bot_index].bot_armor = *(int *) p; // armor ammount + bots[bot_index].bot_armor = *static_cast(p); // armor ammount } void BotClient_CS_Battery(void *p, int bot_index) { @@ -430,23 +430,23 @@ void BotClient_Valve_Damage(void *p, int bot_index) { if (state == 0) { state++; - damage_armor = *(int *) p; + damage_armor = *static_cast(p); } else if (state == 1) { state++; - damage_taken = *(int *) p; + damage_taken = *static_cast(p); } else if (state == 2) { state++; - damage_bits = *(int *) p; + damage_bits = *static_cast(p); } else if (state == 3) { state++; - damage_origin.x = *(float *) p; + damage_origin.x = *static_cast(p); } else if (state == 4) { state++; - damage_origin.y = *(float *) p; + damage_origin.y = *static_cast(p); } else if (state == 5) { state = 0; - damage_origin.z = *(float *) p; + damage_origin.z = *static_cast(p); if ((damage_armor > 0) || (damage_taken > 0)) { // Damage recieved: @@ -561,9 +561,9 @@ void BotClient_CS_SayText(void *p, int bot_index) { // handling of this "SayText" thingy. if (counterstrike == 0) { if (state == 0) { - ucEntIndex = *(unsigned char *) p; + ucEntIndex = *static_cast(p); } else if (state == 1) { - cBot *pBot = &bots[bot_index]; + const cBot *pBot = &bots[bot_index]; if (ENTINDEX(pBot->pEdict) != ucEntIndex) { char sentence[MAX_SENTENCE_LENGTH]; @@ -574,7 +574,7 @@ void BotClient_CS_SayText(void *p, int bot_index) { memset(chSentence, 0, sizeof(chSentence)); memset(netname, 0, sizeof(netname)); - strcpy(sentence, (char *) p); // the actual sentence + strcpy(sentence, static_cast(p)); // the actual sentence int length = 0; @@ -589,7 +589,7 @@ void BotClient_CS_SayText(void *p, int bot_index) { tc++; } - edict_t *pPlayer = INDEXENT(ucEntIndex); + const edict_t *pPlayer = INDEXENT(ucEntIndex); strcpy(netname, STRING(pPlayer->v.netname)); ChatEngine.set_sentence(netname, chSentence); @@ -600,7 +600,7 @@ void BotClient_CS_SayText(void *p, int bot_index) { // CS 1.6 if (state == 0) { // who sent this message? - ucEntIndex = *(unsigned char *) p; + ucEntIndex = *static_cast(p); } // to who? else if (state == 1) { @@ -625,10 +625,10 @@ void BotClient_CS_SayText(void *p, int bot_index) { memset(netname, 0, sizeof(netname)); // copy in memory - strcpy(sentence, (char *) p); + strcpy(sentence, static_cast(p)); // copy netname - edict_t *pPlayer = INDEXENT(ucEntIndex); + const edict_t *pPlayer = INDEXENT(ucEntIndex); strcpy(netname, STRING(pPlayer->v.netname)); // and give chatengine something to do @@ -659,20 +659,20 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { // byte : blue */ static int state = 0; // current state machine state - static int EnableIcon; - if (p == 0) // A bandaid. Make this whole thing more robust! + if (p == nullptr) // A bandaid. Make this whole thing more robust! { state = 0; return; } switch (state++) { - case 0: // Enable or not? - EnableIcon = *(int *) p; // check the byte + static int EnableIcon; + case 0: // Enable or not? + EnableIcon = *static_cast(p); // check the byte break; case 1: // Which icon - if (strcmp((char *) p, "buyzone") == 0) { + if (strcmp(static_cast(p), "buyzone") == 0) { switch (EnableIcon) { case 0: // Not in buy zone state = 0; @@ -682,7 +682,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp((char *) p, "c4") == 0) { + } else if (strcmp(static_cast(p), "c4") == 0) { switch (EnableIcon) { case 0: // No C4 bots[bot_index].bHUD_C4_plantable = false; @@ -697,7 +697,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp((char *) p, "defuser") == 0) { + } else if (strcmp(static_cast(p), "defuser") == 0) { switch (EnableIcon) { case 0: // No defuser state = 0; @@ -707,7 +707,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp((char *) p, "rescue") == 0) { + } else if (strcmp(static_cast(p), "rescue") == 0) { switch (EnableIcon) { case 0: // Not in rescue zone state = 0; @@ -744,7 +744,7 @@ void BotClient_CS_Money(void *p, int bot_index) { if (state == 0) { state++; - bots[bot_index].bot_money = *(int *) p; // amount of money + bots[bot_index].bot_money = *static_cast(p); // amount of money } else { state = 0; // ingore this field } @@ -756,17 +756,17 @@ void BotClient_Valve_DeathMsg(void *p, int bot_index) { static int state = 0; // current state machine state static int killer_index; static int victim_index; - static edict_t *victim_edict; - static int index; if (state == 0) { state++; - killer_index = *(int *) p; // ENTINDEX() of killer + killer_index = *static_cast(p); // ENTINDEX() of killer } else if (state == 1) { state++; - victim_index = *(int *) p; // ENTINDEX() of victim + victim_index = *static_cast(p); // ENTINDEX() of victim } else if (state == 2) { - state = 0; + static int index; + static edict_t *victim_edict; + state = 0; victim_edict = INDEXENT(victim_index); @@ -776,7 +776,7 @@ void BotClient_Valve_DeathMsg(void *p, int bot_index) { if (index != -1) { if ((killer_index == 0) || (killer_index == victim_index)) { // bot killed by world (worldspawn) or bot killed self... - bots[index].killer_edict = NULL; + bots[index].killer_edict = nullptr; } else { // store edict of player that killed this bot... bots[index].killer_edict = INDEXENT(killer_index); @@ -808,17 +808,17 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { static int state = 0; // current state machine state static int duration; static int hold_time; - static int fade_flags; if (state == 0) { state++; - duration = *(int *) p; + duration = *static_cast(p); } else if (state == 1) { state++; - hold_time = *(int *) p; + hold_time = *static_cast(p); } else if (state == 2) { - state++; - fade_flags = *(int *) p; + static int fade_flags; + state++; + fade_flags = *static_cast(p); } else if (state == 6) { state = 0; @@ -891,7 +891,7 @@ void BotClient_CS_HLTV(void *p, int bot_index) { */ if (state == 0) { - players = *(int *) p; // check the byte + players = *static_cast(p); // check the byte state++; } else if (state == 1) { // I check here on purpose. Multiple HLTV messages get sent within the game, diff --git a/bot_func.cpp b/bot_func.cpp index 4bdcb82..6b87eea 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -68,7 +68,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, const Vector dest, char *checkname) { if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; - edict_t *pent = tr.pHit; // Ok now retrieve the entity + const edict_t *pent = tr.pHit; // Ok now retrieve the entity strcpy(entity_blocker, STRING(pent->v.classname)); // the classname if (strcmp(entity_blocker, checkname) == 0) @@ -93,13 +93,13 @@ bool VectorIsVisible(const Vector start, const Vector dest, char *checkname) { TraceResult tr; // trace a line from bot's eyes to destination... - UTIL_TraceLine(start, dest, dont_ignore_monsters, NULL, &tr); + UTIL_TraceLine(start, dest, dont_ignore_monsters, nullptr, &tr); // Als we geblokt worden EN we checken voor een naam if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; - edict_t *pent = tr.pHit; // Ok now retrieve the entity + const edict_t *pent = tr.pHit; // Ok now retrieve the entity strcpy(entity_blocker, STRING(pent->v.classname)); // the classname if (strcmp(entity_blocker, checkname) == 0) @@ -156,7 +156,7 @@ int FUNC_InFieldOfView(edict_t *pEntity, const Vector dest) { // 45 degrees to the right is the limit of the normal view angle // rsm - START angle bug fix - int angle = abs((int) view_angle - (int) entity_angles.y); + int angle = abs(static_cast(view_angle) - static_cast(entity_angles.y)); if (angle > 180) angle = 360 - angle; @@ -204,7 +204,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int width, int noise, int red, int green, int blue, int brightness, int speed) { - MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, visibleForWho); + MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, visibleForWho); WRITE_BYTE(TE_BEAMPOINTS); WRITE_COORD(start.x); WRITE_COORD(start.y); @@ -235,7 +235,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int */ cBot *getCloseFellowBot(cBot *pBot) { edict_t *pEdict = pBot->pEdict; - cBot *closestBot = NULL; + cBot *closestBot = nullptr; // Loop through all clients for (int i = 1; i <= gpGlobals->maxClients; i++) { @@ -249,7 +249,7 @@ cBot *getCloseFellowBot(cBot *pBot) { cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); // skip anything that is not a RealBot - if (pBotPointer == NULL) // not using FL_FAKECLIENT here so it is multi-bot compatible + if (pBotPointer == nullptr) // not using FL_FAKECLIENT here so it is multi-bot compatible continue; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < NODE_ZONE) { @@ -268,14 +268,14 @@ cBot *getCloseFellowBot(cBot *pBot) { */ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { edict_t *pEdict = pBot->pEdict; - const int FOV = 90; // TODO: use server var "default_fov" ? for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - // skip this player if not alive (i.e. dead or dying) + constexpr int FOV = 90;// TODO: use server var "default_fov" ? + // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; @@ -286,14 +286,14 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - const int distance = NODE_ZONE; + constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < FOV) { return pPlayer; } } } - return NULL; + return nullptr; } /** @@ -304,15 +304,15 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { edict_t * getEntityNearbyBotInFOV(cBot *pBot) { edict_t *pEdict = pBot->pEdict; - edict_t *pent = NULL; - while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 45)) != NULL) { + edict_t *pent = nullptr; + while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 45)) != nullptr) { if (pent == pEdict) continue; // skip self if (FInViewCone(&pent->v.origin, pEdict)) { return pent; // yes it is the case } } - return NULL; + return nullptr; } /** @@ -340,7 +340,7 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - const int distance = NODE_ZONE; + constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { return true; } @@ -409,7 +409,7 @@ bool BotShouldJump(cBot *pBot) { if (pBot->isJumping()) return false; // already jumping TraceResult tr; - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... @@ -615,8 +615,8 @@ int FUNC_BotEstimateHearVector(cBot *pBot, Vector v_sound) { // Added Stefan // 7 November 2001 int FUNC_PlayerSpeed(edict_t *edict) { - if (edict != NULL) - return (int) edict->v.velocity.Length2D(); // Return speed of any edict given + if (edict != nullptr) + return static_cast(edict->v.velocity.Length2D()); // Return speed of any edict given return 0; } @@ -743,7 +743,7 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { // Returns true/false if an entity is on a ladder bool FUNC_IsOnLadder(edict_t *pEntity) { - if (pEntity == NULL) + if (pEntity == nullptr) return false; if (pEntity->v.movetype == MOVETYPE_FLY) @@ -760,8 +760,8 @@ bool FUNC_IsOnLadder(edict_t *pEntity) { * @return */ bool isHostageFree(cBot *pBotWhoIsAsking, edict_t *pHostage) { - if (pHostage == NULL) return false; - if (pBotWhoIsAsking == NULL) return false; + if (pHostage == nullptr) return false; + if (pBotWhoIsAsking == nullptr) return false; for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); @@ -808,12 +808,12 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { edict_t *pHostage = pBot->getHostageToRescue(); - if (pHostage == NULL) { + if (pHostage == nullptr) { pHostage = pBot->findHostageToRescue(); } // still NULL - if (pHostage == NULL) { + if (pHostage == nullptr) { // Note: this means a hostage that is near and visible and rescueable etc. return; // nothing to do yet } @@ -870,7 +870,7 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { } bool isHostageRescued(cBot *pBot, edict_t *pHostage) { - if (pHostage == NULL) return false; + if (pHostage == nullptr) return false; if (FBitSet(pHostage->v.effects, EF_NODRAW)) { // pBot->rprint("isHostageRescued()", "Hostage is rescued"); @@ -881,7 +881,7 @@ bool isHostageRescued(cBot *pBot, edict_t *pHostage) { } bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { - if (pHostage == NULL) return false; + if (pHostage == nullptr) return false; // pBot->rprint("isHostageRescueable"); // Already rescued? @@ -900,7 +900,7 @@ bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { } // Already used by bot? - if (pBot != NULL) { + if (pBot != nullptr) { // rblog("isHostageRescueable - pBot is != NULL\n"); if (pBot->isUsingHostage(pHostage)) return false; // Is the hostage not used by *any other* bot? @@ -915,7 +915,7 @@ bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { } bool FUNC_EdictIsAlive(edict_t *pEdict) { - if (pEdict == NULL) return false; + if (pEdict == nullptr) return false; return pEdict->v.health > 0; } diff --git a/bot_navigate.cpp b/bot_navigate.cpp index f644f38..d8365bd 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -77,7 +77,7 @@ bool BotCanJumpUp(cBot * pBot) { // that the bot can not get onto. TraceResult tr; - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... @@ -196,7 +196,7 @@ bool BotCanDuckUnder(cBot * pBot) { // we can duck under it. TraceResult tr; - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... diff --git a/dll.cpp b/dll.cpp index b7ac175..855b9e0 100644 --- a/dll.cpp +++ b/dll.cpp @@ -65,7 +65,7 @@ DLL_GLOBAL const Vector g_vecZero = Vector(0, 0, 0); cGame Game; cNodeMachine NodeMachine; cChatEngine ChatEngine; -FILE *fpRblog = NULL; +FILE *fpRblog = nullptr; float f_load_time = 0.0; float f_minplayers_think = 0.0; // timer used to add realbots if internet play enabled @@ -81,11 +81,11 @@ int num_bots = 0; int prev_num_bots = 0; bool g_GameRules = FALSE; edict_t *clients[32]; -edict_t *pHostEdict = NULL; +edict_t *pHostEdict = nullptr; float welcome_time = 0.0; bool welcome_sent = false; -FILE *bot_cfg_fp = NULL; +FILE *bot_cfg_fp = nullptr; bool need_to_open_cfg = TRUE; float bot_cfg_pause_time = 0.0; float respawn_time = 0.0; @@ -128,14 +128,14 @@ mutil_funcs_t *gpMetaUtilFuncs; meta_globals_t *gpMetaGlobals; META_FUNCTIONS gMetaFunctionTable = { - NULL, // pfnGetEntityAPI() - NULL, // pfnGetEntityAPI_Post() + nullptr, // pfnGetEntityAPI() + nullptr, // pfnGetEntityAPI_Post() GetEntityAPI2, // pfnGetEntityAPI2() GetEntityAPI2_Post, // pfnGetEntityAPI2_Post() - NULL, // pfnGetNewDLLFunctions() - NULL, // pfnGetNewDLLFunctions_Post() + nullptr, // pfnGetNewDLLFunctions() + nullptr, // pfnGetNewDLLFunctions_Post() GetEngineFunctions, // pfnGetEngineFunctions() - NULL, // pfnGetEngineFunctions_Post() + nullptr, // pfnGetEngineFunctions_Post() }; plugin_info_t Plugin_info = { @@ -285,7 +285,7 @@ void GameDLLInit() { rblog("Initializing clients.."); for (int i = 0; i < 32; i++) - clients[i] = NULL; + clients[i] = nullptr; rblog("OK\n"); // initialize the bots array of structures... @@ -297,13 +297,13 @@ void GameDLLInit() { bool bInstalledCorrectly = false; FILE* fp = fopen("realbot/dll/realbot_mm.dll", "rb"); - if (fp != NULL) { + if (fp != nullptr) { bInstalledCorrectly = true; fclose(fp); } fp = fopen("realbot/dll/realbot_mm_i386.so", "rb"); - if (fp != NULL) { + if (fp != nullptr) { bInstalledCorrectly = true; fclose(fp); } @@ -315,10 +315,10 @@ void GameDLLInit() { // When installed correctly let the user know if (bInstalledCorrectly) - REALBOT_PRINT(NULL, "GAMEDLLINIT", + REALBOT_PRINT(nullptr, "GAMEDLLINIT", "Notice: RealBot is installed in the correct directory."); else - REALBOT_PRINT(NULL, "GAMEDLLINIT", + REALBOT_PRINT(nullptr, "GAMEDLLINIT", "WARNING: RealBot is NOT installed in the correct directory."); Game.Init(); @@ -347,13 +347,13 @@ void GameDLLInit() { // test file, if found = STEAM Linux/Win32 dedicated server fp = fopen("valve/steam.inf", "rb"); - if (fp != NULL) { + if (fp != nullptr) { fclose(fp); // test was successful, close it counterstrike = 1; // its cs 1.6 } // test file, if found = STEAM Win32 listenserver fp = fopen("FileSystem_Steam.dll", "rb"); - if (fp != NULL) { + if (fp != nullptr) { fclose(fp); // test was successful, close it counterstrike = 1; // its cs 1.6 } @@ -369,7 +369,7 @@ void GameDLLInit() { // INITIALIZATION int Spawn(edict_t *pent) { if (gpGlobals->deathmatch) { - char *pClassname = (char *) STRING(pent->v.classname); + const char *pClassname = const_cast(STRING(pent->v.classname)); if (strcmp(pClassname, "worldspawn") == 0) { // do level initialization stuff here... @@ -416,10 +416,7 @@ BOOL ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) { if (gpGlobals->deathmatch) { - int i; - int count = 0; - - // check if this client is the listen server client + // check if this client is the listen server client if (strcmp(pszAddress, "loopback") == 0) { // save the edict of the listen server client... pHostEdict = pEntity; @@ -431,7 +428,11 @@ ClientConnect(edict_t *pEntity, const char *pszName, // check if this is NOT a bot joining the server... if (strcmp(pszAddress, "127.0.0.1") != 0) { - // don't try to add bots for 60 seconds, give client time to get added + + int count = 0; + int i; + + // don't try to add bots for 60 seconds, give client time to get added bot_check_time = gpGlobals->time + 60.0; for (i = 0; i < 32; i++) { @@ -467,7 +468,7 @@ void ClientDisconnect(edict_t *pEntity) { i++; if (i < 32) - clients[i] = NULL; + clients[i] = nullptr; // when a bot... for (i = 0; i < 32; i++) { @@ -476,7 +477,7 @@ void ClientDisconnect(edict_t *pEntity) { // someone kicked this bot off of the server... bots[i].bIsUsed = false; // this slot is now free to use bots[i].fKickTime = gpGlobals->time; // save the kicked time - bots[i].pEdict = NULL; // make NULL + bots[i].pEdict = nullptr; // make NULL break; } } @@ -488,7 +489,7 @@ void ClientDisconnect(edict_t *pEntity) { void ClientPutInServer(edict_t *pEntity) { int i = 0; - while ((i < 32) && (clients[i] != NULL)) + while ((i < 32) && (clients[i] != nullptr)) i++; if (i < 32) @@ -529,12 +530,10 @@ void StartFrame() { // REALBOT_PRINT("StartFrame", "BEGIN"); edict_t *pPlayer; - static float check_server_cmd = 0.0; - static int i, index, player_index, bot_index; + static int i, player_index, bot_index; static float previous_time = -1.0; static float client_update_time = 0.0; clientdata_s cd; - char msg[256]; int count = 0; int waits = 0; // How many bots had to wait. @@ -568,10 +567,9 @@ void StartFrame() { for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) // is this slot used? { - char cmd[80]; - - if (bots[i].iTeam == kicking_team) { - sprintf(cmd, "kick \"%s\"\n", bots[i].name); + if (bots[i].iTeam == kicking_team) { + char cmd[80]; + sprintf(cmd, "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; } @@ -589,7 +587,9 @@ void StartFrame() { // with the current time. If the current time somehow was less (before) the previous time, then we // assume a reset/restart/reload of a map. if ((gpGlobals->time + 0.1) < previous_time) { - rblog("NEW MAP because time is reset #1\n"); + static int index; + static float check_server_cmd = 0.0; + rblog("NEW MAP because time is reset #1\n"); check_server_cmd = 0.0; // reset at start of map count = 0; @@ -757,7 +757,7 @@ void StartFrame() { // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free)) { // a bot - if (UTIL_GetBotPointer(pPlayer) != NULL) + if (UTIL_GetBotPointer(pPlayer) != nullptr) iBots++; else { if (pPlayer->v.flags & FL_CLIENT) @@ -782,7 +782,7 @@ void StartFrame() { else if (iTotal < min_players) { // add a bot SERVER_PRINT("RBSERVER: Too few player slots filled, adding one bot.\n"); - Game.createBot(NULL, NULL, NULL, NULL, NULL); + Game.createBot(nullptr, nullptr, nullptr, nullptr, nullptr); } } else { if (num_bots > 0) { @@ -828,7 +828,7 @@ void StartFrame() { // When timer is set, create a new bot. if (add_timer > gpGlobals->time && internet_addbot) { internet_addbot = false; - Game.createBot(NULL, NULL, NULL, NULL, NULL); + Game.createBot(nullptr, nullptr, nullptr, nullptr, nullptr); bot_check_time = gpGlobals->time + 5.0; } @@ -938,7 +938,7 @@ void StartFrame() { sprintf(c_team, "%d", bots[index].iTeam); sprintf(c_class, "%d", bots[index].bot_class); - Game.createBot(NULL, c_team, c_skill, c_class, + Game.createBot(nullptr, c_team, c_skill, c_class, bots[index].name); // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function @@ -954,7 +954,8 @@ void StartFrame() { if (g_GameRules) { if (need_to_open_cfg) // have we open bot.cfg file yet? { - char filename[256]; + char msg[256]; + char filename[256]; need_to_open_cfg = FALSE; // only do this once!!! @@ -965,7 +966,7 @@ void StartFrame() { bot_cfg_fp = fopen(filename, "r"); - if (bot_cfg_fp == NULL) + if (bot_cfg_fp == nullptr) ALERT(at_console, "bot.cfg file not found\n"); if (IS_DEDICATED_SERVER()) @@ -975,7 +976,7 @@ void StartFrame() { } if (!IS_DEDICATED_SERVER() && !spawn_time_reset) { - if (pHostEdict != NULL) { + if (pHostEdict != nullptr) { if (IsAlive(pHostEdict)) { spawn_time_reset = TRUE; @@ -1012,13 +1013,13 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { isFakeClientCommand = TRUE; - if ((arg1 == NULL) || (*arg1 == 0)) + if ((arg1 == nullptr) || (*arg1 == 0)) return; - if ((arg2 == NULL) || (*arg2 == 0)) { + if ((arg2 == nullptr) || (*arg2 == 0)) { length = sprintf(&g_argv[0], "%s", arg1); fake_arg_count = 1; - } else if ((arg3 == NULL) || (*arg3 == 0)) { + } else if ((arg3 == nullptr) || (*arg3 == 0)) { length = sprintf(&g_argv[0], "%s %s", arg1, arg2); fake_arg_count = 2; } else { @@ -1051,7 +1052,7 @@ void ProcessBotCfgFile() { if (bot_cfg_pause_time > gpGlobals->time) return; - if (bot_cfg_fp == NULL) + if (bot_cfg_fp == nullptr) return; int cmd_index = 0; @@ -1086,7 +1087,7 @@ void ProcessBotCfgFile() { if (ch == EOF) { fclose(bot_cfg_fp); - bot_cfg_fp = NULL; + bot_cfg_fp = nullptr; bot_cfg_pause_time = 0.0; } @@ -1098,8 +1099,8 @@ void ProcessBotCfgFile() { strcat(server_cmd, "\n"); cmd_index = 0; - char* cmd = cmd_line; - char* arg1 = arg2 = arg3 = arg4 = NULL; + const char* cmd = cmd_line; + const char* arg1 = arg2 = arg3 = arg4 = nullptr; // skip to blank or end of string... while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0)) @@ -1190,7 +1191,7 @@ void RealBot_ServerCommand() { SERVER_PRINT("realbot server [subcommand]\n"); SERVER_PRINT("=============================================================================\n"); } else if (FStrEq(pcmd, "chatrate")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { Game.iMaxSentences = atoi(arg1); if (Game.iMaxSentences < -1) Game.iMaxSentences = -1; @@ -1222,7 +1223,7 @@ void RealBot_ServerCommand() { sprintf(cMessage, "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { const float fVar = atof(arg1); // Only set when valid @@ -1244,7 +1245,7 @@ void RealBot_ServerCommand() { } else sprintf(cMessage, "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "max")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { max_bots = atoi(arg1); if ((max_bots < 0) || (max_bots > 31)) max_bots = -1; @@ -1261,8 +1262,8 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "important")) { // Broadcast if (FStrEq(arg1, "add")) { - if (pHostEdict != NULL) { - NodeMachine.addGoal(NULL, GOAL_IMPORTANT, pHostEdict->v.origin); + if (pHostEdict != nullptr) { + NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, pHostEdict->v.origin); sprintf(cMessage, "REALBOT: Added important area/goal."); } else sprintf(cMessage, "REALBOT: Only a listen server can execute this command!"); @@ -1284,7 +1285,7 @@ void RealBot_ServerCommand() { sprintf(cMessage, "REALBOT: Killing all bots."); end_round = true; } else if (FStrEq(pcmd, "csversion")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { const int temp = atoi(arg1); if (temp <= 0) counterstrike = 0; // cs 1.5 @@ -1307,7 +1308,7 @@ void RealBot_ServerCommand() { "REALBOT: bot-rules are set for Counter-Strike 1.6."); } } else if (FStrEq(pcmd, "internet")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { // switch on/off internet mode const int temp = atoi(arg1); @@ -1326,7 +1327,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "internet_interval")) { // 1st argument - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { // switch on/off internet mode int temp = atoi(arg1); @@ -1337,7 +1338,7 @@ void RealBot_ServerCommand() { } } // 2nd argument - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { // switch on/off internet mode int temp = atoi(arg2); @@ -1354,7 +1355,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "remove") && kick_amount_bots == 0) { // ARG1 - Amount - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { // get amount const int temp = atoi(arg1); @@ -1365,7 +1366,7 @@ void RealBot_ServerCommand() { kick_amount_bots = 0; } // ARG 2 - Team - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { // get team int team = 0; @@ -1393,16 +1394,16 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "roundlimit")) { // Check if Arguments are valid - if (((arg2 != NULL) && (*arg2 != 0)) - && ((arg1 != NULL) && (*arg1 != 0))) { + if (((arg2 != nullptr) && (*arg2 != 0)) + && ((arg1 != nullptr) && (*arg1 != 0))) { int s1 = -1, s2 = -1; // argument 1 - if ((arg1 != NULL) && (*arg1 != 0)) + if ((arg1 != nullptr) && (*arg1 != 0)) s1 = atoi(arg1); // argument 2 - if ((arg2 != NULL) && (*arg2 != 0)) + if ((arg2 != nullptr) && (*arg2 != 0)) s2 = atoi(arg2); Game.SetPlayingRounds(s1, s2); sprintf(cMessage, @@ -1415,11 +1416,11 @@ void RealBot_ServerCommand() { int s1 = -2, s2 = -2; // argument 1 - if ((arg1 != NULL) && (*arg1 != 0)) + if ((arg1 != nullptr) && (*arg1 != 0)) s1 = atoi(arg1); // argument 2 - if ((arg2 != NULL) && (*arg2 != 0)) + if ((arg2 != nullptr) && (*arg2 != 0)) s2 = atoi(arg2); // When first argument is invalid @@ -1447,7 +1448,7 @@ void RealBot_ServerCommand() { Game.iRandomMinSkill, Game.iRandomMaxSkill); } } else if (FStrEq(pcmd, "autoskill")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { const int temp = atoi(arg1); if (temp == 1) autoskill = true; @@ -1461,7 +1462,7 @@ void RealBot_ServerCommand() { else sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { const int temp = atoi(arg1); if (temp == 1) Game.iOverrideBotSkill = GAME_YES; @@ -1477,7 +1478,7 @@ void RealBot_ServerCommand() { sprintf(cMessage, "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { - if ((arg1 != NULL) && (*arg1 != 0)) { + if ((arg1 != nullptr) && (*arg1 != 0)) { const int temp = atoi(arg1); if ((temp < -1) || (temp > 10)) { sprintf(cMessage, @@ -1499,7 +1500,7 @@ void RealBot_ServerCommand() { else if (FStrEq(pcmd, "server")) { // Minimum amount of playing players... bots or not if (FStrEq(arg1, "players")) { - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { int temp = atoi(arg2); // argument if (temp > 31) temp = 31; @@ -1518,7 +1519,7 @@ void RealBot_ServerCommand() { // Broadcast what? if (FStrEq(arg2, "version")) { // How do we broadcast version message? - if ((arg3 != NULL) && (*arg3 != 0)) { + if ((arg3 != nullptr) && (*arg3 != 0)) { int temp = atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1534,7 +1535,7 @@ void RealBot_ServerCommand() { "RBSERVER: Broadcasting RealBot version every map change only.\n"); } } else if (FStrEq(arg2, "speech")) { - if (arg2 != NULL) { + if (arg2 != nullptr) { if (atoi(arg2) == 1) Game.bSpeechBroadcasting = true; else @@ -1548,7 +1549,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(arg2, "kills")) { // How do we broadcast kills by bots? - if ((arg3 != NULL) && (*arg3 != 0)) { + if ((arg3 != nullptr) && (*arg3 != 0)) { int temp = atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1583,7 +1584,7 @@ void RealBot_ServerCommand() { } } else if (FStrEq(arg2, "deaths")) { // How do we broadcast deaths by bots. - if ((arg3 != NULL) && (*arg3 != 0)) { + if ((arg3 != nullptr) && (*arg3 != 0)) { int temp = atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1629,7 +1630,7 @@ void RealBot_ServerCommand() { else if (FStrEq(pcmd, "nodes")) { int iOnNode = -1; - if (pHostEdict != NULL) { + if (pHostEdict != nullptr) { iOnNode = NodeMachine.getClosestNode(pHostEdict->v.origin, 35, pHostEdict); } @@ -1639,7 +1640,7 @@ void RealBot_ServerCommand() { bool bValidArg = false; // check for valid argument - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { const int iTo = atoi(arg2); // add connection TO // Add this connection @@ -1667,7 +1668,7 @@ void RealBot_ServerCommand() { bool bValidArg = false; // check for valid argument - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { const int iTo = atoi(arg2); // remove connection TO // remove this connection @@ -1777,7 +1778,7 @@ void RealBot_ServerCommand() { // Don't care whether we are close to a node... if (FStrEq(arg1, "connect")) { // check for valid argument - if ((arg2 != NULL) && (*arg2 != 0) && (arg3 != NULL) + if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) && (*arg3 != 0)) { const int Node1 = atoi(arg2); // add connection TO const int Node2 = atoi(arg3); // add connection TO @@ -1794,7 +1795,7 @@ void RealBot_ServerCommand() { "NODES EDITOR: this command requires TWO numeric arguments!"); } else if (FStrEq(arg1, "disconnect")) { // check for valid argument - if ((arg2 != NULL) && (*arg2 != 0) && (arg3 != NULL) + if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) && (*arg3 != 0)) { const int Node1 = atoi(arg2); const int Node2 = atoi(arg3); @@ -1819,7 +1820,7 @@ void RealBot_ServerCommand() { // Arg 1 is command: if (FStrEq(arg1, "dontshoot")) { // realbot debug dontshoot [1/0] // check for valid argument - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { const int temp = atoi(arg2); if (temp) Game.bDoNotShoot = true; @@ -1834,7 +1835,7 @@ void RealBot_ServerCommand() { } // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { const int temp = atoi(arg2); if (temp) Game.bPistols = true; @@ -1865,7 +1866,7 @@ void RealBot_ServerCommand() { Game.bDebug = -2; sprintf(cMessage, "RBDEBUG: Debug messages off."); } else { - if ((arg2 != NULL) && (*arg2 != 0)) { + if ((arg2 != nullptr) && (*arg2 != 0)) { const int temp = atoi(arg2); Game.bDebug = temp; sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); @@ -1902,9 +1903,9 @@ void RealBot_ServerCommand() { sprintf(cMessage, "RBDEBUG: Drawing nodes - disabled."); } else if (FStrEq(arg2, "path")) { int iFrom = -1, iTo = -1; - if ((arg3 != NULL) && (*arg3 != 0)) + if ((arg3 != nullptr) && (*arg3 != 0)) iFrom = atoi(arg3); - if ((arg4 != NULL) && (*arg4 != 0)) + if ((arg4 != nullptr) && (*arg4 != 0)) iTo = atoi(arg4); if (iFrom > -1) { @@ -1914,12 +1915,12 @@ void RealBot_ServerCommand() { } sprintf(cMessage, "RBDEBUG: Creating path from [%d] to [%d].", iFrom, iTo); - NodeMachine.createPath(iFrom, iTo, 0, NULL, PATH_DANGER); + NodeMachine.createPath(iFrom, iTo, 0, nullptr, PATH_DANGER); } else { sprintf(cMessage, "RBDEBUG: Usage: realbot debug nodes path "); } } else if (FStrEq(arg2, "drawpath")) { - if ((arg3 != NULL) && (*arg3 != 0)) + if ((arg3 != nullptr) && (*arg3 != 0)) draw_nodepath = atoi(arg3); if (draw_nodepath > -1) { sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); diff --git a/engine.cpp b/engine.cpp index 50a2729..1d04ce0 100644 --- a/engine.cpp +++ b/engine.cpp @@ -60,9 +60,9 @@ bool radio_message_from = false; bool show_beginmessage = true; // End Ditlew's Radio -void (*botMsgFunction)(void *, int) = NULL; +void (*botMsgFunction)(void *, int) = nullptr; -void (*botMsgEndFunction)(void *, int) = NULL; +void (*botMsgEndFunction)(void *, int) = nullptr; int botMsgIndex; @@ -152,113 +152,113 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict if (gpGlobals->deathmatch) { // Fix this up for CS 1.6 weaponlists // 01/07/04 - Stefan - Thanks to Whistler for pointing this out! - if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", NULL)) + if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) botMsgFunction = BotClient_CS_WeaponList; if (edict) { - int index = UTIL_GetBotIndex(edict); + const int index = UTIL_GetBotIndex(edict); // is this message for a bot? if (index != -1) { - botMsgFunction = NULL; // no msg function until known otherwise - botMsgEndFunction = NULL; // no msg end function until known otherwise + botMsgFunction = nullptr; // no msg function until known otherwise + botMsgEndFunction = nullptr; // no msg end function until known otherwise botMsgIndex = index; // index of bot receiving message if (mod_id == VALVE_DLL) { - if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", NULL)) + if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) botMsgFunction = BotClient_Valve_WeaponList; else if (msg_type == - GET_USER_MSG_ID(PLID, "CurWeapon", NULL)) + GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) botMsgFunction = BotClient_Valve_CurrentWeapon; - else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", nullptr)) botMsgFunction = BotClient_Valve_AmmoX; else if (msg_type == - GET_USER_MSG_ID(PLID, "AmmoPickup", NULL)) + GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) botMsgFunction = BotClient_Valve_AmmoPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeapPickup", NULL)) + GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) botMsgFunction = BotClient_Valve_WeaponPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "ItemPickup", NULL)) + GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) botMsgFunction = BotClient_Valve_ItemPickup; - else if (msg_type == GET_USER_MSG_ID(PLID, "Health", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "Health", nullptr)) botMsgFunction = BotClient_Valve_Health; - else if (msg_type == GET_USER_MSG_ID(PLID, "Battery", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "Battery", nullptr)) botMsgFunction = BotClient_Valve_Battery; else if (msg_type == - GET_USER_MSG_ID(PLID, "DeathMsg", NULL)) + GET_USER_MSG_ID(PLID, "DeathMsg", nullptr)) botMsgFunction = BotClient_Valve_Damage; else if (msg_type == - GET_USER_MSG_ID(PLID, "ScreenFade", NULL)) + GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) botMsgFunction = BotClient_Valve_ScreenFade; } else if (mod_id == CSTRIKE_DLL) { - if (msg_type == GET_USER_MSG_ID(PLID, "VGUIMenu", NULL)) + if (msg_type == GET_USER_MSG_ID(PLID, "VGUIMenu", nullptr)) botMsgFunction = BotClient_CS_VGUI; else if (msg_type == - GET_USER_MSG_ID(PLID, "ShowMenu", NULL)) + GET_USER_MSG_ID(PLID, "ShowMenu", nullptr)) botMsgFunction = BotClient_CS_ShowMenu; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeaponList", NULL)) { + GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) { botMsgFunction = BotClient_CS_WeaponList; //DebugOut("BUGBUG: WEAPONLIST FUNCTION CALLED\n"); } else if (msg_type == - GET_USER_MSG_ID(PLID, "CurWeapon", NULL)) + GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) botMsgFunction = BotClient_CS_CurrentWeapon; - else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", nullptr)) botMsgFunction = BotClient_CS_AmmoX; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeapPickup", NULL)) + GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) botMsgFunction = BotClient_CS_WeaponPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "AmmoPickup", NULL)) + GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) botMsgFunction = BotClient_CS_AmmoPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "ItemPickup", NULL)) + GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) botMsgFunction = BotClient_CS_ItemPickup; - else if (msg_type == GET_USER_MSG_ID(PLID, "Health", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "Health", nullptr)) botMsgFunction = BotClient_CS_Health; - else if (msg_type == GET_USER_MSG_ID(PLID, "Battery", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "Battery", nullptr)) botMsgFunction = BotClient_CS_Battery; - else if (msg_type == GET_USER_MSG_ID(PLID, "Damage", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "Damage", nullptr)) botMsgFunction = BotClient_CS_Damage; else if (msg_type == - GET_USER_MSG_ID(PLID, "StatusIcon", NULL)) { - BotClient_CS_StatusIcon(0, -1); // clear state -- redo this -- BERKED + GET_USER_MSG_ID(PLID, "StatusIcon", nullptr)) { + BotClient_CS_StatusIcon(nullptr, -1); // clear state -- redo this -- BERKED botMsgFunction = BotClient_CS_StatusIcon; } - if (msg_type == GET_USER_MSG_ID(PLID, "SayText", NULL)) { + if (msg_type == GET_USER_MSG_ID(PLID, "SayText", nullptr)) { botMsgFunction = BotClient_CS_SayText; - } else if (msg_type == GET_USER_MSG_ID(PLID, "Money", NULL)) + } else if (msg_type == GET_USER_MSG_ID(PLID, "Money", nullptr)) botMsgFunction = BotClient_CS_Money; else if (msg_type == - GET_USER_MSG_ID(PLID, "ScreenFade", NULL)) + GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) botMsgFunction = BotClient_CS_ScreenFade; } } } else if (msg_dest == MSG_ALL) { - botMsgFunction = NULL; // no msg function until known otherwise + botMsgFunction = nullptr; // no msg function until known otherwise botMsgIndex = -1; // index of bot receiving message (none) if (mod_id == VALVE_DLL) { - if (msg_type == GET_USER_MSG_ID(PLID, "DeathMsg", NULL)) + if (msg_type == GET_USER_MSG_ID(PLID, "DeathMsg", nullptr)) botMsgFunction = BotClient_Valve_DeathMsg; } else if (mod_id == CSTRIKE_DLL) { - if (msg_type == GET_USER_MSG_ID(PLID, "DeathMsg", NULL)) + if (msg_type == GET_USER_MSG_ID(PLID, "DeathMsg", nullptr)) botMsgFunction = BotClient_CS_DeathMsg; - else if (msg_type == GET_USER_MSG_ID(PLID, "SayText", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "SayText", nullptr)) botMsgFunction = BotClient_CS_SayText; } } // STEFAN else if (msg_dest == MSG_SPEC) { - botMsgFunction = NULL; // no msg function until known otherwise + botMsgFunction = nullptr; // no msg function until known otherwise botMsgIndex = -1; // index of bot receiving message (none) if (mod_id == CSTRIKE_DLL) { - if (msg_type == GET_USER_MSG_ID(PLID, "HLTV", NULL)) { + if (msg_type == GET_USER_MSG_ID(PLID, "HLTV", nullptr)) { botMsgFunction = BotClient_CS_HLTV; } - else if (msg_type == GET_USER_MSG_ID(PLID, "SayText", NULL)) + else if (msg_type == GET_USER_MSG_ID(PLID, "SayText", nullptr)) botMsgFunction = BotClient_CS_SayText; } @@ -272,11 +272,11 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict void pfnMessageEnd() { if (gpGlobals->deathmatch) { if (botMsgEndFunction) - (*botMsgEndFunction)(NULL, botMsgIndex); // NULL indicated msg end + (*botMsgEndFunction)(nullptr, botMsgIndex); // NULL indicated msg end // clear out the bot message function pointers... - botMsgFunction = NULL; - botMsgEndFunction = NULL; + botMsgFunction = nullptr; + botMsgEndFunction = nullptr; } if (Game.bEngineDebug) @@ -289,7 +289,7 @@ void pfnWriteByte(int iValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &iValue, botMsgIndex); + (*botMsgFunction)(static_cast(&iValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -305,7 +305,7 @@ void pfnWriteChar(int iValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &iValue, botMsgIndex); + (*botMsgFunction)(static_cast(&iValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -320,7 +320,7 @@ void pfnWriteShort(int iValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &iValue, botMsgIndex); + (*botMsgFunction)(static_cast(&iValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -336,7 +336,7 @@ void pfnWriteLong(int iValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &iValue, botMsgIndex); + (*botMsgFunction)(static_cast(&iValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -353,7 +353,7 @@ void pfnWriteAngle(float flValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &flValue, botMsgIndex); + (*botMsgFunction)(static_cast(&flValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -370,7 +370,7 @@ void pfnWriteCoord(float flValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &flValue, botMsgIndex); + (*botMsgFunction)(static_cast(&flValue), botMsgIndex); } if (Game.bEngineDebug) { @@ -392,7 +392,7 @@ void pfnWriteString(const char *sz) { if (gpGlobals->deathmatch) { // Ditlew's Radio - if ((strstr(sz, "(RADIO):") != NULL) && !radio_message) { + if ((strstr(sz, "(RADIO):") != nullptr) && !radio_message) { // We found an old radio message, we should convert the strings... radio_message = true; // we found a radio message @@ -403,22 +403,22 @@ void pfnWriteString(const char *sz) { // Now search for any compatible radio command (old string). // if found then convert the message in the new way so the code // thinks its CS 1.1 and thus every version lower then CS 1.1 should work too... - if ((strstr(sz, "Follow Me") != NULL)) { + if ((strstr(sz, "Follow Me") != nullptr)) { // convert string strcpy(message, "#Follow me"); - } else if ((strstr(sz, "You Take the Point") != NULL)) { + } else if ((strstr(sz, "You Take the Point") != nullptr)) { // convert string strcpy(message, "#You_take_the_point"); - } else if ((strstr(sz, "Need backup") != NULL)) { + } else if ((strstr(sz, "Need backup") != nullptr)) { // convert string strcpy(message, "#Need_backup"); - } else if ((strstr(sz, "Taking Fire.. Need Assistance!") != NULL)) { + } else if ((strstr(sz, "Taking Fire.. Need Assistance!") != nullptr)) { // convert string strcpy(message, "#Taking_fire"); - } else if ((strstr(sz, "Team, fall back!") != NULL)) { + } else if ((strstr(sz, "Team, fall back!") != nullptr)) { // convert string strcpy(message, "#Team_fall_back"); - } else if ((strstr(sz, "Go go go") != NULL)) { + } else if ((strstr(sz, "Go go go") != nullptr)) { // convert string strcpy(message, "#Go_go_go"); } @@ -528,7 +528,7 @@ void pfnWriteEntity(int iValue) { if (gpGlobals->deathmatch) { // if this message is for a bot, call the client message function... if (botMsgFunction) - (*botMsgFunction)((void *) &iValue, botMsgIndex); + (*botMsgFunction)(static_cast(&iValue), botMsgIndex); } RETURN_META(MRES_IGNORED); @@ -574,7 +574,7 @@ void pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed) { // Set client max speed (CS / All mods) // Check if edict_t is a bot, then set maxspeed - cBot *pPlayerBot = NULL; + cBot *pPlayerBot = nullptr; int index; for (index = 0; index < 32; index++) { diff --git a/game.cpp b/game.cpp index 4180d67..9e48265 100644 --- a/game.cpp +++ b/game.cpp @@ -163,10 +163,10 @@ char *cGame::RandomSentence() { void cGame::DetermineMapGoal() const { rblog("DetermineMapGoal called\n"); - edict_t *pEnt = NULL; + edict_t *pEnt = nullptr; int hostagesFound = 0; - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "hostage_entity")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "hostage_entity")) != nullptr) { hostagesFound++; } @@ -178,12 +178,12 @@ void cGame::DetermineMapGoal() const int rescueZonesFound = 0; // GOAL #3 - Hostage rescue zone - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "func_hostage_rescue")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "func_hostage_rescue")) != nullptr) { rescueZonesFound++; } // rescue zone can also be an entity of info_hostage_rescue - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_hostage_rescue")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_hostage_rescue")) != nullptr) { rescueZonesFound++; } @@ -196,11 +196,11 @@ void cGame::DetermineMapGoal() const int bombSpots = 0; // GOAL #4 - Bombspot zone // Bomb spot - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "func_bomb_target")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "func_bomb_target")) != nullptr) { bombSpots++; } - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_bomb_target")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_bomb_target")) != nullptr) { bombSpots++; } memset(msg, 0, sizeof(msg)); @@ -288,13 +288,13 @@ void cGame::LoadCFG() { // NOTE: This function is just a copy/paste stuff from Botmans template, nothing more, nothing less // TODO: Rewrite this, can be done much cleaner. void cGame::LoadNames() { - char name_buffer[80]; char filename[256]; UTIL_BuildFileNameRB("rb_names.txt", filename); FILE* bot_name_fp = fopen(filename, "r"); - if (bot_name_fp != NULL) { - while ((iAmountNames < MAX_BOT_NAMES) && - (fgets(name_buffer, 80, bot_name_fp) != NULL)) { + if (bot_name_fp != nullptr) { + char name_buffer[80]; + while ((iAmountNames < MAX_BOT_NAMES) && + (fgets(name_buffer, 80, bot_name_fp) != nullptr)) { int length = strlen(name_buffer); if (name_buffer[length - 1] == '\n') { name_buffer[length - 1] = 0; // remove '\n' @@ -398,7 +398,7 @@ void cGame::LoadBuyTable() { // GAME: Update global vars (called by StartFrame) void cGame::UpdateGameStatus() { - edict_t* pEnt = NULL; + edict_t* pEnt = nullptr; // ------------------ // Update: Dropped C4 @@ -407,7 +407,7 @@ void cGame::UpdateGameStatus() { vDroppedC4 = Vector(9999, 9999, 9999); // Find the dropped bomb - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "weaponbox")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "weaponbox")) != nullptr) { // when DROPPED C4 if ((FStrEq(STRING(pEnt->v.model), "models/w_backpack.mdl"))) { vDroppedC4 = pEnt->v.origin; // this is the origin. @@ -419,10 +419,10 @@ void cGame::UpdateGameStatus() { // Update: Is the bomb planted? // ------------------ // Same as dropped c4, its NOT, unless stated otherwise. - pEnt = NULL; + pEnt = nullptr; bool bPlanted = bBombPlanted; - while ((pEnt = UTIL_FindEntityByClassname(pEnt, "grenade")) != NULL) { + while ((pEnt = UTIL_FindEntityByClassname(pEnt, "grenade")) != nullptr) { if (UTIL_GetGrenadeType(pEnt) == 4) { bPlanted = true; // Found planted bomb! break; @@ -481,7 +481,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg char botName[BOT_NAME_LEN + 1]; memset(botName, 0, sizeof(botName)); // if name given, use that - if ((nameArg != NULL) && (*nameArg != 0)) { + if ((nameArg != nullptr) && (*nameArg != 0)) { strncpy(botName, nameArg, BOT_NAME_LEN - 1); botName[BOT_NAME_LEN] = 0; // make sure botName is null terminated } else { // else pick random one or fallback to default "RealBot" @@ -508,7 +508,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg int botSkill = -2; // -2, not valid // Skill argument provided - if ((skillArg != NULL) && (*skillArg != 0)) { + if ((skillArg != nullptr) && (*skillArg != 0)) { botSkill = atoi(skillArg); // set to given skill } @@ -525,7 +525,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // CREATE fake client! edict_t *pBotEdict = (*g_engfuncs.pfnCreateFakeClient)(botName); if (FNullEnt(pBotEdict)) { - REALBOT_PRINT(NULL, "cGame::CreateBot", "Cannot create bot, server is full"); + REALBOT_PRINT(nullptr, "cGame::CreateBot", "Cannot create bot, server is full"); return GAME_MSG_FAIL_SERVERFULL; // failed } @@ -544,16 +544,16 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // (from LINK_ENTITY_TO_CLASS for player object) // FIX: Free data for bot, so we can fill in new - if (pBotEdict->pvPrivateData != NULL) + if (pBotEdict->pvPrivateData != nullptr) FREE_PRIVATE(pBotEdict); - pBotEdict->pvPrivateData = NULL; + pBotEdict->pvPrivateData = nullptr; pBotEdict->v.frags = 0; // END OF FIX: --- score resetted CALL_GAME_ENTITY(PLID, "player", VARS(pBotEdict)); char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pBotEdict); - int clientIndex = ENTINDEX(pBotEdict); + const int clientIndex = ENTINDEX(pBotEdict); (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, "model", ""); (*g_engfuncs.pfnSetClientKeyValue)(clientIndex, infobuffer, "rate", "3500.000000"); @@ -639,11 +639,11 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg pBot->ipBuyArmour = 0; // here we set team - if ((teamArg != NULL) && (teamArg[0] != 0)) { + if ((teamArg != nullptr) && (teamArg[0] != 0)) { pBot->iTeam = atoi(teamArg); // and class - if ((modelArg != NULL) && (modelArg[0] != 0)) { + if ((modelArg != nullptr) && (modelArg[0] != 0)) { pBot->bot_class = atoi(modelArg); } } @@ -660,7 +660,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // Debug message (without BOT) void REALBOT_PRINT(const char *Function, const char *msg) { - REALBOT_PRINT(NULL, Function, msg); + REALBOT_PRINT(nullptr, Function, msg); } // Debug message @@ -705,7 +705,7 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { const float roundTimeInSeconds = roundTimeInMinutes * 60; const float roundTimeRemaining = roundTimeInSeconds - roundElapsedTimeInSeconds; const int minutesLeft = roundTimeRemaining / 60; - const int secondsLeft = (int)roundTimeRemaining % 60; + const int secondsLeft = static_cast(roundTimeRemaining) % 60; sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); diff --git a/util.cpp b/util.cpp index 1bb8af4..35c6ccd 100644 --- a/util.cpp +++ b/util.cpp @@ -112,7 +112,7 @@ edict_t *UTIL_FindEntityInSphere(edict_t *pentStart, if (!FNullEnt(pentEntity)) return pentEntity; - return NULL; + return nullptr; } edict_t *UTIL_FindEntityByString(edict_t *pentStart, @@ -122,7 +122,7 @@ edict_t *UTIL_FindEntityByString(edict_t *pentStart, if (!FNullEnt(pentEntity)) return pentEntity; - return NULL; + return nullptr; } edict_t *UTIL_FindEntityByClassname(edict_t *pentStart, @@ -153,7 +153,7 @@ void ClientPrint(edict_t *pEntity, int msg_dest, const char *msg_name) { if (gmsgTextMsg == 0) gmsgTextMsg = REG_USER_MSG("TextMsg", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgTextMsg, NULL, pEntity); + MESSAGE_BEGIN(MSG_ONE, gmsgTextMsg, nullptr, pEntity); WRITE_BYTE(msg_dest); WRITE_STRING(msg_name); @@ -187,7 +187,7 @@ void UTIL_SayText(const char *pText, edict_t *pEdict) { if (gmsgSayText == 0) gmsgSayText = REG_USER_MSG("SayText", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pEdict); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEdict); WRITE_BYTE(ENTINDEX(pEdict)); //if (mod_id == FRONTLINE_DLL) // WRITE_SHORT(0); @@ -200,14 +200,14 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { char *pc; // make sure the text has content - for (pc = message; pc != NULL && *pc != 0; pc++) { + for (pc = message; pc != nullptr && *pc != 0; pc++) { if (isprint(*pc) && !isspace(*pc)) { - pc = NULL; // we've found an alphanumeric character, so text is valid + pc = nullptr; // we've found an alphanumeric character, so text is valid break; } } - if (pc != NULL) + if (pc != nullptr) return; // no character found, so say nothing // turn on color set 2 (color on, no sound) @@ -216,8 +216,8 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { else sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); - int j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator - if ((int) strlen(message) > j) + const int j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator + if (static_cast(strlen(message)) > j) message[j] = 0; strcat(text, message); @@ -231,20 +231,20 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { if (gmsgSayText == 0) gmsgSayText = REG_USER_MSG("SayText", -1); - int sender_team = UTIL_GetTeam(pEntity); + const int sender_team = UTIL_GetTeam(pEntity); - edict_t* client = NULL; - while (((client = UTIL_FindEntityByClassname(client, "player")) != NULL) + edict_t* client = nullptr; + while (((client = UTIL_FindEntityByClassname(client, "player")) != nullptr) && (!FNullEnt(client))) { if (client == pEntity) // skip sender of message continue; - int player_team = UTIL_GetTeam(client); + const int player_team = UTIL_GetTeam(client); if (teamonly && (sender_team != player_team)) continue; - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, client); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, client); WRITE_BYTE(ENTINDEX(pEntity)); //if (mod_id == FRONTLINE_DLL) // WRITE_SHORT(0); @@ -253,7 +253,7 @@ void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { } // print to the sending client - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pEntity); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEntity); WRITE_BYTE(ENTINDEX(pEntity)); //if (mod_id == FRONTLINE_DLL) // WRITE_SHORT(0); @@ -361,12 +361,12 @@ cBot *UTIL_GetBotPointer(edict_t *pEdict) { } } - return NULL; // return NULL if edict is not a bot + return nullptr; // return NULL if edict is not a bot } bool IsAlive(edict_t *pEdict) { // FIX: Make sure the edict is valid and such, else return false: - return ((pEdict != NULL) && // VALID + return ((pEdict != nullptr) && // VALID (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD (pEdict->v.health > 0) && // ENOUGHT HEALTH !(pEdict->v.flags & FL_NOTARGET) && // ? @@ -379,7 +379,7 @@ bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { Vector2D vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); vec2LOS = vec2LOS.Normalize(); - float flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); + const float flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); if (flDot > 0.50) // 60 degree field of view { @@ -394,7 +394,7 @@ bool FVisible(const Vector &vecOrigin, edict_t *pEdict) { TraceResult tr; // look through caller's eyes - Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; + const Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; const int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); const int bLookerInWater = @@ -420,7 +420,7 @@ Vector GetGunPosition(edict_t *pEdict) { void UTIL_SelectItem(edict_t *pEdict, char *item_name) { /*BotDebug( item_name); */ - FakeClientCommand(pEdict, item_name, NULL, NULL); + FakeClientCommand(pEdict, item_name, nullptr, nullptr); } Vector VecBModelOrigin(edict_t *pEdict) { @@ -433,7 +433,7 @@ UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, if (gmsgShowMenu == 0) gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, NULL, pEdict); + MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, nullptr, pEdict); WRITE_SHORT(slots); WRITE_CHAR(displaytime); @@ -783,8 +783,8 @@ char *UTIL_GiveWeaponName(int id) { void UTIL_BotSprayLogo(edict_t *pEntity, char *logo_name) { TraceResult pTrace; UTIL_MakeVectors(pEntity->v.v_angle); - Vector v_src = pEntity->v.origin + pEntity->v.view_ofs; - Vector v_dest = v_src + gpGlobals->v_forward * 80; + const Vector v_src = pEntity->v.origin + pEntity->v.view_ofs; + const Vector v_dest = v_src + gpGlobals->v_forward * 80; UTIL_TraceLine(v_src, v_dest, ignore_monsters, pEntity->v.pContainingEntity, &pTrace); @@ -879,17 +879,17 @@ int UTIL_GetGrenadeType(edict_t *pEntity) { // 2 functions from podbot source unsigned short FixedUnsigned16(float value, float scale) { - int output = (int)value * scale; + int output = static_cast(value) * scale; if (output < 0) output = 0; if (output > 0xFFFF) output = 0xFFFF; - return (unsigned short) output; + return static_cast(output); } short FixedSigned16(float value, float scale) { - int output = (int)value * scale; + int output = static_cast(value) * scale; if (output > 32767) output = 32767; @@ -897,14 +897,14 @@ short FixedSigned16(float value, float scale) { if (output < -32768) output = -32768; - return (short) output; + return static_cast(output); } // Using POD/SDK source to print nice messages on the client machine void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { // FROM PODBOT SOURCE // Hacked together Version of HUD_DrawString - MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, edict); + MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); WRITE_BYTE(TE_TEXTMESSAGE); WRITE_BYTE(1); WRITE_SHORT(FixedSigned16(-1, 1 << 13)); @@ -922,7 +922,7 @@ void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { WRITE_SHORT(FixedUnsigned16(2, 1 << 8)); WRITE_SHORT(FixedUnsigned16(6, 1 << 8)); WRITE_SHORT(FixedUnsigned16(0.1, 1 << 8)); - WRITE_STRING((const char *) &msg[0]); + WRITE_STRING(static_cast(&msg[0])); MESSAGE_END(); } @@ -966,7 +966,7 @@ void UTIL_SayTextBot(const char *pText, cBot *pBot) { if (pPlayer) if (IsAlive(pPlayer)) // alive { - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pPlayer); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); sprintf(&szTemp[1], "%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); @@ -979,7 +979,7 @@ void UTIL_SayTextBot(const char *pText, cBot *pBot) { edict_t *pPlayer = INDEXENT(i); if (pPlayer) if (!IsAlive(pPlayer)) { - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pPlayer); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); From f218dcc28b9ae1105e6ae5f88be8338a0bbd9be3 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 18 Dec 2021 17:05:46 +0000 Subject: [PATCH 019/114] Version Updated --- build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cpp b/build.cpp index 2cfe18e..8273554 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -char *rb_version_nr = "4.0.1"; +char *rb_version_nr = "4.0.2-APG"; From 9d5807d8889b5618680b02221b05c3612bde1a92 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 18 Dec 2021 17:15:21 +0000 Subject: [PATCH 020/114] Non-static members initialised --- NodeMachine.cpp | 4 ++-- NodeMachine.h | 20 ++++++++++---------- game.h | 14 +++++++------- realbot_mm.vcxproj | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index ded5a55..c7ee35e 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2237,7 +2237,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn bool pathFound = false; // is it still valid to loop through the lists for pathfinding? - int nodesEvaluated = 0; + int nodesEvaluated = 0; //Not used? [APG]RoboCop[CL] // INIT: End // PATHFINDER: Start while (!pathFound) { @@ -2745,7 +2745,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } // Near Node - bool bNearNode = false; + bool bNearNode = false; //Variable Reassigned [APG]RoboCop[CL] if (pBot->isOnLadder()) { pBot->rprint("Bot is on ladder"); // Set touch radius diff --git a/NodeMachine.h b/NodeMachine.h index fbe2a15..69211bc 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -176,19 +176,19 @@ class cNodeMachine { tGoal *getGoal(int index); private: - tNode Nodes[MAX_NODES]; // Nodes - tInfoNode InfoNodes[MAX_NODES]; // Info for Nodes (metadata) - tPlayer Players[32]; // Players to keep track of, for node plotting - tGoal Goals[MAX_GOALS]; // Goals to pursue in the game - tMeredian Meredians[MAX_MEREDIANS][MAX_MEREDIANS]; // Meredian lookup search for Nodes, squared + tNode Nodes[MAX_NODES] = {}; // Nodes + tInfoNode InfoNodes[MAX_NODES] = {}; // Info for Nodes (metadata) + tPlayer Players[32] = {}; // Players to keep track of, for node plotting + tGoal Goals[MAX_GOALS] = {}; // Goals to pursue in the game + tMeredian Meredians[MAX_MEREDIANS][MAX_MEREDIANS] = {}; // Meredian lookup search for Nodes, squared - int iPath[MAX_BOTS][MAX_PATH_NODES]; // 32 bots, with max waypoints paths (TODO: move to bot class?) + int iPath[MAX_BOTS][MAX_PATH_NODES] = {}; // 32 bots, with max waypoints paths (TODO: move to bot class?) - int iMaxUsedNodes; + int iMaxUsedNodes = 0; - byte iVisChecked[MAX_NODES]; - unsigned char *cVisTable; - tTrouble Troubles[MAX_TROUBLE]; + byte iVisChecked[MAX_NODES] = {}; + unsigned char * cVisTable = nullptr; + tTrouble Troubles[MAX_TROUBLE] = {}; void FindMinMax() const; diff --git a/game.h b/game.h index 6c47021..74248c6 100644 --- a/game.h +++ b/game.h @@ -139,13 +139,13 @@ class cGame { private: // --------------------- // private variables - char cSpeechSentences[16][80]; - int iAmountNames; - char cBotNames[MAX_BOT_NAMES][BOT_NAME_LEN + 1]; - int iMinPlayRounds, iMaxPlayRounds; // Min/Max playable rounds - bool bNewRound; // New round triggered? - float fRoundTime; // Round time - float fUpdateGoalTimer; + char cSpeechSentences[16][80] = {}; + int iAmountNames = 0; + char cBotNames[MAX_BOT_NAMES][BOT_NAME_LEN + 1] = {}; + int iMinPlayRounds = 0, iMaxPlayRounds = 0; // Min/Max playable rounds + bool bNewRound = false; // New round triggered? + float fRoundTime = 0; // Round time + float fUpdateGoalTimer = 0; }; #endif // GAME_H \ No newline at end of file diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index f97f3c2..577e905 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -51,7 +51,7 @@ MaxSpeed OnlyExplicitInline .\dependencies\hlsdk\dlls;.\dependencies\hlsdk\common;.\dependencies\hlsdk\pm_shared;.\dependencies\hlsdk\engine;.\dependencies\hlsdk\public;.\dependencies\metamod-hl1\metamod;%(AdditionalIncludeDirectories) - NDEBUG;WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + NDEBUG;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreaded true From 15fa328fc919f25a76c4db947dc0a220950cda99 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 18 Dec 2021 18:19:41 +0000 Subject: [PATCH 021/114] Performance enhancements --- Makefile | 3 ++- NodeMachine.cpp | 28 ++++++++++++++-------------- NodeMachine.h | 20 ++++++++++---------- bot.cpp | 8 ++++---- bot.h | 6 +++--- bot_func.cpp | 14 +++++++------- bot_func.h | 16 ++++++++-------- 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 386def3..3c1568c 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ HLSDK_DIR = ./dependencies/hlsdk BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe \ - -Wno-write-strings -I"${META_DIR}" -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" \ + -Wno-write-strings -Wno-attributes -std=gnu++14 -static-libstdc++ -shared-libgcc \ + -I"${META_DIR}" -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" \ -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" OBJ = NodeMachine.o \ diff --git a/NodeMachine.cpp b/NodeMachine.cpp index c7ee35e..7cbae86 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -375,7 +375,7 @@ Vector cNodeMachine::node_vector(int iNode) const } // Input: Vector, Output X and Y Meredians -void cNodeMachine::VectorToMeredian(const Vector vOrigin, int *iX, int *iY) { +void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) { // Called for lookupt and for storing float iCoordX = vOrigin.x + 8192.0; // map height (converts from - to +) float iCoordY = vOrigin.y + 8192.0; // map width (converts from - to +) @@ -403,7 +403,7 @@ void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { } // Does the node float? -bool cNodeMachine::node_float(const Vector vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); @@ -435,7 +435,7 @@ bool cNodeMachine::node_float(const Vector vOrigin, edict_t *pEdict) { } // Does the node stand on a crate? or a steep slope? -bool cNodeMachine::node_on_crate(const Vector vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); @@ -472,7 +472,7 @@ bool cNodeMachine::node_on_crate(const Vector vOrigin, edict_t *pEdict) { * @param pEdict * @return */ -int cNodeMachine::getClosestNode(const Vector vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) { // REDO: Need faster method to find a node // TOADD: For secure results all nodes should be checked to figure out the real // 'closest' node. @@ -542,7 +542,7 @@ int cNodeMachine::getClosestNode(const Vector vOrigin, float fDist, edict_t *pEd * @param pEdict * @return */ -int cNodeMachine::getFurthestNode(const Vector vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) { // Use Meredians to search for nodes // TODO: we should take care in the situation where we're at the 'edge' of such a meridian (subspace). So we should // basicly take edging meridians as well when too close to the edge. @@ -700,7 +700,7 @@ int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) { } // Compute the horizontal distance between A and B (ignoring z coordinate) -static float horizontal_distance(const Vector a, const Vector b) { +static float horizontal_distance(const Vector& a, const Vector& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } @@ -708,7 +708,7 @@ static float horizontal_distance(const Vector a, const Vector b) { // Return the floor below V // TO BE IMPROVED use pEntityCOntaining -static Vector FloorBelow(const Vector V) { +static Vector FloorBelow(const Vector& V) { static TraceResult tr; // Keep it available even outside of the call // First use this hull @@ -878,7 +878,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const } // Adding a node: another way... -int cNodeMachine::add2(const Vector vOrigin, int iType, edict_t *pEntity) { +int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { // Do not add a node when there is already one close if (getClosestNode(vOrigin, NODE_ZONE, pEntity) > -1) return -1; @@ -978,7 +978,7 @@ int cNodeMachine::getFreeNodeIndex() const } // Adding a node -int cNodeMachine::addNode(const Vector vOrigin, edict_t *pEntity) { +int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // Do not add a node when there is already one close if (getClosestNode(vOrigin, NODE_ZONE, pEntity) > -1) @@ -1853,7 +1853,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { } // Adds a new goal to the array -void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector vVec) { +void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { // // 14/06/04 // Be carefull with adding SERVER_PRINT messages here @@ -2481,7 +2481,7 @@ void cNodeMachine::makeAllWaypointsAvailable() } // Find a node which has almost no danger! -int cNodeMachine::node_camp(const Vector vOrigin, int iTeam) { +int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) { // Use Meredians to search for nodes int iX, iY; VectorToMeredian(vOrigin, &iX, &iY); @@ -2560,7 +2560,7 @@ void cNodeMachine::vis_calculate(int iFrom) { } // Find a node to look at when camping -int cNodeMachine::node_look_camp(const Vector vOrigin, int iTeam, +int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict) { rblog("node_look_camp - start\n"); @@ -4069,7 +4069,7 @@ static void InitDebugBitmap() { } // Draw a small cross -static void DrawPoint(const Vector v, unsigned char color) { +static void DrawPoint(const Vector& v, unsigned char color) { if (bmp_buffer == nullptr) { fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); @@ -4100,7 +4100,7 @@ static void DrawPoint(const Vector v, unsigned char color) { // From PMB and Botman's code -static void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsigned char color) { +static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsigned char color) { // blind copy of botman's Bresenham(). This function prints a vector line into a bitmap dot // matrix. The dot matrix (bmp_buffer) is a global array. The size of the bitmap is always // assumed to be DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT pixels (currently 2000 * 2000 to fit with diff --git a/NodeMachine.h b/NodeMachine.h index 69211bc..3bd9556 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -43,14 +43,14 @@ class cNodeMachine { public: // ----------------- - int addNode(Vector vOrigin, edict_t *pEntity); + int addNode(const Vector& vOrigin, edict_t *pEntity); int Reachable(int iStart, int iEnd) const; - int add2(Vector vOrigin, int iType, edict_t *pEntity); + int add2(const Vector& vOrigin, int iType, edict_t *pEntity); - int getClosestNode(Vector vOrigin, float fDist, edict_t *pEdict); // returns a close node - int getFurthestNode(Vector vOrigin, float fDist, edict_t *pEdict); // returns a node within dist, but most far away + int getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict); // returns a close node + int getFurthestNode(const Vector& vOrigin, float fDist, edict_t *pEdict); // returns a node within dist, but most far away int getFreeNodeIndex() const; // ----------------- @@ -98,16 +98,16 @@ class cNodeMachine { bool hasGoalWithEdict(edict_t *pEdict) const; - void addGoal(edict_t *pEdict, int goalType, Vector vVec); + void addGoal(edict_t *pEdict, int goalType, const Vector& vVec); tGoal * getRandomGoalByType(int goalType); // return a node close to a iType goal (random) - static bool node_float(Vector vOrigin, edict_t *pEdict); + static bool node_float(const Vector& vOrigin, edict_t *pEdict); - static bool node_on_crate(Vector vOrigin, edict_t *pEdict); + static bool node_on_crate(const Vector& vOrigin, edict_t *pEdict); int node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance); - int node_look_camp(Vector vOrigin, int iTeam, edict_t *pEdict); + int node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict); // ----------------- void danger(int iNode, int iTeam); // Make spot dangerous @@ -127,7 +127,7 @@ class cNodeMachine { int node_look_at_hear(int iFrom, int iTo, edict_t *pEdict); - int node_camp(Vector vOrigin, int iTeam); + int node_camp(const Vector& vOrigin, int iTeam); void vis_calculate(int iFrom); @@ -143,7 +143,7 @@ class cNodeMachine { int getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex); // ----------------- - static void VectorToMeredian(Vector vOrigin, int *iX, int *iY); // Input: origin, output X and Y Meredians + static void VectorToMeredian(const Vector& vOrigin, int *iX, int *iY); // Input: origin, output X and Y Meredians void AddToMeredian(int iX, int iY, int iNode); // ----------------- diff --git a/bot.cpp b/bot.cpp index 2afe2da..f3d36d9 100644 --- a/bot.cpp +++ b/bot.cpp @@ -601,7 +601,7 @@ void cBot::rememberEnemyFound() { /****************************************************************************** Function purpose: Sets vHead to aim at vector ******************************************************************************/ -void cBot::setHeadAiming(const Vector vTarget) { +void cBot::setHeadAiming(const Vector& vTarget) { vHead = vTarget; } @@ -3827,7 +3827,7 @@ bool BotRadioAction() { } // Is entity visible? (from Entity view) -bool EntityIsVisible(edict_t *pEntity, const Vector dest) { +bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { //DebugOut("bot: EntityIsVisible()\n"); TraceResult tr; @@ -3885,7 +3885,7 @@ float cBot::getDistanceTo(int nodeIndex) { * @param vDest * @return */ -float cBot::getDistanceTo(const Vector vDest) const +float cBot::getDistanceTo(const Vector& vDest) const { return func_distance(pEdict->v.origin, vDest); } @@ -3959,7 +3959,7 @@ int cBot::getAmountOfHostagesBeingRescued() const // Will return true when the vector is visible. // TODO: Make this function more flexible, ie able to hit an entity that it searches // and return true on that as well. (mix it with the above function) -bool cBot::canSeeVector(const Vector vDest) const +bool cBot::canSeeVector(const Vector& vDest) const { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; diff --git a/bot.h b/bot.h index f1bdb18..6704320 100644 --- a/bot.h +++ b/bot.h @@ -400,7 +400,7 @@ class cBot { int CarryWeaponType() const; - void setHeadAiming(Vector vTarget); // Aim at vector + void setHeadAiming(const Vector& vTarget); // Aim at vector void AimAtEnemy(); void PickBestWeapon(); @@ -414,7 +414,7 @@ class cBot { float ReactionTime(int iSkill); // Reaction time based upon skill void FindCover(); - bool canSeeVector(Vector vDest) const; + bool canSeeVector(const Vector& vDest) const; bool canSeeEntity(edict_t *pEntity) const; @@ -431,7 +431,7 @@ class cBot { // Get methods float getDistanceTo(int nodeIndex); - float getDistanceTo(Vector vDest) const; + float getDistanceTo(const Vector& vDest) const; // "is" Methods (booleans, statements, etc) bool isDead() const; diff --git a/bot_func.cpp b/bot_func.cpp index 6b87eea..9ccf755 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -55,7 +55,7 @@ extern cNodeMachine NodeMachine; #define TOTAL_SCORE 16300 // 16000 money + 100 health + 100 fear + 100 camp desire bool -VectorIsVisibleWithEdict(edict_t *pEdict, const Vector dest, char *checkname) { +VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -89,7 +89,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, const Vector dest, char *checkname) { } -bool VectorIsVisible(const Vector start, const Vector dest, char *checkname) { +bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { TraceResult tr; // trace a line from bot's eyes to destination... @@ -135,7 +135,7 @@ float func_distance(Vector v1, Vector v2) { * @param dest * @return */ -int FUNC_InFieldOfView(edict_t *pEntity, const Vector dest) { +int FUNC_InFieldOfView(edict_t *pEntity, const Vector& dest) { // NOTE: Copy from Botman's BotInFieldOfView() routine. // find angles from source to destination... Vector entity_angles = UTIL_VecToAngles(dest); @@ -171,7 +171,7 @@ int FUNC_InFieldOfView(edict_t *pEntity, const Vector dest) { * @param start * @param end */ -void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end) { +void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end) { DrawBeam(visibleForWho, start, end, 25, 1, 255, 255, 255, 255, 1); } @@ -184,7 +184,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end) { * @param g * @param b */ -void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int r, int g, int b) { +void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, int r, int g, int b) { DrawBeam(visibleForWho, start, end, 25, 1, r, g, b, 255, 1); } @@ -201,7 +201,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int * @param brightness * @param speed */ -void DrawBeam(edict_t *visibleForWho, const Vector start, const Vector end, int width, +void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, int width, int noise, int red, int green, int blue, int brightness, int speed) { MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, visibleForWho); @@ -606,7 +606,7 @@ bool FUNC_ShouldTakeCover(cBot *pBot) { return RANDOM_LONG(0, TOTAL_SCORE) < (vMoney + vHealth + vCamp); } -int FUNC_BotEstimateHearVector(cBot *pBot, Vector v_sound) { +int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { // here we normally figure out where to look at when we hear an enemy, RealBot AI PR 2 lagged a lot on this so we need another approach return -1; diff --git a/bot_func.h b/bot_func.h index e3bdc13..7effabf 100644 --- a/bot_func.h +++ b/bot_func.h @@ -38,15 +38,15 @@ void botFixIdealYaw(edict_t * pEdict); bool BotCanJumpUp(cBot * pBot); bool BotCanDuckUnder(cBot * pBot); -bool EntityIsVisible(edict_t * pEntity, Vector dest); +bool EntityIsVisible(edict_t * pEntity, const Vector& dest); // bot_func.cpp -bool VectorIsVisible(Vector start, Vector dest, char *checkname); +bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname); float func_distance(Vector v1, Vector v2); -void DrawBeam(edict_t * visibleForWho, Vector start, Vector end); -void DrawBeam(edict_t * visibleForWho, Vector start, Vector end, int red, int green, int blue); -void DrawBeam(edict_t * visibleForWho, Vector start, Vector end, +void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end); +void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end, int red, int green, int blue); +void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end, int width, int noise, int red, int green, int blue, int brightness, int speed); @@ -86,15 +86,15 @@ bool isHostageRescueable(cBot *pBot, edict_t *pHostage); bool isHostageRescued(cBot *pBot, edict_t *pHostage); bool isHostageFree(cBot * pBotWhoIsAsking, edict_t * pHostage); // is this hostage not used by any other bot? -int FUNC_BotEstimateHearVector(cBot * pBot, Vector v_sound); +int FUNC_BotEstimateHearVector(cBot * pBot, const Vector& v_sound); bool FUNC_EdictIsAlive(edict_t *pEdict); bool FUNC_BotHoldsZoomWeapon(cBot * pBot); -int FUNC_InFieldOfView(edict_t * pEntity, Vector dest); +int FUNC_InFieldOfView(edict_t * pEntity, const Vector& dest); -bool VectorIsVisibleWithEdict(edict_t * pEdict, Vector dest, +bool VectorIsVisibleWithEdict(edict_t * pEdict, const Vector& dest, char *checkname); bool BOT_DecideTakeCover(cBot * pBot); From 64f1787d90d09235753f54b5a4e62666a538687f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 19 Dec 2021 23:40:55 +0000 Subject: [PATCH 022/114] Tiny tweaks --- NodeMachine.cpp | 4 ++-- engine.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 7cbae86..0bdab99 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -3375,12 +3375,12 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // (current score + gained score) / 2.0; // Since both scores can be max 1.0, meaning we keep it between 0.0 and 1.0 // A score of 1.0 is max. - const int maxCheckedScore = 5; pBot->rprint_normal("cNodeMachine::path_think", "going to choose goal"); for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { + const int maxCheckedScore = 5; - // Make sure this goal is valid + // Make sure this goal is valid if (Goals[goalIndex].iNode < 0) { continue; } diff --git a/engine.cpp b/engine.cpp index 1d04ce0..0aabaaa 100644 --- a/engine.cpp +++ b/engine.cpp @@ -40,7 +40,7 @@ //#include "engine.h" #include "game.h" -extern enginefuncs_t g_engfuncs; +extern enginefuncs_t g_engfuncs; //Redundant? [APG]RoboCop[CL] extern cBot bots[32]; extern cGame Game; From 163ac16c732beb387d3d7ff9c413dc87762032a2 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 20 Dec 2021 00:11:36 +0000 Subject: [PATCH 023/114] Neatened the scripts --- NodeDataTypes.h | 12 ++++++------ dll.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index dab5cd8..0254f13 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -124,16 +124,16 @@ const unsigned long g_iMaxVisibilityByte = (MAX_NODES * MAX_NODES) / 8; // doors (doors.cpp) HLSDK #define SF_DOOR_ROTATE_Y 0 -#define SF_DOOR_START_OPEN 1 +#define SF_DOOR_START_OPEN 1 #define SF_DOOR_ROTATE_BACKWARDS 2 #define SF_DOOR_PASSABLE 8 -#define SF_DOOR_ONEWAY 16 -#define SF_DOOR_NO_AUTO_RETURN 32 +#define SF_DOOR_ONEWAY 16 +#define SF_DOOR_NO_AUTO_RETURN 32 #define SF_DOOR_ROTATE_Z 64 #define SF_DOOR_ROTATE_X 128 #define SF_DOOR_USE_ONLY 256 // door must be opened by player's use button. -#define SF_DOOR_NOMONSTERS 512 // Monster can't open -#define SF_DOOR_SILENT 0x80000000 +#define SF_DOOR_NOMONSTERS 512 // Monster can't open +#define SF_DOOR_SILENT 0x80000000 // Player information on map @@ -146,9 +146,9 @@ typedef struct { // Astar Node informaiton typedef struct { int state; // OPEN/CLOSED + int parent; // Who opened this node? double cost; // Cost double danger; - int parent; // Who opened this node? } tNodestar; diff --git a/dll.cpp b/dll.cpp index 855b9e0..f2bca5f 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1155,7 +1155,7 @@ void ProcessBotCfgFile() { ALERT(at_console, msg); if (IS_DEDICATED_SERVER()) - printf(msg); + printf("%s", msg); SERVER_COMMAND(server_cmd); } From 3a472e4982fad976ff558b8f18c3203e94656144 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 25 Feb 2022 17:42:36 +0000 Subject: [PATCH 024/114] Converting misled doubles into floats --- ChatEngine.cpp | 2 +- IniParser.cpp | 10 +-- NodeMachine.cpp | 165 ++++++++++++++++++++++-------------------- bot.cpp | 176 +++++++++++++++++++++++---------------------- bot.h | 4 +- bot_buycode.cpp | 2 +- bot_client.cpp | 8 +-- bot_func.cpp | 22 +++--- bot_navigate.cpp | 24 +++---- dll.cpp | 72 +++++++++---------- realbot_mm.vcxproj | 2 +- util.cpp | 30 ++++---- 12 files changed, 263 insertions(+), 254 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index e2912e2..44702c5 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -84,7 +84,7 @@ void cChatEngine::initAndload() { // think void cChatEngine::think() { - if (fThinkTimer + 1.0 > gpGlobals->time) return; // not time yet to think + if (fThinkTimer + 1.0f > gpGlobals->time) return; // not time yet to think // decrease over time to avoid flooding if (Game.iProducedSentences > 1) { diff --git a/IniParser.cpp b/IniParser.cpp index 79a7bd2..a267b80 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -933,10 +933,10 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { //30.8.04 redefined by frashman // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); fMinReact = - RANDOM_FLOAT((pBot->bot_skill / 20) + 0.05, - (pBot->bot_skill / 5) + 0.05); + RANDOM_FLOAT((pBot->bot_skill / 20) + 0.05f, + (pBot->bot_skill / 5) + 0.05f); - const float fMaxReact = fMinReact + RANDOM_FLOAT(0.05, 0.2); + const float fMaxReact = fMinReact + RANDOM_FLOAT(0.05f, 0.2f); // SET them pBot->fpMinReactTime = fMinReact; @@ -945,8 +945,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Set Offsets (note, they are extra upon current aiming code) // 30.8.04 redefined by frashman // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); - const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5) + 0.05, - (pBot->bot_skill / 2) + 0.05); + const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5) + 0.05f, + (pBot->bot_skill / 2) + 0.05f); // SET pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 0bdab99..f518f69 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -32,6 +32,7 @@ * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 **/ +#include #include #include #include @@ -377,8 +378,8 @@ Vector cNodeMachine::node_vector(int iNode) const // Input: Vector, Output X and Y Meredians void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) { // Called for lookupt and for storing - float iCoordX = vOrigin.x + 8192.0; // map height (converts from - to +) - float iCoordY = vOrigin.y + 8192.0; // map width (converts from - to +) + float iCoordX = vOrigin.x + 8192.0f; // map height (converts from - to +) + float iCoordY = vOrigin.y + 8192.0f; // map width (converts from - to +) // Meredian: iCoordX = iCoordX / SIZE_MEREDIAN; @@ -405,7 +406,7 @@ void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { // Does the node float? bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); + const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2f)); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) //UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -417,11 +418,11 @@ bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { &tr); // if nothing hit: floating too high, return false - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return true; // floating // *NOTE*: Actually this check should not be nescesary! - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) if (tr.pHit == pEdict) return true; @@ -437,7 +438,7 @@ bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { // Does the node stand on a crate? or a steep slope? bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2)); + const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2f)); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) if (pEdict) @@ -448,15 +449,15 @@ bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { &tr); // if nothing hit: floating too high, return false - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return false; // hit something - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { // thanks a million to PMB , so i know what the difference // is between something straight (crate) and steep... although i have // no clue yet how to compute these values myself. - if ( /*tr.vecPlaneNormal.z >= 0.7 && */ tr.vecPlaneNormal.z == 1.0) { + if ( /*tr.vecPlaneNormal.z >= 0.7 && */ tr.vecPlaneNormal.z == 1.0f) { return true; } } @@ -520,7 +521,7 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE } // if nothing hit: - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { if (pEdict != nullptr) { if (FInViewCone(&nodeVector, pEdict) // in FOV && FVisible(nodeVector, pEdict)) { @@ -587,7 +588,7 @@ int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, edict_t *p } // if nothing hit: - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { if (pEdict != nullptr) { if (FInViewCone(&nodeVector, pEdict) // in FOV && FVisible(nodeVector, pEdict)) { @@ -786,7 +787,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const printf("TraceHull --> tr.flFraction = %.2f\n", tr.flFraction); #endif - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; // If either start/end is on ladder, assume we can fly without falling @@ -795,7 +796,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const (Nodes[iEnd].iNodeBits & BIT_LADDER)) { UTIL_TraceHull(Start, End, ignore_monsters, human_hull, nullptr, &tr); - return tr.flFraction >= 1.0; + return tr.flFraction >= 1.0f; } // Heurestic for falling @@ -995,8 +996,8 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // SET BITS: bool bIsInWater = false; - bool indexNodeFloats = false; - bool bIndexOnCrate = false; + bool indexNodeFloats; + bool bIndexOnCrate; if (pEntity) { // Does this thing float? @@ -1118,7 +1119,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (indexNodeFloats == false && // we stand on something nodeIsHigherThanOrigin && // we MUST jump (not fall) bNeighbourWater == false && - fabs(slopeDistance) > MAX_JUMPHEIGHT) // and cannot jump to it + std::fabs(slopeDistance) > MAX_JUMPHEIGHT) // and cannot jump to it { // SERVER_PRINT("Cannot jump to it"); continue; // next neighbour @@ -1128,7 +1129,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (indexNodeFloats == false && // we stand on something nodeIsHigherThanOrigin && // we MUST jump (not fall) bNeighbourWater == false && - fabs(slopeDistance) > MAX_FALLHEIGHT) // and cannot jump to it + std::fabs(slopeDistance) > MAX_FALLHEIGHT) // and cannot jump to it { // SERVER_PRINT("Insanity jump not possible either!\n"); continue; // next neighbour @@ -1164,7 +1165,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { hull_type, pEntity->v.pContainingEntity, &tr); // if nothing hit: - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // Add this to the neighbouring list Nodes[currentIndex].iNeighbour[neighbourId] = nodeIndex; @@ -1190,7 +1191,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (bNeighbourFloats == false && // we stand on something Nodes[currentIndex].origin.z > Nodes[nodeIndex].origin.z && // we MUST jump (not fall) bIsInWater == false && - fabs(fallDistance) > MAX_JUMPHEIGHT) // and cannot jump to it + std::fabs(fallDistance) > MAX_JUMPHEIGHT) // and cannot jump to it bCanConnect = false; // cannot connect // All water stuff can connect to each other @@ -1804,7 +1805,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { ignore_monsters, point_hull, nullptr, &tr); // within distance and 'reachable' - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { const double costIncrease = (fDist / NODE_CONTACT_DIST) * NODE_CONTACT_STEP; InfoNodes[i].fContact[iTeam] += costIncrease; } @@ -1843,7 +1844,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { ignore_monsters, point_hull, nullptr, &tr); // within distance and reachable - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { const double costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; InfoNodes[i].fDanger[iTeam] += costIncrease; } @@ -1878,7 +1879,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { goalType == GOAL_VIPSAFETY || goalType == GOAL_RESCUEZONE || goalType == GOAL_BOMBSPOT) { - distance = NODE_ZONE * 0.8; + distance = NODE_ZONE * 0.8f; } int nNode = getClosestNode(vVec, distance, pEdict); @@ -2136,22 +2137,22 @@ void cNodeMachine::scale_contact() { // rescale all other values to stay correct. int iTeam = 0; while (iTeam < 2) { - float fHighest = 0.0; - int i = 0; // <-- ADDED BY PMB ELSE LINUX COMPILER ISNT HAPPY + float fHighest = 0.0f; + int i; // <-- ADDED BY PMB ELSE LINUX COMPILER ISNT HAPPY for (i = 0; i < MAX_NODES; i++) if (InfoNodes[i].fContact[iTeam] > fHighest) fHighest = InfoNodes[i].fContact[iTeam]; - if (fHighest < 1.0) { + if (fHighest < 1.0f) { iTeam++; continue; // no need to rescale } // Check how much we passed the limit - const float fLimit = 1.0 / fHighest; + const float fLimit = 1.0f / fHighest; // Now rescale all for (i = 0; i < MAX_NODES; i++) - if (InfoNodes[i].fContact[iTeam] > 0.0) + if (InfoNodes[i].fContact[iTeam] > 0.0f) InfoNodes[i].fContact[iTeam] *= fLimit; // rescale iTeam++; @@ -2166,22 +2167,22 @@ void cNodeMachine::scale_danger() { // rescale all other danger values to stay correct. int iTeam = 0; while (iTeam < 2) { - float fHighest = 0.0; - int i = 0; // ADDED BY PMB FOR COMPILING UNDER LINUX + float fHighest = 0.0f; + int i; // ADDED BY PMB FOR COMPILING UNDER LINUX for (i = 0; i < MAX_NODES; i++) if (InfoNodes[i].fDanger[iTeam] > fHighest) fHighest = InfoNodes[i].fDanger[iTeam]; - if (fHighest < 0.8) { + if (fHighest < 0.8f) { iTeam++; continue; // no need to rescale } // Check how much we passed the limit - const float fLimit = 0.7 / fHighest; + const float fLimit = 0.7f / fHighest; // Now rescale all for (i = 0; i < MAX_NODES; i++) - if (InfoNodes[i].fDanger[iTeam] > 0.0) + if (InfoNodes[i].fDanger[iTeam] > 0.0f) InfoNodes[i].fDanger[iTeam] *= fLimit; // rescale iTeam++; @@ -2547,7 +2548,7 @@ void cNodeMachine::vis_calculate(int iFrom) { { UTIL_TraceHull(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, point_hull, nullptr, &tr); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { SetVisibilityFromTo(iFrom, i, false); SetVisibilityFromTo(i, iFrom, false); } else { @@ -2564,7 +2565,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict) { rblog("node_look_camp - start\n"); - float fDanger = -0.1; + float fDanger = -0.1f; float fDistance = 0; int iBestNode = -2; @@ -2584,7 +2585,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, UTIL_TraceLine(Nodes[iFrom].origin, Nodes[iNode].origin, ignore_monsters, ignore_glass, pEdict, &tr); //UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "NODE, MEREDIAN: VISIBILITY NOT KNOWN \n"); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { bVisible = false; // Set to false SetVisibilityFromTo(iFrom, iNode, false); @@ -2693,7 +2694,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { bool isGood = false; // if nothing hit: - if (trb.flFraction >= 1.0) + if (trb.flFraction >= 1.0f) isGood = true; else { // we hit this button we check for @@ -2715,8 +2716,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_walk", "This is the button I was looking for, it is close and I can use it"); // wait a little - pBot->setTimeToWait(0.5); - pBot->fButtonTime = gpGlobals->time + 5.0; + pBot->setTimeToWait(0.5f); + pBot->fButtonTime = gpGlobals->time + 5.0f; pBot->setTimeToMoveToNode(3); pBot->forgetPath(); return; @@ -2762,7 +2763,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (BotShouldDuck(pBot)) { UTIL_BotPressKey(pBot, IN_DUCK); - pBot->f_hold_duck = gpGlobals->time + 0.2; + pBot->f_hold_duck = gpGlobals->time + 0.2f; } bNearNode = pBot->getDistanceToNextNode() < 25; @@ -2797,7 +2798,9 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } char msg[255]; - sprintf(msg, "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", pBot->getCurrentPathNodeToHeadFor(), requiredDistance, pBot->getDistanceToNextNode(), pBot->getMoveToNodeTimeRemaining()); + sprintf(msg, "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", + pBot->getCurrentPathNodeToHeadFor(), requiredDistance, pBot->getDistanceToNextNode(), + pBot->getMoveToNodeTimeRemaining()); pBot->rprint_trace("cNodeMachine::path_walk (bNear)", msg); bNearNode = pBot->getDistanceToNextNode() < requiredDistance; @@ -2805,7 +2808,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // If we should duck, duck. if (BotShouldDuck(pBot)) { UTIL_BotPressKey(pBot, IN_DUCK); - pBot->f_hold_duck = gpGlobals->time + 0.2; + pBot->f_hold_duck = gpGlobals->time + 0.2f; } } @@ -2902,7 +2905,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (strcmp(STRING(pEntityHit->v.classname), "player") == 0) { pBot->rprint_trace("cNodeMachine::path_walk", "Another player between me and next node."); if (pBot->hasTimeToMoveToNode()) { - pBot->strafeRight(0.2); + pBot->strafeRight(0.2f); pBot->rprint_trace("cNodeMachine::path_walk", "Time left to move to node, so lets try strafing to unstuck."); return; } else { @@ -2918,10 +2921,12 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - unstuck // - go back in path... - constexpr float timeEvaluatingMoveSpeed = 0.1; + constexpr float timeEvaluatingMoveSpeed = 0.1f; const bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; - constexpr double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. Else it would trigger stuck logic too soon, too often. + constexpr double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. + // Else it would trigger stuck logic too soon, too often. + const double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; double expectedMoveDistance = speedInOneTenthOfASecond; if (pBot->isFreezeTime()) expectedMoveDistance = 0; @@ -2932,7 +2937,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { char msg[255]; memset(msg, 0, sizeof(msg)); - sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, expectedMoveDistance, notStuckForAWhile); + sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, + expectedMoveDistance, notStuckForAWhile); pBot->rprint_trace("cNodeMachine::path_walk", msg); const bool isStuck = distanceMoved < expectedMoveDistance && pBot->shouldBeAbleToMove() && notStuckForAWhile; // also did not evaluate this logic for 0.5 second @@ -2963,7 +2969,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vector &vector) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "START"); - pBot->fNotStuckTime = gpGlobals->time + 0.25; // give some time to unstuck + pBot->fNotStuckTime = gpGlobals->time + 0.25f; // give some time to unstuck const int iFrom = pBot->getPreviousPathNodeToHeadFor(); const int iTo = currentNodeToHeadFor; @@ -3021,7 +3027,8 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec } memset(msg, 0, sizeof(msg)); - sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", playerNearbyInFOV != nullptr, hostageNearbyInFOV != nullptr, pBotStuck != nullptr, timeRemaining); + sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", + playerNearbyInFOV != nullptr, hostageNearbyInFOV != nullptr, pBotStuck != nullptr, timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); if (playerNearbyInFOV) { @@ -3091,7 +3098,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec // make sure we head to the current node pBot->vBody = currentNode.origin; pBot->vHead = currentNode.origin; - pBot->fNotStuckTime = gpGlobals->time + 0.5; // give a bit more time + pBot->fNotStuckTime = gpGlobals->time + 0.5f; // give a bit more time } else { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "I can no longer see the current node to head for"); IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(iFrom, iTo); @@ -3367,8 +3374,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { int iFinalGoalNode = -1; int iFinalGoalIndex = -1; - constexpr float MAX_DISTANCE = 16384.0; // theoretical max distance - constexpr float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0; + constexpr float MAX_DISTANCE = 16384.0f; // theoretical max distance + constexpr float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0f; // 01-07-2008; Instead of using 'scores', use a normalized score. // We do: @@ -3405,14 +3412,14 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { score += weight; // Take into consideration how many times this goal has been selected - score = (score + (1.0f - (Goals[goalIndex].iChecked / maxCheckedScore))) / 2.0f; + score = (score + (1.0f - (Goals[goalIndex].iChecked / static_cast(maxCheckedScore)))) / 2.0f; // Danger (is important) - score = (score + InfoNodes[Goals[goalIndex].iNode].fDanger[UTIL_GetTeam(pBot->pEdict)]) / 1.5; + score = (score + InfoNodes[Goals[goalIndex].iNode].fDanger[UTIL_GetTeam(pBot->pEdict)]) / 1.5f; // How many bots have already taken this goal? - float goalAlreadyUsedScore = 0.0; - float teamMembers = 1.0; // count self by default + float goalAlreadyUsedScore = 0.0f; + float teamMembers = 1.0f; // count self by default for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { // not a bot @@ -3433,14 +3440,14 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } // add favoriteness - score = (score + (1.0 - (goalAlreadyUsedScore / teamMembers))) / 2.0; + score = (score + (1.0f - (goalAlreadyUsedScore / teamMembers))) / 2.0f; // Goals regardless of map/game type const int goalType = Goals[goalIndex].iType; if (goalType == GOAL_SPAWNCT || goalType == GOAL_SPAWNT) { const float goalscore = fDistanceToGoal / MAX_GOAL_DISTANCE; - score = (score + goalscore) / 2.0; + score = (score + goalscore) / 2.0f; } if (Game.bHostageRescueMap) { @@ -3472,35 +3479,35 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { // Terrorist pick randomly this location if (RANDOM_LONG(0, 100) < 25) { - goalscore = RANDOM_FLOAT(0.1, 0.6); + goalscore = RANDOM_FLOAT(0.1f, 0.6f); } } - score = (score + goalscore) / 2.0; + score = (score + goalscore) / 2.0f; } else if (goalType == GOAL_RESCUEZONE) { if (pBot->isCounterTerrorist()) { if (pBot->isEscortingHostages()) { pBot->rprint("I am escorting hostages - prioritizing for rescue zone"); // highest priority - score = 2.0; + score = 2.0f; } else { - score = 0.2; + score = 0.2f; } } else if (pBot->isTerrorist()) { // TODO: when hostages are being rescued, go to a rescue zone to catch CT's and // prevent rescue - score = 0.2; + score = 0.2f; } } } else { // it is a DE_ map if (goalType == GOAL_BOMBSPOT) { - float goalscore = 0.0; + float goalscore = 0.0f; if (pBot->isTerrorist()) { if (pBot->hasBomb()) { - goalscore = 2.0; // plant it! + goalscore = 2.0f; // plant it! } else { const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; - goalscore = (0.7 * mul); + goalscore = (0.7f * mul); } } else if (pBot->isCounterTerrorist()) { @@ -3528,7 +3535,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { ); const float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; - goalscore = 1.5 + score; + goalscore = 1.5f + score; memset(msg, 0, sizeof(msg)); sprintf(msg, "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", distanceToC4FromCloseNode, @@ -3547,11 +3554,11 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { pBot->rprint_trace("path_think/determine goal", "Bomb is not planted"); const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; - goalscore = (0.7 * mul); + goalscore = (0.7f * mul); } } // this is weird? what? - score = (score + goalscore) / 2.0; + score = (score + goalscore) / 2.0f; } // GOAL is a bombspot } // bomb plant map @@ -3568,7 +3575,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } } else { // terrorists pick random - score = (score + RANDOM_FLOAT(0.0, 1.0)) / 2.0; + score = (score + RANDOM_FLOAT(0.0f, 1.0f)) / 2.0f; } } @@ -3609,7 +3616,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // was previous goal as well, don't go there if (pBot->iPreviousGoalNode == goalIndex) { - score *= 0.2; // low chance + score *= 0.2f; // low chance } @@ -3847,7 +3854,7 @@ int cNodeMachine::node_cover(int iFrom, int iTo, edict_t *pEdict) { UTIL_TraceLine(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, ignore_glass, pEdict, &tr); - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) bVisible = false; } else { if (GetVisibilityFromTo(iFrom, i) == VIS_BLOCKED) // BERKED @@ -3915,7 +3922,7 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, UTIL_TraceLine(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, ignore_glass, pEdict, &tr); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { SetVisibilityFromTo(iFrom, i, false); SetVisibilityFromTo(i, iFrom, false); } @@ -3926,7 +3933,7 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, UTIL_TraceLine(Nodes[iOrigin].origin, Nodes[i].origin, ignore_monsters, ignore_glass, pEdict, &tr); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { SetVisibilityFromTo(iOrigin, i, false); SetVisibilityFromTo(i, iOrigin, false); } @@ -4430,8 +4437,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (x = 0; x < DEBUG_BMP_WIDTH; x++) { Meredian = - static_cast((float)x * scale + minx + - 8192.0) / static_cast(SIZE_MEREDIAN); + static_cast(static_cast(x) * scale + minx + + 8192.0f) / static_cast(SIZE_MEREDIAN); if (Meredian & 0x01) { for (y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4441,8 +4448,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (y = 0; y < DEBUG_BMP_HEIGHT; y++) { Meredian = - static_cast((float)y * scale + miny + - 8192.0) / static_cast(SIZE_MEREDIAN); + static_cast(static_cast(y) * scale + miny + + 8192.0f) / static_cast(SIZE_MEREDIAN); if (Meredian & 0x01) { for (x = 0; x < DEBUG_BMP_HEIGHT; x++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4571,7 +4578,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) pBot->pEdict, &trb); // if nothing hit: - if (trb.flFraction >= 1.0) { + if (trb.flFraction >= 1.0f) { // Button found to head for! pButtonEdict = pent; break; @@ -4609,7 +4616,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) bool isGood = false; // if nothing hit: - if (trb.flFraction >= 1.0) { + if (trb.flFraction >= 1.0f) { pButtonEdict = pent; break; } else { @@ -4643,7 +4650,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) pBot->pEdict, &trb); // if nothing hit: - if (trb.flFraction >= 1.0) { + if (trb.flFraction >= 1.0f) { pButtonEdict = pent; break; } diff --git a/bot.cpp b/bot.cpp index f3d36d9..c324c15 100644 --- a/bot.cpp +++ b/bot.cpp @@ -72,6 +72,7 @@ bool CBaseBot::IsShootableThruObstacle(Vector vecDest) */ +#include #include #include #include @@ -170,7 +171,7 @@ void cBot::SpawnInit() { distanceMovedTimer = gpGlobals->time; distanceMoved = 0; fBlindedTime = gpGlobals->time; - f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1, 0.9); + f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); fWanderTime = gpGlobals->time; f_strafe_time = gpGlobals->time; @@ -342,7 +343,7 @@ void cBot::NewRound() { distanceMovedTimer = gpGlobals->time; distanceMoved = 0; fBlindedTime = gpGlobals->time; - f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1, 0.9); + f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); fWanderTime = gpGlobals->time; f_strafe_time = gpGlobals->time; @@ -486,7 +487,7 @@ void cBot::NewRound() { void cBot::PrepareChat(char sentence[128]) { if (Game.iProducedSentences <= Game.iMaxSentences) { // makes bot chat away - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.1, 2.0); + fChatTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); strcpy(chChatSentence, sentence); // copy this Game.iProducedSentences++; } @@ -653,18 +654,18 @@ void cBot::AimAtEnemy() { // factor in distance, the further away the more deviation - which is based on skill const int skillReversed = (10 - bot_skill) + 1; - float fScale = 0.5 + (fDistance / (64 * + float fScale = 0.5f + (fDistance / (64 * skillReversed)); // a good skilled bot is less impacted by distance than a bad skilled bot - if (CarryWeaponType() == SNIPER) fScale *= 0.80; // sniping improves aiming + if (CarryWeaponType() == SNIPER) fScale *= 0.80f; // sniping improves aiming // Set target here Vector vTarget; if (bot_skill <= 1) - vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-0.5, 1.1); // aim for the head + vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-0.5f, 1.1f); // aim for the head else if (bot_skill > 1 && bot_skill < 4) vTarget = pEnemyEdict->v.origin + - pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5, 2.5); // aim for the head more fuzzy + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy else vTarget = pEnemyEdict->v.origin; // aim for body @@ -741,7 +742,7 @@ void cBot::FightEnemy() { if (CarryWeaponType() == SNIPER) { if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; zoomed++; if (zoomed > ZOOM_TWICE) @@ -750,7 +751,7 @@ void cBot::FightEnemy() { } else if (FUNC_BotHoldsZoomWeapon(this)) { if (zoomed < ZOOM_ONCE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; zoomed++; } } @@ -816,7 +817,7 @@ void cBot::pickWeapon(int weaponId) { UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(weaponId)); f_c4_time = gpGlobals->time - 1; // reset C4 timer data // give Counter-Strike time to switch weapon (animation, update state, etc) - f_update_weapon_time = gpGlobals->time + 0.7; + f_update_weapon_time = gpGlobals->time + 0.7f; } bool cBot::ownsFavoritePrimaryWeapon() const @@ -910,7 +911,7 @@ void cBot::PickBestWeapon() { UTIL_SelectItem(pEdict, "weapon_hegrenade"); // select grenade f_wait_time = gpGlobals->time + 1; // wait 1 second (stand still 1 sec) f_gren_time = - gpGlobals->time + (1.0 + RANDOM_FLOAT(0.5, 1.5)); // and determine how long we should hold it + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon return; } @@ -925,7 +926,7 @@ void cBot::PickBestWeapon() { UTIL_SelectItem(pEdict, "weapon_flashbang"); // select grenade f_wait_time = gpGlobals->time + 1; // wait 1 second (stand still 1 sec) f_gren_time = - gpGlobals->time + (1.0 + RANDOM_FLOAT(0.5, 1.5)); // and determine how long we should hold it + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon return; } @@ -952,7 +953,7 @@ void cBot::PickBestWeapon() { // We still have ammo! if (iTotalAmmo > 0) { UTIL_BotPressKey(this, IN_RELOAD); - f_update_weapon_time = gpGlobals->time + 0.7; // update timer + f_update_weapon_time = gpGlobals->time + 0.7f; // update timer return; } else { // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code @@ -1015,7 +1016,7 @@ void cBot::FireWeapon() { if (f_sec_weapon < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK); - f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05, 0.2); + f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05f, 0.2f); } } else if (CarryWeaponType() == PRIMARY) { @@ -1029,39 +1030,39 @@ void cBot::FireWeapon() { if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) || CarryWeapon(CS_WEAPON_AUG)) && (bot_skill < 3)) { - float f_burst = (2048 / fDistance) + 0.1; - if (f_burst < 0.1) - f_burst = 0.1; - if (f_burst > 0.4) - f_burst = 0.4; + float f_burst = (2048 / fDistance) + 0.1f; + if (f_burst < 0.1f) + f_burst = 0.1f; + if (f_burst > 0.4f) + f_burst = 0.4f; // CS 1.6 less burst if (counterstrike == 1) - if (f_burst > 0.3) - f_burst = 0.3; + if (f_burst > 0.3f) + f_burst = 0.3f; f_prim_weapon = gpGlobals->time + f_burst; f_shoot_wait_time = gpGlobals->time + (f_burst * 3); } else // other weapons { - float f_burst = 0.1; + float f_burst = 0.1f; if (fDistance > 300 && bot_skill < 6) { f_burst = ((fDistance - 300) / 550); - if (f_burst < 0.1) - f_burst = 0.0; - if (f_burst > 0.7) - f_burst = 0.7; + if (f_burst < 0.1f) + f_burst = 0.0f; + if (f_burst > 0.7f) + f_burst = 0.7f; // CS 1.6 less burst if (counterstrike == 1) - if (f_burst > 0.2) - f_burst = 0.2; + if (f_burst > 0.2f) + f_burst = 0.2f; if (f_prim_weapon < gpGlobals->time) f_prim_weapon = gpGlobals->time + f_burst; } f_shoot_wait_time = - gpGlobals->time + f_burst + RANDOM_FLOAT(0.2, 0.7); + gpGlobals->time + f_burst + RANDOM_FLOAT(0.2f, 0.7f); } } } // give the bot alteast 0.3 seconds to fire its weapon @@ -1078,7 +1079,7 @@ void cBot::FireWeapon() { // COVER: Take cover, using tracelines all the time! FindCover(); } - } else if (f_gren_time + 0.5 < gpGlobals->time) { + } else if (f_gren_time + 0.5f < gpGlobals->time) { // NOTE: Should not happen, a bot cannot 'forget' this... f_gren_time = gpGlobals->time + 1; } @@ -1090,7 +1091,7 @@ void cBot::FireWeapon() { else if (CarryWeaponType() == SNIPER) { setMoveSpeed(f_max_speed / 2); UTIL_BotPressKey(this, IN_ATTACK); // Hold fire - f_shoot_time = gpGlobals->time + 1.0; + f_shoot_time = gpGlobals->time + 1.0f; } // SNIPER else if (CarryWeaponType() == SHIELD) { if (fDistance > 550) { @@ -1099,7 +1100,7 @@ void cBot::FireWeapon() { } else { // draw shield! UTIL_BotPressKey(this, IN_ATTACK2); // secondary attack makes shield draw - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; } } else { // get weapon here. @@ -1107,7 +1108,7 @@ void cBot::FireWeapon() { rblog ("BOT: Enemy is close enough, i should withdraw shield to attack this enemy\n"); UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; } } } else { @@ -1181,11 +1182,11 @@ void cBot::Combat() { lastSeenEnemyVector = Vector(0, 0, 0); // random waiting - f_wait_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0, 0.4)); + f_wait_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 0.4f)); // keep on walking when afraid (perhaps there are more enemies) if (RANDOM_LONG(0, 100) < ipFearRate) - f_walk_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0, 2.0)); + f_walk_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 2.0f)); InteractWithPlayers(); // check any new enemy here immediately @@ -1229,26 +1230,26 @@ void cBot::FindCover() { // First check the right.. UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_right, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) cover_vect = v_right; } // Now check at the left UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_left, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { // If we already found a wpt, then randomly pick this one if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) @@ -1267,14 +1268,14 @@ void cBot::FindCover() { UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_right, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { // If we already found a wpt, then randomly pick this one if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) @@ -1287,14 +1288,14 @@ void cBot::FindCover() { // Now check at the left UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_left, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { // If we already found a wpt, then randomly pick this one if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) @@ -1355,7 +1356,7 @@ void cBot::InteractWithFriends() { // TODO TODO TODO; make this thing really work - return; + //return; // We interact with our players in some way // @@ -1444,7 +1445,7 @@ void cBot::InteractWithPlayers() { // Unzoom (for sniper guns) if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; zoomed++; } if (zoomed > ZOOM_TWICE) @@ -1454,7 +1455,7 @@ void cBot::InteractWithPlayers() { // Unzoom (for other guns with only 1 zoom) if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; zoomed = ZOOM_NONE; } } else { @@ -1489,7 +1490,7 @@ void cBot::InteractWithPlayers() { else // pick secondary UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); - f_update_weapon_time = gpGlobals->time + 0.7; + f_update_weapon_time = gpGlobals->time + 0.7f; } } // ------------------------------------------------ @@ -1538,7 +1539,7 @@ void cBot::InteractWithPlayers() { if (CarryWeaponType() == SNIPER) { if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; zoomed++; } } @@ -1558,7 +1559,7 @@ void cBot::InteractWithPlayers() { // pBot->pBotEnemy->v.origin); // Does our enemy (when a bot) has focus on us? - bool focused = false; + bool focused; cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); if (playerbot) { if (playerbot->pEnemyEdict == pEdict) @@ -1709,10 +1710,10 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { // the quickest way to turn to face that direction // find the difference in the current and ideal angle - const float diff = fabs(current - ideal); + const float diff = std::fabs(current - ideal); // check if the bot is already facing the idealpitch direction... - if (diff <= 1.0) + if (diff <= 1.0f) return static_cast(current); // return number of degrees turned // check if difference is less than the max degrees per turn @@ -1722,15 +1723,15 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { // here we have four cases, both angle positive, one positive and // the other negative, one negative and the other positive, or // both negative. handle each case separately... - if ((current >= 0.0) && (ideal >= 0.0)) // both positive + if ((current >= 0.0f) && (ideal >= 0.0f)) // both positive { if (current > ideal) current -= speed; else current += speed; - } else if ((current >= 0.0) && (ideal < 0.0)) { - current_180 = current - 180.0; + } else if ((current >= 0.0f) && (ideal < 0.0f)) { + current_180 = current - 180.0f; if (current_180 > ideal) current += speed; @@ -1828,7 +1829,7 @@ bool cBot::Defuse() { this->rprint("Defuse()", "I'll start defusing the bomb"); // when we are 'about to' defuse, we simply set the timers f_defuse = gpGlobals->time + 90; // hold as long as you can - f_allow_keypress = gpGlobals->time + 1.5; // And stop any key pressing the first second + f_allow_keypress = gpGlobals->time + 1.5f; // And stop any key pressing the first second // ABOUT TO DEFUSE BOMB } @@ -1840,7 +1841,7 @@ bool cBot::Defuse() { UTIL_BotPressKey(this, IN_DUCK); if (func_distance(pEdict->v.origin, vC4) > 50 - && f_allow_keypress + 0.5 > gpGlobals->time) { + && f_allow_keypress + 0.5f > gpGlobals->time) { setMoveSpeed(f_max_speed / 2); } } @@ -1898,7 +1899,7 @@ void cBot::Act() { // todo, camping can be done standing too, but this does not look 'cool' atm. UTIL_BotPressKey(this, IN_DUCK); - setMoveSpeed(0.0); // do not move + setMoveSpeed(0.0f); // do not move PickBestWeapon(); // pick weapon, do not stare with knife // when dropped C4 and CT we look at C4 @@ -1937,7 +1938,7 @@ void cBot::Act() { if (isTerrorist()) { // When still having the C4 setMoveSpeed(0.0f); -// f_strafe_speed = 0.0; +// f_strafe_speed = 0.0f; // When no C4 selected yet, select it if (!isHoldingWeapon(CS_WEAPON_C4)) { @@ -1971,7 +1972,7 @@ void cBot::Act() { pEdict->v.button &= (~IN_RUN); // release IN_RUN rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed(static_cast(((int)f_max_speed) / 2 + ((int)f_max_speed) / 50)); + setMoveSpeed(static_cast(int(f_max_speed) / 2 + int(f_max_speed) / 50)); } // When we are at max speed, press IN_RUN to get a running animation @@ -2051,7 +2052,7 @@ void cBot::Act() { if (pEdict->v.v_angle.x > 180) pEdict->v.v_angle.x -= 360; - Vector v_shouldbe = pEdict->v.angles; + Vector v_shouldbe; // Vector how it should be, however, we don't allow such a fast turn! v_shouldbe.x = pEdict->v.v_angle.x / 3; @@ -2117,23 +2118,23 @@ void cBot::CheckAround() { // TRACELINE: forward UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForward = tr.flFraction < 1.0; + const bool bHitForward = tr.flFraction < 1.0f; // TRACELINE: Left UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitLeft = tr.flFraction < 1.0; + const bool bHitLeft = tr.flFraction < 1.0f; // TRACELINE: Right UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitRight = tr.flFraction < 1.0; + const bool bHitRight = tr.flFraction < 1.0f; // TRACELINE: Forward left UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForwardLeft = tr.flFraction < 1.0; + const bool bHitForwardLeft = tr.flFraction < 1.0f; // TRACELINE: Forward right UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForwardRight = tr.flFraction < 1.0; + const bool bHitForwardRight = tr.flFraction < 1.0f; char msg[255]; @@ -2334,7 +2335,7 @@ void cBot::startWandering(float time) { } void cBot::stopMoving() { - this->setMoveSpeed(0.0); + this->setMoveSpeed(0.0f); } void cBot::forgetGoal() { @@ -2867,7 +2868,7 @@ void cBot::Memory() { NodeMachine.getClosestNode(vHear, NODE_ZONE * 2, pHearPlayer); // if nothing hit: - if (tr.flFraction >= 1.0) { + if (tr.flFraction >= 1.0f) { // we can look at this spot vEar = vHear; } @@ -3042,7 +3043,7 @@ edict_t * cBot::findHostageToRescue() { if (!isHostageRescueable(this, pent)) continue; if (!canSeeEntity(pent)) continue; // skip too far hostages, leave it up to the goal picking to get closer - if (getDistanceTo(pent->v.origin) > (NODE_ZONE * 2.5)) continue; + if (getDistanceTo(pent->v.origin) > (NODE_ZONE * 2.5f)) continue; char msg[255]; sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); @@ -3208,7 +3209,7 @@ void cBot::Think() { rprint("console_nr == 0"); //whatever this means // do some chatting if (RANDOM_LONG(0, 200) < ipChatRate) { - if (fChatTime + 0.5 < gpGlobals->time) + if (fChatTime + 0.5f < gpGlobals->time) if (chChatSentence[0] == '\0') // we did not want to say anything { // we should say something now? @@ -3235,7 +3236,7 @@ void cBot::Think() { if (chChatSentence[0] == '\0') // we did not want to say anything if (RANDOM_LONG(0, 100) < ipChatRate) // rate fChatTime = gpGlobals->time + - RANDOM_FLOAT(0.0, ((Game.iProducedSentences + 1) / 2)); // wait + RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + 1) / 2)); // wait } @@ -3281,7 +3282,7 @@ void cBot::Think() { // save current position as previous prevOrigin = pEdict->v.origin; - distanceMovedTimer = gpGlobals->time + 0.1; + distanceMovedTimer = gpGlobals->time + 0.1f; } // NEW ROUND @@ -3337,14 +3338,14 @@ void cBot::Think() { // NEW: When round time is over and still busy playing, kill bots const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); - if (Game.getRoundStartedTime() + 10.0 + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { + if (Game.getRoundStartedTime() + 10.0f + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { end_round = true; // round is ended } // FREEZETIME: if (Game.getRoundStartedTime() > gpGlobals->time && freezeTime < gpGlobals->time) { - freezeTime = gpGlobals->time + RANDOM_FLOAT(0.1, 2.0); + freezeTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); } // 1 SECOND START OF ROUND @@ -3410,7 +3411,7 @@ void cBot::Think() { if (hasShield()) { if (!hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); // draw shield - f_allow_keypress = gpGlobals->time + 0.7; + f_allow_keypress = gpGlobals->time + 0.7f; } } @@ -3421,7 +3422,7 @@ void cBot::Think() { && f_update_weapon_time < gpGlobals->time && bWalkKnife && bMayFromGame) { UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(-1)); // -1 is knife - f_update_weapon_time = gpGlobals->time + 0.7; + f_update_weapon_time = gpGlobals->time + 0.7f; } // When holding a grenade (and not switching to another weapon) @@ -3434,7 +3435,7 @@ void cBot::Think() { else // pick secondary UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); - f_update_weapon_time = gpGlobals->time + 0.7; + f_update_weapon_time = gpGlobals->time + 0.7f; } // Think about objectives @@ -3751,13 +3752,13 @@ bool BotRadioAction() { // Taking fire! if (strstr(message, "#Taking_fire") != nullptr) { // todo todo todo backup our friend - // unstood = true; + unstood = true; } // Team fall back! if (strstr(message, "#Team_fall_back") != nullptr) { } - // Go GO Go, stop camping, stop following, get the heck out of there! + // Go Go Go, stop camping, stop following, get the heck out of there! if (strstr(message, "#Go_go_go") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); unstood = true; @@ -3781,7 +3782,7 @@ bool BotRadioAction() { UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! } - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8, 2.0); + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); radios++; } } @@ -3837,7 +3838,7 @@ bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { dont_ignore_monsters, pEntity->v.pContainingEntity, &tr); // check if line of sight to object is not blocked (i.e. visible) - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return true; else @@ -3857,7 +3858,7 @@ bool cBot::canSeeEntity(edict_t *pEntity) const UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); // it hit anything - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { // if it hit the entity we wanted to see, then its ok! if (tr.pHit == pEntity) return true; return false; @@ -3967,7 +3968,7 @@ bool cBot::canSeeVector(const Vector& vDest) const // trace a line from bot's eyes to destination... UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; return true; @@ -4168,7 +4169,7 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const UTIL_TraceHull(vOrigin, node->origin, dont_ignore_monsters, head_hull, pEdict, &tr); // if nothing hit (else a wall is in between and we don't care about that): - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { if (tr.pHit) { return tr.pHit; } @@ -4230,7 +4231,8 @@ void cBot::increaseTimeToMoveToNode(float timeInSeconds) { const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); char msg[255]; memset(msg, 0, sizeof(msg)); - sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); + sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", + timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); rprint_trace("increaseTimeToMoveToNode", msg); } else { rprint_trace("increaseTimeToMoveToNode", "Refused to increase time"); @@ -4310,7 +4312,7 @@ bool cBot::createPath(int destinationNode, int flags) { void cBot::doDuck() { UTIL_BotPressKey(this, IN_DUCK); - this->f_hold_duck = gpGlobals->time + 0.5; + this->f_hold_duck = gpGlobals->time + 0.5f; this->increaseTimeToMoveToNode(0.5); } @@ -4343,11 +4345,11 @@ void cBot::doJump(Vector &vector) { void cBot::doJump() { rprint_trace("doJump", "no vector"); UTIL_BotPressKey(this, IN_JUMP); - this->f_jump_time = gpGlobals->time + 0.5; + this->f_jump_time = gpGlobals->time + 0.5f; // duck like this, because doDuck increases node time *again*, so no UTIL_BotPressKey(this, IN_DUCK); // DUCK jump by default - this->f_hold_duck = gpGlobals->time + 0.5; + this->f_hold_duck = gpGlobals->time + 0.5f; this->increaseTimeToMoveToNode(0.75); } diff --git a/bot.h b/bot.h index 6704320..5b5039f 100644 --- a/bot.h +++ b/bot.h @@ -119,8 +119,8 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3); #define WANDER_LEFT 1 #define WANDER_RIGHT 2 -#define BOT_PITCH_SPEED 20 -#define BOT_YAW_SPEED 20 +#define BOT_PITCH_SPEED 30 +#define BOT_YAW_SPEED 30 #define RESPAWN_NONE 0 // Added by Stefan #define RESPAWN_IDLE 1 diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 858ad0b..c9e859f 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -487,7 +487,7 @@ void BotConsole(cBot *pBot) { // reset pBot->console_nr = -1; - pBot->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.2, 0.5); + pBot->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.2f, 0.5f); } if (pBot->console_nr > 0) diff --git a/bot_client.cpp b/bot_client.cpp index 641bb3b..6b0df25 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -27,7 +27,7 @@ * **/ - +#include #include #include #include @@ -459,7 +459,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { if (pBot->getPathIndex() > 0) { // was one node further, so we can use previous node! const int iNode = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, pBot->getPreviousPathIndex()); - const float fDist = fabs(damage_origin.z - NodeMachine.node_vector(iNode).z); + const float fDist = std::fabs(damage_origin.z - NodeMachine.node_vector(iNode).z); if (fDist > 90) { // we know where we came from, and we know where we went to const int iNodeTo = NodeMachine.getNodeIndexFromBotForPath(pBot->iBotIndex, @@ -822,12 +822,12 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { } else if (state == 6) { state = 0; - float length = (duration + hold_time) / 4096.0; + float length = (duration + hold_time) / 4096.0f; int iDevide = bots[bot_index].bot_skill; if (iDevide < 1) iDevide = 1; - length -= ((10 / iDevide) * 0.5); + length -= ((10 / iDevide) * 0.5f); bots[bot_index].fBlindedTime = gpGlobals->time + length; diff --git a/bot_func.cpp b/bot_func.cpp index 9ccf755..95671ab 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -65,7 +65,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { pEdict->v.pContainingEntity, &tr); // When our check string is not "none" and the traceline has a hit... - if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0) { + if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; const edict_t *pent = tr.pHit; // Ok now retrieve the entity @@ -79,7 +79,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { } else { // check if line of sight to object is not blocked (i.e. visible) - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return true; else return false; @@ -96,7 +96,7 @@ bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { UTIL_TraceLine(start, dest, dont_ignore_monsters, nullptr, &tr); // Als we geblokt worden EN we checken voor een naam - if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0) { + if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; const edict_t *pent = tr.pHit; // Ok now retrieve the entity @@ -110,7 +110,7 @@ bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { } else { // check if line of sight to object is not blocked (i.e. visible) // Als er NONE wordt opgegeven dan checken we gewoon of we worden geblokt - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return TRUE; else return FALSE; @@ -428,7 +428,7 @@ bool BotShouldJump(cBot *pBot) { UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { pBot->rprint_trace("BotShouldJump", "I cannot jump because something is blocking the max jump height"); return false; } else { @@ -442,7 +442,7 @@ bool BotShouldJump(cBot *pBot) { // trace a line forward at maximum jump height... UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { pBot->rprint_trace("BotShouldJump", "cannot jump because body is blocked"); return false; } else { @@ -474,7 +474,7 @@ bool BotShouldJump(cBot *pBot) { UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0) { + if (tr.flFraction < 1.0f) { pBot->rprint_trace("BotShouldJump", "Yes should jump, kneecaps hit something, so it is jumpable"); return true; } @@ -551,7 +551,7 @@ bool BotShouldDuck(cBot *pBot) { UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return false; v_source = pEdict->v.origin; @@ -561,7 +561,7 @@ bool BotShouldDuck(cBot *pBot) { UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; return true; @@ -678,8 +678,8 @@ void FUNC_HearingTodo(cBot *pBot) { // More chance on getting to true const int health = pBot->bot_health; - int action = 0; - int etime = 0; + int action; + int etime; if (health < 25) action = 2; diff --git a/bot_navigate.cpp b/bot_navigate.cpp index d8365bd..d711258 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -98,7 +98,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; // now check same height to one side of the bot... @@ -113,7 +113,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; // now check same height on the other side of the bot... @@ -128,7 +128,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; // now trace from head level downward to check for obstructions... @@ -150,7 +150,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; // now check same height to one side of the bot... @@ -165,7 +165,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; // now check same height on the other side of the bot... @@ -180,7 +180,7 @@ bool BotCanJumpUp(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return FALSE; return TRUE; @@ -217,7 +217,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; // now check same height to one side of the bot... @@ -230,7 +230,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; // now check same height on the other side of the bot... @@ -244,7 +244,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace hit something, return FALSE - if (tr.flFraction < 1.0) + if (tr.flFraction < 1.0f) return false; // now trace from the ground up to check for object to duck under... @@ -261,7 +261,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return false; // now check same height to one side of the bot... @@ -276,7 +276,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return false; // now check same height on the other side of the bot... @@ -291,7 +291,7 @@ bool BotCanDuckUnder(cBot * pBot) { pEdict->v.pContainingEntity, &tr); // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0) + if (tr.flFraction >= 1.0f) return false; return true; diff --git a/dll.cpp b/dll.cpp index f2bca5f..2fa7c1e 100644 --- a/dll.cpp +++ b/dll.cpp @@ -388,11 +388,11 @@ int Spawn(edict_t *pent) { g_GameRules = TRUE; //bot_cfg_pause_time = 0.0; - respawn_time = 0.0; + respawn_time = 0.0f; spawn_time_reset = FALSE; prev_num_bots = num_bots; num_bots = 0; - bot_check_time = gpGlobals->time + 30.0; + bot_check_time = gpGlobals->time + 30.0f; rblog("SPAWN : f_load_time is set\n"); f_load_time = gpGlobals->time + 6; @@ -433,7 +433,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, int i; // don't try to add bots for 60 seconds, give client time to get added - bot_check_time = gpGlobals->time + 60.0; + bot_check_time = gpGlobals->time + 60.0f; for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) // count the number of bots in use @@ -586,11 +586,11 @@ void StartFrame() { // which is determined by comparing the previously recorded time (at the end of this function) // with the current time. If the current time somehow was less (before) the previous time, then we // assume a reset/restart/reload of a map. - if ((gpGlobals->time + 0.1) < previous_time) { + if ((gpGlobals->time + 0.1f) < previous_time) { static int index; - static float check_server_cmd = 0.0; + static float check_server_cmd = 0.0f; rblog("NEW MAP because time is reset #1\n"); - check_server_cmd = 0.0; // reset at start of map + check_server_cmd = 0.0f; // reset at start of map count = 0; @@ -600,7 +600,7 @@ void StartFrame() { if (count >= prev_num_bots) { pBot->bIsUsed = false; pBot->respawn_state = RESPAWN_NONE; - pBot->fKickTime = 0.0; + pBot->fKickTime = 0.0f; } if (pBot->bIsUsed) // is this slot used? @@ -610,18 +610,18 @@ void StartFrame() { } // check for any bots that were very recently kicked... - if ((pBot->fKickTime + 5.0) > previous_time) { + if ((pBot->fKickTime + 5.0f) > previous_time) { pBot->respawn_state = RESPAWN_NEED_TO_RESPAWN; count++; } else { - pBot->fKickTime = 0.0; // reset to prevent false spawns later + pBot->fKickTime = 0.0f; // reset to prevent false spawns later } // set the respawn time if (IS_DEDICATED_SERVER()) { - respawn_time = gpGlobals->time + 5.0; + respawn_time = gpGlobals->time + 5.0f; } else { - respawn_time = gpGlobals->time + 20.0; + respawn_time = gpGlobals->time + 20.0f; } // Send welcome message @@ -635,9 +635,9 @@ void StartFrame() { NodeMachine.resetCheckedValuesForGoals(); //ChatEngine.fThinkTimer = gpGlobals->time; - client_update_time = gpGlobals->time + 10.0; // start updating client data again + client_update_time = gpGlobals->time + 10.0f; // start updating client data again - bot_check_time = gpGlobals->time + 30.0; + bot_check_time = gpGlobals->time + 30.0f; } // New map/reload/restart // @@ -645,7 +645,7 @@ void StartFrame() { // if (!welcome_sent) { int iIndex = 0; - if (welcome_time == 0.0) { + if (welcome_time == 0.0f) { // go through all clients (except bots) for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { @@ -653,13 +653,13 @@ void StartFrame() { // skip invalid players if ((pPlayer) && (!pPlayer->free)) { // we found a player which is alive. w00t - welcome_time = gpGlobals->time + 10.0; + welcome_time = gpGlobals->time + 10.0f; break; } } } - if ((welcome_time > 0.0) && (welcome_time < gpGlobals->time)) { + if ((welcome_time > 0.0f) && (welcome_time < gpGlobals->time)) { // let's send a welcome message to this client... char total_welcome[256]; sprintf(total_welcome, "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); @@ -705,7 +705,7 @@ void StartFrame() { } if (client_update_time <= gpGlobals->time) { - client_update_time = gpGlobals->time + 1.0; + client_update_time = gpGlobals->time + 1.0f; for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) { @@ -722,8 +722,8 @@ void StartFrame() { } // a few seconds after map load we assign goals - if (f_load_time < gpGlobals->time && f_load_time != 0.0) { - f_load_time = 0.0; // do not load again + if (f_load_time < gpGlobals->time && f_load_time != 0.0f) { + f_load_time = 0.0f; // do not load again rblog("NEW MAP because time is reset #2\n"); Game.DetermineMapGoal(); Game.resetRoundTime(); @@ -791,11 +791,11 @@ void StartFrame() { } } // 2 seconds thinking - f_minplayers_think = gpGlobals->time + 2; + f_minplayers_think = gpGlobals->time + 2.0f; } // INTERNET MODE: if (internet_play == false) - add_timer = gpGlobals->time + 2.0; + add_timer = gpGlobals->time + 2.0f; else // ------------ INTERNET MODE IS ON ------------ { bool max_serverbots = true; // Reached MAX bots? @@ -829,7 +829,7 @@ void StartFrame() { if (add_timer > gpGlobals->time && internet_addbot) { internet_addbot = false; Game.createBot(nullptr, nullptr, nullptr, nullptr, nullptr); - bot_check_time = gpGlobals->time + 5.0; + bot_check_time = gpGlobals->time + 5.0f; } } @@ -916,7 +916,7 @@ void StartFrame() { } // are we currently respawning bots and is it time to spawn one yet? - if ((respawn_time > 1.0) && (respawn_time <= gpGlobals->time)) { + if ((respawn_time > 1.0f) && (respawn_time <= gpGlobals->time)) { int index = 0; // find bot needing to be respawned... while ((index < 32) @@ -944,10 +944,10 @@ void StartFrame() { // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function f_minplayers_think = gpGlobals->time + 15; // do not check this for 15 seconds from now - respawn_time = gpGlobals->time + 2.0; // set next respawn time - bot_check_time = gpGlobals->time + 5.0; + respawn_time = gpGlobals->time + 3.0f; // set next respawn time + bot_check_time = gpGlobals->time + 5.0f; } else { - respawn_time = 0.0; + respawn_time = 0.0f; } } @@ -970,9 +970,9 @@ void StartFrame() { ALERT(at_console, "bot.cfg file not found\n"); if (IS_DEDICATED_SERVER()) - bot_cfg_pause_time = gpGlobals->time + 5.0; + bot_cfg_pause_time = gpGlobals->time + 5.0f; else - bot_cfg_pause_time = gpGlobals->time + 20.0; + bot_cfg_pause_time = gpGlobals->time + 20.0f; } if (!IS_DEDICATED_SERVER() && !spawn_time_reset) { @@ -980,18 +980,18 @@ void StartFrame() { if (IsAlive(pHostEdict)) { spawn_time_reset = TRUE; - if (respawn_time >= 1.0) - respawn_time = min(respawn_time, gpGlobals->time + (float) 1.0); + if (respawn_time >= 1.0f) + respawn_time = min(respawn_time, gpGlobals->time + (float) 1.0f); - if (bot_cfg_pause_time >= 1.0) + if (bot_cfg_pause_time >= 1.0f) bot_cfg_pause_time = min(bot_cfg_pause_time, - gpGlobals->time + (float) 1.0); + gpGlobals->time + (float) 1.0f); } } } // DO BOT.CFG crap here - if ((bot_cfg_fp) && (bot_cfg_pause_time >= 1.0) + if ((bot_cfg_fp) && (bot_cfg_pause_time >= 1.0f) && (bot_cfg_pause_time <= gpGlobals->time)) { // process bot.cfg file options... ProcessBotCfgFile(); @@ -1208,11 +1208,11 @@ void RealBot_ServerCommand() { } } else if (FStrEq(pcmd, "sound")) { - EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "misc/imgood12.wav", 1.0, + EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "misc/imgood12.wav", 1.0f, ATTN_NORM, 0, 100); } else if (FStrEq(pcmd, "add")) { const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); - bot_check_time = gpGlobals->time + 5.0; + bot_check_time = gpGlobals->time + 5.0f; if (iStatus == GAME_MSG_SUCCESS) sprintf(cMessage, "REALBOT: Successfully created bot."); @@ -1872,7 +1872,7 @@ void RealBot_ServerCommand() { sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); } else { Game.bDebug = -1; - sprintf(cMessage, "RBDEBUG: Debug messages on for all bots", Game.bDebug); + sprintf(cMessage, "RBDEBUG: Debug messages on for all bots"/*, Game.bDebug*/); } } } else if (FStrEq(arg1, "verbosity")) { // realbot verbosity diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 577e905..3373d9f 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -13,7 +13,7 @@ DynamicLibrary - v142 + v143 false MultiByte diff --git a/util.cpp b/util.cpp index 35c6ccd..6af8780 100644 --- a/util.cpp +++ b/util.cpp @@ -381,7 +381,7 @@ bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { const float flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); - if (flDot > 0.50) // 60 degree field of view + if (flDot > 0.50f) // 60 degree field of view { return TRUE; } else { @@ -407,7 +407,7 @@ bool FVisible(const Vector &vecOrigin, edict_t *pEdict) { UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, pEdict, &tr); - if (tr.flFraction != 1.0) { + if (tr.flFraction != 1.0f) { return FALSE; // Line of sight is not established } else { return TRUE; // line of sight is valid. @@ -534,7 +534,7 @@ void UTIL_BotPressKey(cBot *pBot, int type) { // FIX: Do not let bots do anything with this weapon for 0.7 second. So the engine can // update the information. - pBot->f_update_weapon_time = gpGlobals->time + 0.7; + pBot->f_update_weapon_time = gpGlobals->time + 0.7f; } // KEY: End @@ -793,7 +793,7 @@ void UTIL_BotSprayLogo(edict_t *pEntity, char *logo_name) { if (index < 0) return; - if ((pTrace.pHit) && (pTrace.flFraction < 1.0)) { + if ((pTrace.pHit) && (pTrace.flFraction < 1.0f)) { if (pTrace.pHit->v.solid != SOLID_BSP) return; @@ -921,23 +921,23 @@ void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { WRITE_SHORT(FixedUnsigned16(0.0078125, 1 << 8)); WRITE_SHORT(FixedUnsigned16(2, 1 << 8)); WRITE_SHORT(FixedUnsigned16(6, 1 << 8)); - WRITE_SHORT(FixedUnsigned16(0.1, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(0.1f, 1 << 8)); WRITE_STRING(static_cast(&msg[0])); MESSAGE_END(); } void UTIL_FixAngles(Vector *Angles) { - if (Angles->x > 180.0) - Angles->x -= 360.0; - if (Angles->x < -180.0) - Angles->x += 360.0; - if (Angles->y > 180.0) - Angles->y -= 360.0; - if (Angles->y < -180.0) - Angles->y += 360.0; - - Angles->z = 0.0; + if (Angles->x > 180.0f) + Angles->x -= 360.0f; + if (Angles->x < -180.0f) + Angles->x += 360.0f; + if (Angles->y > 180.0f) + Angles->y -= 360.0f; + if (Angles->y < -180.0f) + Angles->y += 360.0f; + + Angles->z = 0.0f; } void UTIL_SayTextBot(const char *pText, cBot *pBot) { From 7ce14236242625c534bb9a468bbe768e2251ad1c Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Mar 2022 13:57:53 +0000 Subject: [PATCH 025/114] Code Modernised --- NodeMachine.cpp | 2 +- bot.cpp | 33 +++++++++++++-------------------- bot_client.cpp | 4 ++-- bot_func.cpp | 2 +- build.cpp | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index f518f69..2010841 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -3406,7 +3406,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } // A bit off randomness - float weight = 50 / pBot->ipRandom; // (yes, this will give us 1 or higher score) + float weight = static_cast(50) / pBot->ipRandom; // (yes, this will give us 1 or higher score) weight *= score; score += weight; diff --git a/bot.cpp b/bot.cpp index c324c15..9b1e191 100644 --- a/bot.cpp +++ b/bot.cpp @@ -136,7 +136,7 @@ void cBot::SpawnInit() { fUpdateTime = gpGlobals->time; fLastRunPlayerMoveTime = gpGlobals->time - 0.1f; fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5, 5); + fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); @@ -159,7 +159,7 @@ void cBot::SpawnInit() { f_c4_time = gpGlobals->time; f_update_weapon_time = gpGlobals->time; f_follow_time = gpGlobals->time; - f_jump_time = 0.0; + f_jump_time = 0.0f; f_hold_duck = gpGlobals->time; f_camp_time = gpGlobals->time; f_wait_time = gpGlobals->time; @@ -176,11 +176,11 @@ void cBot::SpawnInit() { f_strafe_time = gpGlobals->time; // Personality Related (these gets changed when loading personality file) - fpXOffset = 0.0; - fpYOffset = 0.0; - fpZOffset = 0.0; - fpMinReactTime = 0.0; - fpMaxReactTime = 0.0; + fpXOffset = 0.0f; + fpYOffset = 0.0f; + fpZOffset = 0.0f; + fpMinReactTime = 0.0f; + fpMaxReactTime = 0.0f; // ------------------------ // POINTERS @@ -2874,7 +2874,7 @@ void cBot::Memory() { } // we go to the destination - const float fTime = 5 + (ipFearRate / 7); + const float fTime = 5 + (ipFearRate / static_cast(7)); if (RANDOM_LONG(0, 100) < ipFearRate && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk @@ -4019,16 +4019,10 @@ void BotThink(cBot *pBot) { char msg[255]; sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); - g_engfuncs.pfnRunPlayerMove(pBot->pEdict, - pBot->vecMoveAngles, - pBot->f_move_speed, - pBot->f_strafe_speed, - upMove, - pBot->pEdict->v.button, - 0, - msecval); - - constexpr float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps + g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, + upMove, pBot->pEdict->v.button, 0, msecval); + + const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; } @@ -4044,8 +4038,7 @@ void cBot::Dump() { _snprintf(buffer, 180, "%s (#%d %s): timers, now= %.0f, c4_time=%.0f, camp_time=%.0f, wait_time=%.0f, cover_time=%.0f, wander=%.0f, MoveToNodeTime=%.0f\n", name, iBotIndex, (iTeam == 1) ? "T" : "CT", gpGlobals->time, - f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, - fMoveToNodeTime); + f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, fMoveToNodeTime); rblog(buffer); _snprintf(buffer, 180, " GoalNode=%d, CurrentNode=%d, iPathFlags=", iGoalNode, iCurrentNode); diff --git a/bot_client.cpp b/bot_client.cpp index 6b0df25..8db4f0f 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -822,12 +822,12 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { } else if (state == 6) { state = 0; - float length = (duration + hold_time) / 4096.0f; + float length = (static_castduration + hold_time) / 4096.0f; int iDevide = bots[bot_index].bot_skill; if (iDevide < 1) iDevide = 1; - length -= ((10 / iDevide) * 0.5f); + length -= ((static_cast(10) / iDevide) * 0.5f); bots[bot_index].fBlindedTime = gpGlobals->time + length; diff --git a/bot_func.cpp b/bot_func.cpp index 95671ab..b8a96cd 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -965,7 +965,7 @@ bool BOT_DecideTakeCover(cBot *pBot) { // logs into a file void rblog(char *txt) { // output to stdout - printf(txt); + printf("%s", txt); // and to reallog file if (fpRblog) { diff --git a/build.cpp b/build.cpp index 8273554..4c239fa 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -char *rb_version_nr = "4.0.2-APG"; +char *rb_version_nr = "4.0.3-APG"; From 53077f76a062d82b324a71dffe7044e55b4c661d Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Mar 2022 13:58:38 +0000 Subject: [PATCH 026/114] Update dll.cpp --- dll.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dll.cpp b/dll.cpp index 2fa7c1e..766f5fb 100644 --- a/dll.cpp +++ b/dll.cpp @@ -43,7 +43,7 @@ // this makes sure function `min` is available (instead of fmin). #include -using namespace std; +//using namespace std; DLL_FUNCTIONS gFunctionTable; DLL_FUNCTIONS gFunctionTable_post; @@ -67,13 +67,13 @@ cNodeMachine NodeMachine; cChatEngine ChatEngine; FILE *fpRblog = nullptr; -float f_load_time = 0.0; -float f_minplayers_think = 0.0; // timer used to add realbots if internet play enabled +float f_load_time = 0.0f; +float f_minplayers_think = 0.0f; // timer used to add realbots if internet play enabled int mod_id = CSTRIKE_DLL; // should be changed to 0 when we are going to do multi-mod stuff int m_spriteTexture = 0; bool isFakeClientCommand = FALSE; int fake_arg_count; -float bot_check_time = 30.0; +float bot_check_time = 30.0f; int min_bots = -1; int max_bots = -1; int min_players = -1; // minimum amount of players that should be in the server all the time @@ -82,13 +82,13 @@ int prev_num_bots = 0; bool g_GameRules = FALSE; edict_t *clients[32]; edict_t *pHostEdict = nullptr; -float welcome_time = 0.0; +float welcome_time = 0.0f; bool welcome_sent = false; FILE *bot_cfg_fp = nullptr; bool need_to_open_cfg = TRUE; -float bot_cfg_pause_time = 0.0; -float respawn_time = 0.0; +float bot_cfg_pause_time = 0.0f; +float respawn_time = 0.0f; bool spawn_time_reset = FALSE; // Interval between joining bots. From b4997c9dbfa77a972a72b92d774ede3cfa6a226a Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Mar 2022 14:08:43 +0000 Subject: [PATCH 027/114] Tiny fixes --- bot_client.cpp | 2 +- build.cpp | 2 +- dll.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/bot_client.cpp b/bot_client.cpp index 8db4f0f..1b7eda6 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -822,7 +822,7 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { } else if (state == 6) { state = 0; - float length = (static_castduration + hold_time) / 4096.0f; + float length = (static_cast(duration + hold_time)) / 4096.0f; int iDevide = bots[bot_index].bot_skill; if (iDevide < 1) iDevide = 1; diff --git a/build.cpp b/build.cpp index 4c239fa..4a5d2f4 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -char *rb_version_nr = "4.0.3-APG"; +const char *rb_version_nr = "4.0.3-APG"; diff --git a/dll.cpp b/dll.cpp index 766f5fb..446a344 100644 --- a/dll.cpp +++ b/dll.cpp @@ -99,8 +99,8 @@ int internet_min_interval = 10; // Counter-Strike 1.6 or 1.5 int counterstrike = 0; // Default 1.5 -void UpdateClientData(const struct edict_s *ent, int sendweapons, - struct clientdata_s *cd); +void UpdateClientData(const edict_s *ent, int sendweapons, + clientdata_s *cd); void ProcessBotCfgFile(); @@ -1043,6 +1043,67 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { isFakeClientCommand = FALSE; } +/*void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) // KWo 02.03.2010 - thanks to MeRcyLeZZ +{ + static int sending; + static int bot_index; + static edict_t* pPlayer; + + if (g_i_cv_latencybot != 2) + RETURN_META(MRES_IGNORED); + + sending = 0; + + // Scoreboard key being pressed? + if (!FNullEnt(ent) && ent->v.flags & FL_CLIENT + && (ent->v.button & IN_SCORE || ent->v.oldbuttons & IN_SCORE)) + { + pPlayer = INDEXENT(ENTINDEX(ent)); + + for (bot_index = 0; bot_index < gpGlobals->maxClients; bot_index++) + { + if (bots[bot_index].is_used && !FNullEnt(bots[bot_index].pEdict)) + { + // Send message with the weird arguments + switch (sending) + { + case 0: + { + // Start a new message + MESSAGE_BEGIN(MSG_ONE_UNRELIABLE, SVC_PINGS, NULL, pPlayer); + WRITE_BYTE(bots[bot_index].iOffsetPing[0] * 64 + (1 + 2 * bot_index)); + WRITE_SHORT(bots[bot_index].iArgPing[0]); + sending++; + } + case 1: + { + // Append additional data + WRITE_BYTE(bots[bot_index].iOffsetPing[1] * 128 + (2 + 4 * bot_index)); + WRITE_SHORT(bots[bot_index].iArgPing[1]); + sending++; + } + case 2: + { + // Append additional data and end message + WRITE_BYTE(4 + 8 * bot_index); + WRITE_SHORT(bots[bot_index].iArgPing[2]); + WRITE_BYTE(0); + MESSAGE_END(); + sending = 0; + } + } + } + } + // End message if not yet sent + if (sending) + { + WRITE_BYTE(0); + MESSAGE_END(); + } + } + RETURN_META(MRES_IGNORED); +}*/ + void ProcessBotCfgFile() { char cmd_line[256]; static char server_cmd[80]; From 04772abac9dc610a4ac0a0d8cb5188ddfc9b87ae Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Mar 2022 15:15:38 +0000 Subject: [PATCH 028/114] Version 4.0.3-APG ready --- NodeMachine.cpp | 13 ------------- bot.cpp | 12 ++++++------ dll.cpp | 22 +++++++++++++--------- game.cpp | 4 +--- 4 files changed, 20 insertions(+), 31 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 2010841..d78e887 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2276,9 +2276,6 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // a node that should be closed is an evaluated node and the most preferred one. // open up all neighbouring nodes, and close this one if (nodeToClose > -1) { -// char msg[255]; -// sprintf(msg, "Found node to close [%d]\n", nodeToClose); -// rblog(msg); astar_list[nodeToClose].state = CLOSED; int botTeam = -1; if (pBot) { @@ -2287,7 +2284,6 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn openNeighbourNodes(nodeStartIndex, nodeToClose, nodeTargetIndex, botTeam); } else { -// rblog("Did not find any open waypoint\n"); break; } } @@ -2304,15 +2300,6 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn for (nodeIndex = 0; nodeIndex < MAX_PATH_NODES; nodeIndex++) { const tNodestar &nodeStar = astar_list[nodeIndex]; if (nodeStar.state == AVAILABLE) continue; - -// char msg[255]; -// memset(msg, 0, sizeof(msg)); -// if (nodeStar.state == CLOSED) { -// sprintf(msg, "Node [%d] is CLOSED. Cost = %f. Parent = %d\n", nodeIndex, nodeStar.cost, nodeStar.parent); -// } else if (nodeStar.state == OPEN) { -// sprintf(msg, "Node [%d] is OPEN. Cost = %f. Parent = %d\n", nodeIndex, nodeStar.cost, nodeStar.parent); -// } -// rblog(msg); } // Build path (from goal to start, read out parent waypoint to backtrace) diff --git a/bot.cpp b/bot.cpp index 9b1e191..7714287 100644 --- a/bot.cpp +++ b/bot.cpp @@ -274,7 +274,7 @@ void cBot::SpawnInit() { // ------------------------ // FLOATS // ------------------------ - f_strafe_speed = 0.0; + f_strafe_speed = 0.0f; f_max_speed = CVAR_GET_FLOAT("sv_maxspeed"); // ------------------------ @@ -309,7 +309,7 @@ void cBot::NewRound() { fLastRunPlayerMoveTime = gpGlobals->time; fCheckHostageStatusTimer = gpGlobals->time; fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5, 5); + fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5.0f); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); @@ -434,7 +434,7 @@ void cBot::NewRound() { // ------------------------ // VECTORS // ------------------------ - prevOrigin = Vector(9999.0, 9999.0, 9999.0); + prevOrigin = Vector(9999.0f, 9999.0f, 9999.0f); lastSeenEnemyVector = Vector(0, 0, 0); vEar = Vector(9999, 9999, 9999); @@ -3236,7 +3236,7 @@ void cBot::Think() { if (chChatSentence[0] == '\0') // we did not want to say anything if (RANDOM_LONG(0, 100) < ipChatRate) // rate fChatTime = gpGlobals->time + - RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + 1) / 2)); // wait + RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + static_cast(1)) / 2)); // wait } @@ -3646,8 +3646,8 @@ bool BotRadioAction() { if (BotPointer == nullptr) continue; // somehow this fucked up, bail out - const float distance = func_distance(plr->v.origin, - BotPointer->pEdict->v.origin); // distance between the 2 + const auto distance = func_distance(plr->v.origin, + BotPointer->pEdict->v.origin); // distance between the 2 // Same team, randomly, do we even listen to the radio? // the more further away, the more chance it will not listen diff --git a/dll.cpp b/dll.cpp index 446a344..558d84c 100644 --- a/dll.cpp +++ b/dll.cpp @@ -55,7 +55,7 @@ extern cBot bots[32]; extern bool radio_message; -extern char *rb_version_nr; +extern const char *rb_version_nr; extern char *message; // DLL specific variables @@ -99,8 +99,7 @@ int internet_min_interval = 10; // Counter-Strike 1.6 or 1.5 int counterstrike = 0; // Default 1.5 -void UpdateClientData(const edict_s *ent, int sendweapons, - clientdata_s *cd); +//void UpdateClientData(const edict_s *ent, int sendweapons, clientdata_s *cd); //Not used? [APG]RoboCop[CL] void ProcessBotCfgFile(); @@ -523,20 +522,25 @@ void ClientCommand(edict_t *pEntity) { RETURN_META(MRES_IGNORED); } - // TODO: Revise this method void StartFrame() { if (!gpGlobals->deathmatch) return; // bots only work in 'deathmatch mode' -// REALBOT_PRINT("StartFrame", "BEGIN"); + //REALBOT_PRINT("StartFrame", "BEGIN"); edict_t *pPlayer; static int i, player_index, bot_index; - static float previous_time = -1.0; - static float client_update_time = 0.0; + static float previous_time = -1.0f; + static float client_update_time = 0.0f; clientdata_s cd; int count = 0; int waits = 0; // How many bots had to wait. + // Experimental autovacate script from POD-Bot [APG]RoboCop[CL] + max_bots = max_bots > gpGlobals->maxClients ? gpGlobals->maxClients : max_bots < 0 ? 0 : max_bots; + min_bots = min_bots > gpGlobals->maxClients ? gpGlobals->maxClients : min_bots < 0 ? 0 : min_bots; + if (max_bots < min_bots) + min_bots = max_bots; + // When a user - or anything else - specified a higher number of 0 to // kick bots, then we will do as told. if (kick_amount_bots > 0) { @@ -626,7 +630,7 @@ void StartFrame() { // Send welcome message welcome_sent = false; - welcome_time = 0.0; + welcome_time = 0.0f; } NodeMachine.init_players(); @@ -736,7 +740,7 @@ void StartFrame() { // Send a message to clients about RealBot every round if (Game.iVersionBroadcasting == BROADCAST_ROUND) { welcome_sent = false; - welcome_time = gpGlobals->time + 2; + welcome_time = gpGlobals->time + 2.0f; } NodeMachine.init_round(); diff --git a/game.cpp b/game.cpp index 9e48265..17cd717 100644 --- a/game.cpp +++ b/game.cpp @@ -328,7 +328,6 @@ bool cGame::NamesAvailable() const return false; } // NamesAvailable() - // Picks a random name // rewritten on april 10th 2004 void cGame::SelectName(char *name) const @@ -529,7 +528,6 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg return GAME_MSG_FAIL_SERVERFULL; // failed } - char ptr[128]; // allocate space for message from ClientConnect int freeBotIndex = 0; @@ -589,7 +587,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg pBot->bIsUsed = true; pBot->respawn_state = RESPAWN_IDLE; pBot->fCreateTime = gpGlobals->time; - pBot->fKickTime = 0.0; + pBot->fKickTime = 0.0f; pBot->name[0] = 0; // name not set by server yet pBot->bot_money = 0; From 28cca6977b1114a92e3ce29643055f99eca8f280 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 1 Mar 2022 17:24:38 +0000 Subject: [PATCH 029/114] Update todo.txt --- todo.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/todo.txt b/todo.txt index 65546df..8f18fdb 100644 --- a/todo.txt +++ b/todo.txt @@ -3,7 +3,6 @@ - Bots should have better knowledge about goals (mainly for invesitigating which bomb site got the live C4 in) - Improve pathfinder - Chat rate should be lower @ default -- Improve code in overall, ugly! - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. From 394559dd8f339ed12940a3975a2f0a6a1df4efb0 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 4 Mar 2022 00:56:31 +0000 Subject: [PATCH 030/114] Reducing risk bot stuck in a cluster --- bot_navigate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bot_navigate.cpp b/bot_navigate.cpp index d711258..2b74878 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -43,7 +43,7 @@ extern int mod_id; extern edict_t *pHostEdict; -#define SCAN_RADIUS 45 // Radius to scan to prevent blocking with players +#define SCAN_RADIUS 60 // Radius to scan to prevent blocking with players /** * Given an angle, makes sure it wraps around properly @@ -51,8 +51,8 @@ extern edict_t *pHostEdict; * @return */ float fixAngle(float angle) { - if (angle > 180) return (angle - 360); - if (angle < -180) return (angle + 360); + if (angle > 180.0f) return (angle - 360.0f); + if (angle < -180.0f) return (angle + 360.0f); return angle; } From a9c66eaa796a7c3966c41793297f309da2802618 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 4 Mar 2022 02:09:50 +0000 Subject: [PATCH 031/114] Fixed CS 1.6 Buy for Five-seveN --- ChatEngine.h | 2 +- IniParser.h | 4 ++-- NodeDataTypes.h | 4 ++-- bot.cpp | 37 ++++++++++++++++++++----------------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/ChatEngine.h b/ChatEngine.h index 227e0bd..8ef75a6 100644 --- a/ChatEngine.h +++ b/ChatEngine.h @@ -29,7 +29,7 @@ // Chatting Engine #define MAX_BLOCKS 100 -#define BLOCK_DEATHS MAX_BLOCKS-1 +#define BLOCK_DEATHS (MAX_BLOCKS-1) static const int MAX_SENTENCE_LENGTH = 128; // Reply block diff --git a/IniParser.h b/IniParser.h index 3e0284f..7dcf534 100644 --- a/IniParser.h +++ b/IniParser.h @@ -33,7 +33,7 @@ **/ // Sections -#define INI_NONE -1 +#define INI_NONE (-1) #define INI_SKILL 0 // Bot skill #define INI_WEAPON 1 // Bot weapon preference #define INI_GAME 2 // Bot general game behaviour @@ -50,7 +50,7 @@ // NOTE: For weapon_buy_table.iId! // 'Words' -#define WORD_NONE -1 +#define WORD_NONE (-1) #define WORD_WALK 0 #define WORD_RUN 1 #define WORD_SHOOT 2 diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 0254f13..d051802 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -111,7 +111,7 @@ // Meridian stuff #define SIZE_MEREDIAN 256 #define MAP_MAX_SIZE 16384 -#define MAX_MEREDIANS MAP_MAX_SIZE / SIZE_MEREDIAN // Size of HL map divided by SIZE of a meridian to evenly spread +#define MAX_MEREDIANS (MAP_MAX_SIZE / SIZE_MEREDIAN) // Size of HL map divided by SIZE of a meridian to evenly spread #define MAX_NODES_IN_MEREDIANS 120 // EVY: higher number, number of nodes per meredian //#define MAX_NODES_IN_MEREDIANS 80 // (size meredian / zone (~6) times 2 (surface) , rounded to 80 @@ -120,7 +120,7 @@ #define CLOSED 2 // closed, do nothing with it #define AVAILABLE 3 // available, may open -const unsigned long g_iMaxVisibilityByte = (MAX_NODES * MAX_NODES) / 8; +const unsigned long g_iMaxVisibilityByte = MAX_NODES * MAX_NODES / 8; // doors (doors.cpp) HLSDK #define SF_DOOR_ROTATE_Y 0 diff --git a/bot.cpp b/bot.cpp index 7714287..72157e9 100644 --- a/bot.cpp +++ b/bot.cpp @@ -654,7 +654,7 @@ void cBot::AimAtEnemy() { // factor in distance, the further away the more deviation - which is based on skill const int skillReversed = (10 - bot_skill) + 1; - float fScale = 0.5f + (fDistance / (64 * + float fScale = 0.5f + (fDistance / static_cast(64 * skillReversed)); // a good skilled bot is less impacted by distance than a bad skilled bot if (CarryWeaponType() == SNIPER) fScale *= 0.80f; // sniping improves aiming @@ -671,7 +671,7 @@ void cBot::AimAtEnemy() { // Based upon how far, we make this fuzzy float fDy, fDz; - float fDx = fDy = fDz = ((bot_skill + 1) * fScale); + float fDx = fDy = fDz = static_cast(bot_skill + 1) * fScale; // Example 1: // Super skilled bot (bot_skill 1), with enemy of 2048 units away. Results into: @@ -1972,7 +1972,7 @@ void cBot::Act() { pEdict->v.button &= (~IN_RUN); // release IN_RUN rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed(static_cast(int(f_max_speed) / 2 + int(f_max_speed) / 50)); + setMoveSpeed(((f_max_speed) / 2 + (f_max_speed) / 50)); } // When we are at max speed, press IN_RUN to get a running animation @@ -2045,12 +2045,12 @@ void cBot::Act() { // ------------------------------------------- vTarget = (vHead - pEdict->v.origin); pEdict->v.v_angle = UTIL_VecToAngles(vTarget); - if (pEdict->v.v_angle.y > 180) - pEdict->v.v_angle.y -= 360; + if (pEdict->v.v_angle.y > 180.0f) + pEdict->v.v_angle.y -= 360.0f; // Paulo-La-Frite - START bot aiming bug fix - if (pEdict->v.v_angle.x > 180) - pEdict->v.v_angle.x -= 360; + if (pEdict->v.v_angle.x > 180.0f) + pEdict->v.v_angle.x -= 360.0f; Vector v_shouldbe; @@ -2603,7 +2603,7 @@ void cBot::performBuyActions(int weaponIdToBuy) { } // CS 1.6 only - if (counterstrike == 1) { // FRASHMAN 30/08/04: redone switch block, it was full of errors + else if (counterstrike == 1) { // FRASHMAN 30/08/04: redone switch block, it was full of errors switch (weaponIdToBuy) { //Pistols case CS_WEAPON_GLOCK18: @@ -2618,9 +2618,12 @@ void cBot::performBuyActions(int weaponIdToBuy) { case CS_WEAPON_DEAGLE: performBuyWeapon("1", "4"); break; + case CS_WEAPON_FIVESEVEN: + performBuyWeapon("1", "5"); + break; // CT Only case CS_WEAPON_ELITE: performBuyWeapon("1", "5"); - break; + break; // T Only //ShotGUNS case CS_WEAPON_M3: performBuyWeapon("2", "1"); @@ -2631,10 +2634,10 @@ void cBot::performBuyActions(int weaponIdToBuy) { //SMG case CS_WEAPON_MAC10: performBuyWeapon("3", "1"); - break; + break; // T Only case CS_WEAPON_TMP: performBuyWeapon("3", "1"); - break; + break; // CT Only case CS_WEAPON_MP5NAVY: performBuyWeapon("3", "2"); break; @@ -2647,16 +2650,16 @@ void cBot::performBuyActions(int weaponIdToBuy) { //rifles case CS_WEAPON_GALIL: performBuyWeapon("4", "1"); - break; + break; // T Only case CS_WEAPON_FAMAS: performBuyWeapon("4", "1"); - break; + break; // CT Only case CS_WEAPON_AK47: performBuyWeapon("4", "2"); - break; + break; // T Only case CS_WEAPON_M4A1: performBuyWeapon("4", "3"); - break; + break; // CT Only case CS_WEAPON_SG552: performBuyWeapon("4", "4"); break; @@ -2665,10 +2668,10 @@ void cBot::performBuyActions(int weaponIdToBuy) { break; case CS_WEAPON_SG550: performBuyWeapon("4", "5"); - break; + break; // CT Only case CS_WEAPON_G3SG1: performBuyWeapon("4", "6"); - break; + break; // T Only //machinegun case CS_WEAPON_M249: performBuyWeapon("5", "1"); From 33f94f6127861f8ba9c099c4f000a7e1a26fcd6f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 4 Mar 2022 02:15:17 +0000 Subject: [PATCH 032/114] Reduce chances of using pistols --- bot.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bot.cpp b/bot.cpp index 72157e9..d976a6b 100644 --- a/bot.cpp +++ b/bot.cpp @@ -2662,10 +2662,10 @@ void cBot::performBuyActions(int weaponIdToBuy) { break; // CT Only case CS_WEAPON_SG552: performBuyWeapon("4", "4"); - break; + break; // T Only case CS_WEAPON_AUG: performBuyWeapon("4", "4"); - break; + break; // CT Only case CS_WEAPON_SG550: performBuyWeapon("4", "5"); break; // CT Only @@ -2699,6 +2699,9 @@ void cBot::performBuyActions(int weaponIdToBuy) { case CS_DEFUSEKIT: performBuyWeapon("8", "6"); break; + default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] + performBuyWeapon("3", "2"); + break; } // This differs per team From a7a40d045939a36e1e862f160d40aaab2f82abd0 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 4 Mar 2022 02:22:39 +0000 Subject: [PATCH 033/114] Altered BuyCode --- bot.cpp | 16 ++++++++-------- bot_buycode.cpp | 13 ++++++++----- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/bot.cpp b/bot.cpp index d976a6b..6def965 100644 --- a/bot.cpp +++ b/bot.cpp @@ -2699,9 +2699,9 @@ void cBot::performBuyActions(int weaponIdToBuy) { case CS_DEFUSEKIT: performBuyWeapon("8", "6"); break; - default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] - performBuyWeapon("3", "2"); - break; + //default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] + // performBuyWeapon("3", "2"); + // break; } // This differs per team @@ -2880,7 +2880,7 @@ void cBot::Memory() { } // we go to the destination - const float fTime = 5 + (ipFearRate / static_cast(7)); + const float fTime = 5 + ipFearRate / static_cast(7); if (RANDOM_LONG(0, 100) < ipFearRate && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk @@ -3313,7 +3313,7 @@ void cBot::Think() { // need backup! if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "3", ""); + UTIL_BotRadioMessage(this, 3, "3", nullptr); } BOT_DecideTakeCover(this); @@ -3783,9 +3783,9 @@ bool BotRadioAction() { const bool report_back = false; if (!report_back) { - UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! + UTIL_BotRadioMessage(BotPointer, 3, "1", nullptr); // Roger that! } else { - UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! + UTIL_BotRadioMessage(BotPointer, 3, "6", nullptr); // Reporting in! } BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); @@ -4021,7 +4021,7 @@ void BotThink(cBot *pBot) { const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; pBot->fLastRunPlayerMoveTime = gpGlobals->time; - constexpr double upMove = 0.0; + const double upMove = 0.0; char msg[255]; sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); diff --git a/bot_buycode.cpp b/bot_buycode.cpp index c9e859f..c2512b7 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -110,15 +110,18 @@ bool GoodWeaponForTeam(int weapon, int team) { case CS_WEAPON_AK47: return false; break; - case CS_WEAPON_ELITE: + case CS_WEAPON_DEAGLE: return false; break; - case CS_WEAPON_MAC10: + case CS_WEAPON_MP5NAVY: return false; break; case CS_WEAPON_GALIL: return false; break; + case CS_WEAPON_P90: + return false; + break; // 30.8.04 added by frashman case CS_WEAPON_G3SG1: return false; @@ -129,19 +132,19 @@ bool GoodWeaponForTeam(int weapon, int team) { case CS_WEAPON_AUG: return false; break; - case CS_WEAPON_FIVESEVEN: + case CS_WEAPON_DEAGLE: return false; break; case CS_WEAPON_M4A1: return false; break; - case CS_WEAPON_TMP: + case CS_WEAPON_MP5NAVY: return false; break; case CS_WEAPON_FAMAS: return false; break; - case CS_WEAPON_SHIELD: + case CS_WEAPON_P90: return false; break; //30.8.04 added by Frashman From cbfabb13598771ae4dc14922faeacbe786cc0fba Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 4 Mar 2022 03:22:54 +0000 Subject: [PATCH 034/114] Experimental changes --- IniParser.cpp | 4 ++-- NodeDataTypes.h | 8 ++++---- NodeMachine.cpp | 33 ++++++++++++++++----------------- bot.cpp | 6 +++--- bot_client.cpp | 2 +- bot_func.cpp | 12 ++++++------ game.cpp | 2 +- util.cpp | 6 +++--- 8 files changed, 36 insertions(+), 37 deletions(-) diff --git a/IniParser.cpp b/IniParser.cpp index a267b80..7c04830 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -926,9 +926,9 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Skill, everything but botskill can change. // Determine reaction time based upon botskill here - float fMinReact = 0.0; + float fMinReact = 0.0f; if (pBot->bot_skill == 0) - fMinReact = 0.0; + fMinReact = 0.0f; else //30.8.04 redefined by frashman // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); diff --git a/NodeDataTypes.h b/NodeDataTypes.h index d051802..faf21fd 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -91,12 +91,12 @@ // Node costs #define NODE_DANGER 8192 // Value -#define NODE_DANGER_STEP 0.5 // Step to take to get dangerous -#define NODE_DANGER_DIST 512.0 // Distance +#define NODE_DANGER_STEP 0.5f // Step to take to get dangerous +#define NODE_DANGER_DIST 512.0f // Distance // Node contact costs #define NODE_CONTACT 8192 -#define NODE_CONTACT_STEP 0.2 +#define NODE_CONTACT_STEP 0.2f #define NODE_CONTACT_DIST 128 // Node boundries @@ -147,7 +147,7 @@ typedef struct { typedef struct { int state; // OPEN/CLOSED int parent; // Who opened this node? - double cost; // Cost + float cost; // Cost double danger; } tNodestar; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index d78e887..d400c5b 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -1845,7 +1845,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { // within distance and reachable if (tr.flFraction >= 1.0f) { - const double costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; + const float costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; InfoNodes[i].fDanger[iTeam] += costIncrease; } } @@ -2425,7 +2425,7 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou float cost = gCost + hCost; if (botTeam > -1) { - const double dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; + const float dangerCost = InfoNodes[neighbourNode].fDanger[botTeam] * cost; // double contactCost = InfoNodes[neighbourNode].fContact[botTeam] * cost; cost += dangerCost; @@ -2799,18 +2799,17 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } } - constexpr bool shouldDrawWaypointBeamsFromBot = false; + bool shouldDrawWaypointBeamsFromBot = false; + if (shouldDrawWaypointBeamsFromBot) { - tNode *nodeHeadingFor = this->getNode(currentNodeToHeadFor); + const tNode *nodeHeadingFor = this->getNode(currentNodeToHeadFor); - int player_index = 0; - for (player_index = 1; player_index <= gpGlobals->maxClients; - player_index++) { + for (int player_index = 1; player_index <= gpGlobals->maxClients; + player_index++) { edict_t *pPlayer = INDEXENT(player_index); if (pPlayer && !pPlayer->free) { - if (FBitSet(pPlayer->v.flags, FL_CLIENT) && - shouldDrawWaypointBeamsFromBot) { // do not draw for now + if (FBitSet(pPlayer->v.flags, FL_CLIENT)) { // do not draw for now DrawBeam( pPlayer, // player sees beam @@ -2908,13 +2907,13 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - unstuck // - go back in path... - constexpr float timeEvaluatingMoveSpeed = 0.1f; + const float timeEvaluatingMoveSpeed = 0.1f; const bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; - constexpr double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. + const double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. // Else it would trigger stuck logic too soon, too often. - const double speedInOneTenthOfASecond = (pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; + const double speedInOneTenthOfASecond = static_cast(pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; double expectedMoveDistance = speedInOneTenthOfASecond; if (pBot->isFreezeTime()) expectedMoveDistance = 0; if (pBot->isWalking()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; @@ -3399,7 +3398,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { score += weight; // Take into consideration how many times this goal has been selected - score = (score + (1.0f - (Goals[goalIndex].iChecked / static_cast(maxCheckedScore)))) / 2.0f; + score = (score + (1.0f - Goals[goalIndex].iChecked / static_cast(maxCheckedScore))) / 2.0f; // Danger (is important) score = (score + InfoNodes[Goals[goalIndex].iNode].fDanger[UTIL_GetTeam(pBot->pEdict)]) / 1.5f; @@ -4424,8 +4423,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (x = 0; x < DEBUG_BMP_WIDTH; x++) { Meredian = - static_cast(static_cast(x) * scale + minx + - 8192.0f) / static_cast(SIZE_MEREDIAN); + (x * scale + minx + + 8192.0f) / SIZE_MEREDIAN; if (Meredian & 0x01) { for (y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4435,8 +4434,8 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (y = 0; y < DEBUG_BMP_HEIGHT; y++) { Meredian = - static_cast(static_cast(y) * scale + miny + - 8192.0f) / static_cast(SIZE_MEREDIAN); + (y * scale + miny + + 8192.0f) / SIZE_MEREDIAN; if (Meredian & 0x01) { for (x = 0; x < DEBUG_BMP_HEIGHT; x++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; diff --git a/bot.cpp b/bot.cpp index 6def965..e94da12 100644 --- a/bot.cpp +++ b/bot.cpp @@ -3313,7 +3313,7 @@ void cBot::Think() { // need backup! if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "3", nullptr); + UTIL_BotRadioMessage(this, 3, "3", ""); } BOT_DecideTakeCover(this); @@ -3783,9 +3783,9 @@ bool BotRadioAction() { const bool report_back = false; if (!report_back) { - UTIL_BotRadioMessage(BotPointer, 3, "1", nullptr); // Roger that! + UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! } else { - UTIL_BotRadioMessage(BotPointer, 3, "6", nullptr); // Reporting in! + UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! } BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); diff --git a/bot_client.cpp b/bot_client.cpp index 1b7eda6..524c850 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -827,7 +827,7 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { if (iDevide < 1) iDevide = 1; - length -= ((static_cast(10) / iDevide) * 0.5f); + length -= (static_cast(10) / static_cast(iDevide) * 0.5f); bots[bot_index].fBlindedTime = gpGlobals->time + length; diff --git a/bot_func.cpp b/bot_func.cpp index b8a96cd..d3fb13b 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -85,7 +85,7 @@ VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { return false; } - return false; + //return false; } @@ -522,7 +522,7 @@ bool BotShouldDuck(cBot *pBot) { return false; } - return BotCanDuckUnder(pBot); + //return BotCanDuckUnder(pBot); //Makes the code underneath unreachable? [APG]RoboCop[CL] // WHen a bot should jump, something is blocking his way. // Most of the time it is a fence, or a 'half wall' that reaches from body to feet @@ -532,7 +532,7 @@ bool BotShouldDuck(cBot *pBot) { // When head blocked and waist is free, then we should duck... TraceResult tr; - Vector v_duck, v_source, v_dest; + Vector v_duck; edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... @@ -544,8 +544,8 @@ bool BotShouldDuck(cBot *pBot) { UTIL_MakeVectors(v_duck); // Check if head is blocked - v_source = pEdict->v.origin + Vector(0, 0, +37); - v_dest = v_source + gpGlobals->v_forward * 24; + Vector v_source = pEdict->v.origin + Vector(0, 0, +37); + Vector v_dest = v_source + gpGlobals->v_forward * 24; // trace a line forward at maximum jump height... UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, @@ -679,7 +679,7 @@ void FUNC_HearingTodo(cBot *pBot) { const int health = pBot->bot_health; int action; - int etime; + float etime; if (health < 25) action = 2; diff --git a/game.cpp b/game.cpp index 17cd717..4a30865 100644 --- a/game.cpp +++ b/game.cpp @@ -702,7 +702,7 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { const float roundTimeInSeconds = roundTimeInMinutes * 60; const float roundTimeRemaining = roundTimeInSeconds - roundElapsedTimeInSeconds; - const int minutesLeft = roundTimeRemaining / 60; + const int minutesLeft = static_cast(roundTimeRemaining) / 60; const int secondsLeft = static_cast(roundTimeRemaining) % 60; sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); diff --git a/util.cpp b/util.cpp index 6af8780..e56486d 100644 --- a/util.cpp +++ b/util.cpp @@ -879,7 +879,7 @@ int UTIL_GetGrenadeType(edict_t *pEntity) { // 2 functions from podbot source unsigned short FixedUnsigned16(float value, float scale) { - int output = static_cast(value) * scale; + int output = static_cast(value * scale); if (output < 0) output = 0; if (output > 0xFFFF) @@ -889,7 +889,7 @@ unsigned short FixedUnsigned16(float value, float scale) { } short FixedSigned16(float value, float scale) { - int output = static_cast(value) * scale; + int output = static_cast(value * scale); if (output > 32767) output = 32767; @@ -946,7 +946,7 @@ void UTIL_SayTextBot(const char *pText, cBot *pBot) { char szTemp[160]; char szName[BOT_NAME_LEN + 1]; - int i = 0; + int i; // clear out memset(szTemp, 0, sizeof(szTemp)); From 9299daf460e88c109a791eb83560e8c25a4d0ac2 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 15 Mar 2022 15:58:49 +0000 Subject: [PATCH 035/114] Update todo.txt --- todo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo.txt b/todo.txt index 8f18fdb..fc7bbc6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,6 @@ - Bots may not camp when last in team (or second last?) - Bots should know when others are near its waypoint, so it won't run into each other -- Bots should have better knowledge about goals (mainly for invesitigating which bomb site got the live C4 in) +- Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) - Improve pathfinder - Chat rate should be lower @ default - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples From 00f454dc2626323d194bda172631ff923c676ea1 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 2 Apr 2022 13:34:02 +0100 Subject: [PATCH 036/114] Attempting fixing the Todos --- NodeMachine.cpp | 4 ++-- bot.cpp | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index d400c5b..e75e84b 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -428,8 +428,8 @@ bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { // if inside wall: return false if (tr.fStartSolid == 1) { - // todo: make sure the node does not start within this wall - return false; // not floating + rblog("(node) node_float | node is inside wall!\n"); + return false; } return false; // not floating diff --git a/bot.cpp b/bot.cpp index e94da12..b5b3e59 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1896,12 +1896,12 @@ void cBot::Act() { // camp if (f_camp_time > gpGlobals->time) { // When camping we duck and we don't move - // todo, camping can be done standing too, but this does not look 'cool' atm. UTIL_BotPressKey(this, IN_DUCK); + setMoveSpeed(0.0f); // do not move PickBestWeapon(); // pick weapon, do not stare with knife - + // when dropped C4 and CT we look at C4 if (isCounterTerrorist() && Game.vDroppedC4 != Vector(9999, 9999, 9999)) { // look at dropped C4 @@ -1909,19 +1909,25 @@ void cBot::Act() { vHead = Game.vDroppedC4; else { if (iGoalNode > -1) + { + forgetPath(); + forgetGoal(); vHead = vBody = NodeMachine.node_vector(iGoalNode); + } else { - // cannot find a node to the dropped C4, so where do we look at? - // todo : find a node to look at, i.e. something dangerous + vHead = vBody = Game.vDroppedC4; } } } else { // Look at iGoalNode if (iGoalNode > -1) + { + forgetPath(); + forgetGoal(); vHead = vBody = NodeMachine.node_vector(iGoalNode); + } else { - // look where to look at? - // todo : find a node to look at, i.e. something dangerous + vHead = vBody = pEdict->v.origin; } } } @@ -3670,7 +3676,7 @@ bool BotRadioAction() { // If we want to listen to the radio... then handle it! if (bWantToListen) { - bool can_do_negative = true; + bool can_do_negative = false; // Report in team! if (strstr(message, "#Report_in_team") != nullptr) { @@ -3733,7 +3739,7 @@ bool BotRadioAction() { if (strstr(message, "#Stick_together_team") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); unstood = true; - // TODO: Find someone to follow. (to stick with) + can_do_negative = false; } // cover me|| strstr (message, "#Cover_me") != NULL @@ -3757,8 +3763,21 @@ bool BotRadioAction() { // Taking fire! if (strstr(message, "#Taking_fire") != nullptr) { - // todo todo todo backup our friend + BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); unstood = true; + + // Find player who issued this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } // Team fall back! if (strstr(message, "#Team_fall_back") != nullptr) { From c0dc3a86ca8783ee728ff44d2cbe05fa82f0f6af Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 15 Apr 2022 17:16:45 +0100 Subject: [PATCH 037/114] Experimental tweaks --- IniParser.cpp | 6 +++--- NodeDataTypes.h | 2 +- NodeMachine.cpp | 45 ++++++++++++++++++++++----------------------- bot.cpp | 16 ++++++++-------- bot_client.cpp | 12 +++++++----- bot_func.cpp | 14 +++++++------- dll.cpp | 2 +- engine.cpp | 4 ++-- 8 files changed, 51 insertions(+), 50 deletions(-) diff --git a/IniParser.cpp b/IniParser.cpp index 7c04830..0caeb6c 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -926,15 +926,15 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Skill, everything but botskill can change. // Determine reaction time based upon botskill here - float fMinReact = 0.0f; + float fMinReact; if (pBot->bot_skill == 0) fMinReact = 0.0f; else //30.8.04 redefined by frashman // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); fMinReact = - RANDOM_FLOAT((pBot->bot_skill / 20) + 0.05f, - (pBot->bot_skill / 5) + 0.05f); + RANDOM_FLOAT(int(pBot->bot_skill / 20) + 0.05f, + int(pBot->bot_skill / 5) + 0.05f); const float fMaxReact = fMinReact + RANDOM_FLOAT(0.05f, 0.2f); diff --git a/NodeDataTypes.h b/NodeDataTypes.h index faf21fd..a4e00e6 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -96,7 +96,7 @@ // Node contact costs #define NODE_CONTACT 8192 -#define NODE_CONTACT_STEP 0.2f +#define NODE_CONTACT_STEP 0.2 #define NODE_CONTACT_DIST 128 // Node boundries diff --git a/NodeMachine.cpp b/NodeMachine.cpp index e75e84b..b70c738 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -63,8 +63,7 @@ extern int draw_nodepath; //--------------------------------------------------------- //CODE: CHEESEMONSTER -int // BERKED -cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) { +int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) {// BERKED // prevent negative indexes on iVisChecked below -- BERKED if (iFrom < 0 || iFrom > MAX_NODES || iTo < 0 || iTo > MAX_NODES) { return VIS_INVALID; @@ -82,7 +81,7 @@ cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) { const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; - if (iByte < g_iMaxVisibilityByte) { + if (iByte < static_cast(g_iMaxVisibilityByte)) { // Get the Byte that this is in unsigned char *ToReturn = (cVisTable + iByte); // get the bit in the byte @@ -92,8 +91,7 @@ cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) { return VIS_BLOCKED; // BERKED } -void -cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { +void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { // prevent negative indexes on iVisChecked below, fixing SEGV -- BERKED if (iFrom < 0 || iFrom > MAX_NODES || iTo < 0 || iTo > MAX_NODES) { return; @@ -109,7 +107,7 @@ cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; - if (iByte < g_iMaxVisibilityByte) { + if (iByte < static_cast(g_iMaxVisibilityByte)) { unsigned char *ToChange = (cVisTable + iByte); if (bVisible) @@ -174,7 +172,7 @@ void cNodeMachine::init() { } // CODE: From cheesemonster - constexpr unsigned long iSize = g_iMaxVisibilityByte; + const unsigned long iSize = g_iMaxVisibilityByte; //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first @@ -776,7 +774,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const (Nodes[iEnd].iNodeBits & BIT_LADDER) ? "OnLadder" : ""); #endif // Just in case - if (Start.x == 9999 || End.x == 9999) + if (static_cast(Start.x) == 9999 || static_cast(End.x) == 9999) return false; // Quick & dirty check whether we can go through... @@ -942,7 +940,7 @@ int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling, the distance will be bigger. - constexpr int maxDistance = 3 * NODE_ZONE; + const int maxDistance = 3 * NODE_ZONE; if (horizontal_distance(Nodes[newNodeIndex].origin, Nodes[j].origin) > maxDistance) continue; @@ -964,7 +962,7 @@ int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { } /** - * Returns a free node index, this is not bound to a meredian (subcluster)! + * Returns a free node index, this is not bound to a meridian (subcluster)! * @return */ int cNodeMachine::getFreeNodeIndex() const @@ -1278,7 +1276,7 @@ void cNodeMachine::addNodesForPlayers() { // Draw connections of the node we are standing on void cNodeMachine::connections(edict_t *pEntity) { - int closeNode = -1; + int closeNode; char msg[75]; memset(msg, 0, sizeof(msg)); if (draw_nodepath > -1 && draw_nodepath < 32) { @@ -1437,7 +1435,7 @@ void cNodeMachine::experience_save() { FILE* rbl = fopen(filename, "wb"); if (rbl != nullptr) { - constexpr int iVersion = FILE_EXP_VER2; + const int iVersion = FILE_EXP_VER2; fwrite(&iVersion, sizeof(int), 1, rbl); for (int i = 0; i < MAX_NODES; i++) { @@ -1600,7 +1598,7 @@ void cNodeMachine::save() const if (rbl != nullptr) { // Write down version number - constexpr int iVersion = FILE_NODE_VER1; + const int iVersion = FILE_NODE_VER1; fwrite(&iVersion, sizeof(int), 1, rbl); for (int i = 0; i < MAX_NODES; i++) { fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); @@ -1736,6 +1734,7 @@ void cNodeMachine::path_draw(edict_t *pEntity) { int max_drawn = 0; for (int i = 0; i < MAX_NODES; i++) { + //TODO: iPath appears to be out of bounds [APG]RoboCop[CL] const int iNode = iPath[draw_nodepath][i]; const int iNextNode = iPath[draw_nodepath][(i + 1)]; @@ -1748,7 +1747,7 @@ void cNodeMachine::path_draw(edict_t *pEntity) { FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); if (max_drawn < 39 && good && angle_to_waypoint < 50) { - constexpr int red = 255; + const int red = 255; int green = 0; int blue = 255; int width = 15; @@ -1807,7 +1806,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { // within distance and 'reachable' if (tr.flFraction >= 1.0f) { const double costIncrease = (fDist / NODE_CONTACT_DIST) * NODE_CONTACT_STEP; - InfoNodes[i].fContact[iTeam] += costIncrease; + InfoNodes[i].fContact[iTeam] += static_cast(costIncrease); } } } @@ -2209,7 +2208,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn return false; // do not create a path when invalid params given if (pBot) { - int botTeam = UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based + UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based } const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); @@ -2229,7 +2228,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn makeAllWaypointsAvailable(); // Our start waypoint is open - constexpr float gCost = 0.0f; // distance from starting node + const float gCost = 0.0f; // distance from starting node const float hCost = func_distance(Nodes[nodeStartIndex].origin, Nodes[nodeTargetIndex].origin); // distance from end node to node const float cost = gCost + hCost; @@ -2525,7 +2524,7 @@ void cNodeMachine::vis_calculate(int iFrom) { for (int i = 0; i < MAX_NODES; i++) if ((i != iFrom) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { - constexpr float fClosest = 1024; + const float fClosest = 1024; const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { TraceResult tr; @@ -2733,7 +2732,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } // Near Node - bool bNearNode = false; //Variable Reassigned [APG]RoboCop[CL] + bool bNearNode; //Variable Reassigned [APG]RoboCop[CL] if (pBot->isOnLadder()) { pBot->rprint("Bot is on ladder"); // Set touch radius @@ -3254,7 +3253,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->shouldBeWandering()) { int currentNode = -1; for (int attempts = 1; attempts < 5; attempts++) { - const float distance = NODE_ZONE + (attempts * NODE_ZONE); + const float distance = NODE_ZONE + static_cast(attempts * NODE_ZONE); currentNode = pBot->determineCurrentNode(distance); // this also sets current node in bot state if (currentNode > -1) break; } @@ -3360,8 +3359,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { int iFinalGoalNode = -1; int iFinalGoalIndex = -1; - constexpr float MAX_DISTANCE = 16384.0f; // theoretical max distance - constexpr float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0f; + const float MAX_DISTANCE = 16384.0f; // theoretical max distance + const float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0f; // 01-07-2008; Instead of using 'scores', use a normalized score. // We do: @@ -3392,7 +3391,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } // A bit off randomness - float weight = static_cast(50) / pBot->ipRandom; // (yes, this will give us 1 or higher score) + float weight = 50.0f / static_cast(pBot->ipRandom); // (yes, this will give us 1 or higher score) weight *= score; score += weight; diff --git a/bot.cpp b/bot.cpp index b5b3e59..342f562 100644 --- a/bot.cpp +++ b/bot.cpp @@ -876,7 +876,7 @@ void cBot::PickBestWeapon() { // Distance to enemy const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - constexpr float knifeDistance = 300; + const float knifeDistance = 300; // ---------------------------- // In this function all we do is decide what weapon to pick @@ -1816,7 +1816,7 @@ bool cBot::Defuse() { // We can do 2 things now // - If we are not close, we check if we can walk to it, and if so we face to the c4 // - If we are close, we face it and (begin) defuse the bomb. - constexpr int distanceForC4ToBeInReach = 70; + const int distanceForC4ToBeInReach = 70; if (distance < distanceForC4ToBeInReach) { vHead = vC4; vBody = vC4; @@ -2111,7 +2111,7 @@ void cBot::CheckAround() { const Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); // Go forward first - constexpr float distance = 90; + const float distance = 90.0f; const Vector v_forward = v_source + gpGlobals->v_forward * distance; // now really go left/right @@ -2158,20 +2158,20 @@ void cBot::CheckAround() { } if (!bHitForwardLeft && bHitForwardRight) { - strafeLeft(0.5); + strafeLeft(0.5f); rprint_trace("CheckAround", "Can strafe left (forward left)"); } else if (bHitForwardLeft && !bHitForwardRight) { - strafeRight(0.5); + strafeRight(0.5f); rprint_trace("CheckAround", "Can strafe right (forward right)"); } if (bHitLeft && bHitRight) { rprint_trace("CheckAround", "Can't strafe left or right"); } else if (!bHitLeft && bHitRight) { - strafeLeft(0.5); + strafeLeft(0.5f); rprint_trace("CheckAround", "Can strafe left"); } else if (bHitLeft && !bHitRight) { - strafeRight(0.5); + strafeRight(0.5f); rprint_trace("CheckAround", "Can strafe right"); } @@ -2180,7 +2180,7 @@ void cBot::CheckAround() { // ------------------------------------------------------------- edict_t *pent = nullptr; - while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60)) != nullptr) { + while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { char item_name[40]; strcpy(item_name, STRING(pent->v.classname)); diff --git a/bot_client.cpp b/bot_client.cpp index 524c850..83d8bae 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -187,7 +187,7 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { iClip = *static_cast(p); // ammo currently in the clip for this weapon - if (iId <= 31) { + if (iId <= 32) { bots[bot_index].bot_weapons |= (1 << iId); // set this weapon bit if (iState == 1) { @@ -532,7 +532,8 @@ void BotClient_CS_Damage(void *p, int bot_index) { BotClient_Valve_Damage(p, bot_index); } -void BotClient_Gearbox_Damage(void *p, int bot_index) { +// Not required? [APG]RoboCop[CL] +/*void BotClient_Gearbox_Damage(void* p, int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_Damage()\n"); // this is just like the Valve Battery message BotClient_Valve_Damage(p, bot_index); @@ -542,7 +543,7 @@ void BotClient_FLF_Damage(void *p, int bot_index) { //DebugOut("bot_client: BotClient_FLF_Damage()\n"); // this is just like the Valve Battery message BotClient_Valve_Damage(p, bot_index); -} +}*/ void BotClient_CS_SayText(void *p, int bot_index) { @@ -854,7 +855,8 @@ void BotClient_CS_ScreenFade(void *p, int bot_index) { BotClient_Valve_ScreenFade(p, bot_index); } -void BotClient_Gearbox_ScreenFade(void *p, int bot_index) { +// Not required? [APG]RoboCop[CL] +/*void BotClient_Gearbox_ScreenFade(void* p, int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_ScreenFade()\n"); // this is just like the Valve ScreenFade message BotClient_Valve_ScreenFade(p, bot_index); @@ -864,7 +866,7 @@ void BotClient_FLF_ScreenFade(void *p, int bot_index) { //DebugOut("bot_client: BotClient_FLF_ScreenFade()\n"); // this is just like the Valve ScreenFade message BotClient_Valve_ScreenFade(p, bot_index); -} +}*/ // STEFAN // This message gets sent for HLTV, according to Alfred (Valve) also diff --git a/bot_func.cpp b/bot_func.cpp index d3fb13b..ecf4865 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -274,7 +274,7 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - constexpr int FOV = 90;// TODO: use server var "default_fov" ? + int fov = 90;// TODO: use server var "default_fov" ? // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; @@ -286,8 +286,8 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - constexpr int distance = NODE_ZONE; - if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < FOV) { + const int distance = NODE_ZONE; + if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < fov) { return pPlayer; } @@ -319,10 +319,10 @@ edict_t * getEntityNearbyBotInFOV(cBot *pBot) { * Return TRUE of any players are near that could block him, regardless of FOV. Just checks distance * @param pBot * @return - */ + */ //TODO: FOV and angleToPlayer are unused variables [APG]RoboCop[CL] bool isAnyPlayerNearbyBot(cBot *pBot) { edict_t *pEdict = pBot->pEdict; - int FOV = 120; + int fov = 105; for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); @@ -340,7 +340,7 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - constexpr int distance = NODE_ZONE; + const int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { return true; } @@ -533,7 +533,7 @@ bool BotShouldDuck(cBot *pBot) { TraceResult tr; Vector v_duck; - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... diff --git a/dll.cpp b/dll.cpp index 558d84c..5d28555 100644 --- a/dll.cpp +++ b/dll.cpp @@ -289,7 +289,7 @@ void GameDLLInit() { // initialize the bots array of structures... rblog("Initializing memory for bots array.."); - memset(bots, 0, sizeof(bots)); + memset(bots, 0.0f, sizeof(bots)); rblog("OK\n"); rblog("Verifying realbot is installed correctly.."); diff --git a/engine.cpp b/engine.cpp index 0aabaaa..ca4189a 100644 --- a/engine.cpp +++ b/engine.cpp @@ -112,7 +112,7 @@ void pfnRemoveEntity(edict_t *e) { #if DO_DEBUG == 2 { fp = fopen("!rbdebug.txt", "a"); - fprintf(fp, "pfnRemoveEntity: %x\n", e); + fprintf(fp, R"(pfnRemoveEntity: %x)", e); if (e->v.model != 0) fprintf(fp, " model=%s\n", STRING(e->v.model)); fclose(fp); @@ -397,7 +397,7 @@ void pfnWriteString(const char *sz) { radio_message = true; // we found a radio message // Thank god Ditlew you already coded this... - const int length = strlen(sz) - strlen(strstr(sz, " (RADIO)")); + const unsigned length = strlen(sz) - strlen(strstr(sz, " (RADIO)")); strncpy(radio_messenger, sz, length); // Now search for any compatible radio command (old string). From f48a54e1c810d218adfd9fdf6b878d1d59ece5b8 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 15 Apr 2022 18:04:35 +0100 Subject: [PATCH 038/114] TODO added --- NodeMachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index b70c738..082fd68 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -3792,7 +3792,7 @@ char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) default: sprintf(typeAsText, "GOAL UNKNOWN"); } - return typeAsText; + return typeAsText; //TODO: local variable invalid [APG]RoboCop[CL] } // Find cover From 6fe6e0aa44a692c50120845617526aaf18b99818 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 27 Apr 2022 22:22:52 +0100 Subject: [PATCH 039/114] Experiment refactoring and improved IniParser The bots personalities will have lower spammy chat/radio rates, WalkWithKnife and average reaction rates. However the HelpTeammate, has been increased for bots to cooperate more. And the NodeMachine header appears to be muddled. Plus some missing declarations and implementations are newly added. --- ChatEngine.cpp | 44 +++++++++++++++++++++++++++++++++++++------- ChatEngine.h | 5 +++++ IniParser.cpp | 35 ++++++++++++++++++----------------- IniParser.h | 5 +++++ NodeMachine.cpp | 18 +++++++++--------- NodeMachine.h | 8 ++++---- bot.cpp | 37 ++++++++++++++++++++++++++----------- bot.h | 8 ++++---- bot_client.h | 6 ++++++ bot_func.cpp | 12 ++++++------ bot_func.h | 2 +- dll.cpp | 6 +++--- game.cpp | 6 +++--- todo.txt | 1 - util.cpp | 18 +++++++++--------- 15 files changed, 136 insertions(+), 75 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 44702c5..ece947e 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -121,11 +121,11 @@ void cChatEngine::think() { // Scan the message so we know in what block we should be to reply: char word[20]; memset(word, 0, sizeof(word)); - + int c = 0; int wc = 0; - const int sentenceLength = strlen(sentence); + const int sentenceLength = static_cast(strlen(sentence)); // When length is not valid, get out. // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? @@ -283,7 +283,7 @@ void cChatEngine::think() { memset(temp, 0, sizeof(temp)); // get character position - char *name_pos = + const char *name_pos = strstr(ReplyBlock[iTheBlock]. sentence[the_c], "%n"); @@ -314,13 +314,13 @@ void cChatEngine::think() { // we just copied a name to chSentence // set our cursor after the name now (name length + 1) - int tc = strlen(temp); + int tc = static_cast(strlen(temp)); // now finish the sentence // get entire length of ReplyBlock and go until we reach the end const int length = - strlen(ReplyBlock[iTheBlock]. - sentence[the_c]); + static_cast(strlen(ReplyBlock[iTheBlock]. + sentence[the_c])); // for every nC , read character from ReplyBlock @@ -368,7 +368,37 @@ void cChatEngine::think() { memset(sender, 0, sizeof(sender)); - fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0, 0.5); + fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); +} + +void cChatEngine::handle_sentence() //Experimental implementation [APG]RoboCop[CL] +{ + // if we have a sentence to say + if (sentence[0] != '\0') { + // loop through all bots: + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t *pPlayer = INDEXENT(i); + + // skip invalid players and skip self (i.e. this bot) + if (pPlayer && !pPlayer->free) { + cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + + if (pBotPointer != nullptr) + if (RANDOM_LONG(0, 100) < + pBotPointer->ipChatRate + 25) { + // reply: + pBotPointer->PrepareChat(sentence); + //UTIL_SayTextBot(sentence, pBotPointer); + } + } + } + } + + // clear sentence and such + memset(sentence, 0, sizeof(sentence)); + memset(sender, 0, sizeof(sender)); + + fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); } // diff --git a/ChatEngine.h b/ChatEngine.h index 8ef75a6..973b120 100644 --- a/ChatEngine.h +++ b/ChatEngine.h @@ -28,6 +28,9 @@ **/ // Chatting Engine +#ifndef CHATENGINE_H +#define CHATENGINE_H + #define MAX_BLOCKS 100 #define BLOCK_DEATHS (MAX_BLOCKS-1) @@ -64,3 +67,5 @@ class cChatEngine { // handles a sentence, decides to reply on it or not. void handle_sentence(); }; + +#endif // CHATENGINE_H \ No newline at end of file diff --git a/IniParser.cpp b/IniParser.cpp index 0caeb6c..0bddd54 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -484,7 +484,7 @@ float INI_WordValueFLOAT(char result[80]) { if (c > 9) break; } - return atof(number); + return static_cast(atof(number)); } // nothing here, so we return NULL at the end } @@ -727,11 +727,11 @@ void INI_PARSE_IAD() { if (section == INI_AREA) { if (wordtype == WORD_AREAX) - AreaX = INI_WordValueINT(linefeed); + AreaX = static_cast(INI_WordValueINT(linefeed)); if (wordtype == WORD_AREAY) - AreaY = INI_WordValueINT(linefeed); + AreaY = static_cast(INI_WordValueINT(linefeed)); if (wordtype == WORD_AREAZ) - AreaZ = INI_WordValueINT(linefeed); + AreaZ = static_cast(INI_WordValueINT(linefeed)); if (AreaX != 9999 && AreaY != 9999 && AreaZ != 9999) { @@ -918,7 +918,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { pBot->ipBuySmokeGren = RANDOM_LONG(20, 80); pBot->ipBuyDefuseKit = RANDOM_LONG(20, 80); pBot->ipDroppedBomb = RANDOM_LONG(20, 80); - pBot->ipSaveForWeapon = RANDOM_LONG(0, 30); + pBot->ipSaveForWeapon = RANDOM_LONG(0, 20); pBot->ipBuyArmour = RANDOM_LONG(30, 100); pBot->ipFearRate = RANDOM_LONG(20, 60); @@ -932,16 +932,17 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { else //30.8.04 redefined by frashman // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); + // Reaction Time delay added for realistic gameplay [APG]RoboCop[CL] fMinReact = - RANDOM_FLOAT(int(pBot->bot_skill / 20) + 0.05f, - int(pBot->bot_skill / 5) + 0.05f); + RANDOM_FLOAT((pBot->bot_skill / 20) + 0.3f, + (pBot->bot_skill / 5) + 0.3f); - const float fMaxReact = fMinReact + RANDOM_FLOAT(0.05f, 0.2f); + const float fMaxReact = fMinReact + RANDOM_FLOAT(0.2f, 0.4f); // SET them pBot->fpMinReactTime = fMinReact; pBot->fpMaxReactTime = fMaxReact; - + // Set Offsets (note, they are extra upon current aiming code) // 30.8.04 redefined by frashman // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); @@ -952,7 +953,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; // Team - pBot->ipHelpTeammate = RANDOM_LONG(10, 70); + pBot->ipHelpTeammate = RANDOM_LONG(40, 80); // Game pBot->ipHostage = RANDOM_LONG(25, 70); @@ -960,19 +961,19 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { pBot->ipRandom = RANDOM_LONG(25, 70); // Radio - pBot->ipReplyToRadio = RANDOM_LONG(10, 60); - pBot->ipCreateRadio = RANDOM_LONG(10, 60); - pBot->ipHearRate = RANDOM_LONG(10, 60); + pBot->ipReplyToRadio = RANDOM_LONG(10, 20); + pBot->ipCreateRadio = RANDOM_LONG(10, 20); + pBot->ipHearRate = RANDOM_LONG(20, 60); // Person pBot->ipTurnSpeed = RANDOM_LONG(20, 40); pBot->ipCampRate = RANDOM_LONG(0, 60); - pBot->ipChatRate = RANDOM_LONG(0, 30); - pBot->ipWalkWithKnife = RANDOM_LONG(0, 60); + pBot->ipChatRate = RANDOM_LONG(0, 20); + pBot->ipWalkWithKnife = RANDOM_LONG(0, 40); // SAVE TO DISK: - char dirname[256]; - char filename[256]; + //char dirname[256]; + //char filename[256]; // Set Directory name if (mod_id == CSTRIKE_DLL) diff --git a/IniParser.h b/IniParser.h index 7dcf534..8d37d26 100644 --- a/IniParser.h +++ b/IniParser.h @@ -33,6 +33,9 @@ **/ // Sections +#ifndef INIPARSER_H +#define INIPARSER_H + #define INI_NONE (-1) #define INI_SKILL 0 // Bot skill #define INI_WEAPON 1 // Bot weapon preference @@ -118,3 +121,5 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot); void INI_PARSE_BUYTABLE(); void INI_PARSE_IAD(); void INI_PARSE_CHATFILE(); + +#endif // INIPARSER_H \ No newline at end of file diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 082fd68..637991e 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -83,7 +83,7 @@ int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) {// BERKED if (iByte < static_cast(g_iMaxVisibilityByte)) { // Get the Byte that this is in - unsigned char *ToReturn = (cVisTable + iByte); + const unsigned char *ToReturn = (cVisTable + iByte); // get the bit in the byte return ((*ToReturn & (1 << iBit)) > 0) ? VIS_VISIBLE : VIS_BLOCKED; // BERKED } @@ -1233,7 +1233,7 @@ void cNodeMachine::init_players() { void cNodeMachine::init_round() { //UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "NodeMachine: Roundstart\n"); for (int index = 1; index <= gpGlobals->maxClients; index++) { - edict_t *pPlayer = INDEXENT(index); + const edict_t *pPlayer = INDEXENT(index); // skip invalid players if ((pPlayer) && (!pPlayer->free)) @@ -1977,7 +1977,7 @@ int cNodeMachine::getGoalIndexFromNode(int iNode) const void cNodeMachine::updateGoals() { rblog("cNodeMachine::updateGoals - START\n"); for (int i = 0; i < MAX_GOALS; i++) { - tGoal *goal = getGoal(i); + const tGoal *goal = getGoal(i); if (goal == nullptr || goal->iNode < 0) continue; if (goal->iType == GOAL_HOSTAGE) { @@ -2819,7 +2819,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { const int currentNode = pBot->determineCurrentNodeWithTwoAttempts(); if (currentNode > -1) { - tNode *node = getNode(currentNode); + const tNode *node = getNode(currentNode); // close node DrawBeam( @@ -2960,7 +2960,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec const int iTo = currentNodeToHeadFor; // JUMP & DUCK - tNode ¤tNode = Nodes[currentNodeToHeadFor]; + const tNode ¤tNode = Nodes[currentNodeToHeadFor]; if (BotShouldJumpIfStuck(pBot) || (currentNode.iNodeBits & BIT_JUMP)) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased, increase node time - START"); pBot->doJump(vector); @@ -2992,11 +2992,11 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec sprintf(msg, "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); - cBot *pBotStuck = getCloseFellowBot(pBot); + const cBot *pBotStuck = getCloseFellowBot(pBot); // edict_t *playerNearbyInFOV = getPlayerNearbyBotInFOV(pBot); edict_t *entityNearbyInFOV = getEntityNearbyBotInFOV(pBot); - edict_t *playerNearbyInFOV = nullptr; + const edict_t *playerNearbyInFOV = nullptr; edict_t *hostageNearbyInFOV = nullptr; if (entityNearbyInFOV) { @@ -3397,7 +3397,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { score += weight; // Take into consideration how many times this goal has been selected - score = (score + (1.0f - Goals[goalIndex].iChecked / static_cast(maxCheckedScore))) / 2.0f; + score = (score + (1.0f - Goals[goalIndex].iChecked / maxCheckedScore)) / 2.0f; // Danger (is important) score = (score + InfoNodes[Goals[goalIndex].iNode].fDanger[UTIL_GetTeam(pBot->pEdict)]) / 1.5f; @@ -3405,7 +3405,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // How many bots have already taken this goal? float goalAlreadyUsedScore = 0.0f; float teamMembers = 1.0f; // count self by default - + for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { // not a bot cBot *botPointer = &bots[botIndex]; diff --git a/NodeMachine.h b/NodeMachine.h index 3bd9556..e0e8217 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -125,8 +125,8 @@ class cNodeMachine { // ----------------- int node_cover(int iFrom, int iTo, edict_t *pEdict); - int node_look_at_hear(int iFrom, int iTo, edict_t *pEdict); - + int node_look_at_hear(int iFrom, int iOrigin, edict_t* pEdict); + int node_camp(const Vector& vOrigin, int iTeam); void vis_calculate(int iFrom); @@ -167,7 +167,7 @@ class cNodeMachine { // Some debugging by EVY void dump_goals() const; - void dump_path(int iBot, int ThisNode); + void dump_path(int iBot, int CurrentPath); void Draw(); @@ -223,7 +223,7 @@ class cNodeMachine { void ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vector &vector); - void ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pS); + void ExecuteDoorInteractionLogic(cBot* pBot, edict_t* pEntityHit); }; #endif // NODEMACHINE_H diff --git a/bot.cpp b/bot.cpp index 342f562..cae0056 100644 --- a/bot.cpp +++ b/bot.cpp @@ -847,7 +847,7 @@ bool cBot::isOwningWeapon(int weaponId) const */ bool cBot::isHoldingWeapon(int weaponId) const { - return (current_weapon.iId == weaponId); + return current_weapon.iId == weaponId; } bool cBot::hasFavoritePrimaryWeaponPreference() const @@ -860,7 +860,7 @@ bool cBot::hasFavoriteSecondaryWeaponPreference() const return ipFavoSecWeapon > -1; } -bool cBot::canAfford(int price) const +bool cBot::canAfford(int price) const //price muddled with weaponId? [APG]RoboCop[CL] { return this->bot_money > price; } @@ -1141,7 +1141,7 @@ void cBot::Combat() { } // get bot pointer - cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); + const cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); // This bot killed a human; adjust skill when 'autoskill' is on. if (checkpointer == nullptr) { @@ -1390,7 +1390,7 @@ void cBot::InteractWithFriends() { bCanSeePlayer = true; // there are tons of cases - cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + const cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); // It is a fellow bot if (pBotPointer != nullptr) { @@ -1560,7 +1560,7 @@ void cBot::InteractWithPlayers() { // Does our enemy (when a bot) has focus on us? bool focused; - cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); + const cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); if (playerbot) { if (playerbot->pEnemyEdict == pEdict) focused = true; @@ -2063,7 +2063,7 @@ void cBot::Act() { // Vector how it should be, however, we don't allow such a fast turn! v_shouldbe.x = pEdict->v.v_angle.x / 3; v_shouldbe.y = pEdict->v.v_angle.y; - v_shouldbe.z = 0; + v_shouldbe.z = 0; //unused? [APG]RoboCop[CL] // set the body angles to point the gun correctly pEdict->v.angles.x = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.x, v_shouldbe.x); @@ -2483,6 +2483,11 @@ bool cBot::hasSecondaryWeaponEquiped() const return iSecondaryWeapon > -1; } +bool cBot::hasPrimaryWeapon(int weaponId) const +{ + return isOwningWeapon(weaponId); +} + bool cBot::hasSecondaryWeapon(int weaponId) const { return isOwningWeapon(weaponId); @@ -2886,7 +2891,7 @@ void cBot::Memory() { } // we go to the destination - const float fTime = 5 + ipFearRate / static_cast(7); + const float fTime = 5 + static_cast(ipFearRate) / static_cast(7); if (RANDOM_LONG(0, 100) < ipFearRate && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk @@ -2957,6 +2962,16 @@ void cBot::Memory() { } } +void cBot::Walk() //Experimental implementation [APG]RoboCop[CL] +{ + if (f_walk_time + 0.1f < gpGlobals->time) { + f_walk_time = gpGlobals->time + 0.1f; + if (f_walk_time + 0.1f < gpGlobals->time) { + f_walk_time = gpGlobals->time + 0.1f; + } + } +} + // BOT: Do i carry weapon # now? bool cBot::CarryWeapon(int iType) const @@ -3173,7 +3188,7 @@ void cBot::Think() { rprint("Dead, need to re-initialize"); // AUTOSKILL - cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); + const cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); // not killed by a fellow bot, presumably a human player if (botPointerOfKiller == nullptr) { @@ -4202,7 +4217,7 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const */ float cBot::getDistanceToNextNode() const { - tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); if (node) { return getDistanceTo(node->origin); } @@ -4210,14 +4225,14 @@ float cBot::getDistanceToNextNode() const } void cBot::setBodyToNode(int nodeIndex) { - tNode *node = NodeMachine.getNode(nodeIndex); + const tNode *node = NodeMachine.getNode(nodeIndex); if (node) { vBody = node->origin; } } void cBot::lookAtNode(int nodeIndex) { - tNode *node = NodeMachine.getNode(nodeIndex); + const tNode *node = NodeMachine.getNode(nodeIndex); if (node) { vHead = node->origin; } diff --git a/bot.h b/bot.h index 5b5039f..4861dbc 100644 --- a/bot.h +++ b/bot.h @@ -453,9 +453,9 @@ class cBot { bool hasFavoriteSecondaryWeaponPreference() const; bool hasPrimaryWeaponEquiped() const; bool hasSecondaryWeaponEquiped() const; - bool hasPrimaryWeapon(int weaponId); + bool hasPrimaryWeapon(int weaponId) const; bool hasSecondaryWeapon(int weaponId) const; - bool canAfford(int weaponId) const; + bool canAfford(int price) const; //price muddled with weaponId? [APG]RoboCop[CL] // ------------------- // 20/06/04 - CS 1.6 shield functions @@ -627,9 +627,9 @@ void UTIL_BuildFileName(char *filename, char *arg1, char *arg2); void UTIL_BuildFileNameRB(char *subdir, char *filename); -unsigned short FixedUnsigned16(float value, float scale); +unsigned short fixed_unsigned16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] -short FixedSigned16(float value, float scale); +short fixed_signed16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict); diff --git a/bot_client.h b/bot_client.h index 437ca9d..9608fa2 100644 --- a/bot_client.h +++ b/bot_client.h @@ -28,6 +28,10 @@ **/ // COUNTER-STRIKE + +#ifndef BOT_CLIENT_H +#define BOT_CLIENT_H + void BotClient_CS_VGUI(void *p, int bot_index); void BotClient_CS_ShowMenu(void *p, int bot_index); void BotClient_CS_WeaponList(void *p, int bot_index); @@ -60,3 +64,5 @@ void BotClient_Valve_Battery(void *p, int bot_index); void BotClient_Valve_Damage(void *p, int bot_index); void BotClient_Valve_DeathMsg(void *p, int bot_index); void BotClient_Valve_ScreenFade(void *p, int bot_index); + +#endif // BOT_CLIENT_H \ No newline at end of file diff --git a/bot_func.cpp b/bot_func.cpp index ecf4865..5095007 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -234,7 +234,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, in * @return */ cBot *getCloseFellowBot(cBot *pBot) { - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; cBot *closestBot = nullptr; // Loop through all clients @@ -267,14 +267,14 @@ cBot *getCloseFellowBot(cBot *pBot) { * @return */ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - int fov = 90;// TODO: use server var "default_fov" ? + const int fov = 90;// TODO: use server var "default_fov" ? // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; @@ -321,7 +321,7 @@ edict_t * getEntityNearbyBotInFOV(cBot *pBot) { * @return */ //TODO: FOV and angleToPlayer are unused variables [APG]RoboCop[CL] bool isAnyPlayerNearbyBot(cBot *pBot) { - edict_t *pEdict = pBot->pEdict; + const edict_t *pEdict = pBot->pEdict; int fov = 105; for (int i = 1; i <= gpGlobals->maxClients; i++) { @@ -377,7 +377,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { } // should not jump, perhaps its a func_illusionary causing that we're stuck? - edict_t *entityInFov = getEntityNearbyBotInFOV(pBot); + const edict_t *entityInFov = getEntityNearbyBotInFOV(pBot); if (entityInFov && strcmp("func_illusionary", STRING(entityInFov->v.classname)) == 0) { return true; // yes it is the case @@ -711,7 +711,7 @@ void FUNC_HearingTodo(cBot *pBot) { * Created : 16/11/2001 * Changed : 16/11/2001 */ -void FUNC_ClearEnemyPointer(edict_t *pPtr) { +void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG]RoboCop[CL] // Go through all bots and remove their enemy pointer that matches the given // pointer pPtr for (int i = 1; i <= gpGlobals->maxClients; i++) { diff --git a/bot_func.h b/bot_func.h index 7effabf..696baa0 100644 --- a/bot_func.h +++ b/bot_func.h @@ -74,7 +74,7 @@ int FUNC_PlayerSpeed(edict_t * edict); bool FUNC_PlayerRuns(int speed); void FUNC_HearingTodo(cBot * pBot); -void FUNC_ClearEnemyPointer(edict_t * c_pointer); +void FUNC_ClearEnemyPointer(edict_t *pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] bool FUNC_IsOnLadder(edict_t * pEntity); void FUNC_FindBreakable(cBot * pBot); diff --git a/dll.cpp b/dll.cpp index 5d28555..8ce2d36 100644 --- a/dll.cpp +++ b/dll.cpp @@ -322,7 +322,7 @@ void GameDLLInit() { Game.Init(); Game.LoadNames(); - Game.LoadBuyTable(); + cGame::LoadBuyTable(); // NodeMachine NodeMachine.init(); @@ -1975,7 +1975,7 @@ void RealBot_ServerCommand() { if (iFrom > -1) { if (iTo < 0) { - tGoal *ptr = NodeMachine.getRandomGoalByType(GOAL_SPAWNT); + const tGoal *ptr = NodeMachine.getRandomGoalByType(GOAL_SPAWNT); if (ptr) iTo = ptr->iNode; } @@ -2025,7 +2025,7 @@ void RealBot_ServerCommand() { // Not a valid command sprintf(cMessage, "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); - bool bValidCommand = false; + bool bValidCommand = false; //Unused variable boolean [APG]RoboCop[CL] } // Send message diff --git a/game.cpp b/game.cpp index 4a30865..0a6be08 100644 --- a/game.cpp +++ b/game.cpp @@ -295,7 +295,7 @@ void cGame::LoadNames() { char name_buffer[80]; while ((iAmountNames < MAX_BOT_NAMES) && (fgets(name_buffer, 80, bot_name_fp) != nullptr)) { - int length = strlen(name_buffer); + int length = static_cast(strlen(name_buffer)); if (name_buffer[length - 1] == '\n') { name_buffer[length - 1] = 0; // remove '\n' length--; @@ -370,7 +370,7 @@ void cGame::SelectName(char *name) const // check if this name is used for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - edict_t* pPlayer = INDEXENT(iIndex); + const edict_t* pPlayer = INDEXENT(iIndex); if (pPlayer && !pPlayer->free) { if (strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) == 0) { @@ -492,7 +492,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg } // length of name - int lengthOfBotName = strlen(botName); + int lengthOfBotName = static_cast(strlen(botName)); for (int i = 0; i < lengthOfBotName; i++) { if ((botName[i] <= ' ') || (botName[i] > '~') || (botName[i] == '"')) { diff --git a/todo.txt b/todo.txt index fc7bbc6..e356fc5 100644 --- a/todo.txt +++ b/todo.txt @@ -2,7 +2,6 @@ - Bots should know when others are near its waypoint, so it won't run into each other - Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) - Improve pathfinder -- Chat rate should be lower @ default - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. diff --git a/util.cpp b/util.cpp index e56486d..926e6a9 100644 --- a/util.cpp +++ b/util.cpp @@ -72,7 +72,7 @@ int gmsgShowMenu = 0; Vector UTIL_VecToAngles(const Vector &vec) { float rgflVecOut[3]; VEC_TO_ANGLES(vec, rgflVecOut); - return Vector(rgflVecOut); + return {rgflVecOut}; } // Overloaded to add IGNORE_GLASS @@ -878,7 +878,7 @@ int UTIL_GetGrenadeType(edict_t *pEntity) { } // 2 functions from podbot source -unsigned short FixedUnsigned16(float value, float scale) { +unsigned short fixed_unsigned16(float value, float scale) { int output = static_cast(value * scale); if (output < 0) output = 0; @@ -888,7 +888,7 @@ unsigned short FixedUnsigned16(float value, float scale) { return static_cast(output); } -short FixedSigned16(float value, float scale) { +short fixed_signed16(float value, float scale) { int output = static_cast(value * scale); if (output > 32767) @@ -907,8 +907,8 @@ void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); WRITE_BYTE(TE_TEXTMESSAGE); WRITE_BYTE(1); - WRITE_SHORT(FixedSigned16(-1, 1 << 13)); - WRITE_SHORT(FixedSigned16(0, 1 << 13)); + WRITE_SHORT(fixed_signed16(-1, 1 << 13)); + WRITE_SHORT(fixed_signed16(0, 1 << 13)); WRITE_BYTE(2); WRITE_BYTE(r); //r WRITE_BYTE(g); //g @@ -918,10 +918,10 @@ void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { WRITE_BYTE(255); WRITE_BYTE(255); WRITE_BYTE(200); - WRITE_SHORT(FixedUnsigned16(0.0078125, 1 << 8)); - WRITE_SHORT(FixedUnsigned16(2, 1 << 8)); - WRITE_SHORT(FixedUnsigned16(6, 1 << 8)); - WRITE_SHORT(FixedUnsigned16(0.1f, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(0.0078125, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(2, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(6, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(0.1f, 1 << 8)); WRITE_STRING(static_cast(&msg[0])); MESSAGE_END(); } From da5ec1b98b5829ae75fce008a9a10c0da424d0c2 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 27 Apr 2022 22:42:20 +0100 Subject: [PATCH 040/114] Update todo.txt --- todo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/todo.txt b/todo.txt index e356fc5..3da3008 100644 --- a/todo.txt +++ b/todo.txt @@ -2,7 +2,7 @@ - Bots should know when others are near its waypoint, so it won't run into each other - Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) - Improve pathfinder -- Allow bots to duck jump for vaulting upon crates or ledges, cs_italy and de_inferno are good examples +- Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection - improve 'unstucking'... when not stuck by other players. - Allow bots to autovacate for human players From cacea1859840239a0b320fcf1b77f0242270ca73 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 28 Apr 2022 23:01:13 +0100 Subject: [PATCH 041/114] Experimental additional def/implementations etc. Chat/Radio rate reduced further. bot_func readjusted for bots to avoid too expensive weapons and shields, but consider on buying the MP5 for an affordable price. "is_neighbour_node, FUNC_TakeCover, FUNC_FindFarWaypoint, and FUNC_GiveHostage" defined, but still more to come. --- ChatEngine.cpp | 2 +- IniParser.cpp | 4 +- NodeMachine.cpp | 52 ++++++++------ NodeMachine.h | 10 +-- bot.cpp | 12 ++-- bot.h | 10 +-- bot_func.cpp | 171 +++++++++++++++++++++++++++++++++++++---------- bot_func.h | 22 +++--- bot_navigate.cpp | 10 ++- build.cpp | 2 +- game.h | 4 +- util.cpp | 3 +- 12 files changed, 204 insertions(+), 98 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index ece947e..a09fff6 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -402,7 +402,7 @@ void cChatEngine::handle_sentence() //Experimental implementation [APG]RoboCop[C } // -void cChatEngine::set_sentence(char csender[30], char csentence[128]) { +void cChatEngine::set_sentence(char csender[30], char csentence[MAX_SENTENCE_LENGTH]) { if (sender[0] == ' ' || sender[0] == '\0') { // SERVER_PRINT("Sender & sentence set.\nSender="); diff --git a/IniParser.cpp b/IniParser.cpp index 0bddd54..bebd91a 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -961,8 +961,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { pBot->ipRandom = RANDOM_LONG(25, 70); // Radio - pBot->ipReplyToRadio = RANDOM_LONG(10, 20); - pBot->ipCreateRadio = RANDOM_LONG(10, 20); + pBot->ipReplyToRadio = RANDOM_LONG(5, 20); + pBot->ipCreateRadio = RANDOM_LONG(5, 20); pBot->ipHearRate = RANDOM_LONG(20, 60); // Person diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 637991e..7e9ab1e 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -63,7 +63,8 @@ extern int draw_nodepath; //--------------------------------------------------------- //CODE: CHEESEMONSTER -int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) {// BERKED +int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const // BERKED +{ // prevent negative indexes on iVisChecked below -- BERKED if (iFrom < 0 || iFrom > MAX_NODES || iTo < 0 || iTo > MAX_NODES) { return VIS_INVALID; @@ -678,7 +679,7 @@ bool cNodeMachine::remove_neighbour_nodes(int iNode) { } // returns the next free 'neighbour id' for that node -int cNodeMachine::freeNeighbourNodeIndex(tNode *Node) { +int cNodeMachine::freeNeighbourNodeIndex(const tNode *Node) { for (int i = 0; i < MAX_NEIGHBOURS; i++) { if (Node->iNeighbour[i] < 0) { return i; @@ -688,6 +689,17 @@ int cNodeMachine::freeNeighbourNodeIndex(tNode *Node) { return -1; } +int cNodeMachine::is_neighbour_node(tNode node, int iNode) +{ + for (int i = 0; i < MAX_NEIGHBOURS; i++) { + if (node.iNeighbour[i] == iNode) { + return i; + } + } + + return -1; +} + // Return the node id from bot path on Index NR int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) { if (botIndex > -1 && botIndex < MAX_BOTS && @@ -1088,7 +1100,6 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // Check if Index is LOWER then J, if so, the height should be jumpable! // When height does not differ to much we can add this connection. // - // // 14/06/04 - fix: Some slopes are not counted in here..., de_dust jump from crates connects now const bool nodeIsHigherThanOrigin = Nodes[nodeIndex].origin.z > Nodes[currentIndex].origin.z; @@ -1734,7 +1745,7 @@ void cNodeMachine::path_draw(edict_t *pEntity) { int max_drawn = 0; for (int i = 0; i < MAX_NODES; i++) { - //TODO: iPath appears to be out of bounds [APG]RoboCop[CL] + // TODO: iPath appears to be out of bounds [APG]RoboCop[CL] const int iNode = iPath[draw_nodepath][i]; const int iNextNode = iPath[draw_nodepath][(i + 1)]; @@ -2893,9 +2904,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->strafeRight(0.2f); pBot->rprint_trace("cNodeMachine::path_walk", "Time left to move to node, so lets try strafing to unstuck."); return; - } else { - pBot->rprint_trace("cNodeMachine::path_walk", "No time left to move to node, so we continue and let stuck logic kick in"); } + pBot->rprint_trace("cNodeMachine::path_walk", "No time left to move to node, so we continue and let stuck logic kick in"); } pBot->rprint_trace("cNodeMachine::path_walk", "Finished - entity hit end block"); @@ -2968,20 +2978,22 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vec pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased, increase node time - END"); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); return; - } else if (BotShouldDuck(pBot) || (currentNode.iNodeBits & BIT_DUCK)) { - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck tries increased, increase node time - START"); - pBot->doDuck(); - pBot->iDuckTries++; - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck tries increased, increase node time - END"); - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); - return; - } else if (pBot->isOnLadder()) { - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Is stuck on ladder, trying to get of the ladder by jumping"); - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased"); - pBot->doJump(vector); - pBot->iJumpTries++; - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); - return; + } + if (BotShouldDuck(pBot) || (currentNode.iNodeBits & BIT_DUCK)) { + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck tries increased, increase node time - START"); + pBot->doDuck(); + pBot->iDuckTries++; + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck tries increased, increase node time - END"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); + return; + } + if (pBot->isOnLadder()) { + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Is stuck on ladder, trying to get of the ladder by jumping"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased"); + pBot->doJump(vector); + pBot->iJumpTries++; + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); + return; } pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "No need to duck or to jump"); diff --git a/NodeMachine.h b/NodeMachine.h index e0e8217..93280d5 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -60,9 +60,9 @@ class cNodeMachine { bool remove_neighbour_nodes(int iNode); - static int freeNeighbourNodeIndex(tNode *Node); + static int freeNeighbourNodeIndex(const tNode *Node); - int is_neighbour_node(tNode node, int iNode); + static int is_neighbour_node(tNode node, int iNode); // ----------------- void init(); // Init (info)nodes @@ -105,7 +105,7 @@ class cNodeMachine { static bool node_on_crate(const Vector& vOrigin, edict_t *pEdict); - int node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance); + static int node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance); int node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict); @@ -157,7 +157,7 @@ class cNodeMachine { // ------------------- // From cheesemonster: - int GetVisibilityFromTo(int iFrom, int iTo); // BERKED + int GetVisibilityFromTo(int iFrom, int iTo) const; // BERKED void ClearVisibilityTable() const; void SetVisibilityFromTo(int iFrom, int iTo, bool bVisible); @@ -221,7 +221,7 @@ class cNodeMachine { static bool isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHit); - void ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vector &vector); + void ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, const Vector &vector); void ExecuteDoorInteractionLogic(cBot* pBot, edict_t* pEntityHit); }; diff --git a/bot.cpp b/bot.cpp index cae0056..7ba0fa3 100644 --- a/bot.cpp +++ b/bot.cpp @@ -136,7 +136,7 @@ void cBot::SpawnInit() { fUpdateTime = gpGlobals->time; fLastRunPlayerMoveTime = gpGlobals->time - 0.1f; fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5); + fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5.0f); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); @@ -331,7 +331,7 @@ void cBot::NewRound() { f_c4_time = gpGlobals->time; f_update_weapon_time = gpGlobals->time; f_follow_time = gpGlobals->time; - f_jump_time = 0.0; + f_jump_time = 0.0f; f_hold_duck = gpGlobals->time - 1; f_camp_time = gpGlobals->time; f_wait_time = gpGlobals->time; @@ -2009,7 +2009,7 @@ void cBot::Act() { // 'do nothing' for a short period of time. if (f_wait_time > gpGlobals->time) { rprint("Act", "f_wait_time > gpGlobals->time"); - setMoveSpeed(0.0); + setMoveSpeed(0.0f); } // Button usage, change vBody to a 'trigger multiple' because we have to touch these @@ -3913,7 +3913,7 @@ bool cBot::canSeeEntity(edict_t *pEntity) const * @return */ float cBot::getDistanceTo(int nodeIndex) { - tNode *nodePtr = NodeMachine.getNode(nodeIndex); + const tNode *nodePtr = NodeMachine.getNode(nodeIndex); if (nodePtr != nullptr) { return getDistanceTo(nodePtr->origin); } @@ -4366,7 +4366,7 @@ bool cBot::isWalking() { return b; } -void cBot::doJump(Vector &vector) { +void cBot::doJump(const Vector &vector) { rprint_trace("doJump", "With vector"); // stay focussed with body and head to this vector this->vHead = vector; @@ -4384,7 +4384,7 @@ void cBot::doJump() { UTIL_BotPressKey(this, IN_DUCK); // DUCK jump by default this->f_hold_duck = gpGlobals->time + 0.5f; - this->increaseTimeToMoveToNode(0.75); + this->increaseTimeToMoveToNode(0.75f); } bool cBot::isJumping() { diff --git a/bot.h b/bot.h index 4861dbc..7889d00 100644 --- a/bot.h +++ b/bot.h @@ -58,7 +58,7 @@ extern weapon_price_table weapons_table[32]; // Define Join states for other mods #define JOIN_TEAM 1 -#define JOIN_CLASS 2 +#define JOIN_CLASS 2 #define JOIN_NONE 9999 // fix for steam (cs 1.6 bot will crash when FL_FAKECLIENT; @@ -472,10 +472,8 @@ class cBot { // ------------------- void CheckAround(); // Check around body - // ------------------- - - // + bool hasEnemy() const; bool hasEnemy(edict_t * pEdict) const; edict_t * getEnemyEdict() const; @@ -509,8 +507,6 @@ class cBot { int getGoalNode() const; - - void setMoveSpeed(float value); void setStrafeSpeed(float value, float time); void strafeLeft(float time); @@ -570,7 +566,7 @@ class cBot { bool createPath(int destinationNode, int flags); bool createPath(int destinationNode); - void doJump(Vector &vector); + void doJump(const Vector &vector); void doJump(); bool isJumping(); diff --git a/bot_func.cpp b/bot_func.cpp index 5095007..81c1a85 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -54,8 +54,7 @@ extern cNodeMachine NodeMachine; // For taking cover decision #define TOTAL_SCORE 16300 // 16000 money + 100 health + 100 fear + 100 camp desire -bool -VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { +bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -392,7 +391,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { * @return */ bool BotShouldJump(cBot *pBot) { - // WHen a bot should jump, something is blocking his way. + // When a bot should jump, something is blocking his way. // Most of the time it is a fence, or a 'half wall' that reaches from body to feet // However, the body most of the time traces above this wall. // What i do: @@ -431,9 +430,8 @@ bool BotShouldJump(cBot *pBot) { if (tr.flFraction < 1.0f) { pBot->rprint_trace("BotShouldJump", "I cannot jump because something is blocking the max jump height"); return false; - } else { - pBot->rprint_trace("BotShouldJump", "I can make the jump, nothing blocking the jump height"); } + pBot->rprint_trace("BotShouldJump", "I can make the jump, nothing blocking the jump height"); // Ok the body is clear v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); @@ -443,11 +441,10 @@ bool BotShouldJump(cBot *pBot) { UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); if (tr.flFraction < 1.0f) { - pBot->rprint_trace("BotShouldJump", "cannot jump because body is blocked"); + pBot->rprint_trace("BotShouldJump", "Cannot jump because body is blocked"); return false; - } else { - pBot->rprint_trace("BotShouldJump", "Jump body is not blocked"); } + pBot->rprint_trace("BotShouldJump", "Jump body is not blocked"); // Ok the body is clear v_source = pEdict->v.origin + Vector(0, 0, -14); // 14 downwards (from center) ~ roughly the kneecaps @@ -493,7 +490,7 @@ bool BotShouldJump(cBot *pBot) { } // FUNCTION: Calculates angles as pEdict->v.v_angle should be when checking for body -Vector FUNC_CalculateAngles(cBot *pBot) { +Vector FUNC_CalculateAngles(const cBot *pBot) { // aim for the head and/or body const Vector v_target = pBot->vBody - pBot->pEdict->v.origin; Vector v_body = UTIL_VecToAngles(v_target); @@ -524,7 +521,7 @@ bool BotShouldDuck(cBot *pBot) { //return BotCanDuckUnder(pBot); //Makes the code underneath unreachable? [APG]RoboCop[CL] - // WHen a bot should jump, something is blocking his way. + // When a bot should jump, something is blocking his way. // Most of the time it is a fence, or a 'half wall' that reaches from body to feet // However, the body most of the time traces above this wall. // What i do: @@ -532,12 +529,11 @@ bool BotShouldDuck(cBot *pBot) { // When head blocked and waist is free, then we should duck... TraceResult tr; - Vector v_duck; const edict_t *pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... - v_duck = FUNC_CalculateAngles(pBot); + Vector v_duck = FUNC_CalculateAngles(pBot); v_duck.x = 0; // reset pitch to 0 (level horizontally) v_duck.z = 0; // reset roll to 0 (straight up and down) @@ -572,7 +568,7 @@ bool BotShouldDuck(cBot *pBot) { * @param pBot * @return */ -bool FUNC_DoRadio(cBot *pBot) { +bool FUNC_DoRadio(const cBot *pBot) { if (pBot->fDoRadio > gpGlobals->time) // allowed? return false; @@ -606,6 +602,15 @@ bool FUNC_ShouldTakeCover(cBot *pBot) { return RANDOM_LONG(0, TOTAL_SCORE) < (vMoney + vHealth + vCamp); } +bool FUNC_TakeCover(cBot* pBot) //Experimental [APG]RoboCop[CL] +{ + // If we are not allowed to take cover, return false + if (!FUNC_ShouldTakeCover(pBot)) + return false; + + return true; +} + int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { // here we normally figure out where to look at when we hear an enemy, RealBot AI PR 2 lagged a lot on this so we need another approach @@ -614,7 +619,7 @@ int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { // Added Stefan // 7 November 2001 -int FUNC_PlayerSpeed(edict_t *edict) { +int FUNC_PlayerSpeed(const edict_t *edict) { if (edict != nullptr) return static_cast(edict->v.velocity.Length2D()); // Return speed of any edict given @@ -623,45 +628,90 @@ int FUNC_PlayerSpeed(edict_t *edict) { bool FUNC_PlayerRuns(int speed) { if (speed < 200) - return false; // We make no sound - else - return true; // We make sound + return false; // We make no sound + + return true; // We make sound } // return weapon type of edict. // only when 'important enough'. -int FUNC_EdictHoldsWeapon(edict_t *pEdict) { +int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { // sniper guns - if (strcmp("models/p_awp.mdl", STRING(pEdict->v.weaponmodel)) == 0) - return CS_WEAPON_AWP; + //if (strcmp("models/p_awp.mdl", STRING(pEdict->v.weaponmodel)) == 0) //Excluded for high prices and accuracy [APG]RoboCop[CL] + // return CS_WEAPON_AWP; if (strcmp("models/p_scout.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_SCOUT; - // good weapons (ak, m4a1) + // good weapons (ak, m4a1, mp5) if (strcmp("models/p_ak47.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_AK47; if (strcmp("models/p_m4a1.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_M4A1; + if (strcmp("models/p_mp5navy.mdl", STRING(pEdict->v.weaponmodel)) == 0) + return CS_WEAPON_MP5NAVY; // grenade types - if (strcmp("models/p_smokegrenade.mdl", STRING(pEdict->v.weaponmodel)) - == 0) + if (strcmp("models/p_smokegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_SMOKEGRENADE; - if (strcmp("models/p_hegrenade.mdl", STRING(pEdict->v.weaponmodel)) == - 0) + if (strcmp("models/p_hegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_HEGRENADE; - if (strcmp("models/p_flashbang.mdl", STRING(pEdict->v.weaponmodel)) == - 0) + if (strcmp("models/p_flashbang.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_FLASHBANG; - // shield - if (strcmp("models/p_shield.mdl", STRING(pEdict->v.weaponmodel)) == 0) - return CS_WEAPON_SHIELD; + // shield types //Most CS Veterans dislikes the shield [APG]RoboCop[CL] + //if (strcmp("models/p_shield.mdl", STRING(pEdict->v.weaponmodel)) == 0) + // return CS_WEAPON_SHIELD; // unknown return -1; } +int FUNC_FindFarWaypoint(cBot* pBot, Vector avoid, bool safest) //Experimental [APG]RoboCop[CL] +{ + // Find a waypoint that is far away from the enemy. + // If safest is true, then we want the safest waypoint. + // If safest is false, then we want the farthest waypoint. + + // Find the farthest waypoint + int farthest = -1; + float farthest_distance = 0.0f; + + for (int i = 0; i < gpGlobals->maxEntities; i++) { + const edict_t *pEdict = INDEXENT(i); + + if (pEdict == nullptr) + continue; + + if (pEdict->v.flags & FL_DORMANT) + continue; + + if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (farthest == -1) { + farthest = i; + farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + } else { + const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + + if (safest) { + if (distance < farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } else { + if (distance > farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } + } + } + } + } + + return farthest; +} + // Function to let a bot react on some sound which he cannot see void FUNC_HearingTodo(cBot *pBot) { // This is called every frame. @@ -742,7 +792,7 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG } // Returns true/false if an entity is on a ladder -bool FUNC_IsOnLadder(edict_t *pEntity) { +bool FUNC_IsOnLadder(const edict_t *pEntity) { if (pEntity == nullptr) return false; @@ -825,10 +875,9 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { pBot->rprint_trace("TryToGetHostageTargetToFollowMe", "Hostage found, but not rescueable, forgetting..."); pBot->forgetHostage(pHostage); return; - } else { - pBot->rprint_trace("TryToGetHostageTargetToFollowMe", "Remembering hostage (target) to rescue"); - pBot->rememberWhichHostageToRescue(pHostage); } + pBot->rprint_trace("TryToGetHostageTargetToFollowMe", "Remembering hostage (target) to rescue"); + pBot->rememberWhichHostageToRescue(pHostage); // Prevent bots getting to close here const float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); @@ -869,7 +918,8 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { } } -bool isHostageRescued(cBot *pBot, edict_t *pHostage) { +bool isHostageRescued(cBot *pBot, const edict_t *pHostage) //pBot not used [APG]RoboCop[CL] +{ if (pHostage == nullptr) return false; if (FBitSet(pHostage->v.effects, EF_NODRAW)) { @@ -880,6 +930,57 @@ bool isHostageRescued(cBot *pBot, edict_t *pHostage) { return false; } +int FUNC_GiveHostage(cBot* pBot) //Experimental [APG]RoboCop[CL] +{ + if (pBot->isTerrorist()) { + return 0; + } + + // find a hostage to rescue + edict_t *pHostage = pBot->getHostageToRescue(); + + if (pHostage == nullptr) { + pHostage = pBot->findHostageToRescue(); + } + + // still NULL + if (pHostage == nullptr) { + // Note: this means a hostage that is near and visible and rescueable etc. + return 0; // nothing to do yet + } + + // Whenever we have a hostage to go after, verify it is still rescueable + const bool isRescueable = isHostageRescueable(pBot, pHostage); + + if (!isRescueable) { + pBot->rprint_trace("GiveHostage", "Hostage found, but not rescueable, forgetting..."); + pBot->forgetHostage(pHostage); + return 0; + } + pBot->rprint_trace("GiveHostage", "Remembering hostage (target) to rescue"); + pBot->rememberWhichHostageToRescue(pHostage); + + // Prevent bots getting to close here + const float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); + + // From here, we should get the hostage when still visible + if (pBot->canSeeEntity(pHostage)) + { + pBot->rprint_trace("GiveHostage", "I can see the hostage to rescue!"); + // set body to hostage! + pBot->vBody = pBot->vHead = pHostage->v.origin + Vector(0, 0, 36); + // by default run + pBot->setMoveSpeed(pBot->f_max_speed); + + if (distanceToHostage <= 80) + { + pBot->rprint_trace("GiveHostage", "I can see hostage AND really close!"); + pBot->setMoveSpeed(0.0f); // too close, do not move + } + } + return true; //gives any hostage we still have to go for +} + bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { if (pHostage == nullptr) return false; // pBot->rprint("isHostageRescueable"); diff --git a/bot_func.h b/bot_func.h index 696baa0..ae7155b 100644 --- a/bot_func.h +++ b/bot_func.h @@ -35,8 +35,8 @@ void BotThink(cBot * pBot); void botFixIdealPitch(edict_t * pEdict); void botFixIdealYaw(edict_t * pEdict); -bool BotCanJumpUp(cBot * pBot); -bool BotCanDuckUnder(cBot * pBot); +bool BotCanJumpUp(const cBot * pBot); +bool BotCanDuckUnder(const cBot * pBot); bool EntityIsVisible(edict_t * pEntity, const Vector& dest); @@ -58,32 +58,32 @@ bool BotShouldJump(cBot * pBot); bool BotShouldJumpIfStuck(cBot * pBot); bool BotShouldDuck(cBot * pBot); void TryToGetHostageTargetToFollowMe(cBot * pBot); -Vector FUNC_CalculateAngles(cBot * pBot); +Vector FUNC_CalculateAngles(const cBot * pBot); // New funcs -bool FUNC_DoRadio(cBot * pBot); +bool FUNC_DoRadio(const cBot * pBot); bool FUNC_ShouldTakeCover(cBot * pBot); bool FUNC_TakeCover(cBot * pBot); -int FUNC_EdictHoldsWeapon(edict_t * pEdict); +int FUNC_EdictHoldsWeapon(const edict_t * pEdict); int FUNC_FindFarWaypoint(cBot * pBot, Vector avoid, bool safest); -int FUNC_FindCover(int from, int to); -int FUNC_PlayerSpeed(edict_t * edict); +int FUNC_FindCover(int from, int to); //TODO: Add definition for bots to find cover +int FUNC_PlayerSpeed(const edict_t * edict); bool FUNC_PlayerRuns(int speed); void FUNC_HearingTodo(cBot * pBot); void FUNC_ClearEnemyPointer(edict_t *pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] -bool FUNC_IsOnLadder(edict_t * pEntity); -void FUNC_FindBreakable(cBot * pBot); -void FUNC_CheckForBombPlanted(); +bool FUNC_IsOnLadder(const edict_t * pEntity); +void FUNC_FindBreakable(cBot * pBot); //TODO: Add definition for bots to destory glass and crates? +void FUNC_CheckForBombPlanted(edict_t* pEntity); //TODO: Add definition for bots to detect C4s int FUNC_GiveHostage(cBot * pBot); // gives any hostage we still have to go for bool isHostageRescueable(cBot *pBot, edict_t *pHostage); -bool isHostageRescued(cBot *pBot, edict_t *pHostage); +bool isHostageRescued(cBot *pBot, const edict_t *pHostage); bool isHostageFree(cBot * pBotWhoIsAsking, edict_t * pHostage); // is this hostage not used by any other bot? int FUNC_BotEstimateHearVector(cBot * pBot, const Vector& v_sound); diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 2b74878..ad0c095 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -64,7 +64,7 @@ void botFixIdealYaw(edict_t * pEdict) { pEdict->v.ideal_yaw = fixAngle(pEdict->v.ideal_yaw); } -bool BotCanJumpUp(cBot * pBot) { +bool BotCanJumpUp(const cBot * pBot) { // What I do here is trace 3 lines straight out, one unit higher than // the highest normal jumping distance. I trace once at the center of // the body, once at the right side, and once at the left side. If all @@ -104,8 +104,7 @@ bool BotCanJumpUp(cBot * pBot) { // now check same height to one side of the bot... v_source = pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, - -36 + - MAX_JUMPHEIGHT); + -36 + MAX_JUMPHEIGHT); v_dest = v_source + gpGlobals->v_forward * 24; // trace a line forward at maximum jump height... @@ -119,8 +118,7 @@ bool BotCanJumpUp(cBot * pBot) { // now check same height on the other side of the bot... v_source = pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, - -36 + - MAX_JUMPHEIGHT); + -36 + MAX_JUMPHEIGHT); v_dest = v_source + gpGlobals->v_forward * 24; // trace a line forward at maximum jump height... @@ -186,7 +184,7 @@ bool BotCanJumpUp(cBot * pBot) { return TRUE; } -bool BotCanDuckUnder(cBot * pBot) { +bool BotCanDuckUnder(const cBot * pBot) { // What I do here is trace 3 lines straight out, one unit higher than // the ducking height. I trace once at the center of the body, once // at the right side, and once at the left side. If all three of these diff --git a/build.cpp b/build.cpp index 4a5d2f4..75bea9e 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.3-APG"; +const char *rb_version_nr = "4.0.4-APG"; diff --git a/game.h b/game.h index 74248c6..9042aed 100644 --- a/game.h +++ b/game.h @@ -144,8 +144,8 @@ class cGame { char cBotNames[MAX_BOT_NAMES][BOT_NAME_LEN + 1] = {}; int iMinPlayRounds = 0, iMaxPlayRounds = 0; // Min/Max playable rounds bool bNewRound = false; // New round triggered? - float fRoundTime = 0; // Round time - float fUpdateGoalTimer = 0; + float fRoundTime = 0.0f; // Round time + float fUpdateGoalTimer = 0.0f; }; #endif // GAME_H \ No newline at end of file diff --git a/util.cpp b/util.cpp index 926e6a9..798f0c6 100644 --- a/util.cpp +++ b/util.cpp @@ -160,8 +160,7 @@ void ClientPrint(edict_t *pEntity, int msg_dest, const char *msg_name) { MESSAGE_END(); } -void -UTIL_ClientPrintAll(int msg_dest, const char *msg_name, const char *param1, +void UTIL_ClientPrintAll(int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4) { if (gmsgTextMsg == 0) From 56e1db3e58eefa8bd1b79a4ce7753c6ed20fab4d Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 28 Apr 2022 23:09:57 +0100 Subject: [PATCH 042/114] Update NodeMachine.cpp --- NodeMachine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 7e9ab1e..4ad2813 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2962,14 +2962,14 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_walk", "Finished - really the end of the method"); } -void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, Vector &vector) { +void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, const Vector &vector) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "START"); pBot->fNotStuckTime = gpGlobals->time + 0.25f; // give some time to unstuck const int iFrom = pBot->getPreviousPathNodeToHeadFor(); const int iTo = currentNodeToHeadFor; - // JUMP & DUCK + // JUMP & DUCK // TODO: Add a proper and reliable Duck-Jump Node [APG]RoboCop[CL] const tNode ¤tNode = Nodes[currentNodeToHeadFor]; if (BotShouldJumpIfStuck(pBot) || (currentNode.iNodeBits & BIT_JUMP)) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased, increase node time - START"); From b7cd0f06bcaead820226e5fa01e0eb9827a6f7e3 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 30 Apr 2022 20:17:41 +0100 Subject: [PATCH 043/114] Bsp2Rbn experimental proj added --- Bsp2Rbn/Bsp2Rbn.sln | 31 ++++++ Bsp2Rbn/Bsp2Rbn.vcxproj | 176 ++++++++++++++++++++++++++++++++ Bsp2Rbn/Bsp2Rbn.vcxproj.filters | 87 ++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 Bsp2Rbn/Bsp2Rbn.sln create mode 100644 Bsp2Rbn/Bsp2Rbn.vcxproj create mode 100644 Bsp2Rbn/Bsp2Rbn.vcxproj.filters diff --git a/Bsp2Rbn/Bsp2Rbn.sln b/Bsp2Rbn/Bsp2Rbn.sln new file mode 100644 index 0000000..a9af632 --- /dev/null +++ b/Bsp2Rbn/Bsp2Rbn.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32414.318 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bsp2Rbn", "Bsp2Rbn.vcxproj", "{85813A68-52FB-4F75-91BA-DD3B6C50FD68}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Debug|x64.ActiveCfg = Debug|x64 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Debug|x64.Build.0 = Debug|x64 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Debug|x86.ActiveCfg = Debug|Win32 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Debug|x86.Build.0 = Debug|Win32 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Release|x64.ActiveCfg = Release|x64 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Release|x64.Build.0 = Release|x64 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Release|x86.ActiveCfg = Release|Win32 + {85813A68-52FB-4F75-91BA-DD3B6C50FD68}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E7378DCB-1E54-43A4-B950-59F6E738F898} + EndGlobalSection +EndGlobal diff --git a/Bsp2Rbn/Bsp2Rbn.vcxproj b/Bsp2Rbn/Bsp2Rbn.vcxproj new file mode 100644 index 0000000..e11bb09 --- /dev/null +++ b/Bsp2Rbn/Bsp2Rbn.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16.0 + Win32Proj + {85813a68-52fb-4f75-91ba-dd3b6c50fd68} + Bsp2Rbn + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\;..\..\metamod-p\metamod;..\..\hlsdk-2.3-p4\multiplayer\common;..\..\hlsdk-2.3-p4\multiplayer\engine;..\..\hlsdk-2.3-p4\multiplayer\dlls;..\..\hlsdk-2.3-p4\multiplayer\pm_shared;%(AdditionalIncludeDirectories) + /Zc:strictStrings %(AdditionalOptions) + Default + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + ..\;..\..\metamod-p\metamod;..\..\hlsdk-2.3-p4\multiplayer\common;..\..\hlsdk-2.3-p4\multiplayer\engine;..\..\hlsdk-2.3-p4\multiplayer\dlls;..\..\hlsdk-2.3-p4\multiplayer\pm_shared;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + \ No newline at end of file diff --git a/Bsp2Rbn/Bsp2Rbn.vcxproj.filters b/Bsp2Rbn/Bsp2Rbn.vcxproj.filters new file mode 100644 index 0000000..c6780bb --- /dev/null +++ b/Bsp2Rbn/Bsp2Rbn.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file From df71d29d279f2f8df6a4e64a0b5409ca412d7c7b Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 1 May 2022 02:14:49 +0100 Subject: [PATCH 044/114] Adding Experimental DuckJump Node and Func Plus I've added experimental FindBreakable, CheckForBombPlanted and FindCover etc found from bot_func.h --- NodeDataTypes.h | 1 + NodeMachine.cpp | 37 +++++++--- bin/data/cstrike/exp/.DS_Store | Bin 6148 -> 0 bytes bin/data/cstrike/maps/.DS_Store | Bin 6148 -> 0 bytes bin/dll/.DS_Store | Bin 6148 -> 0 bytes bot.cpp | 42 ++++++++--- bot.h | 7 +- bot_func.cpp | 121 ++++++++++++++++++++++++++++++-- bot_func.h | 7 +- bot_navigate.cpp | 2 +- dll.cpp | 3 +- todo.txt | 7 +- 12 files changed, 195 insertions(+), 32 deletions(-) delete mode 100644 bin/data/cstrike/exp/.DS_Store delete mode 100644 bin/data/cstrike/maps/.DS_Store delete mode 100644 bin/dll/.DS_Store diff --git a/NodeDataTypes.h b/NodeDataTypes.h index a4e00e6..0167fbe 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -58,6 +58,7 @@ #define BIT_WATER (1 << 1) #define BIT_JUMP (1 << 2) #define BIT_DUCK (1 << 3) +#define BIT_DUCKJUMP (1 << 4) // Path flags #define PATH_DANGER 39 // Picked a random number here diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 4ad2813..50c3ef3 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -1031,10 +1031,13 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (FUNC_IsOnLadder(pEntity)) indexNodeFloats = false; - if (pEntity->v.button & IN_DUCK) { + if (pEntity->v.button & IN_DUCK) // ?? Nodes[currentIndex].iNodeBits |= BIT_DUCK; - } + + //Experimental - This new node requires for bots to vault onto crates and edges? [APG]RoboCop[CL] + if (pEntity->v.button & BIT_DUCKJUMP) + Nodes[currentIndex].iNodeBits |= BIT_DUCKJUMP; } // do only check pEntity when its not NULL else { @@ -1389,9 +1392,15 @@ void cNodeMachine::draw(edict_t *pEntity) { if (Nodes[i].iNodeBits & BIT_WATER) r = g = 0; - if (Nodes[i].iNodeBits & BIT_DUCK) + if (Nodes[i].iNodeBits & BIT_DUCK) + r = b = 0; + // Jump and DuckJump was missing for those nodes? [APG]RoboCop[CL] + if (Nodes[i].iNodeBits & BIT_JUMP) r = b = 0; + if (Nodes[i].iNodeBits & BIT_DUCKJUMP) + r = b = 0; + if (Nodes[i].iNeighbour[0] < 0) r = 0; @@ -1421,6 +1430,10 @@ void cNodeMachine::draw(edict_t *pEntity) { if (Nodes[iNodeClose].iNodeBits & BIT_DUCK) strcat(Flags, "D"); + // Experimental DuckJump added for this new node [APG]RoboCop[CL] + if (Nodes[iNodeClose].iNodeBits & BIT_DUCKJUMP) + strcat(Flags, "h"); + sprintf(msg, "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", iNodeClose, (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.x, (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.y, @@ -2969,13 +2982,13 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con const int iFrom = pBot->getPreviousPathNodeToHeadFor(); const int iTo = currentNodeToHeadFor; - // JUMP & DUCK // TODO: Add a proper and reliable Duck-Jump Node [APG]RoboCop[CL] + // JUMP & DUCK // TODO: Add a proper and reliable DuckJump Node [APG]RoboCop[CL] const tNode ¤tNode = Nodes[currentNodeToHeadFor]; if (BotShouldJumpIfStuck(pBot) || (currentNode.iNodeBits & BIT_JUMP)) { - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased, increase node time - START"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Jump tries increased, increase node time - START"); pBot->doJump(vector); pBot->iJumpTries++; - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased, increase node time - END"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Jump tries increased, increase node time - END"); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); return; } @@ -2987,9 +3000,17 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); return; } + if (BotShouldDuckJump(pBot) || (currentNode.iNodeBits & BIT_DUCKJUMP)) { + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "DuckJump tries increased, increase node time - START"); + pBot->doDuckJump(); + pBot->iDuckJumpTries++; + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "DuckJump tries increased, increase node time - END"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); + return; + } if (pBot->isOnLadder()) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Is stuck on ladder, trying to get of the ladder by jumping"); - pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck-jump tries increased"); + pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "DuckJump tries increased"); pBot->doJump(vector); pBot->iJumpTries++; pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); @@ -3804,7 +3825,7 @@ char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) default: sprintf(typeAsText, "GOAL UNKNOWN"); } - return typeAsText; //TODO: local variable invalid [APG]RoboCop[CL] + return typeAsText; //TODO: local variable invalid [APG]RoboCop[CL] } // Find cover diff --git a/bin/data/cstrike/exp/.DS_Store b/bin/data/cstrike/exp/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0time) { - // AK, COLT, STEYR AUG, only when enough skill! - if ((CarryWeapon(CS_WEAPON_AK47) - || CarryWeapon(CS_WEAPON_M4A1) - || CarryWeapon(CS_WEAPON_AUG)) && (bot_skill < 3)) { + // AK, COLT, STEYR AUG, SIG SG552 only when enough skill! + if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) + || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) + && (bot_skill < 3)) { float f_burst = (2048 / fDistance) + 0.1f; if (f_burst < 0.1f) f_burst = 0.1f; @@ -1129,6 +1129,7 @@ void cBot::Combat() { // Bot is on ladder if (isOnLadder()) { // TODO: Bot fights when on ladder + return; } @@ -1479,6 +1480,7 @@ void cBot::InteractWithPlayers() { // We do not forget our enemy, but we will try to get the heck out of here. // TODO TODO TODO: code something here? + } // Whenever we hold a knife, get our primary weapon if (CarryWeapon(CS_WEAPON_KNIFE)) { @@ -4010,7 +4012,7 @@ bool cBot::canSeeVector(const Vector& vDest) const if (tr.flFraction < 1.0f) return false; - + return true; } @@ -4154,7 +4156,7 @@ void cBot::checkIfHostagesAreRescued() { if (isHostageRescued(this, hostage4)) forgetHostage(hostage4); } -bool cBot::isOnSameTeamAs(cBot *pBot) const +bool cBot::isOnSameTeamAs(const cBot *pBot) const { if (pBot == nullptr) return false; return pBot->iTeam == this->iTeam; @@ -4347,7 +4349,7 @@ void cBot::doDuck() { UTIL_BotPressKey(this, IN_DUCK); this->f_hold_duck = gpGlobals->time + 0.5f; - this->increaseTimeToMoveToNode(0.5); + this->increaseTimeToMoveToNode(0.5f); } bool cBot::isDucking() { @@ -4388,13 +4390,37 @@ void cBot::doJump() { } bool cBot::isJumping() { - const bool b = keyPressed(IN_JUMP) || f_jump_time > gpGlobals->time; + const bool b = keyPressed(IN_JUMP) || this->f_jump_time > gpGlobals->time; if (b) { rprint_trace("isJumping", "Yes I am jumping"); } return b; } +// Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] +// +void cBot::doDuckJump(){ + rprint_trace("doDuckJump", "no vector"); + UTIL_BotPressKey(this, IN_DUCK); + this->f_hold_duck = gpGlobals->time + 0.75f; + + UTIL_BotPressKey(this, IN_JUMP); + this->f_jump_time = gpGlobals->time + 0.75f; + + this->increaseTimeToMoveToNode(0.75f); +} + +// Bots require both the combination of the (IN_DUCK) and (IN_JUMP) key to be pressed +// in order to properly duck jump. +bool cBot::isDuckJumping() { + const bool b = keyPressed(IN_JUMP) && keyPressed(IN_DUCK) || + this->f_hold_duck > gpGlobals->time && this->f_jump_time > gpGlobals->time ; + if (b) { + rprint_trace("isDuckJumping", "Yes I am DuckJumping"); + } + return b; +} + // $Log: bot.cpp,v $ // Revision 1.21 2004/09/07 18:23:02 eric // - bumped version to 3061 diff --git a/bot.h b/bot.h index 7889d00..54c87a6 100644 --- a/bot.h +++ b/bot.h @@ -307,6 +307,7 @@ class cBot { // Remember stuck stuff int iJumpTries; int iDuckTries; + int iDuckJumpTries; // Experimental DuckJump added for this new node [APG]RoboCop[CL] // ------------------------ // BOOLEANS @@ -533,7 +534,7 @@ class cBot { void checkIfHostagesAreRescued(); - bool isOnSameTeamAs(cBot *pBot) const; + bool isOnSameTeamAs(const cBot *pBot) const; bool shouldBeAbleToMove() const; @@ -570,6 +571,10 @@ class cBot { void doJump(); bool isJumping(); + // Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] + void doDuckJump(); + bool isDuckJumping(); + void doDuck(); bool isDucking(); bool isWalking(); diff --git a/bot_func.cpp b/bot_func.cpp index 81c1a85..1408401 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -321,7 +321,7 @@ edict_t * getEntityNearbyBotInFOV(cBot *pBot) { */ //TODO: FOV and angleToPlayer are unused variables [APG]RoboCop[CL] bool isAnyPlayerNearbyBot(cBot *pBot) { const edict_t *pEdict = pBot->pEdict; - int fov = 105; + //int fov = 105; for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); @@ -337,7 +337,7 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { || (pPlayer->v.flags & FL_CLIENT))) continue; - int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); + //int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); const int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { @@ -405,7 +405,8 @@ bool BotShouldJump(cBot *pBot) { return false; } - if (pBot->isJumping()) return false; // already jumping + if (pBot->isJumping()) + return false; // already jumping TraceResult tr; const edict_t *pEdict = pBot->pEdict; @@ -518,7 +519,7 @@ bool BotShouldDuck(cBot *pBot) { pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); return false; } - + //return BotCanDuckUnder(pBot); //Makes the code underneath unreachable? [APG]RoboCop[CL] // When a bot should jump, something is blocking his way. @@ -563,6 +564,29 @@ bool BotShouldDuck(cBot *pBot) { return true; } +bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboCop[CL] +{ + // This is crucial for bots to sneak inside vents and tight areas in order + // to inflitrate and prooceed on ahead. DuckJump is required for vaulting + // on top of crates, window ledges and edges as an important method. + + if (pBot->isDefusing()) { + pBot->rprint_trace("BotShouldDuckJump", "Returning false because defusing."); + return false; + } + + if (pBot->iDuckJumpTries > 3) { + // tried to duck 3 times, so no longer! + pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); + return false; + } + + if (pBot->isDuckJumping()) + return false; // already duckjumping + + return false; +} + /** * Returns if a bot can and wants to do radio. Wanting is based on personality flag. * @param pBot @@ -605,10 +629,10 @@ bool FUNC_ShouldTakeCover(cBot *pBot) { bool FUNC_TakeCover(cBot* pBot) //Experimental [APG]RoboCop[CL] { // If we are not allowed to take cover, return false - if (!FUNC_ShouldTakeCover(pBot)) - return false; + if (!FUNC_ShouldTakeCover(pBot)) + return false; - return true; + return true; } int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { @@ -712,6 +736,45 @@ int FUNC_FindFarWaypoint(cBot* pBot, Vector avoid, bool safest) //Experimental [ return farthest; } +int FUNC_FindCover(const cBot* pBot) //Experimental [APG]RoboCop[CL] +{ + // Find a waypoint that is far away from the enemy. + // If safest is true, then we want the safest waypoint. + // If safest is false, then we want the farthest waypoint. + + // Find the farthest waypoint + int farthest = -1; + float farthest_distance = 0.0f; + + for (int i = 0; i < gpGlobals->maxEntities; i++) { + const edict_t *pEdict = INDEXENT(i); + + if (pEdict == nullptr) + continue; + + if (pEdict->v.flags & FL_DORMANT) + continue; + + if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (farthest == -1) { + farthest = i; + farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + } else { + const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + + if (distance > farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } + } + } + } + + return farthest; +} + // Function to let a bot react on some sound which he cannot see void FUNC_HearingTodo(cBot *pBot) { // This is called every frame. @@ -802,6 +865,50 @@ bool FUNC_IsOnLadder(const edict_t *pEntity) { return false; } +void FUNC_FindBreakable(edict_t* pEntity) //Experimental [APG]RoboCop[CL] +{ + // The "func_breakable" entity required for glass breaking and weak doors for bots to recognise, + // in order to attack breakable objects that would block their way. + + for (int i = 0; i < gpGlobals->maxEntities; i++) { + edict_t* pEdict = INDEXENT(i); + + if (pEdict == nullptr) + continue; + + if (pEdict->v.flags & FL_DORMANT) + continue; + + if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { + if (strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { + if (pEdict->v.origin == pEntity->v.origin) { + pEntity->v.enemy = pEdict; + return; + } + } + } + } +} + +void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] +{ + // Check if the bot has a bomb planted. + // If so, then we need to go to the bomb site. + // If not, then we need to go to the waypoint. + + // "models/w_c4.mdl" needed for CTs to see the bomb? [APG]RoboCop[CL] + if (pEntity->v.model != 0 && strcmp(STRING(pEntity->v.model), "models/w_c4.mdl") == 0) { + // Bot has a bomb planted. + // Go to the bomb site. + pEntity->v.button |= IN_USE; + pEntity->v.button |= IN_ATTACK; + } else { + // Bot does not have a bomb planted. + // Go to the waypoint. + pEntity->v.button |= IN_USE; + } +} + /** * Returns true when hostage is not marked as being rescued by any other alive bot. * diff --git a/bot_func.h b/bot_func.h index ae7155b..6f7c40f 100644 --- a/bot_func.h +++ b/bot_func.h @@ -57,6 +57,7 @@ edict_t * getEntityNearbyBotInFOV(cBot * pBot); bool BotShouldJump(cBot * pBot); bool BotShouldJumpIfStuck(cBot * pBot); bool BotShouldDuck(cBot * pBot); +bool BotShouldDuckJump(cBot* pBot); void TryToGetHostageTargetToFollowMe(cBot * pBot); Vector FUNC_CalculateAngles(const cBot * pBot); @@ -69,7 +70,7 @@ bool FUNC_TakeCover(cBot * pBot); int FUNC_EdictHoldsWeapon(const edict_t * pEdict); int FUNC_FindFarWaypoint(cBot * pBot, Vector avoid, bool safest); -int FUNC_FindCover(int from, int to); //TODO: Add definition for bots to find cover +int FUNC_FindCover(const cBot* pBot); int FUNC_PlayerSpeed(const edict_t * edict); bool FUNC_PlayerRuns(int speed); @@ -77,8 +78,8 @@ void FUNC_HearingTodo(cBot * pBot); void FUNC_ClearEnemyPointer(edict_t *pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] bool FUNC_IsOnLadder(const edict_t * pEntity); -void FUNC_FindBreakable(cBot * pBot); //TODO: Add definition for bots to destory glass and crates? -void FUNC_CheckForBombPlanted(edict_t* pEntity); //TODO: Add definition for bots to detect C4s +void FUNC_FindBreakable(edict_t* pEntity); +void FUNC_CheckForBombPlanted(edict_t* pEntity); int FUNC_GiveHostage(cBot * pBot); // gives any hostage we still have to go for diff --git a/bot_navigate.cpp b/bot_navigate.cpp index ad0c095..65eccb9 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -139,7 +139,7 @@ bool BotCanJumpUp(const cBot * pBot) { // end point of trace is 99 units straight down from start... // (99 is 108 minus the jump limit height which is 45 - 36 = 9) - // fix by stefan, max jump height is 63 , not 45! (using duck-jump) + // fix by stefan, max jump height is 63 , not 45! (using duckjump) // 108 - (63-36) = 81 v_dest = v_source + Vector(0, 0, -81); diff --git a/dll.cpp b/dll.cpp index 8ce2d36..f9f303e 100644 --- a/dll.cpp +++ b/dll.cpp @@ -535,7 +535,8 @@ void StartFrame() { int count = 0; int waits = 0; // How many bots had to wait. - // Experimental autovacate script from POD-Bot [APG]RoboCop[CL] + // TODO: Add Autovacate regulation with bot count loop + // Experimental autovacate script from POD-Bot Incomplete [APG]RoboCop[CL] max_bots = max_bots > gpGlobals->maxClients ? gpGlobals->maxClients : max_bots < 0 ? 0 : max_bots; min_bots = min_bots > gpGlobals->maxClients ? gpGlobals->maxClients : min_bots < 0 ? 0 : min_bots; if (max_bots < min_bots) diff --git a/todo.txt b/todo.txt index 3da3008..312b58c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,10 @@ - Bots may not camp when last in team (or second last?) - Bots should know when others are near its waypoint, so it won't run into each other - Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) -- Improve pathfinder +- Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Improve the way bots walk path and decide it is a bad connection -- improve 'unstucking'... when not stuck by other players. +- Improve 'unstucking'... when not stuck by other players. - Allow bots to autovacate for human players -- Prevent bots from Team Killing when a player joins T in CZ \ No newline at end of file +- Prevent bots from Team Killing when a player joins T in CZ +- Find an automated solution for removing redundant or excessive nodes that can make the connections less messy \ No newline at end of file From f4dc0a25bdfd89206f00581c8ebcb8aa7ebeece5 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 3 May 2022 00:38:06 +0100 Subject: [PATCH 045/114] Node boundaries altered Increased auto add node distance and reduced max connections --- NodeDataTypes.h | 4 ++-- NodeMachine.cpp | 15 ++++++++++----- build.cpp | 2 +- dll.cpp | 4 ++-- todo.txt | 3 +-- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 0167fbe..f5a70f9 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -102,8 +102,8 @@ // Node boundries #define MAX_NODES 4096 -#define MAX_NEIGHBOURS 16 -#define NODE_ZONE 45 +#define MAX_NEIGHBOURS 8 +#define NODE_ZONE 128 #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 50c3ef3..cb8d6a4 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -465,6 +465,11 @@ bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { return false; } +int cNodeMachine::node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance) //Experimental & Incomplete [APG]RoboCop[CL] +{ + return 0; +} + /** * Find a node close to vOrigin within distance fDist. Ignoring any pEdict it hits. * @param vOrigin @@ -1393,13 +1398,13 @@ void cNodeMachine::draw(edict_t *pEntity) { r = g = 0; if (Nodes[i].iNodeBits & BIT_DUCK) - r = b = 0; + r = b = 50; // Jump and DuckJump was missing for those nodes? [APG]RoboCop[CL] if (Nodes[i].iNodeBits & BIT_JUMP) - r = b = 0; + r = b = 100; if (Nodes[i].iNodeBits & BIT_DUCKJUMP) - r = b = 0; + r = b = 150; if (Nodes[i].iNeighbour[0] < 0) r = 0; @@ -2505,8 +2510,8 @@ int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) { if (iX > -1 && iY > -1) { int iVisibility = 9999; - float fDistance = 9999; - float fDanger = 2.0; + float fDistance = 9999.0f; + float fDanger = 2.0f; // Search in this meredian for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) if (Meredians[iX][iY].iNodes[i] > -1) { diff --git a/build.cpp b/build.cpp index 75bea9e..9372d3a 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.4-APG"; +const char *rb_version_nr = "4.0.5-beta"; diff --git a/dll.cpp b/dll.cpp index f9f303e..a2800ac 100644 --- a/dll.cpp +++ b/dll.cpp @@ -537,10 +537,10 @@ void StartFrame() { // TODO: Add Autovacate regulation with bot count loop // Experimental autovacate script from POD-Bot Incomplete [APG]RoboCop[CL] - max_bots = max_bots > gpGlobals->maxClients ? gpGlobals->maxClients : max_bots < 0 ? 0 : max_bots; + /*max_bots = max_bots > gpGlobals->maxClients ? gpGlobals->maxClients : max_bots < 0 ? 0 : max_bots; min_bots = min_bots > gpGlobals->maxClients ? gpGlobals->maxClients : min_bots < 0 ? 0 : min_bots; if (max_bots < min_bots) - min_bots = max_bots; + min_bots = max_bots;*/ // When a user - or anything else - specified a higher number of 0 to // kick bots, then we will do as told. diff --git a/todo.txt b/todo.txt index 312b58c..17ab439 100644 --- a/todo.txt +++ b/todo.txt @@ -6,5 +6,4 @@ - Improve the way bots walk path and decide it is a bad connection - Improve 'unstucking'... when not stuck by other players. - Allow bots to autovacate for human players -- Prevent bots from Team Killing when a player joins T in CZ -- Find an automated solution for removing redundant or excessive nodes that can make the connections less messy \ No newline at end of file +- Prevent bots from Team Killing when a player joins T in CZ \ No newline at end of file From b3ba6e41a6e11fdff8d4665718441ddac8ee55dc Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 3 May 2022 21:39:54 +0100 Subject: [PATCH 046/114] Node boundaries readjusted Print console neatened up, and increased Jump and DJump attempts --- NodeDataTypes.h | 4 ++-- bot_func.cpp | 6 +++--- dll.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index f5a70f9..d37b85a 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -102,8 +102,8 @@ // Node boundries #define MAX_NODES 4096 -#define MAX_NEIGHBOURS 8 -#define NODE_ZONE 128 +#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 ot 8 as 16 is maybe too much [APG]RoboCop[CL] +#define NODE_ZONE 96 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/bot_func.cpp b/bot_func.cpp index 1408401..0de2be0 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -362,7 +362,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { if (pBot->isJumping()) return false; // already jumping - if (pBot->iJumpTries > 3) { + if (pBot->iJumpTries > 5) { char msg[255]; sprintf(msg, "Returning false because jumped too many times (%d)", pBot->iJumpTries); pBot->rprint_trace("BotShouldJumpIfStuck", msg); @@ -575,8 +575,8 @@ bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboC return false; } - if (pBot->iDuckJumpTries > 3) { - // tried to duck 3 times, so no longer! + if (pBot->iDuckJumpTries > 5) { + // tried to duck 5 times, so no longer! pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); return false; } diff --git a/dll.cpp b/dll.cpp index a2800ac..f5f7997 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1245,7 +1245,7 @@ void RealBot_ServerCommand() { if (FStrEq(pcmd, "help")) { // Give information bSendMessage = false; // do not use 'standard' stuff - SERVER_PRINT("=============================================================================\n"); + SERVER_PRINT("=====================================\n");; SERVER_PRINT("Syntax: realbot [command] [arg1/subcommand] [arg2] [arg3] [arg4]\n\n"); SERVER_PRINT("List of most-used commands; for full command list read the readme.\n\n"); SERVER_PRINT("realbot add (team) (skill) (model) (name)\n"); @@ -1255,7 +1255,7 @@ void RealBot_ServerCommand() { SERVER_PRINT("realbot remove (amount) ((optional) of team 1(T)/2(CT))\n"); SERVER_PRINT("realbot skill (-1(random), 0(godlike)-10(newbie)\n"); SERVER_PRINT("realbot server [subcommand]\n"); - SERVER_PRINT("=============================================================================\n"); + SERVER_PRINT("=====================================\n"); } else if (FStrEq(pcmd, "chatrate")) { if ((arg1 != nullptr) && (*arg1 != 0)) { Game.iMaxSentences = atoi(arg1); @@ -2039,9 +2039,9 @@ void RealBot_ServerCommand() { SERVER_PRINT("\n"); } - SERVER_PRINT("============================================================================\n"); + SERVER_PRINT("=====================================\n"); SERVER_PRINT(cMessage); - SERVER_PRINT("============================================================================\n"); + SERVER_PRINT("=====================================\n"); // Put an extra carriage return when using dedicated server. if (IS_DEDICATED_SERVER()) { From d1d5090b31cbcb9dfa4a20a8c04934cfdb7076e1 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 3 May 2022 21:47:27 +0100 Subject: [PATCH 047/114] Update NodeDataTypes.h --- NodeDataTypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index d37b85a..d3cae33 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -102,7 +102,7 @@ // Node boundries #define MAX_NODES 4096 -#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 ot 8 as 16 is maybe too much [APG]RoboCop[CL] +#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] #define NODE_ZONE 96 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES From f3b2faa6c9332047a3be77184146b58ea20aa140 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 4 May 2022 16:56:43 +0100 Subject: [PATCH 048/114] Node boundaries readjusted --- NodeDataTypes.h | 4 ++-- todo.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index d3cae33..246475f 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -102,8 +102,8 @@ // Node boundries #define MAX_NODES 4096 -#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 96 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define MAX_NEIGHBOURS 8 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] +#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/todo.txt b/todo.txt index 17ab439..c714e69 100644 --- a/todo.txt +++ b/todo.txt @@ -6,4 +6,5 @@ - Improve the way bots walk path and decide it is a bad connection - Improve 'unstucking'... when not stuck by other players. - Allow bots to autovacate for human players -- Prevent bots from Team Killing when a player joins T in CZ \ No newline at end of file +- Prevent bots from Team Killing when a player joins T in CZ +- Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) \ No newline at end of file From 52de5f8602dd76e8f4cf643105cf2e47ce25ba0f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 4 May 2022 17:21:45 +0100 Subject: [PATCH 049/114] Update todo.txt --- todo.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/todo.txt b/todo.txt index c714e69..5c8075d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,10 @@ - Bots may not camp when last in team (or second last?) -- Bots should know when others are near its waypoint, so it won't run into each other +- Bots should know when others are near its waypoint, so it won't run into each other - Done but not fully tested! - Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) -- Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways -- Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples +- Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Not fully tested! +- Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Almost done! - Improve the way bots walk path and decide it is a bad connection -- Improve 'unstucking'... when not stuck by other players. +- Improve 'unstucking'... when not stuck by other players. - Almost done! - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) \ No newline at end of file From dddfaa822e6d16ca3c976d78debb61c727c64c40 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 4 May 2022 22:09:56 +0100 Subject: [PATCH 050/114] Updated Makefile Debug --- Makefile.debug | 4 ++-- todo.txt | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.debug b/Makefile.debug index 76c7fdb..557630d 100644 --- a/Makefile.debug +++ b/Makefile.debug @@ -5,7 +5,7 @@ ARCHFLAG = -m32 -g METAMOD_SRCDIR = ./dependencies/metamod-hl1/metamod HLSDK_BASEDIR = ./dependencies/hlsdk -BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -g +BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -ggdb3 CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O0 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/common" -I"${HLSDK_BASEDIR}/dlls" -I"${HLSDK_BASEDIR}/engine" -I"${HLSDK_BASEDIR}/pm_shared" -I"${HLSDK_BASEDIR}/public" OBJ = NodeMachine.o \ @@ -30,7 +30,7 @@ ifeq ($(UNAME_S),Darwin) SO_SUFFIX = dylib endif -realbot_mm_i386.${SO_SUFFIX}: ${OBJ} +realbot_mm.${SO_SUFFIX}: ${OBJ} ${CPP} ${ARCHFLAG} -fPIC -shared -o $@ ${OBJ} -ldl mkdir -p Release mv $@ ${OBJ} Release diff --git a/todo.txt b/todo.txt index 5c8075d..d6967bf 100644 --- a/todo.txt +++ b/todo.txt @@ -7,4 +7,5 @@ - Improve 'unstucking'... when not stuck by other players. - Almost done! - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ -- Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) \ No newline at end of file +- Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) +- To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up \ No newline at end of file From 03e6cd2474722b6b76d8f492946ab6596ab88bb2 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 4 May 2022 22:54:13 +0100 Subject: [PATCH 051/114] Update util.cpp --- util.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util.cpp b/util.cpp index 798f0c6..9f7c75f 100644 --- a/util.cpp +++ b/util.cpp @@ -309,7 +309,8 @@ int UTIL_GetTeam(edict_t *pEntity) { (strcmp(model_name, "leet") == 0) || // L337 Krew (strcmp(model_name, "artic") == 0) || // Artic Avenger (strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? - (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare + (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare + //(strcmp(model_name, "militia") == 0)) // CZ Militia { return 0; // team Terrorists } else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 From c2f4f2f4f38d0356aa855fe00082f99ee9d0be64 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 5 May 2022 11:05:33 +0100 Subject: [PATCH 052/114] Reverted Node Boundaries --- NodeDataTypes.h | 4 ++-- todo.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 246475f..c40e95d 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -102,8 +102,8 @@ // Node boundries #define MAX_NODES 4096 -#define MAX_NEIGHBOURS 8 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] +#define NODE_ZONE 45 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/todo.txt b/todo.txt index d6967bf..7f4a315 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,10 @@ - Bots may not camp when last in team (or second last?) - Bots should know when others are near its waypoint, so it won't run into each other - Done but not fully tested! -- Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in) +- Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in and hostages) - Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Not fully tested! - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Almost done! - Improve the way bots walk path and decide it is a bad connection -- Improve 'unstucking'... when not stuck by other players. - Almost done! +- Improve 'unstucking'... when not stuck by hostages. - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) From 06f30c8a9663623b715a44a03d2b4965dbd498ab Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 5 May 2022 11:58:01 +0100 Subject: [PATCH 053/114] Update build.cpp --- build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cpp b/build.cpp index 9372d3a..788bc88 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.5-beta"; +const char *rb_version_nr = "4.0.5-beta2"; From 4e86ed7d8213e00b072595abad8fbc6bbcc2fecf Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 5 May 2022 12:34:54 +0100 Subject: [PATCH 054/114] Version 4.0.5beta2 out --- build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cpp b/build.cpp index 9372d3a..788bc88 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.5-beta"; +const char *rb_version_nr = "4.0.5-beta2"; From a0339cce569138e887e4465763cee09fefbd2e68 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 6 May 2022 03:25:07 +0100 Subject: [PATCH 055/114] Chat and wonder rate min increased --- IniParser.cpp | 6 +++--- NodeDataTypes.h | 2 +- bot.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/IniParser.cpp b/IniParser.cpp index bebd91a..352aee1 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -958,11 +958,11 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Game pBot->ipHostage = RANDOM_LONG(25, 70); pBot->ipBombspot = RANDOM_LONG(25, 70); - pBot->ipRandom = RANDOM_LONG(25, 70); + pBot->ipRandom = RANDOM_LONG(40, 80); // Radio - pBot->ipReplyToRadio = RANDOM_LONG(5, 20); - pBot->ipCreateRadio = RANDOM_LONG(5, 20); + pBot->ipReplyToRadio = RANDOM_LONG(10, 25); + pBot->ipCreateRadio = RANDOM_LONG(10, 25); pBot->ipHearRate = RANDOM_LONG(20, 60); // Person diff --git a/NodeDataTypes.h b/NodeDataTypes.h index c40e95d..8528adc 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -103,7 +103,7 @@ // Node boundries #define MAX_NODES 4096 #define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 45 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define NODE_ZONE 128 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/bot.cpp b/bot.cpp index e07625b..d4a9d3f 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1980,7 +1980,7 @@ void cBot::Act() { pEdict->v.button &= (~IN_RUN); // release IN_RUN rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed(((f_max_speed) / 2 + (f_max_speed) / 50)); + setMoveSpeed((f_max_speed) / 2 + (f_max_speed) / 50); } // When we are at max speed, press IN_RUN to get a running animation From 3a653be1dec55c2ee8beab026fb873d0a6c8c077 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 6 May 2022 03:44:19 +0100 Subject: [PATCH 056/114] Update NodeDataTypes.h --- NodeDataTypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 8528adc..1109cc7 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -103,7 +103,7 @@ // Node boundries #define MAX_NODES 4096 #define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 128 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember From 5d483826b3db6de8abc5adec78ce1ffd3c97f404 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 6 May 2022 14:16:55 +0100 Subject: [PATCH 057/114] INI and Boundaries readjusted --- IniParser.cpp | 10 +++++----- NodeDataTypes.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/IniParser.cpp b/IniParser.cpp index 352aee1..88736f4 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -961,15 +961,15 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { pBot->ipRandom = RANDOM_LONG(40, 80); // Radio - pBot->ipReplyToRadio = RANDOM_LONG(10, 25); - pBot->ipCreateRadio = RANDOM_LONG(10, 25); + pBot->ipReplyToRadio = RANDOM_LONG(10, 20); + pBot->ipCreateRadio = RANDOM_LONG(10, 20); pBot->ipHearRate = RANDOM_LONG(20, 60); // Person pBot->ipTurnSpeed = RANDOM_LONG(20, 40); - pBot->ipCampRate = RANDOM_LONG(0, 60); - pBot->ipChatRate = RANDOM_LONG(0, 20); - pBot->ipWalkWithKnife = RANDOM_LONG(0, 40); + pBot->ipCampRate = RANDOM_LONG(0, 40); + pBot->ipChatRate = RANDOM_LONG(10, 20); + pBot->ipWalkWithKnife = RANDOM_LONG(0, 30); // SAVE TO DISK: //char dirname[256]; diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 1109cc7..5ee9cd5 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -103,7 +103,7 @@ // Node boundries #define MAX_NODES 4096 #define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define NODE_ZONE 72 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember From 8f8fa1bc43223bcdfb44e0527183d90e1d203207 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 6 May 2022 15:04:37 +0100 Subject: [PATCH 058/114] Update NodeDataTypes.h --- NodeDataTypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 5ee9cd5..1109cc7 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -103,7 +103,7 @@ // Node boundries #define MAX_NODES 4096 #define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 72 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember From 50b24d43a1093acb7200efa6a2eb364e6b6d7da7 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 6 May 2022 19:03:01 +0100 Subject: [PATCH 059/114] Todo updated --- bot_func.cpp | 2 +- todo.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot_func.cpp b/bot_func.cpp index 0de2be0..a7e94e9 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -865,7 +865,7 @@ bool FUNC_IsOnLadder(const edict_t *pEntity) { return false; } -void FUNC_FindBreakable(edict_t* pEntity) //Experimental [APG]RoboCop[CL] +void FUNC_FindBreakable(edict_t* pEntity) //TODO: not functioning, bots won't shoot windows nor vent doors to proceed [APG]RoboCop[CL] { // The "func_breakable" entity required for glass breaking and weak doors for bots to recognise, // in order to attack breakable objects that would block their way. diff --git a/todo.txt b/todo.txt index 7f4a315..68b7599 100644 --- a/todo.txt +++ b/todo.txt @@ -4,7 +4,7 @@ - Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Not fully tested! - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Almost done! - Improve the way bots walk path and decide it is a bad connection -- Improve 'unstucking'... when not stuck by hostages. +- Improve 'unstucking'... when not stuck by hostages and how to attack glass or vent grills in order to proceed. - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) From d316bf5a4d070ff893c78a27e286ca4e66a5cfe8 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 7 May 2022 23:21:01 +0100 Subject: [PATCH 060/114] Bsp2Rbn neatened and adding AMBuild --- AMBuildScript | 9 +- Bsp2Rbn/AMBuilder | 24 + Bsp2Rbn/Bsp2Rbn.vcxproj | 12 +- Bsp2Rbn/DrawNodes.c | 926 +++++++++++++------------- Bsp2Rbn/DumpNodes.c | 267 ++++---- Bsp2Rbn/Makefile | 2 +- Bsp2Rbn/bspfile.cpp | 1254 ++++++++++++++++++------------------ Bsp2Rbn/bspfile.h | 658 +++++++++---------- Bsp2Rbn/build.cpp | 4 +- Bsp2Rbn/cmdlib.cpp | 1243 +++++++++++++++++------------------ Bsp2Rbn/cmdlib.h | 109 ++-- Bsp2Rbn/dummy.cpp | 119 ++-- Bsp2Rbn/entity.cpp | 321 +++++----- Bsp2Rbn/entity.h | 21 +- Bsp2Rbn/mathlib.cpp | 291 ++++----- Bsp2Rbn/mathlib.h | 190 +++--- Bsp2Rbn/paklib.h | 115 ++-- Bsp2Rbn/scriplib.cpp | 315 +++++---- Bsp2Rbn/scriplib.h | 19 +- Bsp2Rbn/studio_model.h | 179 +++--- Bsp2Rbn/trace.cpp | 736 +++++++++++---------- Bsp2Rbn/trace.h | 21 +- Bsp2Rbn/util.cpp | 1354 +++++++++++++++++++-------------------- Bsp2Rbn/world.cpp | 253 ++++---- Bsp2Rbn/world.h | 16 +- 25 files changed, 4172 insertions(+), 4286 deletions(-) create mode 100644 Bsp2Rbn/AMBuilder diff --git a/AMBuildScript b/AMBuildScript index 4042ec8..e04d482 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -158,10 +158,15 @@ binary.sources += [ 'util.cpp', ] +builder.RunBuildScripts( + [ + 'Bsp2Rbn/AMBuilder', + ], + #{ 'AMXX': AMXX } +) # # Run scripts, add binaries # -builder.Add(binary) - +builder.Add(binary) \ No newline at end of file diff --git a/Bsp2Rbn/AMBuilder b/Bsp2Rbn/AMBuilder new file mode 100644 index 0000000..aec23f5 --- /dev/null +++ b/Bsp2Rbn/AMBuilder @@ -0,0 +1,24 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os.path + +#binary = AMXX.MetaModule(builder, 'bsp2rbn') + +binary.sources = [ + '../../public/sdk/amxxmodule.cpp', + 'CRank.cpp', + 'CMisc.cpp', + 'NBase.cpp', + 'NRank.cpp', + 'usermsg.cpp', + 'Utils.cpp', + 'moduleconfig.cpp', +] + +if builder.target_platform == 'windows': + #binary.sources += ['version.rc'] + binary.compiler.linkflags += [ + '/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1', + '/SECTION:.data,RW', + ] + +##AMXX.modules += [builder.Add(binary)] diff --git a/Bsp2Rbn/Bsp2Rbn.vcxproj b/Bsp2Rbn/Bsp2Rbn.vcxproj index e11bb09..9064879 100644 --- a/Bsp2Rbn/Bsp2Rbn.vcxproj +++ b/Bsp2Rbn/Bsp2Rbn.vcxproj @@ -61,8 +61,8 @@ Application false - v143 - true + v120 + false Unicode @@ -128,15 +128,16 @@ true WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true - ..\;..\..\metamod-p\metamod;..\..\hlsdk-2.3-p4\multiplayer\common;..\..\hlsdk-2.3-p4\multiplayer\engine;..\..\hlsdk-2.3-p4\multiplayer\dlls;..\..\hlsdk-2.3-p4\multiplayer\pm_shared;%(AdditionalIncludeDirectories) + ..\;..\dependencies\metamod-hl1\metamod;..\dependencies\hlsdk\common;..\dependencies\hlsdk\engine;..\dependencies\hlsdk\dlls;..\dependencies\hlsdk\pm_shared;..\dependencies\hlsdk\public;%(AdditionalIncludeDirectories) /Zc:strictStrings %(AdditionalOptions) Default Console - true + false true true + false @@ -159,7 +160,8 @@ true NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true - ..\;..\..\metamod-p\metamod;..\..\hlsdk-2.3-p4\multiplayer\common;..\..\hlsdk-2.3-p4\multiplayer\engine;..\..\hlsdk-2.3-p4\multiplayer\dlls;..\..\hlsdk-2.3-p4\multiplayer\pm_shared;%(AdditionalIncludeDirectories) + ..\;..\dependencies\metamod-hl1\metamod;..\dependencies\hlsdk\common;..\dependencies\hlsdk\engine;..\dependencies\hlsdk\dlls;..\dependencies\hlsdk\pm_shared;..\dependencies\hlsdk\public;%(AdditionalIncludeDirectories) + /Zc:strictStrings %(AdditionalOptions) Console diff --git a/Bsp2Rbn/DrawNodes.c b/Bsp2Rbn/DrawNodes.c index 1d0cd1c..526f196 100644 --- a/Bsp2Rbn/DrawNodes.c +++ b/Bsp2Rbn/DrawNodes.c @@ -1,464 +1,464 @@ -// Based on Pierre-Marie Batty bmpfile.cpp - -// Tuned for Realbot .RBN files by evyncke@students.hec.be, June 2004 - -// RACC - AI development project for first-person shooter games derived from Valve's Half-Life -// (http://www.racc-ai.com/) -// -// The game to engine interfacing code is based on the work done by Jeffrey 'botman' Broome -// (http://planethalflife.com/botman/) -// -// This project is partially based on the work done by Eric Bieschke in his BSDbot -// (http://gamershomepage.com/csbot/) -// -// This project is partially based on the work done by Brendan "Spyro" McCarthy in his ODD Bot -// (http://oddbot.hlfusion.com/) -// -// This project is partially based on the work done by Alistair 'eLiTe' Stewart in his TEAMbot -// (http://www.planethalflife.com/teambot/) -// -// The BMP writing functions in this file come primarily from botman's BSP slicer utility -// (http://planethalflife.com/botman/) -// -// Rational Autonomous Cybernetic Commandos AI -// -// bmpfile.cpp -// - -#include -#include -#include -#include -#include -#include -#include -#include - -extern char * Version ; - -// width and height of the debug bitmap image -#define DEBUG_BMP_WIDTH 2048 -#define DEBUG_BMP_HEIGHT 2048 - -float scalex, scaley, scale; -char *bmp_buffer; - -#include "../bot.h" -#include "../NodeMachine.h" - -extern char * Version ; - -/* Copy from NodeMachine.cpp by Stefan Hendricks */ - -tNode Nodes[MAX_NODES]; // Nodes -tInfoNode InfoNodes[MAX_NODES]; // Info for Nodes -tMeredian Meredians[MAX_MEREDIANS][MAX_MEREDIANS]; // Meredian lookup search for Nodes -int iMaxUsedNodes; -float maxx, maxy, minx, miny ; - -void load (char * mapname) -{ - char filename[256]; - int i, n; - - // Set Directory name - strcpy (filename, mapname); - strcat (filename, ".rbn"); // nodes file - - FILE *rbl; - rbl = fopen (filename, "rb"); - - if (rbl != NULL) - { - int iVersion ; - fread (&iVersion, sizeof (int), 1, rbl); - - // Version 1.0 - if (iVersion == FILE_NODE_VER1) - { - for (i = 0; i < MAX_NODES; i++) - { - fread (&Nodes[i].origin, sizeof (Vector), 1, rbl); - for (n = 0; n < MAX_NEIGHBOURS; n++) - { - fread (&Nodes[i].iNeighbour[n], sizeof (int), 1, rbl); - } - - // save bit flags - fread (&Nodes[i].iNodeBits, sizeof (int), 1, rbl); - - if (Nodes[i].origin != Vector (9999, 9999, 9999)) - iMaxUsedNodes = i; - } - } - } else { - fprintf(stderr,"Cannot open file %s\n",filename) ; - exit ; - } - printf("%d nodes loaded out of %d.\n",iMaxUsedNodes,MAX_NODES) ; -} - -void InitDebugBitmap (void) -{ - // this function allocates memory and clears the debug bitmap buffer - - if (bmp_buffer) - free (bmp_buffer); // reliability check, free BMP buffer if already allocated - bmp_buffer = NULL; - bmp_buffer = (char *) malloc (DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // allocate memory - if (bmp_buffer == NULL) { - fprintf (stderr,"InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024); - exit(1) ; - } - - memset (bmp_buffer, 14, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // Set all to white - return; // yes, it's as simple as that -} - - -void DrawPoint (const Vector v, unsigned char color) -{ - int offset, fraction, x0, y0; - float scalex, scaley, scale; - - if (bmp_buffer == NULL) - { - fprintf (stderr,"DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); - return; // reliability check: cancel if bmp buffer unallocated - } - - // first compute the X and Y divider scale, and take the greatest of both - scalex = (maxx - minx) / DEBUG_BMP_WIDTH ; - scaley = (maxy - miny) / DEBUG_BMP_WIDTH ; - if (scalex > scaley) - scale = scalex + scalex / 100; // add a little offset (margin) for safety - else - scale = scaley + scaley / 100; // add a little offset (margin) for safety - - // translate the world coordinates in image pixel coordinates - x0 = (int) ((v.x - minx) / scale); - y0 = (int) ((v.y - miny) / scale); - - offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf( stderr,"DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1) ; - } - - bmp_buffer[offset] = color; // draw the point itself - if (offset+1 < DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) bmp_buffer[offset+1] = color; // make a small star on the right - if (offset-1 >= 0) bmp_buffer[offset-1] = color; // make a small star on the left - if (offset+DEBUG_BMP_WIDTH < DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) bmp_buffer[offset+DEBUG_BMP_WIDTH] = color; - if (offset-DEBUG_BMP_WIDTH >= 0) bmp_buffer[offset-DEBUG_BMP_WIDTH] = color; // make a small star above -} - -void DrawLineInDebugBitmap (const Vector v_from, const Vector v_to, unsigned char color) -{ - // blind copy of botman's Bresenham(). This function prints a vector line into a bitmap dot - // matrix. The dot matrix (bmp_buffer) is a global array. The size of the bitmap is always - // assumed to be DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT pixels (currently 2000 * 2000 to fit with - // the size of the universe, with an adaptative unit scale, up to 1 pixel = 10 vector units). - - int x0, y0, x1, y1; - int dx, stepx, dy, stepy; - int offset, fraction; - - if (bmp_buffer == NULL) - { - fprintf (stderr,"DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); - return; // reliability check: cancel if bmp buffer unallocated - } - - // translate the world coordinates in image pixel coordinates - x0 = (int) ((v_from.x - minx) / scale); - y0 = (int) ((v_from.y - miny) / scale); - x1 = (int) ((v_to.x - minx) / scale); - y1 = (int) ((v_to.y - miny) / scale); - - dx = (x1 - x0) * 2; - dy = (y1 - y0) * 2; - if (dx < 0) { dx = -dx; stepx = -1; } else stepx = 1; - if (dy < 0) { dy = -dy; stepy = -1; } else stepy = 1; - - offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf( stderr,"DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1) ; - } - - bmp_buffer[offset] = color; // draw the first point of the line - - // is the line rather horizontal than vertical ? We need to know this to determine the step - // advance in the Bresenham grid, either we draw y = f(x), or x = f(y). - if (dx > dy) - { - // the line is rather horizontal, we can draw it safely for incremental values of x - - fraction = 2 * dy - dx; // fraction of height in x0 pixel's 'square' where y0 should be - - // while we've not reached the end of the segment... - while (x0 != x1) - { - // if y0 should rather be drawn on a different height than its previous height... - if (fraction >= 0) - { - y0 += stepy; // draw it one pixel aside, then (depending on line orientation) - fraction -= 2 * dx; // and reset its fraction (Bresenham, not sure I get the math) - } - x0 += stepx; // in either case, draw x0 one pixel aside its previous position - fraction += 2 * dy; // and update y0's fraction (not sure I get the math - but whatever) - - // compute the offset in the BMP buffer corresponding to this point - offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1) ; - } - - bmp_buffer[offset] = color; // set this point to have the specified color - } - } - else - { - // else the line is rather vertical, we NEED to draw it for incremental values of y (if we - // did it for incremental values of x instead, we would drop half the pixels). - - fraction = 2 * dx - dy; // fraction of width in y0 pixel's 'square' where x0 should be - - // while we've not reached the end of the segment... - while (y0 != y1) - { - // if x0 should rather be drawn on a different width than its previous width... - if (fraction >= 0) - { - x0 += stepx; // draw it one pixel aside, then (depending on line orientation) - fraction -= 2 * dy; // and reset its fraction (Bresenham, not sure I get the math) - } - y0 += stepy; // in either case, draw y0 one pixel aside its previous position - fraction += 2 * dx; // and update x0's fraction (not sure I get the math - but whatever) - - // compute the offset in the BMP buffer corresponding to this point - offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf (stderr,"DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1) ; - } - bmp_buffer[offset] = color; // set this point to have the specified color - } - } - - return; // finished, segment has been printed into the BMP dot matrix -} - - -void WriteDebugBitmap (const char *mapname) -{ - // this function writes the debug bitmap image buffer in a .BMP file to disk. The format is - // 256 color and 2000 * 2000 pixels. The center of the world being roughly the center of the - // bitmap. The bitmap is stored in the file specified by 'filename' (which can be a relative - // path from the Half-Life base directory). - char filename[256]; - FILE *fp; - int data_start, file_size; - unsigned long dummy; - - if (bmp_buffer == NULL) - { - fprintf (stderr,"WriteDebugBitmap(): function called with NULL BMP buffer!\n"); - return; // reliability check: cancel if bmp buffer unallocated - } - - // open (or create) the .bmp file for writing in binary mode... - // Set Directory name -// strcpy (filename, "data/cstrike/maps/"); - strcpy (filename, mapname); - strcat (filename, ".bmp"); // bitmap file - fp = fopen (filename, "wb"); - if (fp == NULL) - { - fprintf (stderr,"RACC: WriteDebugBitmap(): unable to open BMP file!\n"); - if (bmp_buffer) - free (bmp_buffer); // cannot open file, free DXF buffer - bmp_buffer = NULL; - return; // cancel if error creating file - } - - // write the BMP header - fwrite ("BM", 2, 1, fp); // write the BMP header tag - fseek (fp, sizeof (unsigned long), SEEK_CUR); // skip the file size field (will write it last) - fwrite ("\0\0", sizeof (short), 1, fp); // dump zeros in the first reserved field (unused) - fwrite ("\0\0", sizeof (short), 1, fp); // dump zeros in the second reserved field (unused) - fseek (fp, sizeof (unsigned long), SEEK_CUR); // skip the data start field (will write it last) - - // write the info header - dummy = 40; - fwrite (&dummy, sizeof (unsigned long), 1, fp); // write the info header size (does 40 bytes) - dummy = DEBUG_BMP_WIDTH; - fwrite (&dummy, sizeof (long), 1, fp); // write the image width (2000 px) - dummy = DEBUG_BMP_HEIGHT; - fwrite (&dummy, sizeof (long), 1, fp); // write the image height (2000 px) - dummy = 1; - fwrite (&dummy, sizeof (short), 1, fp); // write the # of planes (1) - dummy = 8; - fwrite (&dummy, sizeof (short), 1, fp); // write the bit count (8) - dummy = 0; - fwrite (&dummy, sizeof (unsigned long), 1, fp); // write the compression id (no compression) - dummy = DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT; - fwrite (&dummy, sizeof (unsigned long), 1, fp); // write the image size (2000 * 2000) - dummy = 0; - fwrite (&dummy, sizeof (long), 1, fp); // write the X pixels per meter (not specified) - fwrite (&dummy, sizeof (long), 1, fp); // write the Y pixels per meter (not specified) - dummy = 256; - fwrite (&dummy, sizeof (unsigned long), 1, fp); // write the # of colors used (all) - fwrite (&dummy, sizeof (unsigned long), 1, fp); // write the # of important colors (wtf ?) - - // write the color palette (R, G, B, reserved byte) - fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); // 0=BLACK - fputc (0xFF, fp); fputc (0xFF, fp); fputc (0xFF, fp); fputc (0x00, fp); // 1=WHITE - fputc (0x80, fp); fputc (0x80, fp); fputc (0x80, fp); fputc (0x00, fp); // 2=GREY - fputc (0xC0, fp); fputc (0xC0, fp); fputc (0xC0, fp); fputc (0x00, fp); // 3=SILVER - fputc (0x80, fp); fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); // 4=DARK RED - fputc (0xFF, fp); fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); // 5=RED - fputc (0x80, fp); fputc (0x80, fp); fputc (0x00, fp); fputc (0x00, fp); // 6=DARK YELLOW - fputc (0xFF, fp); fputc (0xFF, fp); fputc (0x00, fp); fputc (0x00, fp); // 7=YELLOW - fputc (0x00, fp); fputc (0x80, fp); fputc (0x00, fp); fputc (0x00, fp); // 8=DARK GREEN - fputc (0x00, fp); fputc (0xFF, fp); fputc (0x00, fp); fputc (0x00, fp); // 9=GREEN - fputc (0x00, fp); fputc (0x00, fp); fputc (0x80, fp); fputc (0x00, fp); // 10=DARK BLUE - fputc (0x00, fp); fputc (0x00, fp); fputc (0x80, fp); fputc (0x00, fp); // 11=BLUE - fputc (0x80, fp); fputc (0x00, fp); fputc (0x80, fp); fputc (0x00, fp); // 12=DARK PURPLE - fputc (0x80, fp); fputc (0x00, fp); fputc (0x80, fp); fputc (0x00, fp); // 13=PURPLE - fputc (0xFF, fp); fputc (0xFF, fp); fputc (0xFF, fp); fputc (0x00, fp); // 14=WHITE - fputc (0xEF, fp); fputc (0xEF, fp); fputc (0xEF, fp); fputc (0x00, fp); // 15=WHITE-GREY - fputc (0xDF, fp); fputc (0xDF, fp); fputc (0xDF, fp); fputc (0x00, fp); // 16=GREY - fputc (0xCF, fp); fputc (0xCF, fp); fputc (0xCF, fp); fputc (0x00, fp); // 17=DARKGREY - fputc (0xBF, fp); fputc (0xBF, fp); fputc (0xBF, fp); fputc (0x00, fp); // 18=DARKGREY - fputc (0xAF, fp); fputc (0xAF, fp); fputc (0xAF, fp); fputc (0x00, fp); // 19=DARKGREY - - for (dummy = 20; dummy < 256; dummy++) - { - // fill out the rest of the palette with zeros - fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); fputc (0x00, fp); - } - - // write the actual image data - data_start = ftell (fp); // get the data start position (that's where we are now) - fwrite (bmp_buffer, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT, 1, fp); // write the image - file_size = ftell (fp); // get the file size now that the image is dumped - - // now that we've dumped our data, we know the file size and the data start position - - fseek (fp, 0, SEEK_SET); // rewind - fseek (fp, 2, SEEK_CUR); // skip the BMP header tag "BM" - fwrite (&file_size, sizeof (unsigned long), 1, fp); // write the file size at its location - fseek (fp, sizeof (short), SEEK_CUR); // skip the first reserved field - fseek (fp, sizeof (short), SEEK_CUR); // skip the second reserved field - fwrite (&data_start, sizeof (unsigned long), 1, fp); // write the data start at its location - - fclose (fp); // finished, close the BMP file - - if (bmp_buffer) - free (bmp_buffer); // and free the BMP buffer - bmp_buffer = NULL; - - return; // and return -} - -void FindMinMax(void) -{ - int i ; - - minx = miny = 9999.0 ; - maxx = maxy = -9999.0 ; - for (i=0; i maxx) maxx = Nodes[i].origin.x ; - if (Nodes[i].origin.y > maxy) maxy = Nodes[i].origin.y ; - if (Nodes[i].origin.x < minx) minx = Nodes[i].origin.x ; - if (Nodes[i].origin.y < miny) miny = Nodes[i].origin.y ; - } - - // Add some margin - minx -= 32 ; - miny -= 32 ; - maxx += 32 ; - maxy += 32 ; - // first compute the X and Y divider scale, and take the greatest of both - scalex = (maxx - minx) / DEBUG_BMP_WIDTH ; - scaley = (maxy - miny) / DEBUG_BMP_HEIGHT ; - if (scalex > scaley) - scale = scalex + scalex / 100; // add a little offset (margin) for safety - else - scale = scaley + scaley / 100; // add a little offset (margin) for safety -} - -// Mark meridians as slighly darker in alternance - -void MarkAxis(void) -{ - int x, y, x0, y0 ; - - x0 = (int) ((0 - minx) / scale); - y0 = (int) ((0 - miny) / scale); - - // Mark X axis by keeping X to 0 and varying Y - if ((minx < 0) && (0 < maxx)) - for (y=0; y < DEBUG_BMP_HEIGHT ; y ++) - bmp_buffer[y*DEBUG_BMP_WIDTH+x0]+=2 ; - - // Mar - if ((miny < 0) && (0 < maxy)) - for (x=0; x < DEBUG_BMP_WIDTH; x++) - bmp_buffer[y0*DEBUG_BMP_WIDTH+x]+=2 ; -} - -void MarkMeredians(void) -{ - int x, y ; - int Meredian ; - - // Mark some meredians - for (x=0; x < DEBUG_BMP_WIDTH; x++) { - Meredian = abs(((float) x * scale + minx + 8192.0) / (float) SIZE_MEREDIAN) ; - if (Meredian & 0x01) { - for (y=0; y < DEBUG_BMP_HEIGHT ; y ++) - bmp_buffer[y*DEBUG_BMP_WIDTH+x]++ ; - } - } - - // Mark some meredians - for (y=0; y < DEBUG_BMP_HEIGHT; y++) { - Meredian = abs(((float) y * scale + miny + 8192.0) / (float) SIZE_MEREDIAN) ; - if (Meredian & 0x01) { - for (x=0; x < DEBUG_BMP_HEIGHT ; x ++) - bmp_buffer[y*DEBUG_BMP_WIDTH+x]++ ; - } - } -} - -void PlotNodes(void) -{ - int i, j ; - - for (i=0; i = 0) ; j++) - DrawLineInDebugBitmap(Nodes[i].origin, - Nodes[Nodes[i].iNeighbour[j]].origin,0) ; - for (i=0; i +#include +#include +#include +#include +#include +#include +#include + +extern char* Version; + +// width and height of the debug bitmap image +#define DEBUG_BMP_WIDTH 2048 +#define DEBUG_BMP_HEIGHT 2048 + +float scalex, scaley, scale; +char* bmp_buffer; + +#include "../bot.h" +#include "../NodeMachine.h" + +extern char* Version; + +/* Copy from NodeMachine.cpp by Stefan Hendricks */ + +tNode Nodes[MAX_NODES]; // Nodes +tInfoNode InfoNodes[MAX_NODES]; // Info for Nodes +tMeredian Meredians[MAX_MEREDIANS][MAX_MEREDIANS]; // Meredian lookup search for Nodes +int iMaxUsedNodes; +float maxx, maxy, minx, miny; + +void load(char* mapname) +{ + char filename[256]; + int i, n; + + // Set Directory name + strcpy(filename, mapname); + strcat(filename, ".rbn"); // nodes file + + FILE* rbl; + rbl = fopen(filename, "rb"); + + if (rbl != NULL) + { + int iVersion; + fread(&iVersion, sizeof(int), 1, rbl); + + // Version 1.0 + if (iVersion == FILE_NODE_VER1) + { + for (i = 0; i < MAX_NODES; i++) + { + fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); + for (n = 0; n < MAX_NEIGHBOURS; n++) + { + fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + } + + // save bit flags + fread(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); + + if (Nodes[i].origin != Vector(9999, 9999, 9999)) + iMaxUsedNodes = i; + } + } + } + else { + fprintf(stderr, "Cannot open file %s\n", filename); + exit; + } + printf("%d nodes loaded out of %d.\n", iMaxUsedNodes, MAX_NODES); +} + +void InitDebugBitmap(void) +{ + // this function allocates memory and clears the debug bitmap buffer + + if (bmp_buffer) + free(bmp_buffer); // reliability check, free BMP buffer if already allocated + bmp_buffer = NULL; + bmp_buffer = (char*)malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // allocate memory + if (bmp_buffer == NULL) { + fprintf(stderr, "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024); + exit(1); + } + + memset(bmp_buffer, 14, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // Set all to white + return; // yes, it's as simple as that +} + +void DrawPoint(const Vector v, unsigned char color) +{ + int offset, fraction, x0, y0; + float scalex, scaley, scale; + + if (bmp_buffer == NULL) + { + fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); + return; // reliability check: cancel if bmp buffer unallocated + } + + // first compute the X and Y divider scale, and take the greatest of both + scalex = (maxx - minx) / DEBUG_BMP_WIDTH; + scaley = (maxy - miny) / DEBUG_BMP_WIDTH; + if (scalex > scaley) + scale = scalex + scalex / 100; // add a little offset (margin) for safety + else + scale = scaley + scaley / 100; // add a little offset (margin) for safety + + // translate the world coordinates in image pixel coordinates + x0 = (int)((v.x - minx) / scale); + y0 = (int)((v.y - miny) / scale); + + offset = y0 * DEBUG_BMP_WIDTH + x0; + if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { + fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); + exit(1); + } + + bmp_buffer[offset] = color; // draw the point itself + if (offset + 1 < DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) bmp_buffer[offset + 1] = color; // make a small star on the right + if (offset - 1 >= 0) bmp_buffer[offset - 1] = color; // make a small star on the left + if (offset + DEBUG_BMP_WIDTH < DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) bmp_buffer[offset + DEBUG_BMP_WIDTH] = color; + if (offset - DEBUG_BMP_WIDTH >= 0) bmp_buffer[offset - DEBUG_BMP_WIDTH] = color; // make a small star above +} + +void DrawLineInDebugBitmap(const Vector v_from, const Vector v_to, unsigned char color) +{ + // blind copy of botman's Bresenham(). This function prints a vector line into a bitmap dot + // matrix. The dot matrix (bmp_buffer) is a global array. The size of the bitmap is always + // assumed to be DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT pixels (currently 2000 * 2000 to fit with + // the size of the universe, with an adaptative unit scale, up to 1 pixel = 10 vector units). + + int x0, y0, x1, y1; + int dx, stepx, dy, stepy; + int offset, fraction; + + if (bmp_buffer == NULL) + { + fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); + return; // reliability check: cancel if bmp buffer unallocated + } + + // translate the world coordinates in image pixel coordinates + x0 = (int)((v_from.x - minx) / scale); + y0 = (int)((v_from.y - miny) / scale); + x1 = (int)((v_to.x - minx) / scale); + y1 = (int)((v_to.y - miny) / scale); + + dx = (x1 - x0) * 2; + dy = (y1 - y0) * 2; + if (dx < 0) { dx = -dx; stepx = -1; } + else stepx = 1; + if (dy < 0) { dy = -dy; stepy = -1; } + else stepy = 1; + + offset = y0 * DEBUG_BMP_WIDTH + x0; + if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { + fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); + exit(1); + } + + bmp_buffer[offset] = color; // draw the first point of the line + + // is the line rather horizontal than vertical ? We need to know this to determine the step + // advance in the Bresenham grid, either we draw y = f(x), or x = f(y). + if (dx > dy) + { + // the line is rather horizontal, we can draw it safely for incremental values of x + + fraction = 2 * dy - dx; // fraction of height in x0 pixel's 'square' where y0 should be + + // while we've not reached the end of the segment... + while (x0 != x1) + { + // if y0 should rather be drawn on a different height than its previous height... + if (fraction >= 0) + { + y0 += stepy; // draw it one pixel aside, then (depending on line orientation) + fraction -= 2 * dx; // and reset its fraction (Bresenham, not sure I get the math) + } + x0 += stepx; // in either case, draw x0 one pixel aside its previous position + fraction += 2 * dy; // and update y0's fraction (not sure I get the math - but whatever) + + // compute the offset in the BMP buffer corresponding to this point + offset = y0 * DEBUG_BMP_WIDTH + x0; + if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { + fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); + exit(1); + } + + bmp_buffer[offset] = color; // set this point to have the specified color + } + } + else + { + // else the line is rather vertical, we NEED to draw it for incremental values of y (if we + // did it for incremental values of x instead, we would drop half the pixels). + + fraction = 2 * dx - dy; // fraction of width in y0 pixel's 'square' where x0 should be + + // while we've not reached the end of the segment... + while (y0 != y1) + { + // if x0 should rather be drawn on a different width than its previous width... + if (fraction >= 0) + { + x0 += stepx; // draw it one pixel aside, then (depending on line orientation) + fraction -= 2 * dy; // and reset its fraction (Bresenham, not sure I get the math) + } + y0 += stepy; // in either case, draw y0 one pixel aside its previous position + fraction += 2 * dx; // and update x0's fraction (not sure I get the math - but whatever) + + // compute the offset in the BMP buffer corresponding to this point + offset = y0 * DEBUG_BMP_WIDTH + x0; + if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { + fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); + exit(1); + } + bmp_buffer[offset] = color; // set this point to have the specified color + } + } + + return; // finished, segment has been printed into the BMP dot matrix +} + +void WriteDebugBitmap(const char* mapname) +{ + // this function writes the debug bitmap image buffer in a .BMP file to disk. The format is + // 256 color and 2000 * 2000 pixels. The center of the world being roughly the center of the + // bitmap. The bitmap is stored in the file specified by 'filename' (which can be a relative + // path from the Half-Life base directory). + char filename[256]; + FILE* fp; + int data_start, file_size; + unsigned long dummy; + + if (bmp_buffer == NULL) + { + fprintf(stderr, "WriteDebugBitmap(): function called with NULL BMP buffer!\n"); + return; // reliability check: cancel if bmp buffer unallocated + } + + // open (or create) the .bmp file for writing in binary mode... + // Set Directory name + // strcpy (filename, "data/cstrike/maps/"); + strcpy(filename, mapname); + strcat(filename, ".bmp"); // bitmap file + fp = fopen(filename, "wb"); + if (fp == NULL) + { + fprintf(stderr, "RACC: WriteDebugBitmap(): unable to open BMP file!\n"); + if (bmp_buffer) + free(bmp_buffer); // cannot open file, free DXF buffer + bmp_buffer = NULL; + return; // cancel if error creating file + } + + // write the BMP header + fwrite("BM", 2, 1, fp); // write the BMP header tag + fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the file size field (will write it last) + fwrite("\0\0", sizeof(short), 1, fp); // dump zeros in the first reserved field (unused) + fwrite("\0\0", sizeof(short), 1, fp); // dump zeros in the second reserved field (unused) + fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the data start field (will write it last) + + // write the info header + dummy = 40; + fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the info header size (does 40 bytes) + dummy = DEBUG_BMP_WIDTH; + fwrite(&dummy, sizeof(long), 1, fp); // write the image width (2000 px) + dummy = DEBUG_BMP_HEIGHT; + fwrite(&dummy, sizeof(long), 1, fp); // write the image height (2000 px) + dummy = 1; + fwrite(&dummy, sizeof(short), 1, fp); // write the # of planes (1) + dummy = 8; + fwrite(&dummy, sizeof(short), 1, fp); // write the bit count (8) + dummy = 0; + fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the compression id (no compression) + dummy = DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT; + fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the image size (2000 * 2000) + dummy = 0; + fwrite(&dummy, sizeof(long), 1, fp); // write the X pixels per meter (not specified) + fwrite(&dummy, sizeof(long), 1, fp); // write the Y pixels per meter (not specified) + dummy = 256; + fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of colors used (all) + fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of important colors (wtf ?) + + // write the color palette (R, G, B, reserved byte) + fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); // 0=BLACK + fputc(0xFF, fp); fputc(0xFF, fp); fputc(0xFF, fp); fputc(0x00, fp); // 1=WHITE + fputc(0x80, fp); fputc(0x80, fp); fputc(0x80, fp); fputc(0x00, fp); // 2=GREY + fputc(0xC0, fp); fputc(0xC0, fp); fputc(0xC0, fp); fputc(0x00, fp); // 3=SILVER + fputc(0x80, fp); fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); // 4=DARK RED + fputc(0xFF, fp); fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); // 5=RED + fputc(0x80, fp); fputc(0x80, fp); fputc(0x00, fp); fputc(0x00, fp); // 6=DARK YELLOW + fputc(0xFF, fp); fputc(0xFF, fp); fputc(0x00, fp); fputc(0x00, fp); // 7=YELLOW + fputc(0x00, fp); fputc(0x80, fp); fputc(0x00, fp); fputc(0x00, fp); // 8=DARK GREEN + fputc(0x00, fp); fputc(0xFF, fp); fputc(0x00, fp); fputc(0x00, fp); // 9=GREEN + fputc(0x00, fp); fputc(0x00, fp); fputc(0x80, fp); fputc(0x00, fp); // 10=DARK BLUE + fputc(0x00, fp); fputc(0x00, fp); fputc(0x80, fp); fputc(0x00, fp); // 11=BLUE + fputc(0x80, fp); fputc(0x00, fp); fputc(0x80, fp); fputc(0x00, fp); // 12=DARK PURPLE + fputc(0x80, fp); fputc(0x00, fp); fputc(0x80, fp); fputc(0x00, fp); // 13=PURPLE + fputc(0xFF, fp); fputc(0xFF, fp); fputc(0xFF, fp); fputc(0x00, fp); // 14=WHITE + fputc(0xEF, fp); fputc(0xEF, fp); fputc(0xEF, fp); fputc(0x00, fp); // 15=WHITE-GREY + fputc(0xDF, fp); fputc(0xDF, fp); fputc(0xDF, fp); fputc(0x00, fp); // 16=GREY + fputc(0xCF, fp); fputc(0xCF, fp); fputc(0xCF, fp); fputc(0x00, fp); // 17=DARKGREY + fputc(0xBF, fp); fputc(0xBF, fp); fputc(0xBF, fp); fputc(0x00, fp); // 18=DARKGREY + fputc(0xAF, fp); fputc(0xAF, fp); fputc(0xAF, fp); fputc(0x00, fp); // 19=DARKGREY + + for (dummy = 20; dummy < 256; dummy++) + { + // fill out the rest of the palette with zeros + fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); fputc(0x00, fp); + } + + // write the actual image data + data_start = ftell(fp); // get the data start position (that's where we are now) + fwrite(bmp_buffer, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT, 1, fp); // write the image + file_size = ftell(fp); // get the file size now that the image is dumped + + // now that we've dumped our data, we know the file size and the data start position + + fseek(fp, 0, SEEK_SET); // rewind + fseek(fp, 2, SEEK_CUR); // skip the BMP header tag "BM" + fwrite(&file_size, sizeof(unsigned long), 1, fp); // write the file size at its location + fseek(fp, sizeof(short), SEEK_CUR); // skip the first reserved field + fseek(fp, sizeof(short), SEEK_CUR); // skip the second reserved field + fwrite(&data_start, sizeof(unsigned long), 1, fp); // write the data start at its location + + fclose(fp); // finished, close the BMP file + + if (bmp_buffer) + free(bmp_buffer); // and free the BMP buffer + bmp_buffer = NULL; + + return; // and return +} + +void FindMinMax(void) +{ + int i; + + minx = miny = 9999.0; + maxx = maxy = -9999.0; + for (i = 0; i < iMaxUsedNodes; i++) { + if (Nodes[i].origin.x > maxx) maxx = Nodes[i].origin.x; + if (Nodes[i].origin.y > maxy) maxy = Nodes[i].origin.y; + if (Nodes[i].origin.x < minx) minx = Nodes[i].origin.x; + if (Nodes[i].origin.y < miny) miny = Nodes[i].origin.y; + } + + // Add some margin + minx -= 32; + miny -= 32; + maxx += 32; + maxy += 32; + // first compute the X and Y divider scale, and take the greatest of both + scalex = (maxx - minx) / DEBUG_BMP_WIDTH; + scaley = (maxy - miny) / DEBUG_BMP_HEIGHT; + if (scalex > scaley) + scale = scalex + scalex / 100; // add a little offset (margin) for safety + else + scale = scaley + scaley / 100; // add a little offset (margin) for safety +} + +// Mark meridians as slighly darker in alternance + +void MarkAxis(void) +{ + int x, y, x0, y0; + + x0 = (int)((0 - minx) / scale); + y0 = (int)((0 - miny) / scale); + + // Mark X axis by keeping X to 0 and varying Y + if ((minx < 0) && (0 < maxx)) + for (y = 0; y < DEBUG_BMP_HEIGHT; y++) + bmp_buffer[y * DEBUG_BMP_WIDTH + x0] += 2; + + // Mar + if ((miny < 0) && (0 < maxy)) + for (x = 0; x < DEBUG_BMP_WIDTH; x++) + bmp_buffer[y0 * DEBUG_BMP_WIDTH + x] += 2; +} + +void MarkMeredians(void) +{ + int x, y; + int Meredian; + + // Mark some meredians + for (x = 0; x < DEBUG_BMP_WIDTH; x++) { + Meredian = abs(((float)x * scale + minx + 8192.0) / (float)SIZE_MEREDIAN); + if (Meredian & 0x01) { + for (y = 0; y < DEBUG_BMP_HEIGHT; y++) + bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; + } + } + + // Mark some meredians + for (y = 0; y < DEBUG_BMP_HEIGHT; y++) { + Meredian = abs(((float)y * scale + miny + 8192.0) / (float)SIZE_MEREDIAN); + if (Meredian & 0x01) { + for (x = 0; x < DEBUG_BMP_HEIGHT; x++) + bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; + } + } +} + +void PlotNodes(void) +{ + int i, j; + + for (i = 0; i < iMaxUsedNodes; i++) + for (j = 0; (j < MAX_NEIGHBOURS) && (Nodes[i].iNeighbour[j] >= 0); j++) + DrawLineInDebugBitmap(Nodes[i].origin, + Nodes[Nodes[i].iNeighbour[j]].origin, 0); + for (i = 0; i < iMaxUsedNodes; i++) + DrawPoint(Nodes[i].origin, 5); +} + +int main(int argc, char* argv[]) +{ + printf("DrawNodes Version %s\nBy eric@vyncke.org\n", Version); + if (argc != 2) { + fprintf(stderr, "Usage is %s mapname\n", argv[0]); + exit; + } + load(argv[1]); + FindMinMax(); + InitDebugBitmap(); + MarkMeredians(); + MarkAxis(); + PlotNodes(); + WriteDebugBitmap(argv[1]); +} \ No newline at end of file diff --git a/Bsp2Rbn/DumpNodes.c b/Bsp2Rbn/DumpNodes.c index 5341fe3..1a35d78 100644 --- a/Bsp2Rbn/DumpNodes.c +++ b/Bsp2Rbn/DumpNodes.c @@ -2,7 +2,6 @@ evyncke@hec.be, June 2004 - Based on routines from Stefan H. */ @@ -18,7 +17,7 @@ Based on routines from Stefan H. #include "../bot.h" #include "../NodeMachine.h" -extern char * Version ; +extern char* Version; /* Copy from NodeMachine.cpp by Stefan Hendricks */ @@ -28,170 +27,168 @@ int Meredians[MAX_MEREDIANS][MAX_MEREDIANS]; // Meredian lookup search for No int iMaxUsedNodes; // Input: Vector, Output X and Y Meredians -void VectorToMeredian (Vector vOrigin, int *iX, int *iY) +void VectorToMeredian(Vector vOrigin, int* iX, int* iY) { - // Called for lookupt and for storing - int iCoordX = abs (vOrigin.x + 8192.0); // map height (converts from - to +) - int iCoordY = abs (vOrigin.y + 8192.0); // map width (converts from - to +) + // Called for lookupt and for storing + int iCoordX = abs(vOrigin.x + 8192.0); // map height (converts from - to +) + int iCoordY = abs(vOrigin.y + 8192.0); // map width (converts from - to +) - // Meredian: - iCoordX = abs (iCoordX / SIZE_MEREDIAN); - iCoordY = abs (iCoordY / SIZE_MEREDIAN); + // Meredian: + iCoordX = abs(iCoordX / SIZE_MEREDIAN); + iCoordY = abs(iCoordY / SIZE_MEREDIAN); - *iX = iCoordX; - *iY = iCoordY; + *iX = iCoordX; + *iY = iCoordY; } -void load (char * mapname) +void load(char* mapname) { - char filename[256]; - int i, j, n; - - strcpy (filename, mapname); - strcat (filename, ".rbn"); // nodes file - - FILE *rbl; - rbl = fopen (filename, "rb"); - - if (rbl != NULL) - { - int iVersion ; - fread (&iVersion, sizeof (int), 1, rbl); - - // Version 1.0 - if (iVersion == FILE_NODE_VER1) - { - for (i = 0; i < MAX_NODES; i++) - { - fread (&Nodes[i].origin, sizeof (Vector), 1, rbl); - for (n = 0; n < MAX_NEIGHBOURS; n++) - { - fread (&Nodes[i].iNeighbour[n], sizeof (int), 1, rbl); - } - - // save bit flags - fread (&Nodes[i].iNodeBits, sizeof (int), 1, rbl); - - if (Nodes[i].origin != Vector (9999, 9999, 9999)) - iMaxUsedNodes = i; - } - } - } else { - fprintf(stderr,"Cannot open file %s\n",filename) ; - exit ; - } - printf("%d nodes loaded out of %d.\n",iMaxUsedNodes,MAX_NODES) ; - fclose(rbl) ; - - // Zero the Meredians table - for (i=0;i -1 && iY > -1) - Meredians[iX][iY] ++ ; - } + char filename[256]; + int i, j, n; + + strcpy(filename, mapname); + strcat(filename, ".rbn"); // nodes file + FILE* rbl; + rbl = fopen(filename, "rb"); + if (rbl != NULL) + { + int iVersion; + fread(&iVersion, sizeof(int), 1, rbl); + + // Version 1.0 + if (iVersion == FILE_NODE_VER1) + { + for (i = 0; i < MAX_NODES; i++) + { + fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); + for (n = 0; n < MAX_NEIGHBOURS; n++) + { + fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + } + + // save bit flags + fread(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); + + if (Nodes[i].origin != Vector(9999, 9999, 9999)) + iMaxUsedNodes = i; + } + } + } + else { + fprintf(stderr, "Cannot open file %s\n", filename); + exit; + } + printf("%d nodes loaded out of %d.\n", iMaxUsedNodes, MAX_NODES); + fclose(rbl); + + // Zero the Meredians table + for (i = 0;i < MAX_MEREDIANS;i++) + for (j = 0;j < MAX_MEREDIANS;j++) + Meredians[i][j] = 0; + + // Add nodes to meredians + for (i = 0; i < MAX_NODES; i++) + if (Nodes[i].origin != Vector(9999, 9999, 9999)) + { + int iX, iY; + VectorToMeredian(Nodes[i].origin, &iX, &iY); + if (iX > -1 && iY > -1) + Meredians[iX][iY] ++; + } } -void PrintNodesPair(int iMe, int iNext, Vector Me, Vector Next) +void PrintNodesPair(int iMe, int iNext, Vector Me, Vector Next) { - int MeX, MeY, NextX, NextY ; // Meredians - - printf(" dist(%d,%d)=%.0f",iMe,iNext,(Next-Me).Length()) ; - VectorToMeredian(Me,&MeX,&MeY) ; - VectorToMeredian(Next,&NextX,&NextY) ; - if (abs(Me.z-Next.z) > 5) printf(", altitude diff=%d",abs(Me.z-Next.z)) ; - if ((MeX != NextX) && (MeY != NextY)) - printf(", Both meredians do not match!") ; - else if ((MeX != NextX) || (MeY != NextY)) - printf(", One Meredian does not match!") ; - printf("\n") ; + int MeX, MeY, NextX, NextY; // Meredians + + printf(" dist(%d,%d)=%.0f", iMe, iNext, (Next - Me).Length()); + VectorToMeredian(Me, &MeX, &MeY); + VectorToMeredian(Next, &NextX, &NextY); + if (abs(Me.z - Next.z) > 5) printf(", altitude diff=%d", abs(Me.z - Next.z)); + if ((MeX != NextX) && (MeY != NextY)) + printf(", Both meredians do not match!"); + else if ((MeX != NextX) || (MeY != NextY)) + printf(", One Meredian does not match!"); + printf("\n"); } // Analyze the RBN file which has just been read... void AnalyseNeighbours(void) { - int MeX, MeY, NextX, NextY ; // Meredians - int Count,i,j ; - int Histogram[MAX_NEIGHBOURS+1] ; // Will count the frequency of nodes having 0... N neighbours - Vector Me, Next ; - float Distance ; - - for (i=0;i= 0);j++) - Count ++ ; - Histogram[j]++ ; + for (j = 0; (j < MAX_NEIGHBOURS) && (Nodes[i].iNeighbour[j] >= 0);j++) + Count++; + Histogram[j]++; } - printf("There are %d neighbours (i.e. %.1f neighbour(s) per node out of %d)\n",Count,(float) Count / (float) iMaxUsedNodes,MAX_NEIGHBOURS) ; - printf("Neighbours distribution\n") ; - for (j=0;j NODE_ZONE*2) continue ; - PrintNodesPair(i, i-1, Me, Next) ; + for (i = 1; i < iMaxUsedNodes; i++) + if (Nodes[i].iNeighbour[0] < 0) { + Me = Nodes[i].origin; + Next = Nodes[i - 1].origin; + Distance = (Next - Me).Length(); + if (Distance > NODE_ZONE * 2) continue; + PrintNodesPair(i, i - 1, Me, Next); } - printf("Isolated nodes that are close to the next one (HIGHLY suspicious):\n") ; - for (i=0; i < iMaxUsedNodes-1; i++) - if (Nodes[i].iNeighbour[0]< 0) { - Me=Nodes[i].origin ; - Next=Nodes[i+1].origin ; - Distance=(Next-Me).Length() ; - if (Distance > NODE_ZONE*2) continue ; - PrintNodesPair(i, i+1, Me, Next) ; + printf("Isolated nodes that are close to the next one (HIGHLY suspicious):\n"); + for (i = 0; i < iMaxUsedNodes - 1; i++) + if (Nodes[i].iNeighbour[0] < 0) { + Me = Nodes[i].origin; + Next = Nodes[i + 1].origin; + Distance = (Next - Me).Length(); + if (Distance > NODE_ZONE * 2) continue; + PrintNodesPair(i, i + 1, Me, Next); } } } void AnalyseMeredians(void) { - int i, j ; + int i, j; - for (i=0;i= MAX_NODES_IN_MEREDIANS) printf("Too many nodes on meredians(%d,%d): %d (max %d)\n", - i, j, Meredians[i][j], MAX_NODES_IN_MEREDIANS) ; + i, j, Meredians[i][j], MAX_NODES_IN_MEREDIANS); } -int main (int argc, char * argv[]) +int main(int argc, char* argv[]) { - if (argc != 2) { - fprintf(stderr,"Usage is %s mapname\n",argv[0]) ; - exit ; + if (argc != 2) { + fprintf(stderr, "Usage is %s mapname\n", argv[0]); + exit; } - printf("DumpNodes Version %s\nBy eric@vyncke.org\n",Version) ; - load(argv[1]) ; - AnalyseNeighbours() ; - AnalyseMeredians() ; -} - + printf("DumpNodes Version %s\nBy eric@vyncke.org\n", Version); + load(argv[1]); + AnalyseNeighbours(); + AnalyseMeredians(); +} \ No newline at end of file diff --git a/Bsp2Rbn/Makefile b/Bsp2Rbn/Makefile index 16f37b6..85df3d4 100644 --- a/Bsp2Rbn/Makefile +++ b/Bsp2Rbn/Makefile @@ -8,7 +8,7 @@ METAMOD_SRCDIR = ../../metamod-p/metamod HLSDK_BASEDIR = ../../hlsdk-2.3-p4 BASEFLAGS = -g -Wall -CPPFLAGS = ${BASEFLAGS} -march=${ARCHFLAG} -O2 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/multiplayer/common" -I"${HLSDK_BASEDIR}/multiplayer/dlls" -I"${HLSDK_BASEDIR}/multiplayer/engine" -I"${HLSDK_BASEDIR}/multiplayer/pm_shared" +CPPFLAGS = ${BASEFLAGS} -march=${ARCHFLAG} -O2 -w -I"${METAMOD_SRCDIR}" -I"${HLSDK_BASEDIR}/multiplayer/common" -I"${HLSDK_BASEDIR}/multiplayer/dlls" -I"${HLSDK_BASEDIR}/multiplayer/engine" -I"${HLSDK_BASEDIR}/multiplayer/pm_shared" -I"${HLSDK_BASEDIR}/multiplayer/public" all: Bsp2Rbn DumpNodes DrawNodes diff --git a/Bsp2Rbn/bspfile.cpp b/Bsp2Rbn/bspfile.cpp index 046b1cd..c02cbe5 100644 --- a/Bsp2Rbn/bspfile.cpp +++ b/Bsp2Rbn/bspfile.cpp @@ -2,8 +2,8 @@ * * Copyright (c) 1998, Valve LLC. All rights reserved. * -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ @@ -27,70 +27,69 @@ // Make all of these dynamice for BSP_tool... int nummodels = 0; -dmodel_t *dmodels = NULL; +dmodel_t* dmodels = NULL; int visdatasize = 0; -byte *dvisdata = NULL; +byte* dvisdata = NULL; int lightdatasize = 0; -byte *dlightdata = NULL; +byte* dlightdata = NULL; int texdatasize = 0; -byte *dtexdata = NULL; +byte* dtexdata = NULL; int entdatasize = 0; -char *dentdata = NULL; +char* dentdata = NULL; int numleafs = 0; -dleaf_t *dleafs = NULL; +dleaf_t* dleafs = NULL; int numplanes = 0; -dplane_t *dplanes = NULL; +dplane_t* dplanes = NULL; int numvertexes = 0; -dvertex_t *dvertexes = NULL; +dvertex_t* dvertexes = NULL; int numnodes = 0; -dnode_t *dnodes = NULL; +dnode_t* dnodes = NULL; int numtexinfo = 0; -texinfo_t *texinfo = NULL; +texinfo_t* texinfo = NULL; int numfaces = 0; -dface_t *dfaces = NULL; +dface_t* dfaces = NULL; int numclipnodes = 0; -dclipnode_t *dclipnodes = NULL; +dclipnode_t* dclipnodes = NULL; int numedges = 0; -dedge_t *dedges = NULL; +dedge_t* dedges = NULL; int nummarksurfaces = 0; -unsigned short *dmarksurfaces = NULL; +unsigned short* dmarksurfaces = NULL; int numsurfedges = 0; -int *dsurfedges = NULL; +int* dsurfedges = NULL; int num_entities = 0; entity_t entities[MAX_MAP_ENTITIES]; - #ifdef __linux__ -unsigned _rotl ( unsigned val, int shift) +unsigned _rotl(unsigned val, int shift) { - register unsigned hibit; /* non-zero means hi bit set */ - register unsigned num = val; /* number to rotate */ - - shift &= 0x1f; /* modulo 32 -- this will also make - negative shifts work */ - while (shift--) { - hibit = num & 0x80000000; /* get high bit */ - num <<= 1; /* shift left one bit */ - if (hibit) - num |= 1; /* set lo bit if hi bit was set */ - } - - return num; + register unsigned hibit; /* non-zero means hi bit set */ + register unsigned num = val; /* number to rotate */ + + shift &= 0x1f; /* modulo 32 -- this will also make + negative shifts work */ + while (shift--) { + hibit = num & 0x80000000; /* get high bit */ + num <<= 1; /* shift left one bit */ + if (hibit) + num |= 1; /* set lo bit if hi bit was set */ + } + + return num; } #endif @@ -100,17 +99,17 @@ FastChecksum =============== */ -int FastChecksum(char *buffer, int bytes) +int FastChecksum(char* buffer, int bytes) { - int checksum = 0; + int checksum = 0; - while( bytes-- ) - { - checksum = _rotl(checksum, 4) ^ *(char *)buffer; - buffer++; - } + while (bytes--) + { + checksum = _rotl(checksum, 4) ^ *(char*)buffer; + buffer++; + } - return checksum; + return checksum; } /* @@ -118,66 +117,65 @@ int FastChecksum(char *buffer, int bytes) CompressVis =============== */ -int CompressVis (byte *vis, byte *dest) +int CompressVis(byte* vis, byte* dest) { - int j; - int rep; - int visrow; - byte *dest_p; - - dest_p = dest; - visrow = (numleafs + 7)>>3; - - for (j=0 ; j> 3; + + for (j = 0; j < visrow; j++) + { + *dest_p++ = vis[j]; + if (vis[j]) + continue; + + rep = 1; + for (j++; j < visrow; j++) + if (vis[j] || rep == 255) + break; + else + rep++; + *dest_p++ = rep; + j--; + } + + return dest_p - dest; } - /* =================== DecompressVis =================== */ -void DecompressVis (byte *in, byte *decompressed) +void DecompressVis(byte* in, byte* decompressed) { - int c; - byte *out; - int row; - - row = (numleafs+7)>>3; - out = decompressed; - - do - { - if (*in) - { - *out++ = *in++; - continue; - } - - c = in[1]; - in += 2; - while (c) - { - *out++ = 0; - c--; - } - } while (out - decompressed < row); + int c; + byte* out; + int row; + + row = (numleafs + 7) >> 3; + out = decompressed; + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); } //============================================================================= @@ -189,186 +187,184 @@ SwapBSPFile Byte swaps all data in a bsp file. ============= */ -void SwapBSPFile (qboolean todisk) +void SwapBSPFile(qboolean todisk) { - int i, j, c; - dmodel_t *d; - dmiptexlump_t *mtl; - - -// models - for (i=0 ; iheadnode[j] = LittleLong (d->headnode[j]); - - d->visleafs = LittleLong (d->visleafs); - d->firstface = LittleLong (d->firstface); - d->numfaces = LittleLong (d->numfaces); - - for (j=0 ; j<3 ; j++) - { - d->mins[j] = LittleFloat(d->mins[j]); - d->maxs[j] = LittleFloat(d->maxs[j]); - d->origin[j] = LittleFloat(d->origin[j]); - } - } - -// -// vertexes -// - for (i=0 ; inummiptex; - else - c = LittleLong(mtl->nummiptex); - mtl->nummiptex = LittleLong (mtl->nummiptex); - for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); - } - -// -// marksurfaces -// - for (i=0 ; iheadnode[j] = LittleLong(d->headnode[j]); + + d->visleafs = LittleLong(d->visleafs); + d->firstface = LittleLong(d->firstface); + d->numfaces = LittleLong(d->numfaces); + + for (j = 0; j < 3; j++) + { + d->mins[j] = LittleFloat(d->mins[j]); + d->maxs[j] = LittleFloat(d->maxs[j]); + d->origin[j] = LittleFloat(d->origin[j]); + } + } + + // + // vertexes + // + for (i = 0; i < numvertexes; i++) + { + for (j = 0; j < 3; j++) + dvertexes[i].point[j] = LittleFloat(dvertexes[i].point[j]); + } + + // + // planes + // + for (i = 0; i < numplanes; i++) + { + for (j = 0; j < 3; j++) + dplanes[i].normal[j] = LittleFloat(dplanes[i].normal[j]); + dplanes[i].dist = LittleFloat(dplanes[i].dist); + dplanes[i].type = LittleLong(dplanes[i].type); + } + + // + // texinfos + // + for (i = 0; i < numtexinfo; i++) + { + for (j = 0; j < 8; j++) + texinfo[i].vecs[0][j] = LittleFloat(texinfo[i].vecs[0][j]); + texinfo[i].miptex = LittleLong(texinfo[i].miptex); + texinfo[i].flags = LittleLong(texinfo[i].flags); + } + + // + // faces + // + for (i = 0; i < numfaces; i++) + { + dfaces[i].texinfo = LittleShort(dfaces[i].texinfo); + dfaces[i].planenum = LittleShort(dfaces[i].planenum); + dfaces[i].side = LittleShort(dfaces[i].side); + dfaces[i].lightofs = LittleLong(dfaces[i].lightofs); + dfaces[i].firstedge = LittleLong(dfaces[i].firstedge); + dfaces[i].numedges = LittleShort(dfaces[i].numedges); + } + + // + // nodes + // + for (i = 0; i < numnodes; i++) + { + dnodes[i].planenum = LittleLong(dnodes[i].planenum); + for (j = 0; j < 3; j++) + { + dnodes[i].mins[j] = LittleShort(dnodes[i].mins[j]); + dnodes[i].maxs[j] = LittleShort(dnodes[i].maxs[j]); + } + dnodes[i].children[0] = LittleShort(dnodes[i].children[0]); + dnodes[i].children[1] = LittleShort(dnodes[i].children[1]); + dnodes[i].firstface = LittleShort(dnodes[i].firstface); + dnodes[i].numfaces = LittleShort(dnodes[i].numfaces); + } + + // + // leafs + // + for (i = 0; i < numleafs; i++) + { + dleafs[i].contents = LittleLong(dleafs[i].contents); + for (j = 0; j < 3; j++) + { + dleafs[i].mins[j] = LittleShort(dleafs[i].mins[j]); + dleafs[i].maxs[j] = LittleShort(dleafs[i].maxs[j]); + } + + dleafs[i].firstmarksurface = LittleShort(dleafs[i].firstmarksurface); + dleafs[i].nummarksurfaces = LittleShort(dleafs[i].nummarksurfaces); + dleafs[i].visofs = LittleLong(dleafs[i].visofs); + } + + // + // clipnodes + // + for (i = 0; i < numclipnodes; i++) + { + dclipnodes[i].planenum = LittleLong(dclipnodes[i].planenum); + dclipnodes[i].children[0] = LittleShort(dclipnodes[i].children[0]); + dclipnodes[i].children[1] = LittleShort(dclipnodes[i].children[1]); + } + + // + // miptex + // + if (texdatasize) + { + mtl = (dmiptexlump_t*)dtexdata; + if (todisk) + c = mtl->nummiptex; + else + c = LittleLong(mtl->nummiptex); + mtl->nummiptex = LittleLong(mtl->nummiptex); + for (i = 0; i < c; i++) + mtl->dataofs[i] = LittleLong(mtl->dataofs[i]); + } + + // + // marksurfaces + // + for (i = 0; i < nummarksurfaces; i++) + dmarksurfaces[i] = LittleShort(dmarksurfaces[i]); + + // + // surfedges + // + for (i = 0; i < numsurfedges; i++) + dsurfedges[i] = LittleLong(dsurfedges[i]); + + // + // edges + // + for (i = 0; i < numedges; i++) + { + dedges[i].v[0] = LittleShort(dedges[i].v[0]); + dedges[i].v[1] = LittleShort(dedges[i].v[1]); + } } +dheader_t* header; -dheader_t *header; - -int CopyLump (int lump, void **dest, int size) +int CopyLump(int lump, void** dest, int size) { - int length, ofs; - int num; + int length, ofs; + int num; - length = header->lumps[lump].filelen; - ofs = header->lumps[lump].fileofs; + length = header->lumps[lump].filelen; + ofs = header->lumps[lump].fileofs; - if (length % size) - Error ("LoadBSPFile: odd lump size"); + if (length % size) + Error("LoadBSPFile: odd lump size"); - num = length / size; + num = length / size; - if (*dest == NULL) - { - // allocate memory for this lump... - *dest = malloc(num * size); + if (*dest == NULL) + { + // allocate memory for this lump... + *dest = malloc(num * size); - if (*dest == NULL) - Error("Error allocating memory for BSP file lump!\n"); - } + if (*dest == NULL) + Error("Error allocating memory for BSP file lump!\n"); + } - memcpy (*dest, (byte *)header + ofs, length); + memcpy(*dest, (byte*)header + ofs, length); - return num; + return num; } /* @@ -376,82 +372,81 @@ int CopyLump (int lump, void **dest, int size) LoadBSPFile ============= */ -void LoadBSPFile (char *filename) +void LoadBSPFile(char* filename) { - int i; - -// -// load the file header -// - if (LoadFile (filename, (void **)&header) < sizeof(dheader_t)) - Error ("File %s is too short",filename) ; - - if (header == NULL) - Error ("Cannot read file %s",filename) ; - -// swap the header - for (i=0 ; i< sizeof(dheader_t)/4 ; i++) - ((int *)header)[i] = LittleLong ( ((int *)header)[i]); - - if (header->version != BSPVERSION) - Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); - - nummodels = CopyLump (LUMP_MODELS, (void **)&dmodels, sizeof(dmodel_t)); - numvertexes = CopyLump (LUMP_VERTEXES, (void **)&dvertexes, sizeof(dvertex_t)); - numplanes = CopyLump (LUMP_PLANES, (void **)&dplanes, sizeof(dplane_t)); - numleafs = CopyLump (LUMP_LEAFS, (void **)&dleafs, sizeof(dleaf_t)); - numnodes = CopyLump (LUMP_NODES, (void **)&dnodes, sizeof(dnode_t)); - numtexinfo = CopyLump (LUMP_TEXINFO, (void **)&texinfo, sizeof(texinfo_t)); - numclipnodes = CopyLump (LUMP_CLIPNODES, (void **)&dclipnodes, sizeof(dclipnode_t)); - numfaces = CopyLump (LUMP_FACES, (void **)&dfaces, sizeof(dface_t)); - nummarksurfaces = CopyLump (LUMP_MARKSURFACES, (void **)&dmarksurfaces, sizeof(dmarksurfaces[0])); - numsurfedges = CopyLump (LUMP_SURFEDGES, (void **)&dsurfedges, sizeof(dsurfedges[0])); - numedges = CopyLump (LUMP_EDGES, (void **)&dedges, sizeof(dedge_t)); - - texdatasize = CopyLump (LUMP_TEXTURES, (void **)&dtexdata, 1); - visdatasize = CopyLump (LUMP_VISIBILITY, (void **)&dvisdata, 1); - lightdatasize = CopyLump (LUMP_LIGHTING, (void **)&dlightdata, 1); - entdatasize = CopyLump (LUMP_ENTITIES, (void **)&dentdata, 1); - - free (header); // everything has been copied out - -// -// swap everything -// - SwapBSPFile (false); - -// dmodels_checksum = FastChecksum( (char *)dmodels, nummodels*sizeof(dmodels[0]) ); -// dvertexes_checksum = FastChecksum( (char *)dvertexes, numvertexes*sizeof(dvertexes[0]) ); -// dplanes_checksum = FastChecksum( (char *)dplanes, numplanes*sizeof(dplanes[0]) ); -// dleafs_checksum = FastChecksum( (char *)dleafs, numleafs*sizeof(dleafs[0]) ); -// dnodes_checksum = FastChecksum( (char *)dnodes, numnodes*sizeof(dnodes[0]) ); -// texinfo_checksum = FastChecksum( (char *)texinfo, numtexinfo*sizeof(texinfo[0]) ); -// dclipnodes_checksum = FastChecksum( (char *)dclipnodes, numclipnodes*sizeof(dclipnodes[0]) ); -// dfaces_checksum = FastChecksum( (char *)dfaces, numfaces*sizeof(dfaces[0]) ); -// dmarksurfaces_checksum = FastChecksum( (char *)dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]) ); -// dsurfedges_checksum = FastChecksum( (char *)dsurfedges, numsurfedges*sizeof(dsurfedges[0]) ); -// dedges_checksum = FastChecksum( (char *)dedges, numedges*sizeof(dedges[0]) ); -// dtexdata_checksum = FastChecksum( (char *)dtexdata, numedges*sizeof(dtexdata[0]) ); -// dvisdata_checksum = FastChecksum( (char *)dvisdata, visdatasize*sizeof(dvisdata[0]) ); -// dlightdata_checksum = FastChecksum( (char *)dlightdata, lightdatasize*sizeof(dlightdata[0]) ); -// dentdata_checksum = FastChecksum( (char *)dentdata, entdatasize*sizeof(dentdata[0]) ); - + int i; + + // + // load the file header + // + if (LoadFile(filename, (void**)&header) < sizeof(dheader_t)) + Error("File %s is too short", filename); + + if (header == NULL) + Error("Cannot read file %s", filename); + + // swap the header + for (i = 0; i < sizeof(dheader_t) / 4; i++) + ((int*)header)[i] = LittleLong(((int*)header)[i]); + + if (header->version != BSPVERSION) + Error("%s is version %i, not %i", filename, header->version, BSPVERSION); + + nummodels = CopyLump(LUMP_MODELS, (void**)&dmodels, sizeof(dmodel_t)); + numvertexes = CopyLump(LUMP_VERTEXES, (void**)&dvertexes, sizeof(dvertex_t)); + numplanes = CopyLump(LUMP_PLANES, (void**)&dplanes, sizeof(dplane_t)); + numleafs = CopyLump(LUMP_LEAFS, (void**)&dleafs, sizeof(dleaf_t)); + numnodes = CopyLump(LUMP_NODES, (void**)&dnodes, sizeof(dnode_t)); + numtexinfo = CopyLump(LUMP_TEXINFO, (void**)&texinfo, sizeof(texinfo_t)); + numclipnodes = CopyLump(LUMP_CLIPNODES, (void**)&dclipnodes, sizeof(dclipnode_t)); + numfaces = CopyLump(LUMP_FACES, (void**)&dfaces, sizeof(dface_t)); + nummarksurfaces = CopyLump(LUMP_MARKSURFACES, (void**)&dmarksurfaces, sizeof(dmarksurfaces[0])); + numsurfedges = CopyLump(LUMP_SURFEDGES, (void**)&dsurfedges, sizeof(dsurfedges[0])); + numedges = CopyLump(LUMP_EDGES, (void**)&dedges, sizeof(dedge_t)); + + texdatasize = CopyLump(LUMP_TEXTURES, (void**)&dtexdata, 1); + visdatasize = CopyLump(LUMP_VISIBILITY, (void**)&dvisdata, 1); + lightdatasize = CopyLump(LUMP_LIGHTING, (void**)&dlightdata, 1); + entdatasize = CopyLump(LUMP_ENTITIES, (void**)&dentdata, 1); + + free(header); // everything has been copied out + + // + // swap everything + // + SwapBSPFile(false); + + // dmodels_checksum = FastChecksum( (char *)dmodels, nummodels*sizeof(dmodels[0]) ); + // dvertexes_checksum = FastChecksum( (char *)dvertexes, numvertexes*sizeof(dvertexes[0]) ); + // dplanes_checksum = FastChecksum( (char *)dplanes, numplanes*sizeof(dplanes[0]) ); + // dleafs_checksum = FastChecksum( (char *)dleafs, numleafs*sizeof(dleafs[0]) ); + // dnodes_checksum = FastChecksum( (char *)dnodes, numnodes*sizeof(dnodes[0]) ); + // texinfo_checksum = FastChecksum( (char *)texinfo, numtexinfo*sizeof(texinfo[0]) ); + // dclipnodes_checksum = FastChecksum( (char *)dclipnodes, numclipnodes*sizeof(dclipnodes[0]) ); + // dfaces_checksum = FastChecksum( (char *)dfaces, numfaces*sizeof(dfaces[0]) ); + // dmarksurfaces_checksum = FastChecksum( (char *)dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]) ); + // dsurfedges_checksum = FastChecksum( (char *)dsurfedges, numsurfedges*sizeof(dsurfedges[0]) ); + // dedges_checksum = FastChecksum( (char *)dedges, numedges*sizeof(dedges[0]) ); + // dtexdata_checksum = FastChecksum( (char *)dtexdata, numedges*sizeof(dtexdata[0]) ); + // dvisdata_checksum = FastChecksum( (char *)dvisdata, visdatasize*sizeof(dvisdata[0]) ); + // dlightdata_checksum = FastChecksum( (char *)dlightdata, lightdatasize*sizeof(dlightdata[0]) ); + // dentdata_checksum = FastChecksum( (char *)dentdata, entdatasize*sizeof(dentdata[0]) ); } //============================================================================ -FILE *wadfile; +FILE* wadfile; dheader_t outheader; -void AddLump (int lumpnum, void *data, int len) +void AddLump(int lumpnum, void* data, int len) { - lump_t *lump; + lump_t* lump; - lump = &header->lumps[lumpnum]; + lump = &header->lumps[lumpnum]; - lump->fileofs = LittleLong( ftell(wadfile) ); - lump->filelen = LittleLong(len); - SafeWrite (wadfile, data, (len+3)&~3); + lump->fileofs = LittleLong(ftell(wadfile)); + lump->filelen = LittleLong(len); + SafeWrite(wadfile, data, (len + 3) & ~3); } /* @@ -461,38 +456,38 @@ WriteBSPFile Swaps the bsp file in place, so it should not be referenced again ============= */ -void WriteBSPFile (char *filename) -{ - header = &outheader; - memset (header, 0, sizeof(dheader_t)); - - SwapBSPFile (true); - - header->version = LittleLong (BSPVERSION); - - wadfile = SafeOpenWrite (filename); - SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later - - AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t)); - AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t)); - AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t)); - AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t)); - AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t)); - AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t)); - AddLump (LUMP_CLIPNODES, dclipnodes, numclipnodes*sizeof(dclipnode_t)); - AddLump (LUMP_MARKSURFACES, dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0])); - AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0])); - AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t)); - AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t)); - - AddLump (LUMP_LIGHTING, dlightdata, lightdatasize); - AddLump (LUMP_VISIBILITY, dvisdata, visdatasize); - AddLump (LUMP_ENTITIES, dentdata, entdatasize); - AddLump (LUMP_TEXTURES, dtexdata, texdatasize); - - fseek (wadfile, 0, SEEK_SET); - SafeWrite (wadfile, header, sizeof(dheader_t)); - fclose (wadfile); +void WriteBSPFile(char* filename) +{ + header = &outheader; + memset(header, 0, sizeof(dheader_t)); + + SwapBSPFile(true); + + header->version = LittleLong(BSPVERSION); + + wadfile = SafeOpenWrite(filename); + SafeWrite(wadfile, header, sizeof(dheader_t)); // overwritten later + + AddLump(LUMP_PLANES, dplanes, numplanes * sizeof(dplane_t)); + AddLump(LUMP_LEAFS, dleafs, numleafs * sizeof(dleaf_t)); + AddLump(LUMP_VERTEXES, dvertexes, numvertexes * sizeof(dvertex_t)); + AddLump(LUMP_NODES, dnodes, numnodes * sizeof(dnode_t)); + AddLump(LUMP_TEXINFO, texinfo, numtexinfo * sizeof(texinfo_t)); + AddLump(LUMP_FACES, dfaces, numfaces * sizeof(dface_t)); + AddLump(LUMP_CLIPNODES, dclipnodes, numclipnodes * sizeof(dclipnode_t)); + AddLump(LUMP_MARKSURFACES, dmarksurfaces, nummarksurfaces * sizeof(dmarksurfaces[0])); + AddLump(LUMP_SURFEDGES, dsurfedges, numsurfedges * sizeof(dsurfedges[0])); + AddLump(LUMP_EDGES, dedges, numedges * sizeof(dedge_t)); + AddLump(LUMP_MODELS, dmodels, nummodels * sizeof(dmodel_t)); + + AddLump(LUMP_LIGHTING, dlightdata, lightdatasize); + AddLump(LUMP_VISIBILITY, dvisdata, visdatasize); + AddLump(LUMP_ENTITIES, dentdata, entdatasize); + AddLump(LUMP_TEXTURES, dtexdata, texdatasize); + + fseek(wadfile, 0, SEEK_SET); + SafeWrite(wadfile, header, sizeof(dheader_t)); + fclose(wadfile); } //============================================================================ @@ -500,37 +495,37 @@ void WriteBSPFile (char *filename) //#define ENTRIES(a) (sizeof(a)/sizeof(*(a))) //#define ENTRYSIZE(a) (sizeof(*(a))) -int ArrayUsage( char *szItem, int items, int maxitems, int itemsize ) +int ArrayUsage(char* szItem, int items, int maxitems, int itemsize) { - float percentage = maxitems ? items * (float)100.0 / maxitems : (float)0.0; - - printf("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)", - szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage ); - if ( percentage > 80.0 ) - printf( "VERY FULL!\n" ); - else if ( percentage > 95.0 ) - printf( "SIZE DANGER!\n" ); - else if ( percentage > 99.9 ) - printf( "SIZE OVERFLOW!!!\n" ); - else - printf( "\n" ); - return items * itemsize; + float percentage = maxitems ? items * (float)100.0 / maxitems : (float)0.0; + + printf("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)", + szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage); + if (percentage > 80.0) + printf("VERY FULL!\n"); + else if (percentage > 95.0) + printf("SIZE DANGER!\n"); + else if (percentage > 99.9) + printf("SIZE OVERFLOW!!!\n"); + else + printf("\n"); + return items * itemsize; } -int GlobUsage( char *szItem, int itemstorage, int maxstorage ) +int GlobUsage(char* szItem, int itemstorage, int maxstorage) { - float percentage = maxstorage ? itemstorage * (float)100.0 / maxstorage : (float)0.0; - printf("%-12s [variable] %7i/%-7i (%4.1f%%)", - szItem, itemstorage, maxstorage, percentage ); - if ( percentage > 80.0 ) - printf( "VERY FULL!\n" ); - else if ( percentage > 95.0 ) - printf( "SIZE DANGER!\n" ); - else if ( percentage > 99.9 ) - printf( "SIZE OVERFLOW!!!\n" ); - else - printf( "\n" ); - return itemstorage; + float percentage = maxstorage ? itemstorage * (float)100.0 / maxstorage : (float)0.0; + printf("%-12s [variable] %7i/%-7i (%4.1f%%)", + szItem, itemstorage, maxstorage, percentage); + if (percentage > 80.0) + printf("VERY FULL!\n"); + else if (percentage > 95.0) + printf("SIZE DANGER!\n"); + else if (percentage > 99.9) + printf("SIZE OVERFLOW!!!\n"); + else + printf("\n"); + return itemstorage; } /* @@ -540,73 +535,71 @@ PrintBSPFileSizes Dumps info about current file ============= */ -void PrintBSPFileSizes (void) +void PrintBSPFileSizes(void) { - int numtextures = texdatasize ? ((dmiptexlump_t*)dtexdata)->nummiptex : 0; - int totalmemory = 0; - - printf("\n"); - printf("Object names Objects/Maxobjs Memory / Maxmem Fullness\n" ); - printf("------------ --------------- --------------- --------\n" ); - - totalmemory += ArrayUsage( "models", nummodels, MAX_MAP_MODELS, sizeof(dmodel_t) ); - totalmemory += ArrayUsage( "planes", numplanes, MAX_MAP_PLANES, sizeof(dplane_t) ); - totalmemory += ArrayUsage( "vertexes", numvertexes, MAX_MAP_VERTS, sizeof(dvertex_t) ); - totalmemory += ArrayUsage( "nodes", numnodes, MAX_MAP_NODES, sizeof(dnode_t) ); - totalmemory += ArrayUsage( "texinfos", numtexinfo, MAX_MAP_TEXINFO, sizeof(texinfo_t) ); - totalmemory += ArrayUsage( "faces", numfaces, MAX_MAP_FACES, sizeof(dface_t) ); - totalmemory += ArrayUsage( "clipnodes", numclipnodes, MAX_MAP_CLIPNODES, sizeof(dclipnode_t) ); - totalmemory += ArrayUsage( "leaves", numleafs, MAX_MAP_LEAFS, sizeof(dleaf_t) ); - totalmemory += ArrayUsage( "marksurfaces", nummarksurfaces, MAX_MAP_MARKSURFACES, sizeof(unsigned short) ); - totalmemory += ArrayUsage( "surfedges", numsurfedges, MAX_MAP_SURFEDGES, sizeof(int) ); - totalmemory += ArrayUsage( "edges", numedges, MAX_MAP_EDGES, sizeof(dedge_t) ); - - totalmemory += GlobUsage( "texdata", texdatasize, MAX_MAP_MIPTEX ); - totalmemory += GlobUsage( "lightdata", lightdatasize, MAX_MAP_LIGHTING ); - totalmemory += GlobUsage( "visdata", visdatasize, MAX_MAP_VISIBILITY ); - totalmemory += GlobUsage( "entdata", entdatasize, MAX_MAP_ENTSTRING ); - - printf( "=== Total BSP file data space used: %d bytes ===\n", totalmemory ); + int numtextures = texdatasize ? ((dmiptexlump_t*)dtexdata)->nummiptex : 0; + int totalmemory = 0; + + printf("\n"); + printf("Object names Objects/Maxobjs Memory / Maxmem Fullness\n"); + printf("------------ --------------- --------------- --------\n"); + + totalmemory += ArrayUsage("models", nummodels, MAX_MAP_MODELS, sizeof(dmodel_t)); + totalmemory += ArrayUsage("planes", numplanes, MAX_MAP_PLANES, sizeof(dplane_t)); + totalmemory += ArrayUsage("vertexes", numvertexes, MAX_MAP_VERTS, sizeof(dvertex_t)); + totalmemory += ArrayUsage("nodes", numnodes, MAX_MAP_NODES, sizeof(dnode_t)); + totalmemory += ArrayUsage("texinfos", numtexinfo, MAX_MAP_TEXINFO, sizeof(texinfo_t)); + totalmemory += ArrayUsage("faces", numfaces, MAX_MAP_FACES, sizeof(dface_t)); + totalmemory += ArrayUsage("clipnodes", numclipnodes, MAX_MAP_CLIPNODES, sizeof(dclipnode_t)); + totalmemory += ArrayUsage("leaves", numleafs, MAX_MAP_LEAFS, sizeof(dleaf_t)); + totalmemory += ArrayUsage("marksurfaces", nummarksurfaces, MAX_MAP_MARKSURFACES, sizeof(unsigned short)); + totalmemory += ArrayUsage("surfedges", numsurfedges, MAX_MAP_SURFEDGES, sizeof(int)); + totalmemory += ArrayUsage("edges", numedges, MAX_MAP_EDGES, sizeof(dedge_t)); + + totalmemory += GlobUsage("texdata", texdatasize, MAX_MAP_MIPTEX); + totalmemory += GlobUsage("lightdata", lightdatasize, MAX_MAP_LIGHTING); + totalmemory += GlobUsage("visdata", visdatasize, MAX_MAP_VISIBILITY); + totalmemory += GlobUsage("entdata", entdatasize, MAX_MAP_ENTSTRING); + + printf("=== Total BSP file data space used: %d bytes ===\n", totalmemory); } - /* ================= ParseEpair ================= */ -epair_t *ParseEpair (void) +epair_t* ParseEpair(void) { - epair_t *e; + epair_t* e; - e = (epair_t *)malloc (sizeof(epair_t)); - memset (e, 0, sizeof(epair_t)); + e = (epair_t*)malloc(sizeof(epair_t)); + memset(e, 0, sizeof(epair_t)); - if (strlen(token) >= MAX_KEY-1) - Error ("ParseEpar: token too long"); - e->key = copystring(token); - GetToken (false); - if (strlen(token) >= MAX_VALUE-1) - Error ("ParseEpar: token too long"); - e->value = copystring(token); + if (strlen(token) >= MAX_KEY - 1) + Error("ParseEpar: token too long"); + e->key = copystring(token); + GetToken(false); + if (strlen(token) >= MAX_VALUE - 1) + Error("ParseEpar: token too long"); + e->value = copystring(token); - return e; + return e; } - void DumpEntity(int i) { - epair_t *e; - entity_t *mapent; - - if ((i<0) || (i>=num_entities)) return ; - mapent = &entities[i]; - e = mapent->epairs ; - printf("Entity #%d:\n",i) ; - while (e != NULL) { - printf("\t%s = %s\n",e->key,e->value) ; - e=e->next ; - } + epair_t* e; + entity_t* mapent; + + if ((i < 0) || (i >= num_entities)) return; + mapent = &entities[i]; + e = mapent->epairs; + printf("Entity #%d:\n", i); + while (e != NULL) { + printf("\t%s = %s\n", e->key, e->value); + e = e->next; + } } /* @@ -614,35 +607,35 @@ void DumpEntity(int i) ParseEntity ================ */ -qboolean ParseEntity (void) +qboolean ParseEntity(void) { - epair_t *e; - entity_t *mapent; + epair_t* e; + entity_t* mapent; - if (!GetToken (true)) - return false; + if (!GetToken(true)) + return false; - if (strcmp (token, "{") ) - Error ("ParseEntity: { not found"); + if (strcmp(token, "{")) + Error("ParseEntity: { not found"); - if (num_entities == MAX_MAP_ENTITIES) - Error ("num_entities == MAX_MAP_ENTITIES"); + if (num_entities == MAX_MAP_ENTITIES) + Error("num_entities == MAX_MAP_ENTITIES"); - mapent = &entities[num_entities]; - num_entities++; + mapent = &entities[num_entities]; + num_entities++; - do - { - if (!GetToken (true)) - Error ("ParseEntity: EOF without closing brace"); - if (!strcmp (token, "}") ) - break; - e = ParseEpair (); - e->next = mapent->epairs; - mapent->epairs = e; - } while (1); + do + { + if (!GetToken(true)) + Error("ParseEntity: EOF without closing brace"); + if (!strcmp(token, "}")) + break; + e = ParseEpair(); + e->next = mapent->epairs; + mapent->epairs = e; + } while (1); - return true; + return true; } /* @@ -652,17 +645,16 @@ ParseEntities Parses the dentdata string into entities ================ */ -void ParseEntities (void) +void ParseEntities(void) { - num_entities = 0; - ParseFromMemory (dentdata, entdatasize); + num_entities = 0; + ParseFromMemory(dentdata, entdatasize); - while (ParseEntity ()) - { - } + while (ParseEntity()) + { + } } - /* ================ UnparseEntities @@ -670,211 +662,209 @@ UnparseEntities Generates the dentdata string from all the entities ================ */ -void UnparseEntities (void) +void UnparseEntities(void) { - char *buf, *end; - epair_t *ep; - char line[2048]; - int i; - - buf = dentdata; - end = buf; - *end = 0; - - for (i=0 ; inext) - { - sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); - strcat (end, line); - end += strlen(line); - } - strcat (end,"}\n"); - end += 2; - - if (end > buf + MAX_MAP_ENTSTRING) - Error ("Entity text too long"); - } - entdatasize = end - buf + 1; + char* buf, * end; + epair_t* ep; + char line[2048]; + int i; + + buf = dentdata; + end = buf; + *end = 0; + + for (i = 0; i < num_entities; i++) + { + ep = entities[i].epairs; + if (!ep) + continue; // ent got removed + + strcat(end, "{\n"); + end += 2; + + for (ep = entities[i].epairs; ep; ep = ep->next) + { + sprintf(line, "\"%s\" \"%s\"\n", ep->key, ep->value); + strcat(end, line); + end += strlen(line); + } + strcat(end, "}\n"); + end += 2; + + if (end > buf + MAX_MAP_ENTSTRING) + Error("Entity text too long"); + } + entdatasize = end - buf + 1; } -void SetKeyValue (entity_t *ent, char *key, char *value) +void SetKeyValue(entity_t* ent, char* key, char* value) { - epair_t *ep; - epair_t *prev_ep = NULL; - - for (ep=ent->epairs ; ep ; ep=ep->next) - { - if (!strcmp (ep->key, key) ) - { - free (ep->value); - ep->value = copystring(value); - return; - } - } - - prev_ep = NULL; - for (ep=ent->epairs ; ep ; prev_ep=ep, ep=ep->next) - ; // get to the end of the linked list - - ep = (epair_t *)malloc (sizeof(*ep)); - memset(ep, 0, sizeof(ep)); - - if (prev_ep) - prev_ep->next = ep; // link it at the end - else - ent->epairs = ep; // link it at the beginning (first and only) - - ep->key = copystring(key); - ep->value = copystring(value); + epair_t* ep; + epair_t* prev_ep = NULL; + + for (ep = ent->epairs; ep; ep = ep->next) + { + if (!strcmp(ep->key, key)) + { + free(ep->value); + ep->value = copystring(value); + return; + } + } + + prev_ep = NULL; + for (ep = ent->epairs; ep; prev_ep = ep, ep = ep->next) + ; // get to the end of the linked list + + ep = (epair_t*)malloc(sizeof(*ep)); + memset(ep, 0, sizeof(ep)); + + if (prev_ep) + prev_ep->next = ep; // link it at the end + else + ent->epairs = ep; // link it at the beginning (first and only) + + ep->key = copystring(key); + ep->value = copystring(value); } -void RemoveKey(entity_t *ent, char *key) +void RemoveKey(entity_t* ent, char* key) { - epair_t *ep; - epair_t *prev_ep = NULL; - - for (ep=ent->epairs ; ep ; ep=ep->next) - { - if (!strcmp (ep->key, key) ) - { - free (ep->value); - free (ep->key); - if (prev_ep) - { - prev_ep->next = ep->next; - free(ep); - } - else - { - ent->epairs = ep->next; - free(ep); - } - return; - } - prev_ep = ep; - } + epair_t* ep; + epair_t* prev_ep = NULL; + + for (ep = ent->epairs; ep; ep = ep->next) + { + if (!strcmp(ep->key, key)) + { + free(ep->value); + free(ep->key); + if (prev_ep) + { + prev_ep->next = ep->next; + free(ep); + } + else + { + ent->epairs = ep->next; + free(ep); + } + return; + } + prev_ep = ep; + } } -int FindEntityByClassname(int index, const char *classname) +int FindEntityByClassname(int index, const char* classname) { - epair_t *ep; + epair_t* ep; - // index should be -1 to start at first entity... - index++; + // index should be -1 to start at first entity... + index++; - while (index < num_entities) - { - ep = entities[index].epairs; + while (index < num_entities) + { + ep = entities[index].epairs; - while (ep) - { - if ((strcmp(ep->key, "classname") == 0) && - (strcmp(ep->value, classname) == 0)) - { - return index; - } + while (ep) + { + if ((strcmp(ep->key, "classname") == 0) && + (strcmp(ep->value, classname) == 0)) + { + return index; + } - ep = ep->next; - } + ep = ep->next; + } - index ++; - } + index++; + } - return -1; // entity not found + return -1; // entity not found } -int FindEntityByWildcard(int index, const char *classname, int length) +int FindEntityByWildcard(int index, const char* classname, int length) { - epair_t *ep; + epair_t* ep; - // index should be -1 to start at first entity... - index++; + // index should be -1 to start at first entity... + index++; - while (index < num_entities) - { - ep = entities[index].epairs; + while (index < num_entities) + { + ep = entities[index].epairs; - while (ep) - { - if ((strcmp(ep->key, "classname") == 0) && - (strncmp(ep->value, classname, length) == 0)) - { - return index; - } + while (ep) + { + if ((strcmp(ep->key, "classname") == 0) && + (strncmp(ep->value, classname, length) == 0)) + { + return index; + } - ep = ep->next; - } + ep = ep->next; + } - index ++; - } + index++; + } - return -1; // entity not found + return -1; // entity not found } -char *ValueForKey (entity_t *ent, char *key) +char* ValueForKey(entity_t* ent, char* key) { - epair_t *ep; + epair_t* ep; - for (ep=ent->epairs ; ep ; ep=ep->next) - if (!strcmp (ep->key, key) ) - return ep->value; - return ""; + for (ep = ent->epairs; ep; ep = ep->next) + if (!strcmp(ep->key, key)) + return ep->value; + return ""; } -vec_t FloatForKey (entity_t *ent, char *key) +vec_t FloatForKey(entity_t* ent, char* key) { - char *k; + char* k; - k = ValueForKey (ent, key); - return (float)atof(k); + k = ValueForKey(ent, key); + return (float)atof(k); } -void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) +void GetVectorForKey(entity_t* ent, char* key, vec3_t vec) { - char *k; - double v1, v2, v3; - - k = ValueForKey (ent, key); -// scanf into doubles, then assign, so it is vec_t size independent - v1 = v2 = v3 = 0; - sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); - vec[0] = (float)v1; - vec[1] = (float)v2; - vec[2] = (float)v3; + char* k; + double v1, v2, v3; + + k = ValueForKey(ent, key); + // scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = v3 = 0; + sscanf(k, "%lf %lf %lf", &v1, &v2, &v3); + vec[0] = (float)v1; + vec[1] = (float)v2; + vec[2] = (float)v3; } - void FreeEntities(void) { - int i; - epair_t *pEpair, *pEpairNext; - - for (i=0; i < num_entities; i++) - { - pEpair = entities[i].epairs; - - while (pEpair) - { - pEpairNext = pEpair->next; - free(pEpair->key); - free(pEpair->value); - free(pEpair); - pEpair = pEpairNext; - } - -// num_entities = 0; EVY - } - num_entities = 0; // EVY: should rather be here - - for (i=0; i < MAX_MAP_ENTITIES; i++) - entities[i].epairs = NULL; -} - + int i; + epair_t* pEpair, * pEpairNext; + + for (i = 0; i < num_entities; i++) + { + pEpair = entities[i].epairs; + + while (pEpair) + { + pEpairNext = pEpair->next; + free(pEpair->key); + free(pEpair->value); + free(pEpair); + pEpair = pEpairNext; + } + + // num_entities = 0; EVY + } + num_entities = 0; // EVY: should rather be here + + for (i = 0; i < MAX_MAP_ENTITIES; i++) + entities[i].epairs = NULL; +} \ No newline at end of file diff --git a/Bsp2Rbn/bspfile.h b/Bsp2Rbn/bspfile.h index 4f015ac..8aef463 100644 --- a/Bsp2Rbn/bspfile.h +++ b/Bsp2Rbn/bspfile.h @@ -1,339 +1,321 @@ -/*** -* -* Copyright (c) 1998, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef __CMDLIB__ -#include "cmdlib.h" -#endif - -#ifndef BSPFILE_H -#define BSPFILE_H - - -// upper design bounds - -#define MAX_MAP_HULLS 4 - -#define MAX_MAP_MODELS 400 -#define MAX_MAP_BRUSHES 4096 -#define MAX_MAP_ENTITIES 1024 -#define MAX_MAP_ENTSTRING (128*1024) - -#define MAX_MAP_PLANES 32767 -#define MAX_MAP_NODES 32767 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 32767 // -#define MAX_MAP_LEAFS 8192 -#define MAX_MAP_VERTS 65535 -#define MAX_MAP_FACES 65535 -#define MAX_MAP_MARKSURFACES 65535 -#define MAX_MAP_TEXINFO 8192 -#define MAX_MAP_EDGES 256000 -#define MAX_MAP_SURFEDGES 512000 -#define MAX_MAP_TEXTURES 512 -#define MAX_MAP_MIPTEX 0x200000 -#define MAX_MAP_LIGHTING 0x200000 -#define MAX_MAP_VISIBILITY 0x200000 - -#define MAX_MAP_PORTALS 65536 - -// key / value pair sizes - -#define MAX_KEY 32 -#define MAX_VALUE 4096 - -//============================================================================= - - -#define BSPVERSION 30 -#define TOOLVERSION 2 - - -typedef struct -{ - int fileofs, filelen; -} lump_t; - -#define LUMP_ENTITIES 0 -#define LUMP_PLANES 1 -#define LUMP_TEXTURES 2 -#define LUMP_VERTEXES 3 -#define LUMP_VISIBILITY 4 -#define LUMP_NODES 5 -#define LUMP_TEXINFO 6 -#define LUMP_FACES 7 -#define LUMP_LIGHTING 8 -#define LUMP_CLIPNODES 9 -#define LUMP_LEAFS 10 -#define LUMP_MARKSURFACES 11 -#define LUMP_EDGES 12 -#define LUMP_SURFEDGES 13 -#define LUMP_MODELS 14 - -#define HEADER_LUMPS 15 - -typedef struct -{ - float mins[3], maxs[3]; - float origin[3]; - int headnode[MAX_MAP_HULLS]; - int visleafs; // not including the solid leaf 0 - int firstface, numfaces; -} dmodel_t; - -typedef struct -{ - int version; - lump_t lumps[HEADER_LUMPS]; -} dheader_t; - -typedef struct -{ - int nummiptex; - int dataofs[4]; // [nummiptex] -} dmiptexlump_t; - -#define MIPLEVELS 4 -typedef struct miptex_s -{ - char name[16]; - unsigned width, height; - unsigned offsets[MIPLEVELS]; // four mip maps stored -} miptex_t; - - -typedef struct -{ - float point[3]; -} dvertex_t; - - -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 - -// 3-5 are non-axial planes snapped to the nearest -#define PLANE_ANYX 3 -#define PLANE_ANYY 4 -#define PLANE_ANYZ 5 - -typedef struct -{ - float normal[3]; - float dist; - int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate -} dplane_t; - - - -#define CONTENTS_EMPTY -1 -#define CONTENTS_SOLID -2 -#define CONTENTS_WATER -3 -#define CONTENTS_SLIME -4 -#define CONTENTS_LAVA -5 -#define CONTENTS_SKY -6 -#define CONTENTS_ORIGIN -7 // removed at csg time -#define CONTENTS_CLIP -8 // changed to contents_solid - -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 -#define CONTENTS_CURRENT_180 -11 -#define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 -#define CONTENTS_CURRENT_DOWN -14 - -#define CONTENTS_TRANSLUCENT -15 - -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct -{ - int planenum; - short children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for sphere culling - short maxs[3]; - unsigned short firstface; - unsigned short numfaces; // counting both sides -} dnode_t; - -typedef struct -{ - int planenum; - short children[2]; // negative numbers are contents -} dclipnode_t; - - -typedef struct texinfo_s -{ - float vecs[2][4]; // [s/t][xyz offset] - int miptex; - int flags; -} texinfo_t; - -#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision - -// note that edge 0 is never used, because negative edge nums are used for -// counterclockwise use of the edge in a face -typedef struct -{ - unsigned short v[2]; // vertex numbers -} dedge_t; - -#define MAXLIGHTMAPS 4 - -typedef struct -{ - short planenum; - short side; - - int firstedge; // we must support > 64k edges - short numedges; - short texinfo; - -// lighting info - byte styles[MAXLIGHTMAPS]; - int lightofs; // start of [numstyles*surfsize] samples -} dface_t; - - - -#define AMBIENT_WATER 0 -#define AMBIENT_SKY 1 -#define AMBIENT_SLIME 2 -#define AMBIENT_LAVA 3 - -#define NUM_AMBIENTS 4 // automatic ambient sounds - -// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas -// all other leafs need visibility info -typedef struct -{ - int contents; - int visofs; // -1 = no visibility info - - short mins[3]; // for frustum culling - short maxs[3]; - - unsigned short firstmarksurface; - unsigned short nummarksurfaces; - - byte ambient_level[NUM_AMBIENTS]; -} dleaf_t; - - -//============================================================================ - - -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - - -// the utilities get to be lazy and just use large static arrays - -// Make all of these dynamic for BSP_tool... - -extern int nummodels; -extern dmodel_t *dmodels; - -extern int visdatasize; -extern byte *dvisdata; - -extern int lightdatasize; -extern byte *dlightdata; - -extern int texdatasize; -extern byte *dtexdata; - -extern int entdatasize; -extern char *dentdata; - -extern int numleafs; -extern dleaf_t *dleafs; - -extern int numplanes; -extern dplane_t *dplanes; - -extern int numvertexes; -extern dvertex_t *dvertexes; - -extern int numnodes; -extern dnode_t *dnodes; - -extern int numtexinfo; -extern texinfo_t *texinfo; - -extern int numfaces; -extern dface_t *dfaces; - -extern int numclipnodes; -extern dclipnode_t *dclipnodes; - -extern int numedges; -extern dedge_t *dedges; - -extern int nummarksurfaces; -extern unsigned short *dmarksurfaces; - -extern int numsurfedges; -extern int *dsurfedges; - - -int FastChecksum(char *buffer, int bytes); - -void DecompressVis (byte *in, byte *decompressed); -int CompressVis (byte *vis, byte *dest); - -void SwapBSPFile (qboolean todisk); -int CopyLump (int lump, void **dest, int size); -void LoadBSPFile (char *filename); -void WriteBSPFile (char *filename); -void PrintBSPFileSizes (void); - - -//=============== - - -typedef struct epair_s -{ - struct epair_s *next; - char *key; - char *value; -} epair_t; - -typedef struct -{ - vec3_t origin; - int firstbrush; - int numbrushes; - epair_t *epairs; -} entity_t; - -extern int num_entities; -extern entity_t entities[MAX_MAP_ENTITIES]; - -void ParseEntities (void); -void DumpEntity(int i) ; -void UnparseEntities (void); - -void SetKeyValue (entity_t *ent, char *key, char *value); -void RemoveKey(entity_t *ent, char *key); -int FindEntityByClassname(int index, const char *classname); -int FindEntityByWildcard(int index, const char *classname, int length); -char *ValueForKey (entity_t *ent, char *key); -// will return "" if not present - -vec_t FloatForKey (entity_t *ent, char *key); -void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); - -epair_t *ParseEpair (void); - -void FreeEntities(void); - - -#endif // BSPFILE_H +/*** +* +* Copyright (c) 1998, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ +#ifndef __CMDLIB__ +#include "cmdlib.h" +#endif + +#ifndef BSPFILE_H +#define BSPFILE_H + +// upper design bounds + +#define MAX_MAP_HULLS 4 + +#define MAX_MAP_MODELS 400 +#define MAX_MAP_BRUSHES 4096 +#define MAX_MAP_ENTITIES 1024 +#define MAX_MAP_ENTSTRING (128*1024) + +#define MAX_MAP_PLANES 32767 +#define MAX_MAP_NODES 32767 // because negative shorts are contents +#define MAX_MAP_CLIPNODES 32767 // +#define MAX_MAP_LEAFS 8192 +#define MAX_MAP_VERTS 65535 +#define MAX_MAP_FACES 65535 +#define MAX_MAP_MARKSURFACES 65535 +#define MAX_MAP_TEXINFO 8192 +#define MAX_MAP_EDGES 256000 +#define MAX_MAP_SURFEDGES 512000 +#define MAX_MAP_TEXTURES 512 +#define MAX_MAP_MIPTEX 0x200000 +#define MAX_MAP_LIGHTING 0x200000 +#define MAX_MAP_VISIBILITY 0x200000 + +#define MAX_MAP_PORTALS 65536 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 4096 + +//============================================================================= + +#define BSPVERSION 30 +#define TOOLVERSION 2 + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_TEXTURES 2 +#define LUMP_VERTEXES 3 +#define LUMP_VISIBILITY 4 +#define LUMP_NODES 5 +#define LUMP_TEXINFO 6 +#define LUMP_FACES 7 +#define LUMP_LIGHTING 8 +#define LUMP_CLIPNODES 9 +#define LUMP_LEAFS 10 +#define LUMP_MARKSURFACES 11 +#define LUMP_EDGES 12 +#define LUMP_SURFEDGES 13 +#define LUMP_MODELS 14 + +#define HEADER_LUMPS 15 + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; + int headnode[MAX_MAP_HULLS]; + int visleafs; // not including the solid leaf 0 + int firstface, numfaces; +} dmodel_t; + +typedef struct +{ + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + int nummiptex; + int dataofs[4]; // [nummiptex] +} dmiptexlump_t; + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[16]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored +} miptex_t; + +typedef struct +{ + float point[3]; +} dvertex_t; + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + +#define CONTENTS_EMPTY -1 +#define CONTENTS_SOLID -2 +#define CONTENTS_WATER -3 +#define CONTENTS_SLIME -4 +#define CONTENTS_LAVA -5 +#define CONTENTS_SKY -6 +#define CONTENTS_ORIGIN -7 // removed at csg time +#define CONTENTS_CLIP -8 // changed to contents_solid + +#define CONTENTS_CURRENT_0 -9 +#define CONTENTS_CURRENT_90 -10 +#define CONTENTS_CURRENT_180 -11 +#define CONTENTS_CURRENT_270 -12 +#define CONTENTS_CURRENT_UP -13 +#define CONTENTS_CURRENT_DOWN -14 + +#define CONTENTS_TRANSLUCENT -15 + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + int planenum; + short children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for sphere culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + +typedef struct +{ + int planenum; + short children[2]; // negative numbers are contents +} dclipnode_t; + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int miptex; + int flags; +} texinfo_t; + +#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 + +typedef struct +{ + short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + + // lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + +#define AMBIENT_WATER 0 +#define AMBIENT_SKY 1 +#define AMBIENT_SLIME 2 +#define AMBIENT_LAVA 3 + +#define NUM_AMBIENTS 4 // automatic ambient sounds + +// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas +// all other leafs need visibility info +typedef struct +{ + int contents; + int visofs; // -1 = no visibility info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstmarksurface; + unsigned short nummarksurfaces; + + byte ambient_level[NUM_AMBIENTS]; +} dleaf_t; + +//============================================================================ + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + +// the utilities get to be lazy and just use large static arrays + +// Make all of these dynamic for BSP_tool... + +extern int nummodels; +extern dmodel_t* dmodels; + +extern int visdatasize; +extern byte* dvisdata; + +extern int lightdatasize; +extern byte* dlightdata; + +extern int texdatasize; +extern byte* dtexdata; + +extern int entdatasize; +extern char* dentdata; + +extern int numleafs; +extern dleaf_t* dleafs; + +extern int numplanes; +extern dplane_t* dplanes; + +extern int numvertexes; +extern dvertex_t* dvertexes; + +extern int numnodes; +extern dnode_t* dnodes; + +extern int numtexinfo; +extern texinfo_t* texinfo; + +extern int numfaces; +extern dface_t* dfaces; + +extern int numclipnodes; +extern dclipnode_t* dclipnodes; + +extern int numedges; +extern dedge_t* dedges; + +extern int nummarksurfaces; +extern unsigned short* dmarksurfaces; + +extern int numsurfedges; +extern int* dsurfedges; + +int FastChecksum(char* buffer, int bytes); + +void DecompressVis(byte* in, byte* decompressed); +int CompressVis(byte* vis, byte* dest); + +void SwapBSPFile(qboolean todisk); +int CopyLump(int lump, void** dest, int size); +void LoadBSPFile(char* filename); +void WriteBSPFile(char* filename); +void PrintBSPFileSizes(void); + +//=============== + +typedef struct epair_s +{ + struct epair_s* next; + char* key; + char* value; +} epair_t; + +typedef struct +{ + vec3_t origin; + int firstbrush; + int numbrushes; + epair_t* epairs; +} entity_t; + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities(void); +void DumpEntity(int i); +void UnparseEntities(void); + +void SetKeyValue(entity_t* ent, char* key, char* value); +void RemoveKey(entity_t* ent, char* key); +int FindEntityByClassname(int index, const char* classname); +int FindEntityByWildcard(int index, const char* classname, int length); +char* ValueForKey(entity_t* ent, char* key); +// will return "" if not present + +vec_t FloatForKey(entity_t* ent, char* key); +void GetVectorForKey(entity_t* ent, char* key, vec3_t vec); + +epair_t* ParseEpair(void); + +void FreeEntities(void); + +#endif // BSPFILE_H diff --git a/Bsp2Rbn/build.cpp b/Bsp2Rbn/build.cpp index 881b47a..4629175 100644 --- a/Bsp2Rbn/build.cpp +++ b/Bsp2Rbn/build.cpp @@ -1,4 +1,4 @@ -char * Version = "0.9.7 of $Date$" ; +char* Version = "0.9.7 of $Date$"; // $Log: build.cpp,v $ // Revision 1.6 2004/07/27 07:43:35 eric @@ -17,4 +17,4 @@ char * Version = "0.9.7 of $Date$" ; // Revision 1.3 2004/07/20 12:36:10 eric // - bumped version to 0.9.3 // - it compiles eventually on Windows with mingw... -// +// \ No newline at end of file diff --git a/Bsp2Rbn/cmdlib.cpp b/Bsp2Rbn/cmdlib.cpp index ec46971..204013d 100644 --- a/Bsp2Rbn/cmdlib.cpp +++ b/Bsp2Rbn/cmdlib.cpp @@ -2,8 +2,8 @@ * * Copyright (c) 1998, Valve LLC. All rights reserved. * -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ @@ -31,7 +31,7 @@ // set these before calling CheckParm int myargc; -char **myargv; +char** myargv; char com_token[1024]; qboolean com_eof; @@ -39,7 +39,6 @@ qboolean com_eof; qboolean archive; char archivedir[1024]; - /* ================= Error @@ -47,44 +46,43 @@ Error For abnormal program terminations ================= */ -void Error (char *error, ...) +void Error(char* error, ...) { - va_list argptr; - char msg[256]; + va_list argptr; + char msg[256]; - va_start (argptr, error); - vsprintf (msg, error, argptr); - va_end (argptr); + va_start(argptr, error); + vsprintf(msg, error, argptr); + va_end(argptr); #ifdef __linux__ - printf("\n************ ERROR ************\n"); - printf("%s\n", msg); + printf("\n************ ERROR ************\n"); + printf("%s\n", msg); #else - char input[1]; + char input[1]; - printf("\n************ ERROR ************\n"); - printf("%s\n", msg); - printf("\nPress to exit\n"); - gets(input); + printf("\n************ ERROR ************\n"); + printf("%s\n", msg); + printf("\nPress to exit\n"); + gets(input); #endif - exit (1); + exit(1); } // only printf if in verbose mode qboolean verbose = false; -void qprintf (char *format, ...) +void qprintf(char* format, ...) { - va_list argptr; + va_list argptr; - if (!verbose) - return; - va_start (argptr,format); - vprintf (format,argptr); - va_end (argptr); + if (!verbose) + return; + va_start(argptr, format); + vprintf(format, argptr); + va_end(argptr); } - /* qdir will hold the path up to the quake directory, including the slash @@ -96,208 +94,203 @@ gamedir will hold qdir + the game directory (id1, id2, etc) */ -char qproject[ 1024 ]={'\0'}; -char qdir[1024]={'\0'}; -char gamedir[1024]={'\0'}; +char qproject[1024] = { '\0' }; +char qdir[1024] = { '\0' }; +char gamedir[1024] = { '\0' }; -void SetQdirFromPath (char *path) +void SetQdirFromPath(char* path) { #ifndef OLD_BOGUS_PATH_CODE - if ( qproject[0]=='\0' ) - { - if ( getenv("QPROJECT") ) - { - char c = qproject[ strlen(qproject)-1 ]; - strcpy( qproject, getenv("QPROJECT") ); - if ( !PATHSEPARATOR( c ) ) - strcat( qproject, "\\" ); - } - else - strcpy( qproject, "quiver\\" ); - } - if ( qproject[0] != '\\' && qproject[0] != '/' && qproject[1] != ':' ) - { - strcpy( qdir, "\\" ); - } - - strcat( qdir, qproject ); - strcpy( gamedir, qdir ); - strcat( gamedir, "\\valve\\" ); + if (qproject[0] == '\0') + { + if (getenv("QPROJECT")) + { + char c = qproject[strlen(qproject) - 1]; + strcpy(qproject, getenv("QPROJECT")); + if (!PATHSEPARATOR(c)) + strcat(qproject, "\\"); + } + else + strcpy(qproject, "quiver\\"); + } + if (qproject[0] != '\\' && qproject[0] != '/' && qproject[1] != ':') + { + strcpy(qdir, "\\"); + } + + strcat(qdir, qproject); + strcpy(gamedir, qdir); + strcat(gamedir, "\\valve\\"); #else - char temp[1024]; - char *c; + char temp[1024]; + char* c; - if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) - { // path is partial - Q_getwd (temp); - strcat (temp, path); - path = temp; - } + if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) + { // path is partial + Q_getwd(temp); + strcat(temp, path); + path = temp; + } -// search for "quake" or quiver in path - if( !qproject[0] ) - { - char *pszProj; + // search for "quake" or quiver in path + if (!qproject[0]) + { + char* pszProj; - pszProj = getenv("QPROJECT"); + pszProj = getenv("QPROJECT"); - if (pszProj != NULL) - strcpy(qproject, pszProj); - else - strcpy(qproject, "quiver"); - } + if (pszProj != NULL) + strcpy(qproject, pszProj); + else + strcpy(qproject, "quiver"); + } try_again: - for (c=path ; *c ; c++) - { - int iSize = 0; - - if (!Q_strncasecmp( c, qproject, strlen( qproject ) ) ) - iSize = strlen( qproject ) + 1; - - if (iSize > 0) - { - strncpy (qdir, path, c + iSize - path); - printf ("qdir: %s\n", qdir); - c += iSize; - while (*c) - { - if (*c == '/' || *c == '\\') - { - strncpy (gamedir, path, c+1-path); - printf ("gamedir: %s\n", gamedir); - return; - } - c++; - } - Error ("No gamedir in %s", path); - return; - } - } - - if (!strcmp(qproject, "quiver")) - { - strcpy(qproject, "prospero"); - goto try_again; - } - - Error ("SetQdirFromPath: no '%s' in %s", qproject, path); + for (c = path; *c; c++) + { + int iSize = 0; + + if (!Q_strncasecmp(c, qproject, strlen(qproject))) + iSize = strlen(qproject) + 1; + + if (iSize > 0) + { + strncpy(qdir, path, c + iSize - path); + printf("qdir: %s\n", qdir); + c += iSize; + while (*c) + { + if (*c == '/' || *c == '\\') + { + strncpy(gamedir, path, c + 1 - path); + printf("gamedir: %s\n", gamedir); + return; + } + c++; + } + Error("No gamedir in %s", path); + return; + } + } + + if (!strcmp(qproject, "quiver")) + { + strcpy(qproject, "prospero"); + goto try_again; + } + + Error("SetQdirFromPath: no '%s' in %s", qproject, path); #endif } - -char *ExpandArg (char *path) +char* ExpandArg(char* path) { - static char full[1024]; - - if (path[0] != '/' && path[0] != '\\' && path[1] != ':') - { - Q_getwd (full); - strcat (full, path); - } - else - strcpy (full, path); - return full; + static char full[1024]; + + if (path[0] != '/' && path[0] != '\\' && path[1] != ':') + { + Q_getwd(full); + strcat(full, path); + } + else + strcpy(full, path); + return full; } -char *ExpandPath (char *path) +char* ExpandPath(char* path) { - char *psz; - static char full[1024]; - if (!qdir) - Error ("ExpandPath called without qdir set"); - if (path[0] == '/' || path[0] == '\\' || path[1] == ':') - return path; - psz = strstr(path, qdir); - if (psz) - strcpy(full, path); - else - sprintf (full, "%s%s", qdir, path); - - return full; + char* psz; + static char full[1024]; + if (!qdir) + Error("ExpandPath called without qdir set"); + if (path[0] == '/' || path[0] == '\\' || path[1] == ':') + return path; + psz = strstr(path, qdir); + if (psz) + strcpy(full, path); + else + sprintf(full, "%s%s", qdir, path); + + return full; } -char *ExpandPathAndArchive (char *path) +char* ExpandPathAndArchive(char* path) { - char *expanded; - char archivename[1024]; + char* expanded; + char archivename[1024]; - expanded = ExpandPath (path); + expanded = ExpandPath(path); - if (archive) - { - sprintf (archivename, "%s/%s", archivedir, path); - QCopyFile (expanded, archivename); - } - return expanded; + if (archive) + { + sprintf(archivename, "%s/%s", archivedir, path); + QCopyFile(expanded, archivename); + } + return expanded; } - -char *copystring(char *s) +char* copystring(char* s) { - char *b; - b = (char *)malloc(strlen(s)+1); - strcpy (b, s); - return b; + char* b; + b = (char*)malloc(strlen(s) + 1); + strcpy(b, s); + return b; } - - /* ================ I_FloatTime ================ */ -double I_FloatTime (void) +double I_FloatTime(void) { - time_t t; - - time (&t); - - return t; + time_t t; + + time(&t); + + return t; #if 0 -// more precise, less portable - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday(&tp, &tzp); - - if (!secbase) - { - secbase = tp.tv_sec; - return tp.tv_usec/1000000.0; - } - - return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; + // more precise, less portable + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec / 1000000.0; + } + + return (tp.tv_sec - secbase) + tp.tv_usec / 1000000.0; #endif } -void Q_getwd (char *out) +void Q_getwd(char* out) { #ifndef __linux__ - _getcwd (out, 256); - strcat (out, "\\"); + _getcwd(out, 256); + strcat(out, "\\"); #else - getcwd (out, 256); + getcwd(out, 256); #endif } - -void Q_mkdir (char *path) +void Q_mkdir(char* path) { #ifndef __linux__ - if (_mkdir (path) != -1) - return; + if (_mkdir(path) != -1) + return; #else - if (mkdir (path, 0777) != -1) - return; + if (mkdir(path, 0777) != -1) + return; #endif - if (errno != EEXIST) - Error ("mkdir %s: %s",path, strerror(errno)); + if (errno != EEXIST) + Error("mkdir %s: %s", path, strerror(errno)); } /* @@ -307,17 +300,15 @@ FileTime returns -1 if not present ============ */ -int FileTime (char *path) +int FileTime(char* path) { - struct stat buf; - - if (stat (path,&buf) == -1) - return -1; - - return buf.st_mtime; -} + struct stat buf; + if (stat(path, &buf) == -1) + return -1; + return buf.st_mtime; +} /* ============== @@ -326,148 +317,143 @@ COM_Parse Parse a token out of a string (into global: char com_token[1024]) ============== */ -char *COM_Parse (char *data) -{ - int c; - int len; - - len = 0; - com_token[0] = 0; - - if (!data) - return NULL; - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - { - com_eof = true; - return NULL; // end of file; - } - data++; - } - -// skip // comments - if (c=='/' && data[1] == '/') - { - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if (c == '\"') - { - data++; - do - { - c = *data++; - if (c=='\"') - { - com_token[len] = 0; - return data; - } - com_token[len] = c; - len++; - } while (1); - } - -// parse single characters - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - { - com_token[len] = c; - len++; - com_token[len] = 0; - return data+1; - } - -// parse a regular word - do - { - com_token[len] = c; - data++; - len++; - c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - break; - } while (c>32); - - com_token[len] = 0; - return data; -} - - -int Q_strncasecmp (char *s1, char *s2, int n) +char* COM_Parse(char* data) { - int c1, c2; - - while (1) - { - c1 = *s1++; - c2 = *s2++; - - if (!n--) - return 0; // strings are equal until end point - - if (c1 != c2) - { - if (c1 >= 'a' && c1 <= 'z') - c1 -= ('a' - 'A'); - if (c2 >= 'a' && c2 <= 'z') - c2 -= ('a' - 'A'); - if (c1 != c2) - return -1; // strings not equal - } - if (!c1) - return 0; // strings are equal - } - - return -1; -} - -int Q_strcasecmp (char *s1, char *s2) -{ - return Q_strncasecmp (s1, s2, 99999); -} + int c; + int len; + len = 0; + com_token[0] = 0; -char *strupr (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = toupper(*in); - in++; - } - return start; -} + if (!data) + return NULL; -char *strlower (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = tolower(*in); - in++; - } - return start; + // skip whitespace +skipwhite: + while ((c = *data) <= ' ') + { + if (c == 0) + { + com_eof = true; + return NULL; // end of file; + } + data++; + } + + // skip // comments + if (c == '/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + + // handle quoted strings specially + if (c == '\"') + { + data++; + do + { + c = *data++; + if (c == '\"') + { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } while (1); + } + + // parse single characters + if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':') + { + com_token[len] = c; + len++; + com_token[len] = 0; + return data + 1; + } + + // parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':') + break; + } while (c > 32); + + com_token[len] = 0; + return data; +} + +int Q_strncasecmp(char* s1, char* s2, int n) +{ + int c1, c2; + + while (1) + { + c1 = *s1++; + c2 = *s2++; + + if (!n--) + return 0; // strings are equal until end point + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + if (!c1) + return 0; // strings are equal + } + + return -1; +} + +int Q_strcasecmp(char* s1, char* s2) +{ + return Q_strncasecmp(s1, s2, 99999); +} + +char* strupr(char* start) +{ + char* in; + in = start; + while (*in) + { + *in = toupper(*in); + in++; + } + return start; +} + +char* strlower(char* start) +{ + char* in; + in = start; + while (*in) + { + *in = tolower(*in); + in++; + } + return start; } - /* ============================================================================= - MISC FUNCTIONS + MISC FUNCTIONS ============================================================================= */ - /* ================= CheckParm @@ -476,283 +462,267 @@ Checks for the given parameter in the program's command line arguments Returns the argument number (1 to argc-1) or 0 if not present ================= */ -int CheckParm (char *check) +int CheckParm(char* check) { - int i; + int i; - for (i = 1;i 0 && !PATHSEPARATOR(path[length])) - length--; - path[length] = 0; + length = strlen(path) - 1; + while (length > 0 && !PATHSEPARATOR(path[length])) + length--; + path[length] = 0; } -void StripExtension (char *path) +void StripExtension(char* path) { - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != '.') - { - length--; - if (path[length] == '/') - return; // no extension - } - if (length) - path[length] = 0; -} + int length; + length = strlen(path) - 1; + while (length > 0 && path[length] != '.') + { + length--; + if (path[length] == '/') + return; // no extension + } + if (length) + path[length] = 0; +} /* ==================== Extract file parts ==================== */ -void ExtractFilePath (char *path, char *dest) +void ExtractFilePath(char* path, char* dest) { - char *src; + char* src; - src = path + strlen(path) - 1; + src = path + strlen(path) - 1; -// -// back up until a \ or the start -// - while (src != path && !PATHSEPARATOR(*(src-1))) - src--; + // + // back up until a \ or the start + // + while (src != path && !PATHSEPARATOR(*(src - 1))) + src--; - memcpy (dest, path, src-path); - dest[src-path] = 0; + memcpy(dest, path, src - path); + dest[src - path] = 0; } -void ExtractFileBase (char *path, char *dest) +void ExtractFileBase(char* path, char* dest) { - char *src; + char* src; - src = path + strlen(path) - 1; + src = path + strlen(path) - 1; -// -// back up until a \ or the start -// - while (src != path && !PATHSEPARATOR(*(src-1))) - src--; - - while (*src && *src != '.') - { - *dest++ = *src++; - } - *dest = 0; + // + // back up until a \ or the start + // + while (src != path && !PATHSEPARATOR(*(src - 1))) + src--; + + while (*src && *src != '.') + { + *dest++ = *src++; + } + *dest = 0; } -void ExtractFileExtension (char *path, char *dest) +void ExtractFileExtension(char* path, char* dest) { - char *src; + char* src; - src = path + strlen(path) - 1; + src = path + strlen(path) - 1; -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.') - src--; - if (src == path) - { - *dest = 0; // no extension - return; - } - - strcpy (dest,src); -} + // + // back up until a . or the start + // + while (src != path && *(src - 1) != '.') + src--; + if (src == path) + { + *dest = 0; // no extension + return; + } + strcpy(dest, src); +} /* ============== ParseNum / ParseHex ============== */ -int ParseHex (char *hex) +int ParseHex(char* hex) { - char *str; - int num; - - num = 0; - str = hex; - - while (*str) - { - num <<= 4; - if (*str >= '0' && *str <= '9') - num += *str-'0'; - else if (*str >= 'a' && *str <= 'f') - num += 10 + *str-'a'; - else if (*str >= 'A' && *str <= 'F') - num += 10 + *str-'A'; - else - Error ("Bad hex number: %s",hex); - str++; - } - - return num; -} + char* str; + int num; + num = 0; + str = hex; -int ParseNum (char *str) -{ - if (str[0] == '$') - return ParseHex (str+1); - if (str[0] == '0' && str[1] == 'x') - return ParseHex (str+2); - return atol (str); -} + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str - '0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str - 'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str - 'A'; + else + Error("Bad hex number: %s", hex); + str++; + } + return num; +} +int ParseNum(char* str) +{ + if (str[0] == '$') + return ParseHex(str + 1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex(str + 2); + return atol(str); +} /* ============================================================================ - BYTE ORDER FUNCTIONS + BYTE ORDER FUNCTIONS ============================================================================ */ @@ -763,120 +733,112 @@ int ParseNum (char *str) #ifdef __BIG_ENDIAN__ -short LittleShort (short l) +short LittleShort(short l) { - byte b1,b2; + byte b1, b2; - b1 = l&255; - b2 = (l>>8)&255; + b1 = l & 255; + b2 = (l >> 8) & 255; - return (b1<<8) + b2; + return (b1 << 8) + b2; } -short BigShort (short l) +short BigShort(short l) { - return l; + return l; } - -int LittleLong (int l) +int LittleLong(int l) { - byte b1,b2,b3,b4; + byte b1, b2, b3, b4; - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; + b1 = l & 255; + b2 = (l >> 8) & 255; + b3 = (l >> 16) & 255; + b4 = (l >> 24) & 255; - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; + return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4; } -int BigLong (int l) +int BigLong(int l) { - return l; + return l; } - -float LittleFloat (float l) +float LittleFloat(float l) { - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; + union { byte b[4]; float f; } in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; } -float BigFloat (float l) +float BigFloat(float l) { - return l; + return l; } - #else - -short BigShort (short l) +short BigShort(short l) { - byte b1,b2; + byte b1, b2; - b1 = l&255; - b2 = (l>>8)&255; + b1 = l & 255; + b2 = (l >> 8) & 255; - return (b1<<8) + b2; + return (b1 << 8) + b2; } -short LittleShort (short l) +short LittleShort(short l) { - return l; + return l; } - -int BigLong (int l) +int BigLong(int l) { - byte b1,b2,b3,b4; + byte b1, b2, b3, b4; - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; + b1 = l & 255; + b2 = (l >> 8) & 255; + b3 = (l >> 16) & 255; + b4 = (l >> 24) & 255; - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; + return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4; } -int LittleLong (int l) +int LittleLong(int l) { - return l; + return l; } -float BigFloat (float l) +float BigFloat(float l) { - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; + union { byte b[4]; float f; } in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; } -float LittleFloat (float l) +float LittleFloat(float l) { - return l; + return l; } - #endif - //======================================================= - // FIXME: byte swap? // this is a 16 bit, non-reflected CRC using the polynomial 0x1021 @@ -888,53 +850,53 @@ float LittleFloat (float l) static unsigned short crctable[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; -void CRC_Init(unsigned short *crcvalue) +void CRC_Init(unsigned short* crcvalue) { - *crcvalue = CRC_INIT_VALUE; + *crcvalue = CRC_INIT_VALUE; } -void CRC_ProcessByte(unsigned short *crcvalue, byte data) +void CRC_ProcessByte(unsigned short* crcvalue, byte data) { - *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; + *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; } unsigned short CRC_Value(unsigned short crcvalue) { - return crcvalue ^ CRC_XOR_VALUE; + return crcvalue ^ CRC_XOR_VALUE; } //============================================================================= @@ -943,22 +905,21 @@ unsigned short CRC_Value(unsigned short crcvalue) CreatePath ============ */ -void CreatePath (char *path) +void CreatePath(char* path) { - char *ofs, c; - - for (ofs = path+1 ; *ofs ; ofs++) - { - c = *ofs; - if (c == '/' || c == '\\') - { // create the directory - *ofs = 0; - Q_mkdir (path); - *ofs = c; - } - } -} + char* ofs, c; + for (ofs = path + 1; *ofs; ofs++) + { + c = *ofs; + if (c == '/' || c == '\\') + { // create the directory + *ofs = 0; + Q_mkdir(path); + *ofs = c; + } + } +} /* ============ @@ -967,18 +928,17 @@ QCopyFile Used to archive source files ============ */ -void QCopyFile (char *from, char *to) +void QCopyFile(char* from, char* to) { - void *buffer; - int length; + void* buffer; + int length; - length = LoadFile (from, &buffer); - CreatePath (to); - SaveFile (to, buffer, length); - free (buffer); + length = LoadFile(from, &buffer); + CreatePath(to); + SaveFile(to, buffer, length); + free(buffer); } - /* ============ ListPak @@ -989,44 +949,41 @@ ListPak void ListPak(char* pakname) { - FILE* f = SafeOpenRead(pakname); - packheader_t head; - packfile_t* pdir; - long i=0,imax=0; - long totlen=0; + FILE* f = SafeOpenRead(pakname); + packheader_t head; + packfile_t* pdir; + long i = 0, imax = 0; + long totlen = 0; - SafeRead(f,&head,sizeof(packheader_t)); - pdir = (packfile_t *)malloc(head.dirlen); + SafeRead(f, &head, sizeof(packheader_t)); + pdir = (packfile_t*)malloc(head.dirlen); - fseek(f,head.dirofs,SEEK_SET); - SafeRead(f,pdir,head.dirlen); - - fseek(f,0,SEEK_END); - totlen=ftell(f); + fseek(f, head.dirofs, SEEK_SET); + SafeRead(f, pdir, head.dirlen); - fclose(f); + fseek(f, 0, SEEK_END); + totlen = ftell(f); - imax=head.dirlen/sizeof(packfile_t); + fclose(f); - for(i;iidentifier) - // set these before calling CheckParm extern int myargc; -extern char **myargv; +extern char** myargv; -char *strupr (char *in); -char *strlower (char *in); -int Q_strncasecmp (char *s1, char *s2, int n); -int Q_strcasecmp (char *s1, char *s2); -void Q_getwd (char *out); +char* strupr(char* in); +char* strlower(char* in); +int Q_strncasecmp(char* s1, char* s2, int n); +int Q_strcasecmp(char* s1, char* s2); +void Q_getwd(char* out); -int filelength (FILE *f); -int FileTime (char *path); +int filelength(FILE* f); +int FileTime(char* path); -void Q_mkdir (char *path); +void Q_mkdir(char* path); extern char qdir[1024]; extern char gamedir[1024]; -void SetQdirFromPath (char *path); -char *ExpandArg (char *path); // from cmd line -char *ExpandPath (char *path); // from scripts -char *ExpandPathAndArchive (char *path); - +void SetQdirFromPath(char* path); +char* ExpandArg(char* path); // from cmd line +char* ExpandPath(char* path); // from scripts +char* ExpandPathAndArchive(char* path); -double I_FloatTime (void); +double I_FloatTime(void); -void Error (char *error, ...); -int CheckParm (char *check); +void Error(char* error, ...); +int CheckParm(char* check); -FILE *SafeOpenWrite (char *filename); -FILE *SafeOpenRead (char *filename); -void SafeRead (FILE *f, void *buffer, int count); -void SafeWrite (FILE *f, void *buffer, int count); +FILE* SafeOpenWrite(char* filename); +FILE* SafeOpenRead(char* filename); +void SafeRead(FILE* f, void* buffer, int count); +void SafeWrite(FILE* f, void* buffer, int count); -int LoadFile (char *filename, void **bufferptr); -void SaveFile (char *filename, void *buffer, int count); +int LoadFile(char* filename, void** bufferptr); +void SaveFile(char* filename, void* buffer, int count); -void DefaultExtension (char *path, char *extension); -void DefaultPath (char *path, char *basepath); -void StripFilename (char *path); -void StripExtension (char *path); +void DefaultExtension(char* path, char* extension); +void DefaultPath(char* path, char* basepath); +void StripFilename(char* path); +void StripExtension(char* path); -void ExtractFilePath (char *path, char *dest); -void ExtractFileBase (char *path, char *dest); -void ExtractFileExtension (char *path, char *dest); +void ExtractFilePath(char* path, char* dest); +void ExtractFileBase(char* path, char* dest); +void ExtractFileExtension(char* path, char* dest); -int ParseNum (char *str); +int ParseNum(char* str); -short BigShort (short l); -short LittleShort (short l); -int BigLong (int l); -int LittleLong (int l); -float BigFloat (float l); -float LittleFloat (float l); +short BigShort(short l); +short LittleShort(short l); +int BigLong(int l); +int LittleLong(int l); +float BigFloat(float l); +float LittleFloat(float l); long flen(FILE* f); - - -char *COM_Parse (char *data); +char* COM_Parse(char* data); extern char com_token[1024]; extern qboolean com_eof; -char *copystring(char *s); - +char* copystring(char* s); -void CRC_Init(unsigned short *crcvalue); -void CRC_ProcessByte(unsigned short *crcvalue, byte data); +void CRC_Init(unsigned short* crcvalue); +void CRC_ProcessByte(unsigned short* crcvalue, byte data); unsigned short CRC_Value(unsigned short crcvalue); -void CreatePath (char *path); -void QCopyFile (char *from, char *to); +void CreatePath(char* path); +void QCopyFile(char* from, char* to); extern qboolean archive; extern char archivedir[1024]; - extern qboolean verbose; -void qprintf (char *format, ...); - +void qprintf(char* format, ...); typedef struct { - char name[56]; - int filepos, filelen; + char name[56]; + int filepos, filelen; } packfile_t; typedef struct { - char id[4]; - int dirofs; - int dirlen; + char id[4]; + int dirofs; + int dirlen; } packheader_t; - void ListPak(char* pakname); #endif // CMDLIB - diff --git a/Bsp2Rbn/dummy.cpp b/Bsp2Rbn/dummy.cpp index 911cf58..c89480d 100644 --- a/Bsp2Rbn/dummy.cpp +++ b/Bsp2Rbn/dummy.cpp @@ -13,7 +13,6 @@ #include #include - #include "../bot.h" #include "../game.h" #include "../bot_weapons.h" @@ -26,7 +25,7 @@ enginefuncs_t g_engfuncs; globalvars_t pGlobals; -globalvars_t *gpGlobals = &pGlobals; +globalvars_t* gpGlobals = &pGlobals; char g_argv[1024]; cBot bots[32]; @@ -39,96 +38,92 @@ cGame Game; cNodeMachine NodeMachine; cChatEngine ChatEngine; -void FakeClientCommand (edict_t * pBot, char *arg1, char *arg2, char *arg3) -{ - fprintf(stderr,"FakeClientCommand is called!\n") ; - exit(1) ; +void FakeClientCommand(edict_t* pBot, char* arg1, char* arg2, char* arg3) +{ + fprintf(stderr, "FakeClientCommand is called!\n"); + exit(1); } - // From game.cpp // Debug message -void REALBOT_PRINT (cBot * pBot, const char *Function, const char *msg) +void REALBOT_PRINT(cBot* pBot, const char* Function, const char* msg) { - // Message format: - // Function name - [BOT NAME, BOT TEAM]: Message - char team[9]; - char name[32]; - - memset(team, 0, sizeof(team)); // clear - memset(name, 0, sizeof(name)); // clear - - strcpy(team, "TERROR"); // t - strcpy(name, "FUNCTION"); - - if (pBot) - { - memset(name, 0, sizeof(name)); // clear - strcpy(name, pBot->name); // copy name - - if (pBot->iTeam == 2) strcpy(team, "COUNTER"); - } - else - { - strcpy(team, "NONE"); - } - - printf ("RBPRINT->[%s '%s']-[Team %s] : %s\n", name, Function, team, msg); - - char msgForFile[512]; - memset(msgForFile, 0, sizeof(msgForFile)); // clear - sprintf (msgForFile, "RBPRINT->[%s '%s']-[Team %s] : %s\n", name, Function, team, msg); - rblog(msgForFile); + // Message format: + // Function name - [BOT NAME, BOT TEAM]: Message + char team[9]; + char name[32]; + + memset(team, 0, sizeof(team)); // clear + memset(name, 0, sizeof(name)); // clear + + strcpy(team, "TERROR"); // t + strcpy(name, "FUNCTION"); + + if (pBot) + { + memset(name, 0, sizeof(name)); // clear + strcpy(name, pBot->name); // copy name + + if (pBot->iTeam == 2) strcpy(team, "COUNTER"); + } + else + { + strcpy(team, "NONE"); + } + + printf("RBPRINT->[%s '%s']-[Team %s] : %s\n", name, Function, team, msg); + + char msgForFile[512]; + memset(msgForFile, 0, sizeof(msgForFile)); // clear + sprintf(msgForFile, "RBPRINT->[%s '%s']-[Team %s] : %s\n", name, Function, team, msg); + rblog(msgForFile); } - // from ChatENgine.cpp void cChatEngine::set_sentence(char csender[30], char csentence[128]) { - fprintf(stderr,"cChatEngine::set_sentence is called!\n") ; - exit(1) ; + fprintf(stderr, "cChatEngine::set_sentence is called!\n"); + exit(1); } // From bot.cpp // Can see Edict? -bool cBot::canSeeEntity (edict_t * pEntity) const +bool cBot::canSeeEntity(edict_t* pEntity) const { - TraceResult tr; - Vector start = pEdict->v.origin + pEdict->v.view_ofs; - Vector vDest = pEntity->v.origin; + TraceResult tr; + Vector start = pEdict->v.origin + pEdict->v.view_ofs; + Vector vDest = pEntity->v.origin; - // trace a line from bot's eyes to destination... - UTIL_TraceLine (start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); + // trace a line from bot's eyes to destination... + UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0) - { - // when the 'hit entity' is the same as pEntity, then its ok - if (tr.pHit == pEntity) - return true; // it is visible + if (tr.flFraction < 1.0) + { + // when the 'hit entity' is the same as pEntity, then its ok + if (tr.pHit == pEntity) + return true; // it is visible - return false; - } + return false; + } - return true; + return true; } -bool cBot::Defuse () +bool cBot::Defuse() { - fprintf(stderr,"cBot::Defuse is called!\n") ; - exit(1) ; + fprintf(stderr, "cBot::Defuse is called!\n"); + exit(1); } - // From IniParser.cpp // Parse IAD file: // Important Area Definition file void INI_PARSE_IAD() { - fprintf(stderr,"INI_PARSE_IAD is called!\n") ; - exit(1) ; -} - + fprintf(stderr, "INI_PARSE_IAD is called!\n"); + exit(1); +} \ No newline at end of file diff --git a/Bsp2Rbn/entity.cpp b/Bsp2Rbn/entity.cpp index 33996de..f8edaab 100644 --- a/Bsp2Rbn/entity.cpp +++ b/Bsp2Rbn/entity.cpp @@ -1,164 +1,159 @@ -// -// BSP_tool - botman's Half-Life BSP utilities -// -// (http://planethalflife.com/botman/) -// -// entity.cpp -// -// Copyright (C) 2001 - Jeffrey "botman" Broome -// -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// -// See the GNU General Public License for more details at: -// http://www.gnu.org/copyleft/gpl.html -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include - -#include -#include - -// chierie de /home/evyncke/cstrike/Realbot/HLSDK/multiplayer/cl_dll/util_vector.h definissant vec3_t comme Vector - - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "entity.h" - -vec3_t spawn_point; -float spawn_point_yaw; - -epair_t *pEpair = NULL; - -int Botman_num_entvars = 0; -Botman_entvars_t Botman_entvars[MAX_MAP_ENTITIES]; - - -void LoadEntVars(void) -{ - int ent_index = 0; - char *value; - - while (ent_index < num_entities) - { - value = ValueForKey(&entities[ent_index], "classname"); - - if (value[0]) - { - strcpy(Botman_entvars[Botman_num_entvars].classname, value); - - // initialize the default entvars fields... - Botman_entvars[Botman_num_entvars].origin[0] = 0.0f; - Botman_entvars[Botman_num_entvars].origin[1] = 0.0f; - Botman_entvars[Botman_num_entvars].origin[2] = 0.0f; - - Botman_entvars[Botman_num_entvars].angles[0] = 0.0f; - Botman_entvars[Botman_num_entvars].angles[1] = 0.0f; - Botman_entvars[Botman_num_entvars].angles[2] = 0.0f; - - Botman_entvars[Botman_num_entvars].rendermode = 0; - Botman_entvars[Botman_num_entvars].renderamt = 1.0f; - Botman_entvars[Botman_num_entvars].rendercolor[0] = 1.0f; - Botman_entvars[Botman_num_entvars].rendercolor[1] = 1.0f; - Botman_entvars[Botman_num_entvars].rendercolor[2] = 1.0f; - Botman_entvars[Botman_num_entvars].renderfx = 0; - - Botman_entvars[Botman_num_entvars].brush_model_index = 0; - - Botman_entvars[Botman_num_entvars].studio_model = NULL; - - value = ValueForKey(&entities[ent_index], "origin"); - if (value[0]) - { - sscanf(value, "%f %f %f", &Botman_entvars[Botman_num_entvars].origin[0], - &Botman_entvars[Botman_num_entvars].origin[1], - &Botman_entvars[Botman_num_entvars].origin[2]); - } - - value = ValueForKey(&entities[ent_index], "angle"); - if (value[0]) - { - // set the yaw angle... - sscanf(value, "%f", &Botman_entvars[Botman_num_entvars].angles[1]); - } - - value = ValueForKey(&entities[ent_index], "renderamt"); - if (value[0]) - { - int n_renderamt; - - sscanf(value, "%d", &n_renderamt); - Botman_entvars[Botman_num_entvars].renderamt = n_renderamt / 255.0f; - } - - value = ValueForKey(&entities[ent_index], "rendercolor"); - if (value[0]) - { - int n_color_r, n_color_b, n_color_g; - - sscanf(value, "%d %d %d", &n_color_r, &n_color_g, &n_color_b); - Botman_entvars[Botman_num_entvars].rendercolor[0] = n_color_r / 255.0f; - Botman_entvars[Botman_num_entvars].rendercolor[1] = n_color_g / 255.0f; - Botman_entvars[Botman_num_entvars].rendercolor[2] = n_color_b / 255.0f; - } - - value = ValueForKey(&entities[ent_index], "model"); - if (value[0]) - { - if (sscanf(value, "*%d", &Botman_entvars[Botman_num_entvars].brush_model_index) == 1) - { - dmodel_t *model; - - // calculate the origin for this brush model... - model = &dmodels[Botman_entvars[Botman_num_entvars].brush_model_index]; - - Botman_entvars[Botman_num_entvars].origin[0] = (model->mins[0] + model->maxs[0]) / 2.0f; - Botman_entvars[Botman_num_entvars].origin[1] = (model->mins[1] + model->maxs[1]) / 2.0f; - Botman_entvars[Botman_num_entvars].origin[2] = (model->mins[2] + model->maxs[2]) / 2.0f; - } - } - - if ((strcmp(Botman_entvars[Botman_num_entvars].classname, "func_button") == 0) || - (strcmp(Botman_entvars[Botman_num_entvars].classname, "func_door") == 0)) - { - // always render func_button and func_door entities... - Botman_entvars[Botman_num_entvars].renderamt = 255; - } - - Botman_num_entvars++; - } - - ent_index++; - } -} - - -void InitSpawnPoint(void) -{ - int ent_index; - int count = 0; - char *value; - int pick, loop; - - spawn_point[0] = 0.0; - spawn_point[1] = 0.0; - spawn_point[2] = 0.0; - spawn_point_yaw = 0.0; - -// if (config.spawnpoint[0] == 0) - return; // no spawn points configured, just return - -} +// +// BSP_tool - botman's Half-Life BSP utilities +// +// (http://planethalflife.com/botman/) +// +// entity.cpp +// +// Copyright (C) 2001 - Jeffrey "botman" Broome +// +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License for more details at: +// http://www.gnu.org/copyleft/gpl.html +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include + +#include +#include + +// chierie de /home/evyncke/cstrike/Realbot/HLSDK/multiplayer/cl_dll/util_vector.h definissant vec3_t comme Vector + +#include "cmdlib.h" +#include "mathlib.h" +#include "bspfile.h" +#include "entity.h" + +vec3_t spawn_point; +float spawn_point_yaw; + +epair_t* pEpair = NULL; + +int Botman_num_entvars = 0; +Botman_entvars_t Botman_entvars[MAX_MAP_ENTITIES]; + +void LoadEntVars(void) +{ + int ent_index = 0; + char* value; + + while (ent_index < num_entities) + { + value = ValueForKey(&entities[ent_index], "classname"); + + if (value[0]) + { + strcpy(Botman_entvars[Botman_num_entvars].classname, value); + + // initialize the default entvars fields... + Botman_entvars[Botman_num_entvars].origin[0] = 0.0f; + Botman_entvars[Botman_num_entvars].origin[1] = 0.0f; + Botman_entvars[Botman_num_entvars].origin[2] = 0.0f; + + Botman_entvars[Botman_num_entvars].angles[0] = 0.0f; + Botman_entvars[Botman_num_entvars].angles[1] = 0.0f; + Botman_entvars[Botman_num_entvars].angles[2] = 0.0f; + + Botman_entvars[Botman_num_entvars].rendermode = 0; + Botman_entvars[Botman_num_entvars].renderamt = 1.0f; + Botman_entvars[Botman_num_entvars].rendercolor[0] = 1.0f; + Botman_entvars[Botman_num_entvars].rendercolor[1] = 1.0f; + Botman_entvars[Botman_num_entvars].rendercolor[2] = 1.0f; + Botman_entvars[Botman_num_entvars].renderfx = 0; + + Botman_entvars[Botman_num_entvars].brush_model_index = 0; + + Botman_entvars[Botman_num_entvars].studio_model = NULL; + + value = ValueForKey(&entities[ent_index], "origin"); + if (value[0]) + { + sscanf(value, "%f %f %f", &Botman_entvars[Botman_num_entvars].origin[0], + &Botman_entvars[Botman_num_entvars].origin[1], + &Botman_entvars[Botman_num_entvars].origin[2]); + } + + value = ValueForKey(&entities[ent_index], "angle"); + if (value[0]) + { + // set the yaw angle... + sscanf(value, "%f", &Botman_entvars[Botman_num_entvars].angles[1]); + } + + value = ValueForKey(&entities[ent_index], "renderamt"); + if (value[0]) + { + int n_renderamt; + + sscanf(value, "%d", &n_renderamt); + Botman_entvars[Botman_num_entvars].renderamt = n_renderamt / 255.0f; + } + + value = ValueForKey(&entities[ent_index], "rendercolor"); + if (value[0]) + { + int n_color_r, n_color_b, n_color_g; + + sscanf(value, "%d %d %d", &n_color_r, &n_color_g, &n_color_b); + Botman_entvars[Botman_num_entvars].rendercolor[0] = n_color_r / 255.0f; + Botman_entvars[Botman_num_entvars].rendercolor[1] = n_color_g / 255.0f; + Botman_entvars[Botman_num_entvars].rendercolor[2] = n_color_b / 255.0f; + } + + value = ValueForKey(&entities[ent_index], "model"); + if (value[0]) + { + if (sscanf(value, "*%d", &Botman_entvars[Botman_num_entvars].brush_model_index) == 1) + { + dmodel_t* model; + + // calculate the origin for this brush model... + model = &dmodels[Botman_entvars[Botman_num_entvars].brush_model_index]; + + Botman_entvars[Botman_num_entvars].origin[0] = (model->mins[0] + model->maxs[0]) / 2.0f; + Botman_entvars[Botman_num_entvars].origin[1] = (model->mins[1] + model->maxs[1]) / 2.0f; + Botman_entvars[Botman_num_entvars].origin[2] = (model->mins[2] + model->maxs[2]) / 2.0f; + } + } + + if ((strcmp(Botman_entvars[Botman_num_entvars].classname, "func_button") == 0) || + (strcmp(Botman_entvars[Botman_num_entvars].classname, "func_door") == 0)) + { + // always render func_button and func_door entities... + Botman_entvars[Botman_num_entvars].renderamt = 255; + } + + Botman_num_entvars++; + } + + ent_index++; + } +} + +void InitSpawnPoint(void) +{ + int ent_index; + int count = 0; + char* value; + int pick, loop; + + spawn_point[0] = 0.0; + spawn_point[1] = 0.0; + spawn_point[2] = 0.0; + spawn_point_yaw = 0.0; + + // if (config.spawnpoint[0] == 0) + return; // no spawn points configured, just return +} \ No newline at end of file diff --git a/Bsp2Rbn/entity.h b/Bsp2Rbn/entity.h index d3b5828..52178ad 100644 --- a/Bsp2Rbn/entity.h +++ b/Bsp2Rbn/entity.h @@ -15,7 +15,7 @@ // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License for more details at: // http://www.gnu.org/copyleft/gpl.html @@ -33,17 +33,17 @@ typedef struct Botman_entvars_s { - char classname[64]; - vec3_t origin; - vec3_t angles; + char classname[64]; + vec3_t origin; + vec3_t angles; - int rendermode; - float renderamt; - vec3_t rendercolor; - int renderfx; + int rendermode; + float renderamt; + vec3_t rendercolor; + int renderfx; - int brush_model_index; - StudioModel *studio_model; + int brush_model_index; + StudioModel* studio_model; } Botman_entvars_t; extern int Botman_num_entvars; @@ -58,4 +58,3 @@ void LoadEntVars(void); void InitSpawnPoint(void); #endif - diff --git a/Bsp2Rbn/mathlib.cpp b/Bsp2Rbn/mathlib.cpp index 61f9815..31118ce 100644 --- a/Bsp2Rbn/mathlib.cpp +++ b/Bsp2Rbn/mathlib.cpp @@ -1,9 +1,9 @@ /*** * * Copyright (c) 1996-2001, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ @@ -19,143 +19,140 @@ // chierie de /home/evyncke/cstrike/Realbot/HLSDK/multiplayer/cl_dll/util_vector.h definissant vec3_t comme Vector - #include "cmdlib.h" #include "mathlib.h" -vec3_t vec3_origin = Vector(0,0,0); - +vec3_t vec3_origin = Vector(0, 0, 0); double Vector2DLength(vec3_t v) { - int i; - double length; + int i; + double length; - length = 0; - for (i=0 ; i< 2 ; i++) // ignore the Z axis - length += v[i]*v[i]; - length = (float)sqrt(length); // FIXME + length = 0; + for (i = 0; i < 2; i++) // ignore the Z axis + length += v[i] * v[i]; + length = (float)sqrt(length); // FIXME - return length; + return length; } double VectorLength(vec3_t v) { int i; double length; - + length = 0; - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); // FIXME + for (i = 0; i < 3; i++) + length += v[i] * v[i]; + length = sqrt(length); // FIXME return length; } - -int VectorCompare (vec3_t v1, vec3_t v2) +int VectorCompare(vec3_t v1, vec3_t v2) { int i; - - for (i=0 ; i<3 ; i++) - if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON) + + for (i = 0; i < 3; i++) + if (fabs(v1[i] - v2[i]) > EQUAL_EPSILON) return false; - + return true; } -vec_t Q_rint (vec_t in) +vec_t Q_rint(vec_t in) { - return floor (in + 0.5); + return floor(in + 0.5); } -void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc) +void VectorMA(vec3_t va, double scale, vec3_t vb, vec3_t vc) { - vc[0] = va[0] + scale*vb[0]; - vc[1] = va[1] + scale*vb[1]; - vc[2] = va[2] + scale*vb[2]; + vc[0] = va[0] + scale * vb[0]; + vc[1] = va[1] + scale * vb[1]; + vc[2] = va[2] + scale * vb[2]; } -void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross) { - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; + cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; + cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; + cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; } -vec_t _DotProduct (vec3_t v1, vec3_t v2) +vec_t _DotProduct(vec3_t v1, vec3_t v2) { - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; } -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) +void _VectorSubtract(vec3_t va, vec3_t vb, vec3_t out) { - out[0] = va[0]-vb[0]; - out[1] = va[1]-vb[1]; - out[2] = va[2]-vb[2]; + out[0] = va[0] - vb[0]; + out[1] = va[1] - vb[1]; + out[2] = va[2] - vb[2]; } -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) +void _VectorAdd(vec3_t va, vec3_t vb, vec3_t out) { - out[0] = va[0]+vb[0]; - out[1] = va[1]+vb[1]; - out[2] = va[2]+vb[2]; + out[0] = va[0] + vb[0]; + out[1] = va[1] + vb[1]; + out[2] = va[2] + vb[2]; } -void _VectorCopy (vec3_t in, vec3_t out) +void _VectorCopy(vec3_t in, vec3_t out) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } -void _VectorScale (vec3_t v, vec_t scale, vec3_t out) +void _VectorScale(vec3_t v, vec_t scale, vec3_t out) { out[0] = v[0] * scale; out[1] = v[1] * scale; out[2] = v[2] * scale; } -vec_t VectorNormalize (vec3_t v) +vec_t VectorNormalize(vec3_t v) { int i; double length; -if ( fabs(v[1] - 0.000215956) < 0.0001) -i=1; + if (fabs(v[1] - 0.000215956) < 0.0001) + i = 1; length = 0; - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); + for (i = 0; i < 3; i++) + length += v[i] * v[i]; + length = sqrt(length); if (length == 0) return 0; - - for (i=0 ; i< 3 ; i++) - v[i] /= length; + + for (i = 0; i < 3; i++) + v[i] /= length; return length; } -void VectorInverse (vec3_t v) +void VectorInverse(vec3_t v) { v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; } -void ClearBounds (vec3_t mins, vec3_t maxs) +void ClearBounds(vec3_t mins, vec3_t maxs) { mins[0] = mins[1] = mins[2] = 99999; maxs[0] = maxs[1] = maxs[2] = -99999; } -void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) +void AddPointToBounds(vec3_t v, vec3_t mins, vec3_t maxs) { int i; vec_t val; - for (i=0 ; i<3 ; i++) + for (i = 0; i < 3; i++) { val = v[i]; if (val < mins[i]) @@ -165,158 +162,151 @@ void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) } } -void AngleMatrix (const vec3_t angles, float (*matrix)[4] ) +void AngleMatrix(const vec3_t angles, float(*matrix)[4]) { float angle; float sr, sp, sy, cr, cp, cy; - - angle = angles[2] * (Q_PI*2 / 360); + + angle = angles[2] * (Q_PI * 2 / 360); sy = sin(angle); cy = cos(angle); - angle = angles[1] * (Q_PI*2 / 360); + angle = angles[1] * (Q_PI * 2 / 360); sp = sin(angle); cp = cos(angle); - angle = angles[0] * (Q_PI*2 / 360); + angle = angles[0] * (Q_PI * 2 / 360); sr = sin(angle); cr = cos(angle); // matrix = (Z * Y) * X - matrix[0][0] = cp*cy; - matrix[1][0] = cp*sy; + matrix[0][0] = cp * cy; + matrix[1][0] = cp * sy; matrix[2][0] = -sp; - matrix[0][1] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[2][1] = sr*cp; - matrix[0][2] = (cr*sp*cy+-sr*-sy); - matrix[1][2] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; + matrix[0][1] = sr * sp * cy + cr * -sy; + matrix[1][1] = sr * sp * sy + cr * cy; + matrix[2][1] = sr * cp; + matrix[0][2] = (cr * sp * cy + -sr * -sy); + matrix[1][2] = (cr * sp * sy + -sr * cy); + matrix[2][2] = cr * cp; matrix[0][3] = 0.0; matrix[1][3] = 0.0; matrix[2][3] = 0.0; } -void AngleIMatrix (const vec3_t angles, float matrix[3][4] ) +void AngleIMatrix(const vec3_t angles, float matrix[3][4]) { float angle; float sr, sp, sy, cr, cp, cy; - - angle = angles[2] * (Q_PI*2 / 360); + + angle = angles[2] * (Q_PI * 2 / 360); sy = sin(angle); cy = cos(angle); - angle = angles[1] * (Q_PI*2 / 360); + angle = angles[1] * (Q_PI * 2 / 360); sp = sin(angle); cp = cos(angle); - angle = angles[0] * (Q_PI*2 / 360); + angle = angles[0] * (Q_PI * 2 / 360); sr = sin(angle); cr = cos(angle); // matrix = (Z * Y) * X - matrix[0][0] = cp*cy; - matrix[0][1] = cp*sy; + matrix[0][0] = cp * cy; + matrix[0][1] = cp * sy; matrix[0][2] = -sp; - matrix[1][0] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[1][2] = sr*cp; - matrix[2][0] = (cr*sp*cy+-sr*-sy); - matrix[2][1] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; + matrix[1][0] = sr * sp * cy + cr * -sy; + matrix[1][1] = sr * sp * sy + cr * cy; + matrix[1][2] = sr * cp; + matrix[2][0] = (cr * sp * cy + -sr * -sy); + matrix[2][1] = (cr * sp * sy + -sr * cy); + matrix[2][2] = cr * cp; matrix[0][3] = 0.0; matrix[1][3] = 0.0; matrix[2][3] = 0.0; } -void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]) +void R_ConcatTransforms(const float in1[3][4], const float in2[3][4], float out[3][4]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; + in1[0][2] * in2[2][1]; out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; + in1[0][2] * in2[2][2]; out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + - in1[0][2] * in2[2][3] + in1[0][3]; + in1[0][2] * in2[2][3] + in1[0][3]; out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; + in1[1][2] * in2[2][0]; out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; + in1[1][2] * in2[2][1]; out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; + in1[1][2] * in2[2][2]; out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + - in1[1][2] * in2[2][3] + in1[1][3]; + in1[1][2] * in2[2][3] + in1[1][3]; out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; + in1[2][2] * in2[2][0]; out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; + in1[2][2] * in2[2][1]; out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; + in1[2][2] * in2[2][2]; out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + - in1[2][2] * in2[2][3] + in1[2][3]; + in1[2][2] * in2[2][3] + in1[2][3]; } - - -void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out) +void VectorRotate(const vec3_t in1, const float in2[3][4], vec3_t out) { out[0] = DotProduct(in1, in2[0]); out[1] = DotProduct(in1, in2[1]); out[2] = DotProduct(in1, in2[2]); } - // rotate by the inverse of the matrix -void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out) +void VectorIRotate(const vec3_t in1, const float in2[3][4], vec3_t out) { - out[0] = in1[0]*in2[0][0] + in1[1]*in2[1][0] + in1[2]*in2[2][0]; - out[1] = in1[0]*in2[0][1] + in1[1]*in2[1][1] + in1[2]*in2[2][1]; - out[2] = in1[0]*in2[0][2] + in1[1]*in2[1][2] + in1[2]*in2[2][2]; + out[0] = in1[0] * in2[0][0] + in1[1] * in2[1][0] + in1[2] * in2[2][0]; + out[1] = in1[0] * in2[0][1] + in1[1] * in2[1][1] + in1[2] * in2[2][1]; + out[2] = in1[0] * in2[0][2] + in1[1] * in2[1][2] + in1[2] * in2[2][2]; } - -void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out) +void VectorTransform(const vec3_t in1, const float in2[3][4], vec3_t out) { out[0] = DotProduct(in1, in2[0]) + in2[0][3]; - out[1] = DotProduct(in1, in2[1]) + in2[1][3]; - out[2] = DotProduct(in1, in2[2]) + in2[2][3]; + out[1] = DotProduct(in1, in2[1]) + in2[1][3]; + out[2] = DotProduct(in1, in2[2]) + in2[2][3]; } - // WARNING!!! the "vector" parameter should be NORMALIZED!!! float DistanceToIntersection(const vec3_t origin, const vec3_t vector, - const vec3_t plane_origin, const vec3_t plane_normal) + const vec3_t plane_origin, const vec3_t plane_normal) { - float d = -(DotProduct(plane_normal, plane_origin)); - - float numerator = DotProduct(plane_normal, origin) + d; - float denominator = DotProduct(plane_normal, vector); - - if (fabs(denominator) < 0.00001) - return (-1.0f); // normal is orthogonal to vector, no intersection - - return -(numerator/denominator); -} + float d = -(DotProduct(plane_normal, plane_origin)); + + float numerator = DotProduct(plane_normal, origin) + d; + float denominator = DotProduct(plane_normal, vector); + if (fabs(denominator) < 0.00001) + return (-1.0f); // normal is orthogonal to vector, no intersection + + return -(numerator / denominator); +} // return TRUE or FALSE if vector intersects a plane... bool VectorIntersectPlane(const vec3_t origin, const vec3_t vector, - const vec3_t plane_origin, const vec3_t plane_normal, - vec3_t intersect_point) + const vec3_t plane_origin, const vec3_t plane_normal, + vec3_t intersect_point) { - float dist; - vec3_t v_temp; + float dist; + vec3_t v_temp; - dist = DistanceToIntersection(origin, vector, plane_origin, plane_normal); + dist = DistanceToIntersection(origin, vector, plane_origin, plane_normal); - if (dist < 0) - return FALSE; + if (dist < 0) + return FALSE; - VectorScale(vector, dist, v_temp); - VectorAdd(origin, v_temp, intersect_point); + VectorScale(vector, dist, v_temp); + VectorAdd(origin, v_temp, intersect_point); - return TRUE; + return TRUE; } - -void AngleQuaternion( const vec3_t angles, vec4_t quaternion ) +void AngleQuaternion(const vec3_t angles, vec4_t quaternion) { float angle; float sr, sp, sy, cr, cp, cy; @@ -332,15 +322,14 @@ void AngleQuaternion( const vec3_t angles, vec4_t quaternion ) sr = sin(angle); cr = cos(angle); - quaternion[0] = sr*cp*cy-cr*sp*sy; // X - quaternion[1] = cr*sp*cy+sr*cp*sy; // Y - quaternion[2] = cr*cp*sy-sr*sp*cy; // Z - quaternion[3] = cr*cp*cy+sr*sp*sy; // W + quaternion[0] = sr * cp * cy - cr * sp * sy; // X + quaternion[1] = cr * sp * cy + sr * cp * sy; // Y + quaternion[2] = cr * cp * sy - sr * sp * cy; // Z + quaternion[3] = cr * cp * cy + sr * sp * sy; // W } -void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ) +void QuaternionMatrix(const vec4_t quaternion, float(*matrix)[4]) { - matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2]; matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2]; matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1]; @@ -354,7 +343,7 @@ void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ) matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1]; } -void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) +void QuaternionSlerp(const vec4_t p, vec4_t q, float t, vec4_t qt) { int i; float omega, cosom, sinom, sclp, sclq; @@ -363,8 +352,8 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) float a = 0; float b = 0; for (i = 0; i < 4; i++) { - a += (p[i]-q[i])*(p[i]-q[i]); - b += (p[i]+q[i])*(p[i]+q[i]); + a += (p[i] - q[i]) * (p[i] - q[i]); + b += (p[i] + q[i]) * (p[i] + q[i]); } if (a > b) { for (i = 0; i < 4; i++) { @@ -372,14 +361,14 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) } } - cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; + cosom = p[0] * q[0] + p[1] * q[1] + p[2] * q[2] + p[3] * q[3]; if ((1.0 + cosom) > 0.00000001) { if ((1.0 - cosom) > 0.00000001) { - omega = acos( cosom ); - sinom = sin( omega ); - sclp = sin( (1.0 - t)*omega) / sinom; - sclq = sin( t*omega ) / sinom; + omega = acos(cosom); + sinom = sin(omega); + sclp = sin((1.0 - t) * omega) / sinom; + sclq = sin(t * omega) / sinom; } else { sclp = 1.0 - t; @@ -394,12 +383,10 @@ void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) qt[1] = p[0]; qt[2] = -p[3]; qt[3] = p[2]; - sclp = sin( (1.0 - t) * 0.5 * Q_PI); - sclq = sin( t * 0.5 * Q_PI); + sclp = sin((1.0 - t) * 0.5 * Q_PI); + sclq = sin(t * 0.5 * Q_PI); for (i = 0; i < 3; i++) { qt[i] = sclp * p[i] + sclq * qt[i]; } } -} - - +} \ No newline at end of file diff --git a/Bsp2Rbn/mathlib.h b/Bsp2Rbn/mathlib.h index 50f6ab6..b356b42 100644 --- a/Bsp2Rbn/mathlib.h +++ b/Bsp2Rbn/mathlib.h @@ -1,97 +1,95 @@ -/*** -* -* Copyright (c) 1996-2001, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef __MATHLIB__ -#define __MATHLIB__ - -// mathlib.h - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DOUBLEVEC_T -typedef double vec_t; -#else -typedef float vec_t; -#endif -//typedef vec_t vec3_t[3]; // x,y,z -typedef vec_t vec4_t[4]; // x,y,z,w - -#define SIDE_FRONT 0 -#define SIDE_ON 2 -#define SIDE_BACK 1 -#define SIDE_CROSS -2 - -#define Q_PI 3.14159265358979323846 - -extern vec3_t vec3_origin; - -// Use this definition globally -#define ON_EPSILON 0.01 -#define EQUAL_EPSILON 0.001 - -int VectorCompare (vec3_t v1, vec3_t v2); - -#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) -#define VectorFill(a,b) { (a)[0]=(b); (a)[1]=(b); (a)[2]=(b);} -#define VectorAvg(a) ( ( (a)[0] + (a)[1] + (a)[2] ) / 3 ) -#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];} -#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];} -#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];} -#define VectorScale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];(c)[2]=(b)*(a)[2];} - -vec_t Q_rint (vec_t in); -vec_t _DotProduct (vec3_t v1, vec3_t v2); -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); -void _VectorCopy (vec3_t in, vec3_t out); -void _VectorScale (vec3_t v, vec_t scale, vec3_t out); - -double Vector2DLength(vec3_t v); -double VectorLength(vec3_t v); - -void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc); - -void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); -vec_t VectorNormalize (vec3_t v); -void VectorInverse (vec3_t v); - -void ClearBounds (vec3_t mins, vec3_t maxs); -void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); - -void AngleMatrix (const vec3_t angles, float matrix[3][4] ); -void AngleIMatrix (const vec3_t angles, float matrix[3][4] ); -void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]); - -void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out); -void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out); - -void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out); - -float DistanceToIntersection(const vec3_t origin, const vec3_t vector, - const vec3_t plane_origin, const vec3_t plane_normal); -bool VectorIntersectPlane(const vec3_t origin, const vec3_t vector, - const vec3_t plane_origin, const vec3_t plane_normal, - vec3_t intersect_point); - -void AngleQuaternion( const vec3_t angles, vec4_t quaternion ); -void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ); -void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); - - -#ifdef __cplusplus -} -#endif - -#endif +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ +#ifndef __MATHLIB__ +#define __MATHLIB__ + +// mathlib.h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DOUBLEVEC_T + typedef double vec_t; +#else + typedef float vec_t; +#endif + //typedef vec_t vec3_t[3]; // x,y,z + typedef vec_t vec4_t[4]; // x,y,z,w + +#define SIDE_FRONT 0 +#define SIDE_ON 2 +#define SIDE_BACK 1 +#define SIDE_CROSS -2 + +#define Q_PI 3.14159265358979323846 + + extern vec3_t vec3_origin; + + // Use this definition globally +#define ON_EPSILON 0.01 +#define EQUAL_EPSILON 0.001 + + int VectorCompare(vec3_t v1, vec3_t v2); + +#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) +#define VectorFill(a,b) { (a)[0]=(b); (a)[1]=(b); (a)[2]=(b);} +#define VectorAvg(a) ( ( (a)[0] + (a)[1] + (a)[2] ) / 3 ) +#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];} +#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];} +#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];} +#define VectorScale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];(c)[2]=(b)*(a)[2];} + + vec_t Q_rint(vec_t in); + vec_t _DotProduct(vec3_t v1, vec3_t v2); + void _VectorSubtract(vec3_t va, vec3_t vb, vec3_t out); + void _VectorAdd(vec3_t va, vec3_t vb, vec3_t out); + void _VectorCopy(vec3_t in, vec3_t out); + void _VectorScale(vec3_t v, vec_t scale, vec3_t out); + + double Vector2DLength(vec3_t v); + double VectorLength(vec3_t v); + + void VectorMA(vec3_t va, double scale, vec3_t vb, vec3_t vc); + + void CrossProduct(vec3_t v1, vec3_t v2, vec3_t cross); + vec_t VectorNormalize(vec3_t v); + void VectorInverse(vec3_t v); + + void ClearBounds(vec3_t mins, vec3_t maxs); + void AddPointToBounds(vec3_t v, vec3_t mins, vec3_t maxs); + + void AngleMatrix(const vec3_t angles, float matrix[3][4]); + void AngleIMatrix(const vec3_t angles, float matrix[3][4]); + void R_ConcatTransforms(const float in1[3][4], const float in2[3][4], float out[3][4]); + + void VectorIRotate(const vec3_t in1, const float in2[3][4], vec3_t out); + void VectorRotate(const vec3_t in1, const float in2[3][4], vec3_t out); + + void VectorTransform(const vec3_t in1, const float in2[3][4], vec3_t out); + + float DistanceToIntersection(const vec3_t origin, const vec3_t vector, + const vec3_t plane_origin, const vec3_t plane_normal); + bool VectorIntersectPlane(const vec3_t origin, const vec3_t vector, + const vec3_t plane_origin, const vec3_t plane_normal, + vec3_t intersect_point); + + void AngleQuaternion(const vec3_t angles, vec4_t quaternion); + void QuaternionMatrix(const vec4_t quaternion, float(*matrix)[4]); + void QuaternionSlerp(const vec4_t p, vec4_t q, float t, vec4_t qt); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Bsp2Rbn/paklib.h b/Bsp2Rbn/paklib.h index aec01b1..f9bcc41 100644 --- a/Bsp2Rbn/paklib.h +++ b/Bsp2Rbn/paklib.h @@ -15,7 +15,7 @@ // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License for more details at: // http://www.gnu.org/copyleft/gpl.html @@ -34,13 +34,13 @@ header. This is seperated into three, 4 byte blocks as follows: -Header- - Signature (4 bytes of char, equals 'PACK' in ALL cases. If it doesn't then - it is not considered a pack file.) + it is not considered a pack file.) - Directory Offset (4 bytes, single integer. Specifies the position of the - first of X Directory areas in the file.) + first of X Directory areas in the file.) - Directory Length (4 bytes, single integer. Specifies the length of the X - dirextory areas.) + dirextory areas.) (Note: We can find the number X by dividing the length by the 64, because each directory section is 64 bytes. If the mod of this division is not zero then @@ -49,51 +49,51 @@ header. This is seperated into three, 4 byte blocks as follows: -Directory section- - File name (56 bytes of char, specifies the name of the file pointed to by - the File Position data. Includes path info. ie maps/base1.bsp) + the File Position data. Includes path info. ie maps/base1.bsp) - File Position (4 bytes, single integer. The first byte(address) of the - file named by File Name) + file named by File Name) - File Length (4 bytes, single integer. The length of the file named by - File Name) + File Name) Notes: Normally, the header is at the start of the file and the X number of directory areas at the very end. The file data is usually in between. - ________________________________ - HEADER starts here ---> | - Signature (4 bytes) | - | - Directory Offset (4 bytes) | - | - Directory Length (4 bytes) | - |________________________________| - FILE DATA starts here ---> | | - | | - | BINARY DATA | - | (pointed to by the | - | File Position data) | - | | - ~~~~~ ~~~~~ - ~~~~~ ~~~~~ - | | - | | - | | - | | - |________________________________| + ________________________________ + HEADER starts here ---> | - Signature (4 bytes) | + | - Directory Offset (4 bytes) | + | - Directory Length (4 bytes) | + |________________________________| + FILE DATA starts here ---> | | + | | + | BINARY DATA | + | (pointed to by the | + | File Position data) | + | | + ~~~~~ ~~~~~ + ~~~~~ ~~~~~ + | | + | | + | | + | | + |________________________________| DIRECTORY SECTION starts here ---> | - File name (56 bytes) | - | - File Position (4 bytes) | - | - File Length (4 bytes) | - |________________________________| - | - File name (56 bytes) | - | - File Position (4 bytes) | - | - File Length (4 bytes) | - |________________________________| - | | - ~~~~~ ~~~~~ - ~~~~~ ~~~~~ - |________________________________| - | - File name (56 bytes) | - | - File Position (4 bytes) | - | - File Length (4 bytes) | - |________________________________| + | - File Position (4 bytes) | + | - File Length (4 bytes) | + |________________________________| + | - File name (56 bytes) | + | - File Position (4 bytes) | + | - File Length (4 bytes) | + |________________________________| + | | + ~~~~~ ~~~~~ + ~~~~~ ~~~~~ + |________________________________| + | - File name (56 bytes) | + | - File Position (4 bytes) | + | - File Length (4 bytes) | + |________________________________| */ // @@ -102,34 +102,33 @@ DIRECTORY SECTION starts here ---> | - File name (56 bytes) | typedef struct { - char identification[4]; // should be PACK or KCAP - int dir_offset; // directory offset - int dir_length; // directory length + char identification[4]; // should be PACK or KCAP + int dir_offset; // directory offset + int dir_length; // directory length } pakheader_t; typedef struct { - char filename[56]; // PAK entry filename - int file_pos; // PAK entry file position - int file_length; // PAK entry length + char filename[56]; // PAK entry filename + int file_pos; // PAK entry file position + int file_length; // PAK entry length } pakinfo_t; typedef struct pakconfig_s { - FILE *pakhandle; - pakheader_t pakheader; - pakinfo_t *pakinfo; - int num_entries; - struct pakconfig_s *next_config; + FILE* pakhandle; + pakheader_t pakheader; + pakinfo_t* pakinfo; + int num_entries; + struct pakconfig_s* next_config; } pakconfig_t; -FILE *P_OpenPak (char *filename); -int P_ReadPakHeader(FILE *pakhandle, pakheader_t *pakheader); -void P_ReadPakInfo(FILE *pakhandle, long offset, int num_entries, pakinfo_t *pakinfo); -void P_ReadPakItem(FILE *pakhandle, pakinfo_t *pakinfo, void *buffer); +FILE* P_OpenPak(char* filename); +int P_ReadPakHeader(FILE* pakhandle, pakheader_t* pakheader); +void P_ReadPakInfo(FILE* pakhandle, long offset, int num_entries, pakinfo_t* pakinfo); +void P_ReadPakItem(FILE* pakhandle, pakinfo_t* pakinfo, void* buffer); void Cmd_PakFile(void); -bool SearchPakFilename(char *filename, pakconfig_t **pakconfig, pakinfo_t **pakinfo); -bool LoadPakBSPFile(char *filename); +bool SearchPakFilename(char* filename, pakconfig_t** pakconfig, pakinfo_t** pakinfo); +bool LoadPakBSPFile(char* filename); #endif - diff --git a/Bsp2Rbn/scriplib.cpp b/Bsp2Rbn/scriplib.cpp index 2865066..b55e775 100644 --- a/Bsp2Rbn/scriplib.cpp +++ b/Bsp2Rbn/scriplib.cpp @@ -2,8 +2,8 @@ * * Copyright (c) 1998, Valve LLC. All rights reserved. * -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ @@ -18,21 +18,21 @@ /* ============================================================================= - PARSING STUFF + PARSING STUFF ============================================================================= */ typedef struct { - char filename[1024]; - char *buffer,*script_p,*end_p; - int line; + char filename[1024]; + char* buffer, * script_p, * end_p; + int line; } script_t; #define MAX_INCLUDES 8 script_t scriptstack[MAX_INCLUDES]; -script_t *script; +script_t* script; int scriptline; char token[MAXTOKEN]; @@ -44,64 +44,61 @@ qboolean tokenready; // only true if UnGetToken was just cal AddScriptToStack ============== */ -void AddScriptToStack (char *filename) +void AddScriptToStack(char* filename) { - int size; + int size; - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, ExpandPath (filename) ); + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error("script file exceeded MAX_INCLUDES"); + strcpy(script->filename, ExpandPath(filename)); - size = LoadFile (script->filename, (void **)&script->buffer); + size = LoadFile(script->filename, (void**)&script->buffer); -// printf ("entering %s\n", script->filename); + // printf ("entering %s\n", script->filename); - script->line = 1; + script->line = 1; - script->script_p = script->buffer; - script->end_p = script->buffer + size; + script->script_p = script->buffer; + script->end_p = script->buffer + size; } - /* ============== LoadScriptFile ============== */ -void LoadScriptFile (char *filename) +void LoadScriptFile(char* filename) { - script = scriptstack; - AddScriptToStack (filename); + script = scriptstack; + AddScriptToStack(filename); - endofscript = false; - tokenready = false; + endofscript = false; + tokenready = false; } - /* ============== ParseFromMemory ============== */ -void ParseFromMemory (char *buffer, int size) +void ParseFromMemory(char* buffer, int size) { - script = scriptstack; - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, "memory buffer" ); - - script->buffer = buffer; - script->line = 1; - script->script_p = script->buffer; - script->end_p = script->buffer + size; - - endofscript = false; - tokenready = false; + script = scriptstack; + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error("script file exceeded MAX_INCLUDES"); + strcpy(script->filename, "memory buffer"); + + script->buffer = buffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + + endofscript = false; + tokenready = false; } - /* ============== UnGetToken @@ -116,33 +113,32 @@ GetToken (false); could cross a line boundary. ============== */ -void UnGetToken (void) +void UnGetToken(void) { - tokenready = true; + tokenready = true; } - -qboolean EndOfScript (qboolean crossline) +qboolean EndOfScript(qboolean crossline) { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline+1); - - if (!strcmp (script->filename, "memory buffer")) - { - endofscript = true; - return false; - } - - free (script->buffer); - if (script == scriptstack+1) - { - endofscript = true; - return false; - } - script--; - scriptline = script->line; -// printf ("returning to %s\n", script->filename); - return GetToken (crossline); + if (!crossline) + Error("Line %i is incomplete\n", scriptline + 1); + + if (!strcmp(script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + free(script->buffer); + if (script == scriptstack + 1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + // printf ("returning to %s\n", script->filename); + return GetToken(crossline); } /* @@ -150,92 +146,91 @@ qboolean EndOfScript (qboolean crossline) GetToken ============== */ -qboolean GetToken (qboolean crossline) +qboolean GetToken(qboolean crossline) { - char *token_p; + char* token_p; - if (tokenready) // is a token allready waiting? - { - tokenready = false; - return true; - } + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } - if (script->script_p >= script->end_p) - return EndOfScript (crossline); + if (script->script_p >= script->end_p) + return EndOfScript(crossline); -// -// skip space -// + // + // skip space + // skipspace: - while (*script->script_p <= 32) - { - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - if (*script->script_p++ == '\n') - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline+1); - scriptline = script->line++; - } - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - - if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field - (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline+1); - while (*script->script_p++ != '\n') - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - scriptline = script->line++; - goto skipspace; - } - -// -// copy token -// - token_p = token; - - if (*script->script_p == '"') - { - // quoted token - script->script_p++; - while (*script->script_p != '"') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - script->script_p++; - } - else // regular token - while ( *script->script_p > 32 && *script->script_p != ';') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - - *token_p = 0; - - if (!strcmp (token, "$include")) - { - GetToken (false); - AddScriptToStack (token); - return GetToken (crossline); - } - - return true; + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + return EndOfScript(crossline); + if (*script->script_p++ == '\n') + { + if (!crossline) + Error("Line %i is incomplete\n", scriptline + 1); + scriptline = script->line++; + } + } + + if (script->script_p >= script->end_p) + return EndOfScript(crossline); + + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p) + 1) == '/')) // also make // a comment field + { + if (!crossline) + Error("Line %i is incomplete\n", scriptline + 1); + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return EndOfScript(crossline); + scriptline = script->line++; + goto skipspace; + } + + // + // copy token + // + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error("Token too large on line %i\n", scriptline); + } + script->script_p++; + } + else // regular token + while (*script->script_p > 32 && *script->script_p != ';') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error("Token too large on line %i\n", scriptline); + } + + *token_p = 0; + + if (!strcmp(token, "$include")) + { + GetToken(false); + AddScriptToStack(token); + return GetToken(crossline); + } + + return true; } - /* ============== TokenAvailable @@ -243,28 +238,26 @@ TokenAvailable Returns true if there is another token on the line ============== */ -qboolean TokenAvailable (void) +qboolean TokenAvailable(void) { - char *search_p; + char* search_p; - search_p = script->script_p; + search_p = script->script_p; - if (search_p >= script->end_p) - return false; + if (search_p >= script->end_p) + return false; - while ( *search_p <= 32) - { - if (*search_p == '\n') - return false; - search_p++; - if (search_p == script->end_p) - return false; + while (*search_p <= 32) + { + if (*search_p == '\n') + return false; + search_p++; + if (search_p == script->end_p) + return false; + } - } - - if (*search_p == ';') - return false; - - return true; -} + if (*search_p == ';') + return false; + return true; +} \ No newline at end of file diff --git a/Bsp2Rbn/scriplib.h b/Bsp2Rbn/scriplib.h index 3200c13..306ba99 100644 --- a/Bsp2Rbn/scriplib.h +++ b/Bsp2Rbn/scriplib.h @@ -2,8 +2,8 @@ * * Copyright (c) 1998, Valve LLC. All rights reserved. * -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * ****/ @@ -17,22 +17,19 @@ #ifndef SCRIPLIB_H #define SCRIPLIB_H - #define MAXTOKEN 4096 extern char token[MAXTOKEN]; -extern char *scriptbuffer,*script_p,*scriptend_p; +extern char* scriptbuffer, * script_p, * scriptend_p; extern int grabbed; extern int scriptline; extern qboolean endofscript; +void LoadScriptFile(char* filename); +void ParseFromMemory(char* buffer, int size); -void LoadScriptFile (char *filename); -void ParseFromMemory (char *buffer, int size); - -qboolean GetToken (qboolean crossline); -void UnGetToken (void); -qboolean TokenAvailable (void); +qboolean GetToken(qboolean crossline); +void UnGetToken(void); +qboolean TokenAvailable(void); #endif // SCRIPLIB_H - diff --git a/Bsp2Rbn/studio_model.h b/Bsp2Rbn/studio_model.h index 3fac790..ad08082 100644 --- a/Bsp2Rbn/studio_model.h +++ b/Bsp2Rbn/studio_model.h @@ -1,91 +1,90 @@ -/*** -* -* Copyright (c) 1996-2001, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef __MATHLIB__ -#include "mathlib.h" -#endif - -#ifndef _STUDIO_H_ -#include "studio.h" -#endif - -#ifndef __STUDIO_MODEL__ -#define __STUDIO_MODEL__ - -typedef unsigned char byte; - -class StudioModel -{ -public: - bool Init( char *modelname ); - void DrawModel( void ); - void AdvanceFrame( float dt ); - - void ExtractBbox( float *mins, float *maxs ); - - int SetSequence( int iSequence ); - int GetSequence( void ); - void GetSequenceInfo( float *pflFrameRate, float *pflGroundSpeed ); - - float SetController( int iController, float flValue ); - float SetMouth( float flValue ); - float SetBlending( int iBlender, float flValue ); - int SetBodygroup( int iGroup, int iValue ); - int SetSkin( int iValue ); - -private: - // entity settings - vec3_t m_origin; - vec3_t m_angles; - int m_sequence; // sequence index - float m_frame; // frame - int m_bodynum; // bodypart selection - int m_skinnum; // skin group selection - byte m_controller[4]; // bone controllers - byte m_blending[2]; // animation blending - byte m_mouth; // mouth position - - // internal data - studiohdr_t *m_pstudiohdr; - mstudiomodel_t *m_pmodel; - - studiohdr_t *m_ptexturehdr; - studioseqhdr_t *m_panimhdr[32]; - - vec4_t m_adj; // FIX: non persistant, make static - - studiohdr_t *LoadModel( char *modelname ); - studioseqhdr_t *LoadDemandSequences( char *modelname ); - - void CalcBoneAdj( void ); - void CalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *q ); - void CalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *pos ); - void CalcRotations ( vec3_t *pos, vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f ); - mstudioanim_t *GetAnim( mstudioseqdesc_t *pseqdesc ); - void SlerpBones( vec4_t q1[], vec3_t pos1[], vec4_t q2[], vec3_t pos2[], float s ); - void SetUpBones ( void ); - - void DrawPoints( void ); - - void Lighting (float *lv, int bone, int flags, vec3_t normal); - void Chrome (int *chrome, int bone, vec3_t normal); - - void SetupLighting( void ); - - void SetupModel ( int bodypart ); - - void UploadTexture( mstudiotexture_t *ptexture, byte *data, byte *pal ); -}; - -extern vec3_t g_vright; // needs to be set to viewer's right in order for chrome to work -extern float g_lambert; // modifier for pseudo-hemispherical lighting - -#endif +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ +#ifndef __MATHLIB__ +#include "mathlib.h" +#endif + +#ifndef _STUDIO_H_ +#include "studio.h" +#endif + +#ifndef __STUDIO_MODEL__ +#define __STUDIO_MODEL__ + +typedef unsigned char byte; + +class StudioModel +{ +public: + bool Init(char* modelname); + void DrawModel(void); + void AdvanceFrame(float dt); + + void ExtractBbox(float* mins, float* maxs); + + int SetSequence(int iSequence); + int GetSequence(void); + void GetSequenceInfo(float* pflFrameRate, float* pflGroundSpeed); + + float SetController(int iController, float flValue); + float SetMouth(float flValue); + float SetBlending(int iBlender, float flValue); + int SetBodygroup(int iGroup, int iValue); + int SetSkin(int iValue); + +private: + // entity settings + vec3_t m_origin; + vec3_t m_angles; + int m_sequence; // sequence index + float m_frame; // frame + int m_bodynum; // bodypart selection + int m_skinnum; // skin group selection + byte m_controller[4]; // bone controllers + byte m_blending[2]; // animation blending + byte m_mouth; // mouth position + + // internal data + studiohdr_t* m_pstudiohdr; + mstudiomodel_t* m_pmodel; + + studiohdr_t* m_ptexturehdr; + studioseqhdr_t* m_panimhdr[32]; + + vec4_t m_adj; // FIX: non persistant, make static + + studiohdr_t* LoadModel(char* modelname); + studioseqhdr_t* LoadDemandSequences(char* modelname); + + void CalcBoneAdj(void); + void CalcBoneQuaternion(int frame, float s, mstudiobone_t* pbone, mstudioanim_t* panim, float* q); + void CalcBonePosition(int frame, float s, mstudiobone_t* pbone, mstudioanim_t* panim, float* pos); + void CalcRotations(vec3_t* pos, vec4_t* q, mstudioseqdesc_t* pseqdesc, mstudioanim_t* panim, float f); + mstudioanim_t* GetAnim(mstudioseqdesc_t* pseqdesc); + void SlerpBones(vec4_t q1[], vec3_t pos1[], vec4_t q2[], vec3_t pos2[], float s); + void SetUpBones(void); + + void DrawPoints(void); + + void Lighting(float* lv, int bone, int flags, vec3_t normal); + void Chrome(int* chrome, int bone, vec3_t normal); + + void SetupLighting(void); + + void SetupModel(int bodypart); + + void UploadTexture(mstudiotexture_t* ptexture, byte* data, byte* pal); +}; + +extern vec3_t g_vright; // needs to be set to viewer's right in order for chrome to work +extern float g_lambert; // modifier for pseudo-hemispherical lighting + +#endif diff --git a/Bsp2Rbn/trace.cpp b/Bsp2Rbn/trace.cpp index a132597..34a11f4 100644 --- a/Bsp2Rbn/trace.cpp +++ b/Bsp2Rbn/trace.cpp @@ -40,95 +40,94 @@ typedef vec_t vec3_t[3]; #define MAX(a,b) (a > b ? a : b) #define MIN(a,b) (a < b ? a : b) -dnode_t *gNode; +dnode_t* gNode; // return the leaf node for a point in 3D space... for model rooted on nodenum -static dleaf_t *TracePointInHull0Leaf(const int num, const vec3_t point) +static dleaf_t* TracePointInHull0Leaf(const int num, const vec3_t point) { - vec_t d; - dnode_t *node; - dplane_t *plane; - int nodenum ; - - nodenum = num ; - // walk through the tree to find the leaf for the point... - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planenum]; - d = DotProduct(point, plane->normal) - plane->dist; - if (d > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - - gNode = node; - return &dleafs[-nodenum - 1]; + vec_t d; + dnode_t* node; + dplane_t* plane; + int nodenum; + + nodenum = num; + // walk through the tree to find the leaf for the point... + while (nodenum >= 0) + { + node = &dnodes[nodenum]; + plane = &dplanes[node->planenum]; + d = DotProduct(point, plane->normal) - plane->dist; + if (d > 0) + nodenum = node->children[0]; + else + nodenum = node->children[1]; + } + + gNode = node; + return &dleafs[-nodenum - 1]; } // return contents of a coordinate in 3D space... using hull > 0 (collision hulls) static int TracePointInLeaf(const int hullNumber, const vec3_t point) { - int nodenum; - vec_t d; - dclipnode_t *node; - dplane_t *plane; - - nodenum = dmodels[0].headnode[hullNumber] ; - // walk through the tree to find the leaf for the point... - while (nodenum >= 0) - { - node = &dclipnodes[nodenum]; - plane = &dplanes[node->planenum]; - d = DotProduct(point, plane->normal) - plane->dist; - if (d > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - return nodenum ; + int nodenum; + vec_t d; + dclipnode_t* node; + dplane_t* plane; + + nodenum = dmodels[0].headnode[hullNumber]; + // walk through the tree to find the leaf for the point... + while (nodenum >= 0) + { + node = &dclipnodes[nodenum]; + plane = &dplanes[node->planenum]; + d = DotProduct(point, plane->normal) - plane->dist; + if (d > 0) + nodenum = node->children[0]; + else + nodenum = node->children[1]; + } + return nodenum; } // find the contents of a coordinate in 3D space... using hull > 0 (collision hulls) // Just a wrapper for TracePointInLeaf -int BotmanPointContentsInHull(const int hullNumber,const vec3_t coord) +int BotmanPointContentsInHull(const int hullNumber, const vec3_t coord) { - if (hullNumber == point_hull) - return BotmanPointContents(dmodels[0].headnode[0],coord) ; + if (hullNumber == point_hull) + return BotmanPointContents(dmodels[0].headnode[0], coord); - return TracePointInLeaf(hullNumber,coord); + return TracePointInLeaf(hullNumber, coord); } // find the contents of a coordinate in 3D space... using hull0 (visibility) int BotmanPointContents(const int nodenum, const vec3_t coord) { - dleaf_t *leaf; + dleaf_t* leaf; - leaf = TracePointInHull0Leaf(nodenum,coord) ; + leaf = TracePointInHull0Leaf(nodenum, coord); - // return contents (CONTENTS_EMPTY, CONTENTS_SOLID, CONTENTS_WATER, etc.) - return leaf->contents; + // return contents (CONTENTS_EMPTY, CONTENTS_SOLID, CONTENTS_WATER, etc.) + return leaf->contents; } - -int UTIL_PointContents(const Vector & x) +int UTIL_PointContents(const Vector& x) { - vec3_t point ; - int WorldContent, ModelContent ; - int ent_index, model_index ; - char * value ; + vec3_t point; + int WorldContent, ModelContent; + int ent_index, model_index; + char* value; - point[0]=x.x ; - point[1]=x.y ; - point[2]=x.z ; + point[0] = x.x; + point[1] = x.y; + point[2] = x.z; // Find the content in visibility hull of the world (dmodels[0]) - WorldContent = BotmanPointContents(0,point) ; + WorldContent = BotmanPointContents(0, point); // If not empty, return the result if (WorldContent != CONTENTS_EMPTY) - return WorldContent ; + return WorldContent; // If CONTENTS_EMPTY, need to do further check for water... @@ -139,280 +138,277 @@ int UTIL_PointContents(const Vector & x) value = ValueForKey(&entities[ent_index], "model"); if (value[0]) { sscanf(value, "*%d", &model_index); - ModelContent= BotmanPointContents(dmodels[model_index].headnode[0],point); + ModelContent = BotmanPointContents(dmodels[model_index].headnode[0], point); if (ModelContent == CONTENT_WATER) { -//printf("***Found water !!! (%.0f,%.0f,%.0f)\n",point[0],point[1],point[2]) ; - return ModelContent ; + //printf("***Found water !!! (%.0f,%.0f,%.0f)\n",point[0],point[1],point[2]) ; + return ModelContent; } } - } - return WorldContent ; + return WorldContent; } - - // trace a line from start to end, fill in trace_t structure with result... // Should rather use Quake SV_RecursiveHullCheck() -void BotmanTraceLine(vec3_t start, vec3_t end, botman_trace_t *tr) +void BotmanTraceLine(vec3_t start, vec3_t end, botman_trace_t* tr) { -dleaf_t *startleaf, *endleaf; -int numsteps, totalsteps; -vec3_t move, step, position; -float dist, trace_dist; - - memset(tr, 0, sizeof(botman_trace_t)); - - if ((start[0] < -4095) || (start[0] > 4095) || - (start[1] < -4095) || (start[1] > 4095) || - (start[2] < -4095) || (start[2] > 4095)) - { - // start beyond edge of world is INVALID!!! - fprintf(stderr,"TraceLine: start point beyond edge of world!\n"); - } - - if (end[0] > 4095.0f) - { - float percent = 4095.0f / end[0]; - end[1] = end[1] * percent; - end[2] = end[2] * percent; - end[0] = 4095.0f; - } - - if (end[1] > 4095.0f) - { - float percent = 4095.0f / end[1]; - end[0] = end[0] * percent; - end[2] = end[2] * percent; - end[1] = 4095.0f; - } - - if (end[2] > 4095.0f) - { - float percent = 4095.0f / end[2]; - end[0] = end[0] * percent; - end[1] = end[1] * percent; - end[2] = 4095.0f; - } - - if (end[0] < -4095.0f) - { - float percent = 4095.0f / end[0]; - end[1] = end[1] * percent; - end[2] = end[2] * percent; - end[0] = -4095.0f; - } - - if (end[1] < -4095.0f) - { - float percent = 4095.0f / end[1]; - end[0] = end[0] * percent; - end[2] = end[2] * percent; - end[1] = -4095.0f; - } - - if (end[2] < -4095.0f) - { - float percent = 4095.0f / end[2]; - end[0] = end[0] * percent; - end[1] = end[1] * percent; - end[2] = -4095.0f; - } - - // find the starting and ending leafs... - startleaf = TracePointInHull0Leaf(0,start); - endleaf = TracePointInHull0Leaf(0,end); - - // set endpos, fraction and contents to the default (trace completed) - VectorCopy(end, tr->endpos); - tr->fraction = 1.0f; - tr->contents = endleaf->contents; - - if (startleaf->contents == CONTENTS_SOLID) - tr->startsolid = TRUE; - - // is start and end leaf the same (couldn't possibly hit the world)... - if (startleaf == endleaf) { - if (startleaf->contents == CONTENTS_SOLID) - tr->allsolid = TRUE; - return; - } - - // get the length of each interation of the loop... - VectorSubtract(end, start, move); - dist = (float)VectorLength(move); - - // determine the number of steps from start to end... - if (dist > 1.0f) - numsteps = totalsteps = (int)dist + 1; - else - numsteps = totalsteps = 1; - - // calculate the length of the step vector... - VectorScale(move, (float)2/numsteps, step); - - VectorCopy(start, position); - - while (numsteps) - { - VectorAdd(position, step, position); - - endleaf = TracePointInHull0Leaf(0,position); - - if ((endleaf->contents == CONTENTS_SOLID) || // we hit something solid... - (endleaf->contents == CONTENTS_SKY)) // we hit the sky - { - vec3_t hitpos; - - VectorCopy(position, hitpos); - - // store the hit position - VectorCopy(position, tr->hitpos); - - // back off one step before solid - VectorSubtract(position, step, position); - - // store the end position and end position contents - VectorCopy(position, tr->endpos); - tr->contents = endleaf->contents; - - VectorSubtract(position, start, move); - trace_dist = (float)VectorLength(move); - tr->fraction = trace_dist / dist; - - break; // break out of while loop - } - - numsteps--; - } + dleaf_t* startleaf, * endleaf; + int numsteps, totalsteps; + vec3_t move, step, position; + float dist, trace_dist; + + memset(tr, 0, sizeof(botman_trace_t)); + + if ((start[0] < -4095) || (start[0] > 4095) || + (start[1] < -4095) || (start[1] > 4095) || + (start[2] < -4095) || (start[2] > 4095)) + { + // start beyond edge of world is INVALID!!! + fprintf(stderr, "TraceLine: start point beyond edge of world!\n"); + } + + if (end[0] > 4095.0f) + { + float percent = 4095.0f / end[0]; + end[1] = end[1] * percent; + end[2] = end[2] * percent; + end[0] = 4095.0f; + } + + if (end[1] > 4095.0f) + { + float percent = 4095.0f / end[1]; + end[0] = end[0] * percent; + end[2] = end[2] * percent; + end[1] = 4095.0f; + } + + if (end[2] > 4095.0f) + { + float percent = 4095.0f / end[2]; + end[0] = end[0] * percent; + end[1] = end[1] * percent; + end[2] = 4095.0f; + } + + if (end[0] < -4095.0f) + { + float percent = 4095.0f / end[0]; + end[1] = end[1] * percent; + end[2] = end[2] * percent; + end[0] = -4095.0f; + } + + if (end[1] < -4095.0f) + { + float percent = 4095.0f / end[1]; + end[0] = end[0] * percent; + end[2] = end[2] * percent; + end[1] = -4095.0f; + } + + if (end[2] < -4095.0f) + { + float percent = 4095.0f / end[2]; + end[0] = end[0] * percent; + end[1] = end[1] * percent; + end[2] = -4095.0f; + } + + // find the starting and ending leafs... + startleaf = TracePointInHull0Leaf(0, start); + endleaf = TracePointInHull0Leaf(0, end); + + // set endpos, fraction and contents to the default (trace completed) + VectorCopy(end, tr->endpos); + tr->fraction = 1.0f; + tr->contents = endleaf->contents; + + if (startleaf->contents == CONTENTS_SOLID) + tr->startsolid = TRUE; + + // is start and end leaf the same (couldn't possibly hit the world)... + if (startleaf == endleaf) { + if (startleaf->contents == CONTENTS_SOLID) + tr->allsolid = TRUE; + return; + } + + // get the length of each interation of the loop... + VectorSubtract(end, start, move); + dist = (float)VectorLength(move); + + // determine the number of steps from start to end... + if (dist > 1.0f) + numsteps = totalsteps = (int)dist + 1; + else + numsteps = totalsteps = 1; + + // calculate the length of the step vector... + VectorScale(move, (float)2 / numsteps, step); + + VectorCopy(start, position); + + while (numsteps) + { + VectorAdd(position, step, position); + + endleaf = TracePointInHull0Leaf(0, position); + + if ((endleaf->contents == CONTENTS_SOLID) || // we hit something solid... + (endleaf->contents == CONTENTS_SKY)) // we hit the sky + { + vec3_t hitpos; + + VectorCopy(position, hitpos); + + // store the hit position + VectorCopy(position, tr->hitpos); + + // back off one step before solid + VectorSubtract(position, step, position); + + // store the end position and end position contents + VectorCopy(position, tr->endpos); + tr->contents = endleaf->contents; + + VectorSubtract(position, start, move); + trace_dist = (float)VectorLength(move); + tr->fraction = trace_dist / dist; + + break; // break out of while loop + } + + numsteps--; + } } #define TWO_PI 6.2831853f #define DELTA 0.001f // find the face where the traceline hit... -dface_t *TraceLineFindFace(vec3_t start, botman_trace_t *tr) +dface_t* TraceLineFindFace(vec3_t start, botman_trace_t* tr) { - vec3_t v_intersect, v_normalized, v_temp; - dface_t *return_face = NULL; - float min_diff = 9999.9f; + vec3_t v_intersect, v_normalized, v_temp; + dface_t* return_face = NULL; + float min_diff = 9999.9f; - VectorSubtract(tr->endpos, start, v_normalized); - VectorNormalize(v_normalized); + VectorSubtract(tr->endpos, start, v_normalized); + VectorNormalize(v_normalized); - dleaf_t *endleaf = TracePointInHull0Leaf(0,tr->endpos); + dleaf_t* endleaf = TracePointInHull0Leaf(0, tr->endpos); - unsigned short *p = dmarksurfaces + endleaf->firstmarksurface; + unsigned short* p = dmarksurfaces + endleaf->firstmarksurface; - // find a plane with endpos on one side and hitpos on the other side... - for (int i = 0; i < endleaf->nummarksurfaces; i++) - { - int face_idx = *p++; - - dface_t *face = &dfaces[face_idx]; + // find a plane with endpos on one side and hitpos on the other side... + for (int i = 0; i < endleaf->nummarksurfaces; i++) + { + int face_idx = *p++; - dplane_t *plane = &dplanes[face->planenum]; + dface_t* face = &dfaces[face_idx]; - float d1 = DotProduct(tr->endpos, plane->normal) - plane->dist; - float d2 = DotProduct(tr->hitpos, plane->normal) - plane->dist; + dplane_t* plane = &dplanes[face->planenum]; - if ((d1 > 0 && d2 <= 0)||(d1 <= 0 && d2 > 0)) - { - // found a plane, find the intersection point in the plane... + float d1 = DotProduct(tr->endpos, plane->normal) - plane->dist; + float d2 = DotProduct(tr->hitpos, plane->normal) - plane->dist; - vec3_t plane_origin, v_angle1, v_angle2; + if ((d1 > 0 && d2 <= 0) || (d1 <= 0 && d2 > 0)) + { + // found a plane, find the intersection point in the plane... - VectorScale(plane->normal, plane->dist, plane_origin); + vec3_t plane_origin, v_angle1, v_angle2; - float dist = DistanceToIntersection(start, v_normalized, plane_origin, plane->normal); + VectorScale(plane->normal, plane->dist, plane_origin); - if (dist < 0) - return NULL; // can't find intersection + float dist = DistanceToIntersection(start, v_normalized, plane_origin, plane->normal); - VectorScale(v_normalized, dist, v_temp); - VectorAdd(start, v_temp, v_intersect); + if (dist < 0) + return NULL; // can't find intersection - // loop through all of the vertexes of all the edges of this face and - // find the angle between vertex-n, v_intersect and vertex-n+1, then add - // all these angles together. if the sum of these angles is 360 degrees - // (or 2 PI radians), then the intersect point lies within that polygon. + VectorScale(v_normalized, dist, v_temp); + VectorAdd(start, v_temp, v_intersect); - float angle_sum = 0.0f; + // loop through all of the vertexes of all the edges of this face and + // find the angle between vertex-n, v_intersect and vertex-n+1, then add + // all these angles together. if the sum of these angles is 360 degrees + // (or 2 PI radians), then the intersect point lies within that polygon. - // loop though all of the edges, getting the vertexes... - for (int edge_index = 0; edge_index < face->numedges; edge_index++) - { - vec3_t vertex1, vertex2; + float angle_sum = 0.0f; - // get the coordinates of the vertex of this edge... - int edge = dsurfedges[face->firstedge + edge_index]; + // loop though all of the edges, getting the vertexes... + for (int edge_index = 0; edge_index < face->numedges; edge_index++) + { + vec3_t vertex1, vertex2; - if (edge < 0) - { - edge = -edge; - dedge_t* e = &dedges[edge]; - VectorCopy(dvertexes[e->v[1]].point, vertex1); - VectorCopy(dvertexes[e->v[0]].point, vertex2); - } - else - { - dedge_t* e = &dedges[edge]; - VectorCopy(dvertexes[e->v[0]].point, vertex1); - VectorCopy(dvertexes[e->v[1]].point, vertex2); - } + // get the coordinates of the vertex of this edge... + int edge = dsurfedges[face->firstedge + edge_index]; - // now create vectors from the vertexes to the plane intersect point... - VectorSubtract(vertex1, v_intersect, v_angle1); - VectorSubtract(vertex2, v_intersect, v_angle2); + if (edge < 0) + { + edge = -edge; + dedge_t* e = &dedges[edge]; + VectorCopy(dvertexes[e->v[1]].point, vertex1); + VectorCopy(dvertexes[e->v[0]].point, vertex2); + } + else + { + dedge_t* e = &dedges[edge]; + VectorCopy(dvertexes[e->v[0]].point, vertex1); + VectorCopy(dvertexes[e->v[1]].point, vertex2); + } - VectorNormalize(v_angle1); - VectorNormalize(v_angle2); + // now create vectors from the vertexes to the plane intersect point... + VectorSubtract(vertex1, v_intersect, v_angle1); + VectorSubtract(vertex2, v_intersect, v_angle2); - // find the angle between these vectors... - float angle = DotProduct(v_angle1, v_angle2); + VectorNormalize(v_angle1); + VectorNormalize(v_angle2); - angle = (float)acos(angle); + // find the angle between these vectors... + float angle = DotProduct(v_angle1, v_angle2); - angle_sum += angle; + angle = (float)acos(angle); - edge++; - } + angle_sum += angle; - // is the sum of the angles 360 degrees (2 PI)?... - if ((angle_sum >= (TWO_PI - DELTA)) && (angle_sum <= (TWO_PI + DELTA))) - { - // find the difference between the sum and 2 PI... - float diff = (float)fabs(angle_sum - TWO_PI); + edge++; + } - if (diff < min_diff) // is this the BEST so far?... - { - min_diff = diff; - return_face = face; - } - } - } - } + // is the sum of the angles 360 degrees (2 PI)?... + if ((angle_sum >= (TWO_PI - DELTA)) && (angle_sum <= (TWO_PI + DELTA))) + { + // find the difference between the sum and 2 PI... + float diff = (float)fabs(angle_sum - TWO_PI); + + if (diff < min_diff) // is this the BEST so far?... + { + min_diff = diff; + return_face = face; + } + } + } + } - return return_face; + return return_face; } -static void ConvertTraceResult(botman_trace_t * tr, TraceResult * ptr) +static void ConvertTraceResult(botman_trace_t* tr, TraceResult* ptr) { - ptr->fAllSolid = tr->allsolid ; - ptr->fStartSolid = tr->startsolid ; - ptr->fInOpen = tr->contents == CONTENTS_EMPTY ; // TO BE FIXED - ptr->fInWater = tr->contents == CONTENTS_WATER ; // ???? - ptr->flFraction = tr->fraction ; - ptr->vecEndPos[0] = tr->endpos[0] ; - ptr->vecEndPos[1] = tr->endpos[1] ; - ptr->vecEndPos[2] = tr->endpos[2] ; - ptr->flPlaneDist = 0.0f ; // TO BE FIXED ? - ptr->vecPlaneNormal[0] = 0 ; // TO BE FIXED - ptr->vecPlaneNormal[1] = 0 ; // TO BE FIXED - ptr->vecPlaneNormal[2] = 0 ; // TO BE FIXED - ptr->pHit = NULL ; // TO BE FIXED - ptr->iHitgroup = 0 ; + ptr->fAllSolid = tr->allsolid; + ptr->fStartSolid = tr->startsolid; + ptr->fInOpen = tr->contents == CONTENTS_EMPTY; // TO BE FIXED + ptr->fInWater = tr->contents == CONTENTS_WATER; // ???? + ptr->flFraction = tr->fraction; + ptr->vecEndPos[0] = tr->endpos[0]; + ptr->vecEndPos[1] = tr->endpos[1]; + ptr->vecEndPos[2] = tr->endpos[2]; + ptr->flPlaneDist = 0.0f; // TO BE FIXED ? + ptr->vecPlaneNormal[0] = 0; // TO BE FIXED + ptr->vecPlaneNormal[1] = 0; // TO BE FIXED + ptr->vecPlaneNormal[2] = 0; // TO BE FIXED + ptr->pHit = NULL; // TO BE FIXED + ptr->iHitgroup = 0; } /* @@ -421,23 +417,23 @@ SV_HullPointContents ================== */ -static int SV_HullPointContents (int nodenum, vec3_t p) +static int SV_HullPointContents(int nodenum, vec3_t p) { float d; - dclipnode_t *node; - dplane_t *plane; + dclipnode_t* node; + dplane_t* plane; while (nodenum >= 0) { if (nodenum > numclipnodes) { - fprintf(stderr,"SV_HullPointContents: bad node number"); - exit(1) ; + fprintf(stderr, "SV_HullPointContents: bad node number"); + exit(1); } - + node = &dclipnodes[nodenum]; plane = &dplanes[node->planenum]; - d = DotProduct (plane->normal, p) - plane->dist; + d = DotProduct(plane->normal, p) - plane->dist; if (d < 0) nodenum = node->children[1]; else @@ -455,14 +451,14 @@ SV_RecursiveHullCheck ================== */ -qboolean SV_RecursiveHullCheck (int hullNumber, // Id of hull, 1 = human, ... +qboolean SV_RecursiveHullCheck(int hullNumber, // Id of hull, 1 = human, ... int nodenum, // Clip node to analyse from float p1f, float p2f, // Initialized to 0 & 1 vec3_t p1, vec3_t p2, // P1 = start, P2 = end - TraceResult *trace) + TraceResult* trace) { - dclipnode_t *node; - dplane_t *plane; + dclipnode_t* node; + dplane_t* plane; float t1, t2; float frac; int i; @@ -470,12 +466,12 @@ qboolean SV_RecursiveHullCheck (int hullNumber, // Id of hull, 1 = human, ... int side; float midf; - if ((hullNumber < human_hull) || (hullNumber > head_hull)) { - fprintf(stderr,"Wrong hullNumber in SV_RecursiveHullCheck\n") ; - exit(1) ; + if ((hullNumber < human_hull) || (hullNumber > head_hull)) { + fprintf(stderr, "Wrong hullNumber in SV_RecursiveHullCheck\n"); + exit(1); } -// check for empty + // check for empty if (nodenum < 0) { if (nodenum != CONTENTS_SOLID) @@ -492,125 +488,126 @@ qboolean SV_RecursiveHullCheck (int hullNumber, // Id of hull, 1 = human, ... } if (nodenum > numclipnodes) { - fprintf(stderr,"SV_RecursiveHullCheck: bad node number"); - exit(1) ; + fprintf(stderr, "SV_RecursiveHullCheck: bad node number"); + exit(1); } -// -// find the point distances -// + // + // find the point distances + // node = &dclipnodes[nodenum]; if ((node->planenum > numplanes) || (node->planenum < 0)) { - fprintf(stderr,"SV_RecursiveHullCheck: bad plane number"); - exit(1) ; + fprintf(stderr, "SV_RecursiveHullCheck: bad plane number"); + exit(1); } plane = &dplanes[node->planenum]; - t1 = DotProduct (plane->normal, p1) - plane->dist; - t2 = DotProduct (plane->normal, p2) - plane->dist; - + t1 = DotProduct(plane->normal, p1) - plane->dist; + t2 = DotProduct(plane->normal, p2) - plane->dist; + // Check whether P1 & P2 are on the same side of the plane // Then, continue to check in this smaller space if (t1 >= 0 && t2 >= 0) - return SV_RecursiveHullCheck (hullNumber, node->children[0], p1f, p2f, p1, p2, trace); + return SV_RecursiveHullCheck(hullNumber, node->children[0], p1f, p2f, p1, p2, trace); if (t1 < 0 && t2 < 0) - return SV_RecursiveHullCheck (hullNumber, node->children[1], p1f, p2f, p1, p2, trace); + return SV_RecursiveHullCheck(hullNumber, node->children[1], p1f, p2f, p1, p2, trace); // P1 & P2 are on opposite side of the plane... if (t1 == t2) { - fprintf(stderr,"SV_RecursiveHullCheck: same distance from plane"); - exit(1) ; + fprintf(stderr, "SV_RecursiveHullCheck: same distance from plane"); + exit(1); } -// put the crosspoint DIST_EPSILON pixels on the near side + // put the crosspoint DIST_EPSILON pixels on the near side if (t1 < 0.0) - frac = (t1 + DIST_EPSILON)/(t1-t2); + frac = (t1 + DIST_EPSILON) / (t1 - t2); else - frac = (t1 - DIST_EPSILON)/(t1-t2); + frac = (t1 - DIST_EPSILON) / (t1 - t2); if (frac < 0.0) frac = 0.0; if (frac > 1.0) frac = 1.0; - - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); + + midf = p1f + (p2f - p1f) * frac; + for (i = 0; i < 3; i++) + mid[i] = p1[i] + frac * (p2[i] - p1[i]); side = (t1 < 0); -// move up to the node - if (!SV_RecursiveHullCheck (hullNumber, node->children[side], p1f, midf, p1, mid, trace) ) + // move up to the node + if (!SV_RecursiveHullCheck(hullNumber, node->children[side], p1f, midf, p1, mid, trace)) return false; - if (SV_HullPointContents (node->children[side^1], mid) != CONTENTS_SOLID) - // go past the node - return SV_RecursiveHullCheck (hullNumber, node->children[side^1], midf, p2f, mid, p2, trace); - + if (SV_HullPointContents(node->children[side ^ 1], mid) != CONTENTS_SOLID) + // go past the node + return SV_RecursiveHullCheck(hullNumber, node->children[side ^ 1], midf, p2f, mid, p2, trace); + if (trace->fAllSolid) return false; // never got out of the solid area - + //================== // the other side of the node is solid, this is the impact point //================== if (!side) { - VectorCopy (plane->normal, trace->vecPlaneNormal); + VectorCopy(plane->normal, trace->vecPlaneNormal); trace->flPlaneDist = plane->dist; } else { - VectorSubtract (vec3_origin, plane->normal, trace->vecPlaneNormal); + VectorSubtract(vec3_origin, plane->normal, trace->vecPlaneNormal); trace->flPlaneDist = -plane->dist; } // If mid is SOLID, move mid backwards until it is in EMPTY space - while (SV_HullPointContents (dmodels[0].headnode[hullNumber], mid) == CONTENTS_SOLID) + while (SV_HullPointContents(dmodels[0].headnode[hullNumber], mid) == CONTENTS_SOLID) { frac -= 0.1; if (frac < 0.0) // shouldn't really happen, but does occasionally { -// fprintf(stderr,"SV_RecursiveHullCheck(): backup past 0\n"); + // fprintf(stderr,"SV_RecursiveHullCheck(): backup past 0\n"); break; // Exit loop immediately } // Adjust mid to reflect the value of frac - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); + midf = p1f + (p2f - p1f) * frac; + for (i = 0; i < 3; i++) + mid[i] = p1[i] + frac * (p2[i] - p1[i]); } trace->flFraction = midf; - VectorCopy (mid, trace->vecEndPos); + VectorCopy(mid, trace->vecEndPos); return false; } -void UTIL_TraceHull (const Vector & vecStart, const Vector & vecEnd, - IGNORE_MONSTERS igmon, int hullNumber, edict_t * pentIgnore, - TraceResult * ptr) +void UTIL_TraceHull(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, int hullNumber, edict_t* pentIgnore, + TraceResult* ptr) { - vec3_t start, end ; - botman_trace_t tr ; - - start[0]=vecStart.x ; - start[1]=vecStart.y ; - start[2]=vecStart.z ; - end[0]=vecEnd.x ; - end[1]=vecEnd.y ; - end[2]=vecEnd.z ; - memset(&tr,0,sizeof(botman_trace_t)) ; - tr.fraction=1.0 ; + vec3_t start, end; + botman_trace_t tr; + + start[0] = vecStart.x; + start[1] = vecStart.y; + start[2] = vecStart.z; + end[0] = vecEnd.x; + end[1] = vecEnd.y; + end[2] = vecEnd.z; + memset(&tr, 0, sizeof(botman_trace_t)); + tr.fraction = 1.0; if (hullNumber == point_hull) { - BotmanTraceLine(start, end, &tr) ; - ConvertTraceResult(&tr,ptr) ; - } else { - TraceResult EntTrace ; - int ent_index, model_index ; - char * value ; + BotmanTraceLine(start, end, &tr); + ConvertTraceResult(&tr, ptr); + } + else { + TraceResult EntTrace; + int ent_index, model_index; + char* value; // Set the TraceResult default values - memset(ptr,0,sizeof(TraceResult)) ; - ptr->flFraction = 1.0 ; - ptr->fAllSolid = true ; - SV_RecursiveHullCheck(hullNumber, dmodels[0].headnode[hullNumber], + memset(ptr, 0, sizeof(TraceResult)); + ptr->flFraction = 1.0; + ptr->fAllSolid = true; + SV_RecursiveHullCheck(hullNumber, dmodels[0].headnode[hullNumber], 0.0, 1.0, start, end, ptr); // loop through all the entities looking for "func_wall"... @@ -620,18 +617,15 @@ void UTIL_TraceHull (const Vector & vecStart, const Vector & vecEnd, value = ValueForKey(&entities[ent_index], "model"); if (value[0]) { sscanf(value, "*%d", &model_index); - memset(&EntTrace,0,sizeof(TraceResult)) ; - EntTrace.flFraction = 1.0 ; - EntTrace.fAllSolid = true ; + memset(&EntTrace, 0, sizeof(TraceResult)); + EntTrace.flFraction = 1.0; + EntTrace.fAllSolid = true; SV_RecursiveHullCheck(hullNumber, dmodels[model_index].headnode[hullNumber], 0.0, 1.0, start, end, &EntTrace); if (EntTrace.flFraction < ptr->flFraction) - memcpy(ptr,&EntTrace,sizeof(TraceResult)) ; + memcpy(ptr, &EntTrace, sizeof(TraceResult)); } - } - } - return ; -} - + return; +} \ No newline at end of file diff --git a/Bsp2Rbn/trace.h b/Bsp2Rbn/trace.h index f21a049..356e6fd 100644 --- a/Bsp2Rbn/trace.h +++ b/Bsp2Rbn/trace.h @@ -15,7 +15,7 @@ // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License for more details at: // http://www.gnu.org/copyleft/gpl.html @@ -29,18 +29,17 @@ typedef struct { - bool allsolid; /* if true, plane is not valid */ - bool startsolid; /* if true, the initial point was in a solid area */ - float fraction; /* time completed, 1.0 = didn't hit anything */ - vec3_t hitpos; /* surface hit position (in solid) */ - vec3_t endpos; /* final position (not in solid) */ - int contents; /* contents of endpos */ + bool allsolid; /* if true, plane is not valid */ + bool startsolid; /* if true, the initial point was in a solid area */ + float fraction; /* time completed, 1.0 = didn't hit anything */ + vec3_t hitpos; /* surface hit position (in solid) */ + vec3_t endpos; /* final position (not in solid) */ + int contents; /* contents of endpos */ } botman_trace_t; int BotmanPointContents(const int nodenum, const vec3_t coord); -int BotmanPointContentsInHull(const int hullNumber,const vec3_t coord); -void BotmanTraceLine (vec3_t start, vec3_t end, botman_trace_t *trace); -dface_t *TraceLineFindFace(vec3_t start, botman_trace_t *tr); +int BotmanPointContentsInHull(const int hullNumber, const vec3_t coord); +void BotmanTraceLine(vec3_t start, vec3_t end, botman_trace_t* trace); +dface_t* TraceLineFindFace(vec3_t start, botman_trace_t* tr); #endif - diff --git a/Bsp2Rbn/util.cpp b/Bsp2Rbn/util.cpp index 6bc5e45..9a5167d 100644 --- a/Bsp2Rbn/util.cpp +++ b/Bsp2Rbn/util.cpp @@ -21,7 +21,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -33,9 +33,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -49,8 +49,8 @@ #ifdef __linux__ #include #else -char * basename(char *) ; -char * dirname(char *) ; +char* basename(char*); +char* dirname(char*); #endif #include #include @@ -85,475 +85,473 @@ int gmsgShowMenu = 0; #ifndef __linux__ // 21/07/04 Whistler // Handle both \ and / as separator -char * basename(char * s) +char* basename(char* s) { - char * fs ; - - if ((s == NULL) || (*s == 0)) return "." ; - if (strcmp(s,"\\") == 0) return s ; - if (strcmp(s,"/") == 0) return s ; - fs = strrchr(s,'\\') ; - if (fs == NULL) fs = strrchr(s,'/') ; - if (fs == NULL) return s ; - return fs + 1 ; + char* fs; + + if ((s == NULL) || (*s == 0)) return "."; + if (strcmp(s, "\\") == 0) return s; + if (strcmp(s, "/") == 0) return s; + fs = strrchr(s, '\\'); + if (fs == NULL) fs = strrchr(s, '/'); + if (fs == NULL) return s; + return fs + 1; } -char * dirname(char * s) +char* dirname(char* s) { - char * fs ; + char* fs; if ((s == NULL) || (*s == 0)) return "."; - if (strcmp(s,"\\") == 0) return s; - if (strcmp(s,"/") == 0) return s; - fs = strrchr(s,'\\'); - if (fs == NULL) fs = strrchr(s,'/'); + if (strcmp(s, "\\") == 0) return s; + if (strcmp(s, "/") == 0) return s; + fs = strrchr(s, '\\'); + if (fs == NULL) fs = strrchr(s, '/'); if (fs == NULL) return "."; - * fs = 0; - return s ; + *fs = 0; + return s; } #endif -Vector UTIL_VecToAngles (const Vector & vec) +Vector UTIL_VecToAngles(const Vector& vec) { - float rgflVecOut[3]; - VEC_TO_ANGLES (vec, rgflVecOut); - return Vector (rgflVecOut); + float rgflVecOut[3]; + VEC_TO_ANGLES(vec, rgflVecOut); + return Vector(rgflVecOut); } // Overloaded to add IGNORE_GLASS void -UTIL_TraceLine (const Vector & vecStart, const Vector & vecEnd, - IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, - edict_t * pentIgnore, TraceResult * ptr) +UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, + edict_t* pentIgnore, TraceResult* ptr) { - TRACE_LINE (vecStart, vecEnd, - (igmon == - ignore_monsters ? TRUE : FALSE) | (ignoreGlass ? 0x100 : 0), - pentIgnore, ptr); + TRACE_LINE(vecStart, vecEnd, + (igmon == + ignore_monsters ? TRUE : FALSE) | (ignoreGlass ? 0x100 : 0), + pentIgnore, ptr); } void -UTIL_TraceLine (const Vector & vecStart, const Vector & vecEnd, - IGNORE_MONSTERS igmon, edict_t * pentIgnore, - TraceResult * ptr) +UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, edict_t* pentIgnore, + TraceResult* ptr) { - TRACE_LINE (vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), - pentIgnore, ptr); + TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), + pentIgnore, ptr); } void -UTIL_MakeVectors (const Vector & vecAngles) +UTIL_MakeVectors(const Vector& vecAngles) { - MAKE_VECTORS (vecAngles); + MAKE_VECTORS(vecAngles); } -edict_t * -UTIL_FindEntityInSphere (edict_t * pentStart, const Vector & vecCenter, - float flRadius) +edict_t* +UTIL_FindEntityInSphere(edict_t* pentStart, const Vector& vecCenter, + float flRadius) { - edict_t *pentEntity; + edict_t* pentEntity; - pentEntity = FIND_ENTITY_IN_SPHERE (pentStart, vecCenter, flRadius); + pentEntity = FIND_ENTITY_IN_SPHERE(pentStart, vecCenter, flRadius); - if (!FNullEnt (pentEntity)) - return pentEntity; + if (!FNullEnt(pentEntity)) + return pentEntity; - return NULL; + return NULL; } -edict_t * -UTIL_FindEntityByString (edict_t * pentStart, const char *szKeyword, - const char *szValue) +edict_t* +UTIL_FindEntityByString(edict_t* pentStart, const char* szKeyword, + const char* szValue) { - edict_t *pentEntity; + edict_t* pentEntity; - pentEntity = FIND_ENTITY_BY_STRING (pentStart, szKeyword, szValue); + pentEntity = FIND_ENTITY_BY_STRING(pentStart, szKeyword, szValue); - if (!FNullEnt (pentEntity)) - return pentEntity; - return NULL; + if (!FNullEnt(pentEntity)) + return pentEntity; + return NULL; } -edict_t * -UTIL_FindEntityByClassname (edict_t * pentStart, const char *szName) +edict_t* +UTIL_FindEntityByClassname(edict_t* pentStart, const char* szName) { - return UTIL_FindEntityByString (pentStart, "classname", szName); + return UTIL_FindEntityByString(pentStart, "classname", szName); } -edict_t * -UTIL_FindEntityByTargetname (edict_t * pentStart, const char *szName) +edict_t* +UTIL_FindEntityByTargetname(edict_t* pentStart, const char* szName) { - return UTIL_FindEntityByString (pentStart, "targetname", szName); + return UTIL_FindEntityByString(pentStart, "targetname", szName); } void -UTIL_SetSize (entvars_t * pev, const Vector & vecMin, const Vector & vecMax) +UTIL_SetSize(entvars_t* pev, const Vector& vecMin, const Vector& vecMax) { - SET_SIZE (ENT (pev), vecMin, vecMax); + SET_SIZE(ENT(pev), vecMin, vecMax); } void -UTIL_SetOrigin (entvars_t * pev, const Vector & vecOrigin) +UTIL_SetOrigin(entvars_t* pev, const Vector& vecOrigin) { - SET_ORIGIN (ENT (pev), vecOrigin); + SET_ORIGIN(ENT(pev), vecOrigin); } void -ClientPrint (edict_t * pEntity, int msg_dest, const char *msg_name) +ClientPrint(edict_t* pEntity, int msg_dest, const char* msg_name) { - } void -UTIL_ClientPrintAll (int msg_dest, const char *msg_name, const char *param1, - const char *param2, const char *param3, - const char *param4) +UTIL_ClientPrintAll(int msg_dest, const char* msg_name, const char* param1, + const char* param2, const char* param3, + const char* param4) { } void -UTIL_SayText (const char *pText, edict_t * pEdict) +UTIL_SayText(const char* pText, edict_t* pEdict) { - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG ("SayText", -1); - - MESSAGE_BEGIN (MSG_ONE, gmsgSayText, NULL, pEdict); - WRITE_BYTE (ENTINDEX (pEdict)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING (pText); - MESSAGE_END (); + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); + + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pEdict); + WRITE_BYTE(ENTINDEX(pEdict)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(pText); + MESSAGE_END(); } void -UTIL_HostSay (edict_t * pEntity, int teamonly, char *message) +UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { - int j; - char text[128]; - char *pc; - int sender_team, player_team; - edict_t *client; - - // make sure the text has content - for (pc = message; pc != NULL && *pc != 0; pc++) - { - if (isprint (*pc) && !isspace (*pc)) + int j; + char text[128]; + char* pc; + int sender_team, player_team; + edict_t* client; + + // make sure the text has content + for (pc = message; pc != NULL && *pc != 0; pc++) + { + if (isprint(*pc) && !isspace(*pc)) + { + pc = NULL; // we've found an alphanumeric character, so text is valid + break; + } + } + + if (pc != NULL) + return; // no character found, so say nothing + + // turn on color set 2 (color on, no sound) + if (teamonly) + sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); + else + sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); + + j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator + if ((int)strlen(message) > j) + message[j] = 0; + + strcat(text, message); + strcat(text, "\n"); + + // loop through all players + // Start with the first player. + // This may return the world in single player if the client types something between levels or during spawn + // so check it, or it will infinite loop + + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); + + sender_team = UTIL_GetTeam(pEntity); + + client = NULL; + while (((client = UTIL_FindEntityByClassname(client, "player")) != NULL) && + (!FNullEnt(client))) { - pc = NULL; // we've found an alphanumeric character, so text is valid - break; + if (client == pEntity) // skip sender of message + continue; + + player_team = UTIL_GetTeam(client); + + if (teamonly && (sender_team != player_team)) + continue; + + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, client); + WRITE_BYTE(ENTINDEX(pEntity)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(text); + MESSAGE_END(); } - } - - if (pc != NULL) - return; // no character found, so say nothing - - // turn on color set 2 (color on, no sound) - if (teamonly) - sprintf (text, "%c(TEAM) %s: ", 2, STRING (pEntity->v.netname)); - else - sprintf (text, "%c%s: ", 2, STRING (pEntity->v.netname)); - - j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator - if ((int) strlen (message) > j) - message[j] = 0; - - strcat (text, message); - strcat (text, "\n"); - - // loop through all players - // Start with the first player. - // This may return the world in single player if the client types something between levels or during spawn - // so check it, or it will infinite loop - - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG ("SayText", -1); - - sender_team = UTIL_GetTeam (pEntity); - - client = NULL; - while (((client = UTIL_FindEntityByClassname (client, "player")) != NULL) && - (!FNullEnt (client))) - { - if (client == pEntity) // skip sender of message - continue; - - player_team = UTIL_GetTeam (client); - - if (teamonly && (sender_team != player_team)) - continue; - - MESSAGE_BEGIN (MSG_ONE, gmsgSayText, NULL, client); - WRITE_BYTE (ENTINDEX (pEntity)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING (text); - MESSAGE_END (); - } - - // print to the sending client - MESSAGE_BEGIN (MSG_ONE, gmsgSayText, NULL, pEntity); - WRITE_BYTE (ENTINDEX (pEntity)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING (text); - MESSAGE_END (); - - // echo to server console - g_engfuncs.pfnServerPrint (text); + + // print to the sending client + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pEntity); + WRITE_BYTE(ENTINDEX(pEntity)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(text); + MESSAGE_END(); + + // echo to server console + g_engfuncs.pfnServerPrint(text); } #ifdef DEBUG -edict_t * -DBG_EntOfVars (const entvars_t * pev) +edict_t* +DBG_EntOfVars(const entvars_t* pev) { - if (pev->pContainingEntity != NULL) - return pev->pContainingEntity; - ALERT (at_console, - "entvars_t pContainingEntity is NULL, calling into engine"); - edict_t *pent = (*g_engfuncs.pfnFindEntityByVars) ((entvars_t *) pev); - if (pent == NULL) - ALERT (at_console, "DAMN! Even the engine couldn't FindEntityByVars!"); - ((entvars_t *) pev)->pContainingEntity = pent; - return pent; + if (pev->pContainingEntity != NULL) + return pev->pContainingEntity; + ALERT(at_console, + "entvars_t pContainingEntity is NULL, calling into engine"); + edict_t* pent = (*g_engfuncs.pfnFindEntityByVars) ((entvars_t*)pev); + if (pent == NULL) + ALERT(at_console, "DAMN! Even the engine couldn't FindEntityByVars!"); + ((entvars_t*)pev)->pContainingEntity = pent; + return pent; } #endif //DEBUG // Is the edict a vip or not? bool -UTIL_IsVip (edict_t * pEntity) +UTIL_IsVip(edict_t* pEntity) { - if (mod_id != CSTRIKE_DLL) - return false; - else - { - char *infobuffer; - char model_name[32]; + if (mod_id != CSTRIKE_DLL) + return false; + else + { + char* infobuffer; + char model_name[32]; - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); - strcpy (model_name, (g_engfuncs.pfnInfoKeyValue (infobuffer, "model"))); + infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); + strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - if (strcmp (model_name, "vip") == 0) // VIP - return true; - } + if (strcmp(model_name, "vip") == 0) // VIP + return true; + } - return false; + return false; } // return team number 0 through 3 based what MOD uses for team numbers int -UTIL_GetTeam (edict_t * pEntity) +UTIL_GetTeam(edict_t* pEntity) { - if (mod_id == CSTRIKE_DLL) - { - char *infobuffer; - char model_name[32]; - - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); - strcpy (model_name, (g_engfuncs.pfnInfoKeyValue (infobuffer, "model"))); - - if ((strcmp (model_name, "terror") == 0) || // Phoenix Connektion - (strcmp (model_name, "arab") == 0) || // old L337 Krew - (strcmp (model_name, "leet") == 0) || // L337 Krew - (strcmp (model_name, "artic") == 0) || // Artic Avenger - (strcmp (model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? - (strcmp (model_name, "guerilla") == 0)) // Gorilla Warfare - { - return 0; - } - else if ((strcmp (model_name, "urban") == 0) || // Seal Team 6 - (strcmp (model_name, "gsg9") == 0) || // German GSG-9 - (strcmp (model_name, "sas") == 0) || // UK SAS - (strcmp (model_name, "gign") == 0) || // French GIGN - (strcmp (model_name, "vip") == 0) || // VIP - (strcmp (model_name, "spetsnatz") == 0)) // CZ Spetsnatz + if (mod_id == CSTRIKE_DLL) { - return 1; + char* infobuffer; + char model_name[32]; + + infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); + strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + + if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion + (strcmp(model_name, "arab") == 0) || // old L337 Krew + (strcmp(model_name, "leet") == 0) || // L337 Krew + (strcmp(model_name, "artic") == 0) || // Artic Avenger + (strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? + (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare + { + return 0; + } + else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 + (strcmp(model_name, "gsg9") == 0) || // German GSG-9 + (strcmp(model_name, "sas") == 0) || // UK SAS + (strcmp(model_name, "gign") == 0) || // French GIGN + (strcmp(model_name, "vip") == 0) || // VIP + (strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz + { + return 1; + } + return -1; // return zero if team is unknown } - return -1; // return zero if team is unknown - } - return 0; + return 0; } // return class number 0 through N int -UTIL_GetClass (edict_t * pEntity) +UTIL_GetClass(edict_t* pEntity) { - char *infobuffer; - char model_name[32]; + char* infobuffer; + char model_name[32]; - infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); - strcpy (model_name, (g_engfuncs.pfnInfoKeyValue (infobuffer, "model"))); + infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer) (pEntity); + strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - return 0; + return 0; } int -UTIL_GetBotIndex (edict_t * pEdict) +UTIL_GetBotIndex(edict_t* pEdict) { - int index; + int index; - for (index = 0; index < 32; index++) - { - if (bots[index].pEdict == pEdict) + for (index = 0; index < 32; index++) { - return index; + if (bots[index].pEdict == pEdict) + { + return index; + } } - } - return -1; // return -1 if edict is not a bot + return -1; // return -1 if edict is not a bot } -cBot * -UTIL_GetBotPointer (edict_t * pEdict) +cBot* +UTIL_GetBotPointer(edict_t* pEdict) { - int index; + int index; - for (index = 0; index < 32; index++) - { - if (bots[index].pEdict == pEdict) - { - break; - } - } + for (index = 0; index < 32; index++) + { + if (bots[index].pEdict == pEdict) + { + break; + } + } - if (index < 32) - return (&bots[index]); + if (index < 32) + return (&bots[index]); - return NULL; // return NULL if edict is not a bot + return NULL; // return NULL if edict is not a bot } -bool IsAlive (edict_t * pEdict) { - // FIX: Make sure the edict is valid and such, else return false: - return ((pEdict != NULL) && // VALID - (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD - (pEdict->v.health > 0) && // ENOUGHT HEALTH - !(pEdict->v.flags & FL_NOTARGET) && // ? - (pEdict->v.takedamage != 0)); // CAN TAKE DAMAGE +bool IsAlive(edict_t* pEdict) { + // FIX: Make sure the edict is valid and such, else return false: + return ((pEdict != NULL) && // VALID + (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD + (pEdict->v.health > 0) && // ENOUGHT HEALTH + !(pEdict->v.flags & FL_NOTARGET) && // ? + (pEdict->v.takedamage != 0)); // CAN TAKE DAMAGE } bool -FInViewCone (Vector * pOrigin, edict_t * pEdict) +FInViewCone(Vector* pOrigin, edict_t* pEdict) { #ifdef EVYISWRONG -return TRUE ; + return TRUE; #endif - Vector2D vec2LOS; - float flDot; + Vector2D vec2LOS; + float flDot; - UTIL_MakeVectors (pEdict->v.angles); + UTIL_MakeVectors(pEdict->v.angles); - vec2LOS = (*pOrigin - pEdict->v.origin).Make2D (); - vec2LOS = vec2LOS.Normalize (); + vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); + vec2LOS = vec2LOS.Normalize(); - flDot = DotProduct (vec2LOS, gpGlobals->v_forward.Make2D ()); + flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); - if (flDot > 0.50) // 60 degree field of view - { - return TRUE; - } - else - { - return FALSE; - } + if (flDot > 0.50) // 60 degree field of view + { + return TRUE; + } + else + { + return FALSE; + } } // FVisible() bool -FVisible (const Vector & vecOrigin, edict_t * pEdict) +FVisible(const Vector& vecOrigin, edict_t* pEdict) { #ifdef EVYISWRONG -return TRUE ; + return TRUE; #endif - TraceResult tr; - Vector vecLookerOrigin; - - // look through caller's eyes - vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; - - int bInWater = (UTIL_PointContents (vecOrigin) == CONTENTS_WATER); - int bLookerInWater = - (UTIL_PointContents (vecLookerOrigin) == CONTENTS_WATER); - - // don't look through water - if (bInWater != bLookerInWater) - return FALSE; - - UTIL_TraceLine (vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, - pEdict, &tr); - - if (tr.flFraction != 1.0) - { - return FALSE; // Line of sight is not established - } - else - { - return TRUE; // line of sight is valid. - } + TraceResult tr; + Vector vecLookerOrigin; + + // look through caller's eyes + vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; + + int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); + int bLookerInWater = + (UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER); + + // don't look through water + if (bInWater != bLookerInWater) + return FALSE; + + UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, + pEdict, &tr); + + if (tr.flFraction != 1.0) + { + return FALSE; // Line of sight is not established + } + else + { + return TRUE; // line of sight is valid. + } } Vector -GetGunPosition (edict_t * pEdict) +GetGunPosition(edict_t* pEdict) { - return (pEdict->v.origin + pEdict->v.view_ofs); + return (pEdict->v.origin + pEdict->v.view_ofs); } void -UTIL_SelectItem (edict_t * pEdict, char *item_name) +UTIL_SelectItem(edict_t* pEdict, char* item_name) { - /*BotDebug( item_name); */ - FakeClientCommand (pEdict, item_name, NULL, NULL); + /*BotDebug( item_name); */ + FakeClientCommand(pEdict, item_name, NULL, NULL); } Vector -VecBModelOrigin (edict_t * pEdict) +VecBModelOrigin(edict_t* pEdict) { - return pEdict->v.absmin + (pEdict->v.size * 0.5); + return pEdict->v.absmin + (pEdict->v.size * 0.5); } void -UTIL_ShowMenu (edict_t * pEdict, int slots, int displaytime, bool needmore, - char *pText) +UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, + char* pText) { - if (gmsgShowMenu == 0) - gmsgShowMenu = REG_USER_MSG ("ShowMenu", -1); + if (gmsgShowMenu == 0) + gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); - MESSAGE_BEGIN (MSG_ONE, gmsgShowMenu, NULL, pEdict); + MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, NULL, pEdict); - WRITE_SHORT (slots); - WRITE_CHAR (displaytime); - WRITE_BYTE (needmore); - WRITE_STRING (pText); + WRITE_SHORT(slots); + WRITE_CHAR(displaytime); + WRITE_BYTE(needmore); + WRITE_STRING(pText); - MESSAGE_END (); + MESSAGE_END(); } void -UTIL_BuildFileName (char *filename, char *arg1, char *arg2) +UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { + if (mod_id == VALVE_DLL) + strcpy(filename, "valve/"); + + else if (mod_id == CSTRIKE_DLL) + strcpy(filename, "cstrike/"); - if (mod_id == VALVE_DLL) - strcpy (filename, "valve/"); - - else if (mod_id == CSTRIKE_DLL) - strcpy (filename, "cstrike/"); - - else - { - filename[0] = 0; - return; - } - - if ((arg1) && (*arg1) && (arg2) && (*arg2)) - { - strcat (filename, arg1); - strcat (filename, "/"); - strcat (filename, arg2); - } - else if ((arg1) && (*arg1)) - { - strcat (filename, arg1); - } + else + { + filename[0] = 0; + return; + } + + if ((arg1) && (*arg1) && (arg2) && (*arg2)) + { + strcat(filename, arg1); + strcat(filename, "/"); + strcat(filename, arg2); + } + else if ((arg1) && (*arg1)) + { + strcat(filename, arg1); + } } // added by Tub @@ -561,14 +559,14 @@ UTIL_BuildFileName (char *filename, char *arg1, char *arg2) // Heavily modified in the standalone version void -UTIL_BuildFileNameRB (char *subdir, char *filename) +UTIL_BuildFileNameRB(char* subdir, char* filename) { - char * temp, *temp2 ; + char* temp, * temp2; - temp=strdup(subdir); - temp2=basename(temp) ; - strcpy(filename,temp2) ; - free(temp) ; + temp = strdup(subdir); + temp2 = basename(temp); + strcpy(filename, temp2); + free(temp); } //========================================================= @@ -576,443 +574,438 @@ UTIL_BuildFileNameRB (char *subdir, char *filename) // Preceded by LOG: ( timestamp ) < message > //========================================================= void -UTIL_LogPrintf (char *fmt, ...) +UTIL_LogPrintf(char* fmt, ...) { - va_list argptr; - static char string[1024]; + va_list argptr; + static char string[1024]; - va_start (argptr, fmt); - vsprintf (string, fmt, argptr); - va_end (argptr); + va_start(argptr, fmt); + vsprintf(string, fmt, argptr); + va_end(argptr); - // Print to server console - ALERT (at_logged, "%s", string); + // Print to server console + ALERT(at_logged, "%s", string); } void -UTIL_BotPressKey (cBot * pBot, int type) { - if (type == IN_JUMP || type == IN_DUCK) - if (pBot->f_freeze_time > gpGlobals->time) - return; // do nothing when in freezetime +UTIL_BotPressKey(cBot* pBot, int type) { + if (type == IN_JUMP || type == IN_DUCK) + if (pBot->f_freeze_time > gpGlobals->time) + return; // do nothing when in freezetime - if (type == IN_JUMP) - if (pBot->f_may_jump_time > gpGlobals->time) - return; // do nothing when we may not jump + if (type == IN_JUMP) + if (pBot->f_may_jump_time > gpGlobals->time) + return; // do nothing when we may not jump - if (type == IN_JUMP && pBot->f_camp_time > gpGlobals->time) - return; // Do not jump when camping. + if (type == IN_JUMP && pBot->f_camp_time > gpGlobals->time) + return; // Do not jump when camping. - // don't jump from ladder - if (FUNC_IsOnLadder (pBot->pEdict) && type == IN_JUMP) - return; + // don't jump from ladder + if (FUNC_IsOnLadder(pBot->pEdict) && type == IN_JUMP) + return; - // KEY: Reload - if (type == IN_RELOAD) // when reloading, there is NO zooming (when holding a zoomable weapon or a sniper gun) - { - if (FUNC_BotHoldsZoomWeapon (pBot) - || UTIL_GiveWeaponType (pBot->current_weapon.iId) == SNIPER) + // KEY: Reload + if (type == IN_RELOAD) // when reloading, there is NO zooming (when holding a zoomable weapon or a sniper gun) + { + if (FUNC_BotHoldsZoomWeapon(pBot) + || UTIL_GiveWeaponType(pBot->current_weapon.iId) == SNIPER) - //pBot->zoomed = ZOOM_NONE; // not zoomed anymore + //pBot->zoomed = ZOOM_NONE; // not zoomed anymore - // FIX: Do not let bots do anything with this weapon for 0.7 second. So the engine can - // update the information. - pBot->f_update_weapon_time = gpGlobals->time + 0.7; - } + // FIX: Do not let bots do anything with this weapon for 0.7 second. So the engine can + // update the information. + pBot->f_update_weapon_time = gpGlobals->time + 0.7; + } - // KEY: End - pBot->pEdict->v.button |= type; + // KEY: End + pBot->pEdict->v.button |= type; - if (type == IN_JUMP) - { - if (pBot->f_hold_duck < gpGlobals->time) - pBot->f_hold_duck = gpGlobals->time + 0.35; + if (type == IN_JUMP) + { + if (pBot->f_hold_duck < gpGlobals->time) + pBot->f_hold_duck = gpGlobals->time + 0.35; - pBot->f_may_jump_time = gpGlobals->time + 0.3; - } + pBot->f_may_jump_time = gpGlobals->time + 0.3; + } } int -UTIL_GiveWeaponType (int weapon_id) +UTIL_GiveWeaponType(int weapon_id) { - int kind = NONE; - - // Check 1. Is it a knife? - if (weapon_id == CS_WEAPON_KNIFE) - kind = KNIFE; - - // Check 2, is it a 'tool'? - if (weapon_id == CS_WEAPON_FLASHBANG || - weapon_id == CS_WEAPON_HEGRENADE || weapon_id == CS_WEAPON_SMOKEGRENADE) - kind = GRENADE; - - // Check 3, is it a secondary gun? - if (weapon_id == CS_WEAPON_P228 || - weapon_id == CS_WEAPON_ELITE || - weapon_id == CS_WEAPON_UMP45 || - weapon_id == CS_WEAPON_USP || - weapon_id == CS_WEAPON_GLOCK18 || - weapon_id == CS_WEAPON_DEAGLE || weapon_id == CS_WEAPON_FIVESEVEN) - kind = SECONDARY; - - // Check 4, is it a sniper gun? - if (weapon_id == CS_WEAPON_SCOUT || - weapon_id == CS_WEAPON_SG550 || - weapon_id == CS_WEAPON_AWP || weapon_id == CS_WEAPON_G3SG1) - kind = SNIPER; - - // When the kind of weapon is still not found, its a primary (in CS) - if (kind == NONE) - kind = PRIMARY; - - if (weapon_id < 1) - kind = NONE; - - return kind; + int kind = NONE; + + // Check 1. Is it a knife? + if (weapon_id == CS_WEAPON_KNIFE) + kind = KNIFE; + + // Check 2, is it a 'tool'? + if (weapon_id == CS_WEAPON_FLASHBANG || + weapon_id == CS_WEAPON_HEGRENADE || weapon_id == CS_WEAPON_SMOKEGRENADE) + kind = GRENADE; + + // Check 3, is it a secondary gun? + if (weapon_id == CS_WEAPON_P228 || + weapon_id == CS_WEAPON_ELITE || + weapon_id == CS_WEAPON_UMP45 || + weapon_id == CS_WEAPON_USP || + weapon_id == CS_WEAPON_GLOCK18 || + weapon_id == CS_WEAPON_DEAGLE || weapon_id == CS_WEAPON_FIVESEVEN) + kind = SECONDARY; + + // Check 4, is it a sniper gun? + if (weapon_id == CS_WEAPON_SCOUT || + weapon_id == CS_WEAPON_SG550 || + weapon_id == CS_WEAPON_AWP || weapon_id == CS_WEAPON_G3SG1) + kind = SNIPER; + + // When the kind of weapon is still not found, its a primary (in CS) + if (kind == NONE) + kind = PRIMARY; + + if (weapon_id < 1) + kind = NONE; + + return kind; } // Return weapon ID (depended on mod) int -UTIL_GiveWeaponId (char *name) +UTIL_GiveWeaponId(char* name) { - if (mod_id == CSTRIKE_DLL) - { - if (strcmp (name, "weapon_knife") == 0) - return CS_WEAPON_KNIFE; - - if (strcmp (name, "weapon_c4") == 0) - return CS_WEAPON_C4; - if (strcmp (name, "weapon_mp5navy") == 0) - return CS_WEAPON_MP5NAVY; - if (strcmp (name, "weapon_ak47") == 0) - return CS_WEAPON_AK47; - if (strcmp (name, "weapon_m3") == 0) - return CS_WEAPON_M3; - if (strcmp (name, "weapon_aug") == 0) - return CS_WEAPON_AUG; - if (strcmp (name, "weapon_sg552") == 0) - return CS_WEAPON_SG552; - if (strcmp (name, "weapon_m249") == 0) - return CS_WEAPON_M249; - if (strcmp (name, "weapon_xm1014") == 0) - return CS_WEAPON_XM1014; - if (strcmp (name, "weapon_p90") == 0) - return CS_WEAPON_P90; - if (strcmp (name, "weapon_tmp") == 0) - return CS_WEAPON_TMP; - if (strcmp (name, "weapon_m4a1") == 0) - return CS_WEAPON_M4A1; - if (strcmp (name, "weapon_awp") == 0) - return CS_WEAPON_AWP; - if (strcmp (name, "weapon_fiveseven") == 0) - return CS_WEAPON_FIVESEVEN; - if (strcmp (name, "weapon_ump45") == 0) - return CS_WEAPON_UMP45; - if (strcmp (name, "weapon_sg550") == 0) - return CS_WEAPON_SG550; - if (strcmp (name, "weapon_scout") == 0) - return CS_WEAPON_SCOUT; - if (strcmp (name, "weapon_mac10") == 0) - return CS_WEAPON_MAC10; - if (strcmp (name, "weapon_g3sg1") == 0) - return CS_WEAPON_G3SG1; - if (strcmp (name, "weapon_elite") == 0) - return CS_WEAPON_ELITE; - if (strcmp (name, "weapon_p228") == 0) - return CS_WEAPON_P228; - if (strcmp (name, "weapon_deagle") == 0) - return CS_WEAPON_DEAGLE; - if (strcmp (name, "weapon_usp") == 0) - return CS_WEAPON_USP; - if (strcmp (name, "weapon_glock18") == 0) - return CS_WEAPON_GLOCK18; - // Counter-Strike 1.6 - if (strcmp (name, "weapon_famas") == 0) - return CS_WEAPON_FAMAS; - if (strcmp (name, "weapon_galil") == 0) - return CS_WEAPON_GALIL; - - // TODO: Detect shield carrying. - - } - - return -1; + if (mod_id == CSTRIKE_DLL) + { + if (strcmp(name, "weapon_knife") == 0) + return CS_WEAPON_KNIFE; + + if (strcmp(name, "weapon_c4") == 0) + return CS_WEAPON_C4; + if (strcmp(name, "weapon_mp5navy") == 0) + return CS_WEAPON_MP5NAVY; + if (strcmp(name, "weapon_ak47") == 0) + return CS_WEAPON_AK47; + if (strcmp(name, "weapon_m3") == 0) + return CS_WEAPON_M3; + if (strcmp(name, "weapon_aug") == 0) + return CS_WEAPON_AUG; + if (strcmp(name, "weapon_sg552") == 0) + return CS_WEAPON_SG552; + if (strcmp(name, "weapon_m249") == 0) + return CS_WEAPON_M249; + if (strcmp(name, "weapon_xm1014") == 0) + return CS_WEAPON_XM1014; + if (strcmp(name, "weapon_p90") == 0) + return CS_WEAPON_P90; + if (strcmp(name, "weapon_tmp") == 0) + return CS_WEAPON_TMP; + if (strcmp(name, "weapon_m4a1") == 0) + return CS_WEAPON_M4A1; + if (strcmp(name, "weapon_awp") == 0) + return CS_WEAPON_AWP; + if (strcmp(name, "weapon_fiveseven") == 0) + return CS_WEAPON_FIVESEVEN; + if (strcmp(name, "weapon_ump45") == 0) + return CS_WEAPON_UMP45; + if (strcmp(name, "weapon_sg550") == 0) + return CS_WEAPON_SG550; + if (strcmp(name, "weapon_scout") == 0) + return CS_WEAPON_SCOUT; + if (strcmp(name, "weapon_mac10") == 0) + return CS_WEAPON_MAC10; + if (strcmp(name, "weapon_g3sg1") == 0) + return CS_WEAPON_G3SG1; + if (strcmp(name, "weapon_elite") == 0) + return CS_WEAPON_ELITE; + if (strcmp(name, "weapon_p228") == 0) + return CS_WEAPON_P228; + if (strcmp(name, "weapon_deagle") == 0) + return CS_WEAPON_DEAGLE; + if (strcmp(name, "weapon_usp") == 0) + return CS_WEAPON_USP; + if (strcmp(name, "weapon_glock18") == 0) + return CS_WEAPON_GLOCK18; + // Counter-Strike 1.6 + if (strcmp(name, "weapon_famas") == 0) + return CS_WEAPON_FAMAS; + if (strcmp(name, "weapon_galil") == 0) + return CS_WEAPON_GALIL; + + // TODO: Detect shield carrying. + } + + return -1; } // Return weapon ID (depended on mod) -char * -UTIL_GiveWeaponName (int id) +char* +UTIL_GiveWeaponName(int id) { - if (mod_id == CSTRIKE_DLL) - { - if (id == CS_WEAPON_C4) - return "weapon_c4"; - if (id == CS_WEAPON_MP5NAVY) - return "weapon_mp5navy"; - if (id == CS_WEAPON_AK47) - return "weapon_ak47"; - if (id == CS_WEAPON_M3) - return "weapon_m3"; - if (id == CS_WEAPON_AUG) - return "weapon_aug"; - if (id == CS_WEAPON_SG552) - return "weapon_sg552"; - if (id == CS_WEAPON_M249) - return "weapon_m249"; - if (id == CS_WEAPON_XM1014) - return "weapon_xm1014"; - if (id == CS_WEAPON_P90) - return "weapon_p90"; - if (id == CS_WEAPON_TMP) - return "weapon_tmp"; - if (id == CS_WEAPON_M4A1) - return "weapon_m4a1"; - if (id == CS_WEAPON_AWP) - return "weapon_awp"; - if (id == CS_WEAPON_FIVESEVEN) - return "weapon_fiveseven"; - if (id == CS_WEAPON_UMP45) - return "weapon_ump45"; - if (id == CS_WEAPON_SG550) - return "weapon_ag550"; - if (id == CS_WEAPON_SCOUT) - return "weapon_scout"; - if (id == CS_WEAPON_MAC10) - return "weapon_mac10"; - if (id == CS_WEAPON_G3SG1) - return "weapon_g3sg1"; - if (id == CS_WEAPON_ELITE) - return "weapon_elite"; - if (id == CS_WEAPON_P228) - return "weapon_p228"; - if (id == CS_WEAPON_DEAGLE) - return "weapon_deagle"; - if (id == CS_WEAPON_USP) - return "weapon_usp"; - if (id == CS_WEAPON_GLOCK18) - return "weapon_glock18"; - - // Counter-Strike 1.6 - if (id == CS_WEAPON_FAMAS) - return "weapon_famas"; - if (id == CS_WEAPON_GALIL) - return "weapon_galil"; - - // Unconfirmed shield - if (id == CS_WEAPON_SHIELD) - return "weapon_shield"; - - } - - return "weapon_knife"; // return knife, always good ;) + if (mod_id == CSTRIKE_DLL) + { + if (id == CS_WEAPON_C4) + return "weapon_c4"; + if (id == CS_WEAPON_MP5NAVY) + return "weapon_mp5navy"; + if (id == CS_WEAPON_AK47) + return "weapon_ak47"; + if (id == CS_WEAPON_M3) + return "weapon_m3"; + if (id == CS_WEAPON_AUG) + return "weapon_aug"; + if (id == CS_WEAPON_SG552) + return "weapon_sg552"; + if (id == CS_WEAPON_M249) + return "weapon_m249"; + if (id == CS_WEAPON_XM1014) + return "weapon_xm1014"; + if (id == CS_WEAPON_P90) + return "weapon_p90"; + if (id == CS_WEAPON_TMP) + return "weapon_tmp"; + if (id == CS_WEAPON_M4A1) + return "weapon_m4a1"; + if (id == CS_WEAPON_AWP) + return "weapon_awp"; + if (id == CS_WEAPON_FIVESEVEN) + return "weapon_fiveseven"; + if (id == CS_WEAPON_UMP45) + return "weapon_ump45"; + if (id == CS_WEAPON_SG550) + return "weapon_ag550"; + if (id == CS_WEAPON_SCOUT) + return "weapon_scout"; + if (id == CS_WEAPON_MAC10) + return "weapon_mac10"; + if (id == CS_WEAPON_G3SG1) + return "weapon_g3sg1"; + if (id == CS_WEAPON_ELITE) + return "weapon_elite"; + if (id == CS_WEAPON_P228) + return "weapon_p228"; + if (id == CS_WEAPON_DEAGLE) + return "weapon_deagle"; + if (id == CS_WEAPON_USP) + return "weapon_usp"; + if (id == CS_WEAPON_GLOCK18) + return "weapon_glock18"; + + // Counter-Strike 1.6 + if (id == CS_WEAPON_FAMAS) + return "weapon_famas"; + if (id == CS_WEAPON_GALIL) + return "weapon_galil"; + + // Unconfirmed shield + if (id == CS_WEAPON_SHIELD) + return "weapon_shield"; + } + + return "weapon_knife"; // return knife, always good ;) } // Thanks Botman for this code (from forum). void -UTIL_BotSprayLogo (edict_t * pEntity, char *logo_name) +UTIL_BotSprayLogo(edict_t* pEntity, char* logo_name) { - int index; - TraceResult pTrace; - Vector v_src, v_dest; - UTIL_MakeVectors (pEntity->v.v_angle); - v_src = pEntity->v.origin + pEntity->v.view_ofs; - v_dest = v_src + gpGlobals->v_forward * 80; - UTIL_TraceLine (v_src, v_dest, ignore_monsters, - pEntity->v.pContainingEntity, &pTrace); + int index; + TraceResult pTrace; + Vector v_src, v_dest; + UTIL_MakeVectors(pEntity->v.v_angle); + v_src = pEntity->v.origin + pEntity->v.view_ofs; + v_dest = v_src + gpGlobals->v_forward * 80; + UTIL_TraceLine(v_src, v_dest, ignore_monsters, + pEntity->v.pContainingEntity, &pTrace); - index = DECAL_INDEX (logo_name); + index = DECAL_INDEX(logo_name); - if (index < 0) - return; + if (index < 0) + return; - if ((pTrace.pHit) && (pTrace.flFraction < 1.0)) - { - if (pTrace.pHit->v.solid != SOLID_BSP) - return; + if ((pTrace.pHit) && (pTrace.flFraction < 1.0)) + { + if (pTrace.pHit->v.solid != SOLID_BSP) + return; - MESSAGE_BEGIN (MSG_BROADCAST, SVC_TEMPENTITY); + MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - if (index > 255) - { - WRITE_BYTE (TE_WORLDDECALHIGH); - index -= 256; - } - else - WRITE_BYTE (TE_WORLDDECAL); + if (index > 255) + { + WRITE_BYTE(TE_WORLDDECALHIGH); + index -= 256; + } + else + WRITE_BYTE(TE_WORLDDECAL); - WRITE_COORD (pTrace.vecEndPos.x); - WRITE_COORD (pTrace.vecEndPos.y); - WRITE_COORD (pTrace.vecEndPos.z); - WRITE_BYTE (index); + WRITE_COORD(pTrace.vecEndPos.x); + WRITE_COORD(pTrace.vecEndPos.y); + WRITE_COORD(pTrace.vecEndPos.z); + WRITE_BYTE(index); - MESSAGE_END (); + MESSAGE_END(); - EMIT_SOUND_DYN2 (pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0, - ATTN_NORM, 0, 100); - } + EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0, + ATTN_NORM, 0, 100); + } } // Give a radio message botty boy! void -UTIL_BotRadioMessage (cBot * pBot, int radio, char *arg1, char *arg2) +UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { - // To be sure the console will only change when we MAY change. - // The values will only be changed when console_nr is 0 - if (pBot->console_nr == 0) - { - switch (radio) - { - case 1: - strcpy (pBot->arg1, "radio1"); - break; - case 2: - strcpy (pBot->arg1, "radio2"); - break; - case 3: - strcpy (pBot->arg1, "radio3"); - break; - } - - strcpy (pBot->arg2, arg1); - strcpy (pBot->arg3, arg2); - pBot->console_nr = 1; // Begin message - int iExtra = (100/pBot->ipCreateRadio); - if (iExtra > 30) iExtra=30; - pBot->fDoRadio = gpGlobals->time + iExtra; - } + // To be sure the console will only change when we MAY change. + // The values will only be changed when console_nr is 0 + if (pBot->console_nr == 0) + { + switch (radio) + { + case 1: + strcpy(pBot->arg1, "radio1"); + break; + case 2: + strcpy(pBot->arg1, "radio2"); + break; + case 3: + strcpy(pBot->arg1, "radio3"); + break; + } + + strcpy(pBot->arg2, arg1); + strcpy(pBot->arg3, arg2); + pBot->console_nr = 1; // Begin message + int iExtra = (100 / pBot->ipCreateRadio); + if (iExtra > 30) iExtra = 30; + pBot->fDoRadio = gpGlobals->time + iExtra; + } } ////////////////////////////////// // UTIL_getGrenadeType function // - Stefan ////////////////////////////////// int -UTIL_GetGrenadeType (edict_t * pEntity) +UTIL_GetGrenadeType(edict_t* pEntity) { + char model_name[32]; - char model_name[32]; - - strcpy (model_name, STRING (pEntity->v.model)); + strcpy(model_name, STRING(pEntity->v.model)); - if (strcmp (model_name, "models/w_hegrenade.mdl") == 0) - return 1; // He grenade - if (strcmp (model_name, "models/w_flashbang.mdl") == 0) - return 2; // FlashBang - if (strcmp (model_name, "models/w_smokegrenade.mdl") == 0) - return 3; // SmokeGrenade - if (strcmp (model_name, "models/w_c4.mdl") == 0) - return 4; // C4 Explosive - - return 0; + if (strcmp(model_name, "models/w_hegrenade.mdl") == 0) + return 1; // He grenade + if (strcmp(model_name, "models/w_flashbang.mdl") == 0) + return 2; // FlashBang + if (strcmp(model_name, "models/w_smokegrenade.mdl") == 0) + return 3; // SmokeGrenade + if (strcmp(model_name, "models/w_c4.mdl") == 0) + return 4; // C4 Explosive + return 0; } // 2 functions from podbot source unsigned short -FixedUnsigned16 (float value, float scale) +FixedUnsigned16(float value, float scale) { - int output; + int output; - output = value * scale; - if (output < 0) - output = 0; - if (output > 0xFFFF) - output = 0xFFFF; + output = value * scale; + if (output < 0) + output = 0; + if (output > 0xFFFF) + output = 0xFFFF; - return (unsigned short) output; + return (unsigned short)output; } short -FixedSigned16 (float value, float scale) +FixedSigned16(float value, float scale) { - int output; + int output; - output = value * scale; + output = value * scale; - if (output > 32767) - output = 32767; + if (output > 32767) + output = 32767; - if (output < -32768) - output = -32768; + if (output < -32768) + output = -32768; - return (short) output; + return (short)output; } // Using POD/SDK source to print nice messages on the client machine void -HUD_DrawString (int r, int g, int b, char *msg, edict_t * edict) +HUD_DrawString(int r, int g, int b, char* msg, edict_t* edict) { - // FROM PODBOT SOURCE - // Hacked together Version of HUD_DrawString - MESSAGE_BEGIN (MSG_ONE, SVC_TEMPENTITY, NULL, edict); - WRITE_BYTE (TE_TEXTMESSAGE); - WRITE_BYTE (1); - WRITE_SHORT (FixedSigned16 (-1, 1 << 13)); - WRITE_SHORT (FixedSigned16 (0, 1 << 13)); - WRITE_BYTE (2); - WRITE_BYTE (r); //r - WRITE_BYTE (g); //g - WRITE_BYTE (b); //b - WRITE_BYTE (0); - WRITE_BYTE (255); - WRITE_BYTE (255); - WRITE_BYTE (255); - WRITE_BYTE (200); - WRITE_SHORT (FixedUnsigned16 (0.0078125, 1 << 8)); - WRITE_SHORT (FixedUnsigned16 (2, 1 << 8)); - WRITE_SHORT (FixedUnsigned16 (6, 1 << 8)); - WRITE_SHORT (FixedUnsigned16 (0.1, 1 << 8)); - WRITE_STRING ((const char *) &msg[0]); - MESSAGE_END (); + // FROM PODBOT SOURCE + // Hacked together Version of HUD_DrawString + MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, edict); + WRITE_BYTE(TE_TEXTMESSAGE); + WRITE_BYTE(1); + WRITE_SHORT(FixedSigned16(-1, 1 << 13)); + WRITE_SHORT(FixedSigned16(0, 1 << 13)); + WRITE_BYTE(2); + WRITE_BYTE(r); //r + WRITE_BYTE(g); //g + WRITE_BYTE(b); //b + WRITE_BYTE(0); + WRITE_BYTE(255); + WRITE_BYTE(255); + WRITE_BYTE(255); + WRITE_BYTE(200); + WRITE_SHORT(FixedUnsigned16(0.0078125, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(2, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(6, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(0.1, 1 << 8)); + WRITE_STRING((const char*)&msg[0]); + MESSAGE_END(); } - void -UTIL_FixAngles (Vector * Angles) +UTIL_FixAngles(Vector* Angles) { - if (Angles->x > 180.0) - Angles->x -= 360.0; - if (Angles->x < -180.0) - Angles->x += 360.0; - if (Angles->y > 180.0) - Angles->y -= 360.0; - if (Angles->y < -180.0) - Angles->y += 360.0; - - Angles->z = 0.0; + if (Angles->x > 180.0) + Angles->x -= 360.0; + if (Angles->x < -180.0) + Angles->x += 360.0; + if (Angles->y > 180.0) + Angles->y -= 360.0; + if (Angles->y < -180.0) + Angles->y += 360.0; + + Angles->z = 0.0; } // POD SAYING: -void UTIL_SayTextBot( const char *pText,cBot *pBot) -{ - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG ("SayText", -1); - +void UTIL_SayTextBot(const char* pText, cBot* pBot) +{ + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); + char szTemp[160]; - char szName[BOT_NAME_LEN+1]; - int i=0; - - // clear out - memset (szTemp, 0, sizeof (szTemp)); - memset (szName, 0, sizeof (szName)); + char szName[BOT_NAME_LEN + 1]; + int i = 0; + + // clear out + memset(szTemp, 0, sizeof(szTemp)); + memset(szName, 0, sizeof(szName)); // init - szTemp[0]=2; + szTemp[0] = 2; - int entind=ENTINDEX(pBot->pEdict); + int entind = ENTINDEX(pBot->pEdict); - if(IsAlive(pBot->pEdict)) + if (IsAlive(pBot->pEdict)) { - strcpy(szName,pBot->name); + strcpy(szName, pBot->name); for (i = 1; i <= gpGlobals->maxClients; i++) - { - edict_t *pPlayer = INDEXENT (i); + { + edict_t* pPlayer = INDEXENT(i); // valid if (pPlayer) if (IsAlive(pPlayer)) // alive - { - MESSAGE_BEGIN( MSG_ONE, gmsgSayText,NULL,pPlayer); + { + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pPlayer); WRITE_BYTE(entind); - sprintf(&szTemp[1],"%s : %s",szName,pText); + sprintf(&szTemp[1], "%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } @@ -1020,36 +1013,34 @@ void UTIL_SayTextBot( const char *pText,cBot *pBot) } else { - strcpy(szName,pBot->name); + strcpy(szName, pBot->name); for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT (i); + edict_t* pPlayer = INDEXENT(i); if (pPlayer) if (!IsAlive(pPlayer)) { - MESSAGE_BEGIN( MSG_ONE, gmsgSayText,NULL,pPlayer); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, NULL, pPlayer); WRITE_BYTE(entind); - sprintf(&szTemp[1],"*DEAD*%s : %s",szName,pText); + sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } } } - // pass through on ChatEngine (not always) - if (RANDOM_LONG(0,100) < 90) + if (RANDOM_LONG(0, 100) < 90) { char chSentence[80]; - memset (chSentence, 0, sizeof (chSentence)); - + memset(chSentence, 0, sizeof(chSentence)); + // copy pText to chSentence strcpy(chSentence, pText); // pass through - ChatEngine.set_sentence(pBot->name,chSentence); + ChatEngine.set_sentence(pBot->name, chSentence); } - } // $Log: util.cpp,v $ @@ -1063,5 +1054,4 @@ void UTIL_SayTextBot( const char *pText,cBot *pBot) // - added two other utilities DrawNodes & DumpNodes // - updated README file // - fixed compilation warnings (thanks dstruct2k) -// - +// \ No newline at end of file diff --git a/Bsp2Rbn/world.cpp b/Bsp2Rbn/world.cpp index ac46011..d0bbc06 100644 --- a/Bsp2Rbn/world.cpp +++ b/Bsp2Rbn/world.cpp @@ -15,7 +15,7 @@ // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License for more details at: // http://www.gnu.org/copyleft/gpl.html @@ -27,7 +27,6 @@ #include #include - #include "cmdlib.h" #include "mathlib.h" #include "bspfile.h" @@ -39,144 +38,140 @@ World::World(void) { } - World::~World(void) { - FreeWorld(); + FreeWorld(); } - void World::FreeWorld(void) { - FreeEntities(); - - if (dmodels) - { - free(dmodels); - dmodels = NULL; - nummodels = 0; - } - - if (dvisdata) - { - free(dvisdata); - dvisdata = NULL; - visdatasize = 0; - } - - if (dlightdata) - { - free(dlightdata); - dlightdata = NULL; - lightdatasize = 0; - } - - if (dtexdata) - { - free(dtexdata); - dtexdata = NULL; - texdatasize = 0; - } - - if (dentdata) - { - free(dentdata); - dentdata = NULL; - entdatasize = 0; - } - - if (dleafs) - { - free(dleafs); - dleafs = NULL; - numleafs = 0; - } - - if (dplanes) - { - free(dplanes); - dplanes = NULL; - numplanes = 0; - } - - if (dvertexes) - { - free(dvertexes); - dvertexes = NULL; - numvertexes = 0; - } - - if (dnodes) - { - free(dnodes); - dnodes = NULL; - numnodes = 0; - } - - if (texinfo) - { - free(texinfo); - texinfo = NULL; - numtexinfo = 0; - } - - if (dfaces) - { - free(dfaces); - dfaces = NULL; - numfaces = 0; - } - - if (dclipnodes) - { - free(dclipnodes); - dclipnodes = NULL; - numclipnodes = 0; - } - - if (dedges) - { - free(dedges); - dedges = NULL; - numedges = 0; - } - - if (dmarksurfaces) - { - free(dmarksurfaces); - dmarksurfaces = NULL; - nummarksurfaces = 0; - } - - if (dsurfedges) - { - free(dsurfedges); - dsurfedges = NULL; - numsurfedges = 0; - } + FreeEntities(); + + if (dmodels) + { + free(dmodels); + dmodels = NULL; + nummodels = 0; + } + + if (dvisdata) + { + free(dvisdata); + dvisdata = NULL; + visdatasize = 0; + } + + if (dlightdata) + { + free(dlightdata); + dlightdata = NULL; + lightdatasize = 0; + } + + if (dtexdata) + { + free(dtexdata); + dtexdata = NULL; + texdatasize = 0; + } + + if (dentdata) + { + free(dentdata); + dentdata = NULL; + entdatasize = 0; + } + + if (dleafs) + { + free(dleafs); + dleafs = NULL; + numleafs = 0; + } + + if (dplanes) + { + free(dplanes); + dplanes = NULL; + numplanes = 0; + } + + if (dvertexes) + { + free(dvertexes); + dvertexes = NULL; + numvertexes = 0; + } + + if (dnodes) + { + free(dnodes); + dnodes = NULL; + numnodes = 0; + } + + if (texinfo) + { + free(texinfo); + texinfo = NULL; + numtexinfo = 0; + } + + if (dfaces) + { + free(dfaces); + dfaces = NULL; + numfaces = 0; + } + + if (dclipnodes) + { + free(dclipnodes); + dclipnodes = NULL; + numclipnodes = 0; + } + + if (dedges) + { + free(dedges); + dedges = NULL; + numedges = 0; + } + + if (dmarksurfaces) + { + free(dmarksurfaces); + dmarksurfaces = NULL; + nummarksurfaces = 0; + } + + if (dsurfedges) + { + free(dsurfedges); + dsurfedges = NULL; + numsurfedges = 0; + } } - -void World::LoadBSP(char *bspfile) +void World::LoadBSP(char* bspfile) { - char bsp_filename[256]; - char pathname[256]; - bool bsp_found; - int index, mod_index; - char modname[256]; - int len; - - bsp_found = FALSE; + char bsp_filename[256]; + char pathname[256]; + bool bsp_found; + int index, mod_index; + char modname[256]; + int len; - strcpy(bspname, bspfile); + bsp_found = FALSE; - if (FileTime(bspname) != -1) // does the specified file exist? - LoadBSPFile(bspname); - else - fprintf(stderr,"Cannot load file %s\n",bspname) ; + strcpy(bspname, bspfile); - ParseEntities(); + if (FileTime(bspname) != -1) // does the specified file exist? + LoadBSPFile(bspname); + else + fprintf(stderr, "Cannot load file %s\n", bspname); - LoadEntVars(); -} + ParseEntities(); + LoadEntVars(); +} \ No newline at end of file diff --git a/Bsp2Rbn/world.h b/Bsp2Rbn/world.h index 18233b2..9b68ae8 100644 --- a/Bsp2Rbn/world.h +++ b/Bsp2Rbn/world.h @@ -15,7 +15,7 @@ // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License for more details at: // http://www.gnu.org/copyleft/gpl.html @@ -31,18 +31,17 @@ #ifndef WORLD_H #define WORLD_H - class World { - public: +public: - char bspname[256]; // name of the currently loaded BSP file + char bspname[256]; // name of the currently loaded BSP file - World(void); - ~World(void); + World(void); + ~World(void); - void FreeWorld(void); - void LoadBSP(char *bspfile); + void FreeWorld(void); + void LoadBSP(char* bspfile); }; #ifndef __linux__ @@ -50,4 +49,3 @@ BOOL CenterWindow(HWND hWnd); #endif #endif - From 83b6b3d100119c9b9bc2f2ffdefe73eed9cbf603 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 8 May 2022 00:44:41 +0100 Subject: [PATCH 061/114] VS Project adjusted --- Bsp2Rbn/Bsp2Rbn.vcxproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Bsp2Rbn/Bsp2Rbn.vcxproj b/Bsp2Rbn/Bsp2Rbn.vcxproj index 9064879..fcbab82 100644 --- a/Bsp2Rbn/Bsp2Rbn.vcxproj +++ b/Bsp2Rbn/Bsp2Rbn.vcxproj @@ -49,7 +49,7 @@ Win32Proj {85813a68-52fb-4f75-91ba-dd3b6c50fd68} Bsp2Rbn - 10.0 + 10.0.17763.0 @@ -129,7 +129,6 @@ WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true ..\;..\dependencies\metamod-hl1\metamod;..\dependencies\hlsdk\common;..\dependencies\hlsdk\engine;..\dependencies\hlsdk\dlls;..\dependencies\hlsdk\pm_shared;..\dependencies\hlsdk\public;%(AdditionalIncludeDirectories) - /Zc:strictStrings %(AdditionalOptions) Default @@ -161,7 +160,6 @@ NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true ..\;..\dependencies\metamod-hl1\metamod;..\dependencies\hlsdk\common;..\dependencies\hlsdk\engine;..\dependencies\hlsdk\dlls;..\dependencies\hlsdk\pm_shared;..\dependencies\hlsdk\public;%(AdditionalIncludeDirectories) - /Zc:strictStrings %(AdditionalOptions) Console From 528365bd9b1a5ad881d417ee18c1692bff13a32e Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 8 May 2022 00:47:09 +0100 Subject: [PATCH 062/114] Update Bsp2Rbn.vcxproj --- Bsp2Rbn/Bsp2Rbn.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bsp2Rbn/Bsp2Rbn.vcxproj b/Bsp2Rbn/Bsp2Rbn.vcxproj index fcbab82..0c9f2ae 100644 --- a/Bsp2Rbn/Bsp2Rbn.vcxproj +++ b/Bsp2Rbn/Bsp2Rbn.vcxproj @@ -49,7 +49,7 @@ Win32Proj {85813a68-52fb-4f75-91ba-dd3b6c50fd68} Bsp2Rbn - 10.0.17763.0 + 10.0 From f7ef2bc1e545d2b19534251c81b5b5748189c888 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 8 May 2022 01:06:46 +0100 Subject: [PATCH 063/114] Update todo.txt --- todo.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/todo.txt b/todo.txt index 68b7599..8c6861a 100644 --- a/todo.txt +++ b/todo.txt @@ -7,5 +7,6 @@ - Improve 'unstucking'... when not stuck by hostages and how to attack glass or vent grills in order to proceed. - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ +- To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including unvaultable edges and tall crates - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up \ No newline at end of file From e5adb903cc48ce7f491966256acb6409ebfe9291 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 10 May 2022 12:56:12 +0100 Subject: [PATCH 064/114] Version v4.0.5-beta3 out --- NodeMachine.cpp | 15 ++++++++++----- NodeMachine.h | 4 ++-- bot_func.cpp | 2 +- bot_func.h | 2 +- build.cpp | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index cb8d6a4..1341f3e 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -371,7 +371,7 @@ Vector cNodeMachine::node_vector(int iNode) const return Nodes[iNode].origin; } - return Vector(9999, 9999, 9999); + return {9999, 9999, 9999}; } // Input: Vector, Output X and Y Meredians @@ -465,8 +465,13 @@ bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { return false; } -int cNodeMachine::node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance) //Experimental & Incomplete [APG]RoboCop[CL] +int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance) //Experimental & Incomplete [APG]RoboCop[CL] { + // check if node is dangerous + //int iDangerous = 0; + //int iDangerousCount = 0; + //int iDangerousIndex = 0; + return 0; } @@ -694,7 +699,7 @@ int cNodeMachine::freeNeighbourNodeIndex(const tNode *Node) { return -1; } -int cNodeMachine::is_neighbour_node(tNode node, int iNode) +int cNodeMachine::is_neighbour_node(const tNode& node, int iNode) { for (int i = 0; i < MAX_NEIGHBOURS; i++) { if (node.iNeighbour[i] == iNode) { @@ -729,7 +734,7 @@ static Vector FloorBelow(const Vector& V) { // First use this hull int HullNumber = human_hull; - int HullHeight = 36; + float HullHeight = 36.0f; // Bump V a little higher (to allow for a steep climb) Vector UpALittle = V + Vector(0, 0, HullHeight); @@ -1900,7 +1905,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { return; } - int distance = NODE_ZONE * 2; + float distance = NODE_ZONE * 2; // some goals require very close nodes if (goalType == GOAL_HOSTAGE || diff --git a/NodeMachine.h b/NodeMachine.h index 93280d5..3c8fe89 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -62,7 +62,7 @@ class cNodeMachine { static int freeNeighbourNodeIndex(const tNode *Node); - static int is_neighbour_node(tNode node, int iNode); + static int is_neighbour_node(const tNode& node, int iNode); // ----------------- void init(); // Init (info)nodes @@ -105,7 +105,7 @@ class cNodeMachine { static bool node_on_crate(const Vector& vOrigin, edict_t *pEdict); - static int node_dangerous(int iTeam, Vector vOrigin, float fMaxDistance); + static int node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance); int node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict); diff --git a/bot_func.cpp b/bot_func.cpp index a7e94e9..5256b87 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -690,7 +690,7 @@ int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { return -1; } -int FUNC_FindFarWaypoint(cBot* pBot, Vector avoid, bool safest) //Experimental [APG]RoboCop[CL] +int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest) //Experimental [APG]RoboCop[CL] { // Find a waypoint that is far away from the enemy. // If safest is true, then we want the safest waypoint. diff --git a/bot_func.h b/bot_func.h index 6f7c40f..d5528b3 100644 --- a/bot_func.h +++ b/bot_func.h @@ -69,7 +69,7 @@ bool FUNC_TakeCover(cBot * pBot); int FUNC_EdictHoldsWeapon(const edict_t * pEdict); -int FUNC_FindFarWaypoint(cBot * pBot, Vector avoid, bool safest); +int FUNC_FindFarWaypoint(cBot * pBot, const Vector& avoid, bool safest); int FUNC_FindCover(const cBot* pBot); int FUNC_PlayerSpeed(const edict_t * edict); diff --git a/build.cpp b/build.cpp index 788bc88..d0f1555 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.5-beta2"; +const char *rb_version_nr = "4.0.5-beta3"; From 3700bb4a2f5258c94580de2bc81d7c09d1867718 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Tue, 10 May 2022 13:25:17 +0100 Subject: [PATCH 065/114] AMBuild updated --- AMBuildScript | 12 ++++++------ todo.txt | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index e04d482..ea116a2 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -158,12 +158,12 @@ binary.sources += [ 'util.cpp', ] -builder.RunBuildScripts( - [ - 'Bsp2Rbn/AMBuilder', - ], - #{ 'AMXX': AMXX } -) +#builder.RunBuildScripts( +# [ +# 'Bsp2Rbn/AMBuilder', +# ], +# #{ 'AMXX': AMXX } +#) # # Run scripts, add binaries diff --git a/todo.txt b/todo.txt index 8c6861a..4a42eb7 100644 --- a/todo.txt +++ b/todo.txt @@ -7,6 +7,6 @@ - Improve 'unstucking'... when not stuck by hostages and how to attack glass or vent grills in order to proceed. - Allow bots to autovacate for human players - Prevent bots from Team Killing when a player joins T in CZ -- To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including unvaultable edges and tall crates +- To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up \ No newline at end of file From 1fbefec6050d2c3ea67b218a9649be37c3fdc71c Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 22 Oct 2022 22:30:00 +0100 Subject: [PATCH 066/114] Reverted Node Zone --- NodeDataTypes.h | 68 ++++++++++++++++++++++++------------------------- todo.txt | 3 ++- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 1109cc7..0323a46 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -36,13 +36,13 @@ #define NODEDATATYPES_H // player sizes for path_connection_walkable -#define MAX_JUMPHEIGHT 60 // confirmed // 45 without crouching -#define MAX_FALLHEIGHT 130 // not confirmed (200 is to high, adjusted) -#define MAX_STAIRHEIGHT 18 // confirmed -#define HEAD_HEIGHT 72 // confirmed -#define ORIGIN_HEIGHT 36 // confirmed (?) -#define CROUCHED_HEIGHT 37 // confirmed -#define PLAYER_WIDTH 32 // confirmed (?) +#define MAX_JUMPHEIGHT 60 // confirmed // 45 without crouching +#define MAX_FALLHEIGHT 130 // not confirmed (200 is to high, adjusted) +#define MAX_STAIRHEIGHT 18 // confirmed +#define HEAD_HEIGHT 72 // confirmed +#define ORIGIN_HEIGHT 36 // confirmed (?) +#define CROUCHED_HEIGHT 37 // confirmed +#define PLAYER_WIDTH 32 // confirmed (?) // File version // Version 1.0 @@ -54,10 +54,10 @@ #define FILE_EXP_VER2 2 // Node bits (for navigational performance) -#define BIT_LADDER (1 << 0) -#define BIT_WATER (1 << 1) -#define BIT_JUMP (1 << 2) -#define BIT_DUCK (1 << 3) +#define BIT_LADDER (1 << 0) +#define BIT_WATER (1 << 1) +#define BIT_JUMP (1 << 2) +#define BIT_DUCK (1 << 3) #define BIT_DUCKJUMP (1 << 4) // Path flags @@ -67,7 +67,7 @@ #define PATH_CAMP 31 // camp path // Visibility flags -#define VIS_INVALID 96 // BERKED +#define VIS_INVALID 96 // BERKED #define VIS_UNKNOWN 97 #define VIS_VISIBLE 98 #define VIS_BLOCKED 99 @@ -76,34 +76,34 @@ #define MAX_GOALS 75 // Node types / goal types -#define GOAL_SPAWNCT 1 -#define GOAL_SPAWNT 2 -#define GOAL_BOMBSPOT 3 -#define GOAL_BOMB 4 // updates all the time -#define GOAL_HOSTAGE 5 // updates all the time -#define GOAL_RESCUEZONE 6 // rescue zone (for hostages) -#define GOAL_CONTACT 7 // zones where teams often have contact -#define GOAL_IMPORTANT 8 -#define GOAL_VIP 9 // as_ maps VIP starting point -#define GOAL_VIPSAFETY 10 // as_ maps VIP safety zone -#define GOAL_ESCAPEZONE 11 // es_ maps escape zone -#define GOAL_WEAPON 12 // pre-dropped weapons like in awp_map -#define GOAL_NONE 99 +#define GOAL_SPAWNCT 1 +#define GOAL_SPAWNT 2 +#define GOAL_BOMBSPOT 3 +#define GOAL_BOMB 4 // updates all the time +#define GOAL_HOSTAGE 5 // updates all the time +#define GOAL_RESCUEZONE 6 // rescue zone (for hostages) +#define GOAL_CONTACT 7 // zones where teams often have contact +#define GOAL_IMPORTANT 8 +#define GOAL_VIP 9 // as_ maps VIP starting point +#define GOAL_VIPSAFETY 10 // as_ maps VIP safety zone +#define GOAL_ESCAPEZONE 11 // es_ maps escape zone +#define GOAL_WEAPON 12 // pre-dropped weapons like in awp_map +#define GOAL_NONE 99 // Node costs -#define NODE_DANGER 8192 // Value -#define NODE_DANGER_STEP 0.5f // Step to take to get dangerous -#define NODE_DANGER_DIST 512.0f // Distance +#define NODE_DANGER 8192 // Value +#define NODE_DANGER_STEP 0.5f // Step to take to get dangerous +#define NODE_DANGER_DIST 512.0f // Distance // Node contact costs -#define NODE_CONTACT 8192 -#define NODE_CONTACT_STEP 0.2 -#define NODE_CONTACT_DIST 128 +#define NODE_CONTACT 8192 +#define NODE_CONTACT_STEP 0.2 +#define NODE_CONTACT_DIST 128 // Node boundries -#define MAX_NODES 4096 -#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 64 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +#define MAX_NODES 4096 +#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] +#define NODE_ZONE 45 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember diff --git a/todo.txt b/todo.txt index 4a42eb7..c577dca 100644 --- a/todo.txt +++ b/todo.txt @@ -9,4 +9,5 @@ - Prevent bots from Team Killing when a player joins T in CZ - To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) -- To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up \ No newline at end of file +- To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up +- Ensure that the RealBot personality directories are correctly assigned \ No newline at end of file From 3418f61d0bb2f50c4713373ad102e846485c15e9 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 22 Oct 2022 22:40:14 +0100 Subject: [PATCH 067/114] Added Chat Delay to prevent chat spam --- bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.cpp b/bot.cpp index d4a9d3f..7065a71 100644 --- a/bot.cpp +++ b/bot.cpp @@ -136,7 +136,7 @@ void cBot::SpawnInit() { fUpdateTime = gpGlobals->time; fLastRunPlayerMoveTime = gpGlobals->time - 0.1f; fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5.0f); + fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); From 386933cd4638fdd5ba27589e76a768ef82411f9f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 22 Oct 2022 23:13:07 +0100 Subject: [PATCH 068/114] converting floats --- NodeMachine.cpp | 20 ++++++++++---------- bot.cpp | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 1341f3e..96fc788 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -3397,7 +3397,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // DETERMINE GOAL / FIND GOAL // Loop through all goals. - float highestScore = 0.0; + float highestScore = 0.0f; int iFinalGoalNode = -1; int iFinalGoalIndex = -1; @@ -3485,19 +3485,19 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->isEscortingHostages()) { pBot->rprint("I am escorting hostages - assuming ct spawn is rescue zone and prioritizing"); // highest priority - score = 2.0; + score = 2.0f; } } } if (goalType == GOAL_HOSTAGE) { // counter-terrorist should - float goalscore = 0.0; + float goalscore = 0.0f; if (pBot->isCounterTerrorist()) { if (pBot->isEscortingHostages()) { pBot->rprint("I am escorting hostages - should ignore existing hostages"); // already escorting hostages, low interest for other hostages - goalscore = 0.5; + goalscore = 0.5f; } else { // always go to the most furthest hostage spot, and add some randomness here, else // all bots go to there. @@ -3573,11 +3573,11 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { pBot->rprint_trace("path_think/determine goal", "We know where the C4 is planted, but unfortunately we can't find a close node to the planted c4."); // we can't find a node close to the c4, so we gamble - goalscore = 2.0; // pick + goalscore = 2.0f; // pick } } else { pBot->rprint_trace("path_think/determine goal", "No clue where bomb is, picking bombspot to evaluate"); - goalscore = 2.0; // pick any bombspot + goalscore = 2.0f; // pick any bombspot } } else { pBot->rprint_trace("path_think/determine goal", "Bomb is not planted"); @@ -3625,7 +3625,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { { // Maximum importance when acting as T if (pBot->iTeam == 1) { - score = 2.0; + score = 2.0f; } } @@ -4405,8 +4405,8 @@ static void WriteDebugBitmap(const char *filename) { void cNodeMachine::FindMinMax() const { - minx = miny = 9999.0; - maxx = maxy = -9999.0; + minx = miny = 9999.0f; + maxx = maxy = -9999.0f; for (int i = 0; (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); i++) { @@ -4568,7 +4568,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) pBot->vHead = VecBModelOrigin(pEntityHit); pBot->vBody = pBot->vHead; UTIL_BotPressKey(pBot, IN_USE); - pBot->setTimeToWait(0.5); + pBot->setTimeToWait(0.5f); pBot->fButtonTime = gpGlobals->time + 5; pBot->pButtonEdict = nullptr; diff --git a/bot.cpp b/bot.cpp index 7065a71..5d8011f 100644 --- a/bot.cpp +++ b/bot.cpp @@ -309,7 +309,7 @@ void cBot::NewRound() { fLastRunPlayerMoveTime = gpGlobals->time; fCheckHostageStatusTimer = gpGlobals->time; fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.5f, 5.0f); + fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); fMemoryTime = gpGlobals->time; fDoRadio = gpGlobals->time; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); @@ -429,7 +429,7 @@ void cBot::NewRound() { bFirstOutOfSight = false; - f_strafe_speed = 0.0; + f_strafe_speed = 0.0f; // ------------------------ // VECTORS From bb39de5d33d43711a735e1a946b9397ffe6a0cd4 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 22 Oct 2022 23:28:33 +0100 Subject: [PATCH 069/114] Update bot.cpp --- bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.cpp b/bot.cpp index 5d8011f..565f01c 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1003,7 +1003,7 @@ void cBot::FireWeapon() { } // ------------------------------------------------------------ - float fDistance = 50; + float fDistance = 50.0f; if (hasEnemy()) { fDistance = func_distance(pEdict->v.origin, pEnemyEdict->v.origin); From 702f02ecb0010232e4039a5ac004085524edffc4 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 23 Oct 2022 01:15:10 +0100 Subject: [PATCH 070/114] Neatened Scripts --- Makefile | 2 +- NodeMachine.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3c1568c..1431dc9 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ META_DIR = ./dependencies/metamod-hl1/metamod HLSDK_DIR = ./dependencies/hlsdk BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -Dlinux=1 -CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s -pipe \ +CPPFLAGS = ${BASEFLAGS} ${ARCHFLAG} -O2 -mtune=generic -march=i686 -mmmx -msse -msse2 -O2 -mfpmath=sse -s \ -Wno-write-strings -Wno-attributes -std=gnu++14 -static-libstdc++ -shared-libgcc \ -I"${META_DIR}" -I"${HLSDK_DIR}/common" -I"${HLSDK_DIR}/dlls" \ -I"${HLSDK_DIR}/engine" -I"${HLSDK_DIR}/pm_shared" -I"${HLSDK_DIR}/public" diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 96fc788..8d57f5c 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -465,7 +465,7 @@ bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { return false; } -int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance) //Experimental & Incomplete [APG]RoboCop[CL] +int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance) //TODO: Experimental & Incomplete [APG]RoboCop[CL] { // check if node is dangerous //int iDangerous = 0; @@ -507,7 +507,7 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE const int iNode = Meredians[iX][iY].iNodes[i]; -// if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us + //if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us const float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); if (distanceFromTo < dist) { From 43dd9ec044ab326120f1c6376b839c1a7a65c7fc Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Wed, 2 Nov 2022 15:07:15 +0000 Subject: [PATCH 071/114] Reducing sizebuf_t crashes --- dll.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dll.cpp b/dll.cpp index f5f7997..b0593fe 100644 --- a/dll.cpp +++ b/dll.cpp @@ -834,7 +834,7 @@ void StartFrame() { if (add_timer > gpGlobals->time && internet_addbot) { internet_addbot = false; Game.createBot(nullptr, nullptr, nullptr, nullptr, nullptr); - bot_check_time = gpGlobals->time + 5.0f; + bot_check_time = gpGlobals->time + 8.0f; } } @@ -949,8 +949,8 @@ void StartFrame() { // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function f_minplayers_think = gpGlobals->time + 15; // do not check this for 15 seconds from now - respawn_time = gpGlobals->time + 3.0f; // set next respawn time - bot_check_time = gpGlobals->time + 5.0f; + respawn_time = gpGlobals->time + 5.0f; // set next respawn time + bot_check_time = gpGlobals->time + 8.0f; } else { respawn_time = 0.0f; } @@ -1155,7 +1155,7 @@ void ProcessBotCfgFile() { bot_cfg_fp = nullptr; - bot_cfg_pause_time = 0.0; + bot_cfg_pause_time = 5.0; } cmd_line[cmd_index] = 0; // terminate the command line @@ -1278,7 +1278,7 @@ void RealBot_ServerCommand() { ATTN_NORM, 0, 100); } else if (FStrEq(pcmd, "add")) { const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); - bot_check_time = gpGlobals->time + 5.0f; + bot_check_time = gpGlobals->time + 8.0f; if (iStatus == GAME_MSG_SUCCESS) sprintf(cMessage, "REALBOT: Successfully created bot."); From b0befcb76b3f52eb52ffbade0d57036ed962bb91 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 7 Nov 2022 20:11:12 +0000 Subject: [PATCH 072/114] Added more delay for bot_cfg_pause_time --- dll.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dll.cpp b/dll.cpp index b0593fe..f9812ce 100644 --- a/dll.cpp +++ b/dll.cpp @@ -99,7 +99,7 @@ int internet_min_interval = 10; // Counter-Strike 1.6 or 1.5 int counterstrike = 0; // Default 1.5 -//void UpdateClientData(const edict_s *ent, int sendweapons, clientdata_s *cd); //Not used? [APG]RoboCop[CL] +void UpdateClientData(const edict_s *ent, int sendweapons, clientdata_s *cd); //Not used? [APG]RoboCop[CL] void ProcessBotCfgFile(); @@ -1109,6 +1109,10 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { RETURN_META(MRES_IGNORED); }*/ +void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) //TODO: Needed implemented +{ +} + void ProcessBotCfgFile() { char cmd_line[256]; static char server_cmd[80]; @@ -1155,7 +1159,7 @@ void ProcessBotCfgFile() { bot_cfg_fp = nullptr; - bot_cfg_pause_time = 5.0; + bot_cfg_pause_time = 8.0f; // wait 8 seconds before starting } cmd_line[cmd_index] = 0; // terminate the command line From 594c72f12a784f9416d5d3a64618447d49293c2f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 7 Nov 2022 20:12:49 +0000 Subject: [PATCH 073/114] Added delay for respawn_time --- dll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dll.cpp b/dll.cpp index f9812ce..7b50f26 100644 --- a/dll.cpp +++ b/dll.cpp @@ -949,7 +949,7 @@ void StartFrame() { // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function f_minplayers_think = gpGlobals->time + 15; // do not check this for 15 seconds from now - respawn_time = gpGlobals->time + 5.0f; // set next respawn time + respawn_time = gpGlobals->time + 7.0f; // set next respawn time bot_check_time = gpGlobals->time + 8.0f; } else { respawn_time = 0.0f; From 2d8ac5fed55b7f86b2edb86e824a95a4237ad868 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 7 Nov 2022 20:15:55 +0000 Subject: [PATCH 074/114] Added sizebuf_t comment --- dll.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dll.cpp b/dll.cpp index 7b50f26..bd70dc8 100644 --- a/dll.cpp +++ b/dll.cpp @@ -949,6 +949,7 @@ void StartFrame() { // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function f_minplayers_think = gpGlobals->time + 15; // do not check this for 15 seconds from now + // Added more delay to prevent possible "Tried to write to uninitialized sizebuf_t" crashes - [APG]RoboCop[CL] respawn_time = gpGlobals->time + 7.0f; // set next respawn time bot_check_time = gpGlobals->time + 8.0f; } else { From acd23e36251bc599159a07d9c6422791afd6d076 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 10 Dec 2022 14:13:15 +0000 Subject: [PATCH 075/114] AMBuild updated --- AMBuildScript | 5 ++++- dll.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index ea116a2..4b59baf 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -73,6 +73,7 @@ if cxx.like('gcc'): '-Wno-unused-value', '-fno-strict-aliasing', '-fPIC', + '-msse2', '-m32' ] @@ -95,6 +96,8 @@ elif cxx.like('msvc'): ] cxx.cxxflags += [ + '/std:c++14', + '/arch:SSE2', '/EHsc' ] @@ -106,7 +109,7 @@ elif cxx.like('msvc'): ] if builder.options.opt == '1': - cxx.cflags += ['/Ox'] + cxx.cflags += ['/O2'] cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] if builder.options.debug == '1': diff --git a/dll.cpp b/dll.cpp index bd70dc8..429868c 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1250,7 +1250,7 @@ void RealBot_ServerCommand() { if (FStrEq(pcmd, "help")) { // Give information bSendMessage = false; // do not use 'standard' stuff - SERVER_PRINT("=====================================\n");; + SERVER_PRINT("=====================================\n"); SERVER_PRINT("Syntax: realbot [command] [arg1/subcommand] [arg2] [arg3] [arg4]\n\n"); SERVER_PRINT("List of most-used commands; for full command list read the readme.\n\n"); SERVER_PRINT("realbot add (team) (skill) (model) (name)\n"); From f705c42c566b8597e3cf2b3b88c81dfaa689cfe2 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 10 Dec 2022 16:33:02 +0000 Subject: [PATCH 076/114] Removing old projects --- realbot_mm.dsp | 187 ------------------------- realbot_mm.dsw | 29 ---- realbot_mm.vcproj | 345 ---------------------------------------------- 3 files changed, 561 deletions(-) delete mode 100644 realbot_mm.dsp delete mode 100644 realbot_mm.dsw delete mode 100644 realbot_mm.vcproj diff --git a/realbot_mm.dsp b/realbot_mm.dsp deleted file mode 100644 index 661e798..0000000 --- a/realbot_mm.dsp +++ /dev/null @@ -1,187 +0,0 @@ -# Microsoft Developer Studio Project File - Name="realbot_mm" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=realbot_mm - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "realbot_mm.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "realbot_mm.mak" CFG="realbot_mm - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "realbot_mm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName ""$/SDKSrc/Public/dlls", NVGBAAAA" -# PROP Scc_LocalPath "." -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir ".\Release" -# PROP BASE Intermediate_Dir ".\Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir ".\Release" -# PROP Intermediate_Dir ".\Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /G5 /MT /W3 /WX /GX /Zi /O2 /I "..\metamod" /I "..\..\devtools\sdk\Single-Player Source\common" /I "..\..\devtools\sdk\Single-Player Source\dlls" /I "..\..\devtools\sdk\Single-Player Source\engine" /I "..\..\devtools\sdk\Single-Player Source\pm_shared" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fr /FD /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /def:".\realbot_mm.def" -# SUBTRACT LINK32 /profile /incremental:yes /map -# Begin Custom Build -TargetPath=.\Release\realbot_mm.dll -TargetName=realbot_mm -InputPath=.\Release\realbot_mm.dll -SOURCE="$(InputPath)" - -"$(TargetName)" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - copy $(TargetPath) c:\progra~1\steam\steamapps\s.hendriks2@chello.nl\counter-strike\realbot\dll\realbot_mm.dll - copy $(TargetPath) c:\progra~1\steam\steamapps\s.hendriks2@chello.nl\dedica~1\realbot\dll\realbot_mm.dll - copy $(TargetPath) c:\progra~1\half-life\realbot\dll\realbot_mm.dll - copy $(TargetPath) d:\games\half-life\realbot\dll\realbot_mm.dll - -# End Custom Build -# Begin Target - -# Name "realbot_mm - Win32 Release" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" -# Begin Group "BAL" - -# PROP Default_Filter "" -# Begin Group "Halflife" - -# PROP Default_Filter "" -# Begin Group "Metamod" - -# PROP Default_Filter "" -# End Group -# End Group -# End Group -# Begin Source File - -SOURCE=.\bot.cpp -# End Source File -# Begin Source File - -SOURCE=.\bot_buycode.cpp -# End Source File -# Begin Source File - -SOURCE=.\bot_client.cpp -# End Source File -# Begin Source File - -SOURCE=.\bot_func.cpp -# End Source File -# Begin Source File - -SOURCE=.\bot_navigate.cpp -# End Source File -# Begin Source File - -SOURCE=.\build.cpp -# End Source File -# Begin Source File - -SOURCE=.\ChatEngine.cpp -# End Source File -# Begin Source File - -SOURCE=.\dll.cpp -# End Source File -# Begin Source File - -SOURCE=.\engine.cpp -# End Source File -# Begin Source File - -SOURCE=.\game.cpp -# End Source File -# Begin Source File - -SOURCE=.\IniParser.cpp -# End Source File -# Begin Source File - -SOURCE=.\NodeMachine.cpp -# End Source File -# Begin Source File - -SOURCE=.\util.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\BAL\BAL_Bot.h -# End Source File -# Begin Source File - -SOURCE=.\bot.h -# End Source File -# Begin Source File - -SOURCE=.\bot_client.h -# End Source File -# Begin Source File - -SOURCE=.\bot_func.h -# End Source File -# Begin Source File - -SOURCE=.\bot_weapons.h -# End Source File -# Begin Source File - -SOURCE=.\ChatEngine.h -# End Source File -# Begin Source File - -SOURCE=.\engine.h -# End Source File -# Begin Source File - -SOURCE=.\game.h -# End Source File -# Begin Source File - -SOURCE=.\IniParser.h -# End Source File -# Begin Source File - -SOURCE=.\NodeMachine.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\todo.txt -# End Source File -# End Target -# End Project diff --git a/realbot_mm.dsw b/realbot_mm.dsw deleted file mode 100644 index 1645c6f..0000000 --- a/realbot_mm.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "realbot_mm"=".\realbot_mm.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/realbot_mm.vcproj b/realbot_mm.vcproj deleted file mode 100644 index 8356a27..0000000 --- a/realbot_mm.vcproj +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 2f2bf9f7dd64f03ce47d4ba7401fd587bb40c656 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 4 Jun 2023 22:02:59 +0100 Subject: [PATCH 077/114] Updating AMBuildScript --- .gitignore | 1 + AMBuildScript | 248 +++++++++++++++++++++++--------------------------- configure.py | 45 +++++---- 3 files changed, 142 insertions(+), 152 deletions(-) diff --git a/.gitignore b/.gitignore index cc5b3f4..7a6332f 100644 --- a/.gitignore +++ b/.gitignore @@ -217,3 +217,4 @@ cmake-build-debug/ *.o realbot_mm.so +apg-load diff --git a/AMBuildScript b/AMBuildScript index 4b59baf..3516fb6 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -1,151 +1,131 @@ -import os - -# -# Detect Metamod and HLSDK -# - -def detectMetamod(): - metamod_path = builder.options.metamod_path - if not len(metamod_path): - metamod_path = os.getenv('METAMOD', '') - - if len(metamod_path): - metamod_path = os.path.join(builder.originalCwd, metamod_path) - if not os.path.exists(os.path.join(metamod_path, 'metamod')): - raise Exception('Metamod path does not exist: {0}'.format(metamod_path)) - else: - try_paths = [ - os.path.join(builder.sourcePath, '..', 'metamod'), - os.path.join(builder.sourcePath, '..', 'metamod-am'), - os.path.join(builder.sourcePath, '..', 'metamod-hl1'), - ] - for try_path in try_paths: - if os.path.exists(os.path.join(try_path, 'metamod')): - metamod_path = os.path.normpath(try_path) - break - if not metamod_path: - raise Exception('Could not find the source code to Metamod! Try passing --metamod to configure.py.') - - return metamod_path - -def detectHlsdk(): - hlsdk_path = builder.options.hlsdk_path - if not len(hlsdk_path): - hlsdk_path = os.getenv('HLSDK', '') - - if len(hlsdk_path): - hlsdk_path = os.path.join(builder.originalCwd, hlsdk_path) - if not os.path.exists(hlsdk_path): - raise Exception('Metamod path does not exist: {0}'.format(hlsdk_path)) - else: - try_paths = [ - os.path.join(builder.sourcePath, '..', 'hlsdk'), - ] - for try_path in try_paths: - if os.path.exists(try_path): - hlsdk_path = os.path.normpath(try_path) - break - if not hlsdk_path: - raise Exception('Could not find the HLSDK! Try passing --hlsdk to configure.py.') - - return hlsdk_path - - -metamod_path = detectMetamod() -hlsdk_path = detectHlsdk() - -# -# Compiler settings -# -cxx = builder.DetectCompilers() +# AMBuildScript for RealBot, written by Anonymous Player +# vim: set sts=4 ts=8 sw=4 tw=99 et ft=python: +import os, sys + +builder.cxx = builder.DetectCxx(target_arch = 'x86') + +# Include search paths +include_paths = [ + os.path.join(builder.currentSourcePath, 'dependencies', 'metamod-hl1', 'metamod'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'common'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'public'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'dlls'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'engine'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'game_shared'), + os.path.join(builder.currentSourcePath, 'dependencies', 'hlsdk', 'pm_shared'), +] -cxx.defines += [ - 'HAVE_STDINT_H' +# Compiler setup +builder.cxx.defines += [ + 'HAVE_STDINT_H', ] -if cxx.like('gcc'): - cxx.cflags += [ - '-Wall', - #'-Werror', - '-Wno-write-strings', - '-Wno-error=unused-result', - '-Wno-error=unused-variable', - '-Wno-unused-value', - '-fno-strict-aliasing', - '-fPIC', - '-msse2', - '-m32' +if builder.cxx.like('gcc'): + builder.cxx.defines += [ + 'stricmp=strcasecmp', + 'strcmpi=strcasecmp' ] - - cxx.cxxflags += [ - '-std=gnu++14', - '-fno-exceptions', - '-fno-rtti' + + builder.cxx.c_only_flags += ['-std=gnu99'] +if builder.cxx.target.platform == 'linux': + # Linux defines + builder.cxx.defines += ['_LINUX', 'POSIX', 'LINUX', 'linux'] + # Linux compiler C flags + builder.cxx.cflags += [ + '-pipe', + '-fPIC', + '-msse2', + '-fno-strict-aliasing', + '-Wall', + '-Werror', + '-Wno-uninitialized', + '-Wno-unused', + '-Wno-switch', + '-Wno-format', + '-Wno-format-security', + '-Wno-unknown-attributes', + '-Wno-logical-op-parentheses', + '-Wno-return-stack-address', + '-m32', ] - - cxx.linkflags += [ - '-m32' + # Linux compiler C++ flags + builder.cxx.cxxflags += [ + '-Wno-invalid-offsetof', + '-Wno-write-strings', + '-std=c++17', ] - - if builder.options.opt == '1': - cxx.cflags += ['-O2'] - -elif cxx.like('msvc'): - cxx.cflags += [ - '/W3' + # Linux linker flags + builder.cxx.linkflags += ['-m32', '-ldl', '-lm'] +elif builder.cxx.target.platform == 'windows': + # Windows defines + builder.cxx.defines += [ + '_CRT_SECURE_NO_DEPRECATE', + '_CRT_SECURE_NO_WARNINGS', + '_CRT_NONSTDC_NO_DEPRECATE', + 'NOMINMAX', + 'WIN32', + '_WINDOWS' ] - - cxx.cxxflags += [ - '/std:c++14', - '/arch:SSE2', - '/EHsc' + # Windows compiler C flags + builder.cxx.cflags += [] + # Windows compiler C++ flags + builder.cxx.cxxflags += [ + '/std:c++17', + '/arch:SSE2', + '/fp:precise', + '/Qspectre', + '/EHsc' ] - - cxx.linkflags += [ - '/MACHINE:X86', - '/SUBSYSTEM:WINDOWS', + # Windows linker flags + builder.cxx.linkflags += [ '/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1', - 'kernel32.lib' + '/SECTION:.data,RW', + '/MACHINE:X86' ] - if builder.options.opt == '1': - cxx.cflags += ['/O2'] - cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] - - if builder.options.debug == '1': - cxx.cflags += ['/MTd', '/Od', '/RTC1'] - cxx.linkflags += ['/NODEFAULTLIB:libcmt'] - else: - cxx.cflags += ['/MT'] - - - -# Optimization -if builder.options.opt == '1': - cxx.defines += ['NDEBUG'] - -# Debugging +# Compiler options for optimization ( --enable-optimize ) +if builder.options.optimize == '1': + # Shared optimization definitions + builder.cxx.defines += ['NDEBUG'] + if builder.cxx.target.platform == 'linux': + # Linux optimization flags + builder.cxx.cflags += ['-O2'] + elif builder.cxx.target.platform == 'windows': + # Windows optimization flags + builder.cxx.cflags += ['/O2', '/Zo'] + # Windows optimization link flags + builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + +# Compiler options for debugging ( --enable-debug ) if builder.options.debug == '1': - cxx.defines += ['DEBUG', '_DEBUG'] - - -cxx.includes += [ - os.path.join(metamod_path, 'metamod'), - os.path.join(hlsdk_path, 'common'), - os.path.join(hlsdk_path, 'public'), - os.path.join(hlsdk_path, 'engine'), - os.path.join(hlsdk_path, 'dlls'), - os.path.join(hlsdk_path, 'game_shared'), - os.path.join(hlsdk_path, 'pm_shared'), -] + # Shared debug definitions + builder.cxx.defines += ['DEBUG', '_DEBUG'] + if builder.cxx.target.platform == 'linux': + # Linux debug flags + builder.cxx.cflags += ['-g3', '-O0'] + elif builder.cxx.target.platform == 'windows': + # Windows debug flags + builder.cxx.cflags += ['/Od', '/RTC1', '/MTd'] + # Windows debug link flags + builder.cxx.linkflags += ['/NODEFAULTLIB:libcmt'] + +# Handle --enable-static-lib and --enable-shared-lib +if builder.cxx.target.platform == 'linux': + if builder.options.staticlib == '1': + builder.cxx.linkflags += [ + '-static-libgcc', + '-static-libstdc++' + ] + elif builder.options.sharedlib == '1': + builder.cxx.linkflags += [ + '-shared-libgcc', + ] +library = builder.cxx.Library('realbot_mm') -name = 'realbot_mm' -if builder.target_platform == 'linux': - name += '' +library.compiler.includes += include_paths -binary = cxx.Library(name) -binary.sources += [ +library.sources += [ 'bot.cpp', 'bot_buycode.cpp', 'bot_client.cpp', @@ -172,4 +152,4 @@ binary.sources += [ # Run scripts, add binaries # -builder.Add(binary) \ No newline at end of file +builder.Add(library) \ No newline at end of file diff --git a/configure.py b/configure.py index efb9c06..f3b03d1 100644 --- a/configure.py +++ b/configure.py @@ -1,24 +1,33 @@ -API_VERSION = '2.1' +# AMBuild Configuration Script for RealBot, written by Anonymous Player +# vim: set sts=4 ts=8 sw=4 tw=99 et: +API_VERSION = '2.2.3' import sys try: - from ambuild2 import run - if not run.HasAPI(API_VERSION): - raise Exception() + from ambuild2 import run + if not run.HasAPI(API_VERSION): + raise Exception() except: - sys.stderr.write('AMBuild {0} must be installed to build this project.\n'.format(API_VERSION)) - sys.stderr.write('http://www.alliedmods.net/ambuild\n') - sys.exit(1) + sys.stderr.write('AMBuild {0} must be installed to build this project.\n'.format(API_VERSION)) + sys.stderr.write('http://www.alliedmods.net/ambuild\n') + sys.exit(1) -prep = run.PrepareBuild(sourcePath=sys.path[0]) -prep.default_build_folder = 'obj-' + prep.target_platform -prep.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', - help='Enable debugging symbols') -prep.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', - help='Enable optimization') -prep.options.add_option('--metamod', type='string', dest='metamod_path', default='', - help='Path to Metamod source code') -prep.options.add_option('--hlsdk', type='string', dest='hlsdk_path', default='', - help='Path to the HLSDK') +def make_objdir_name(p): + return 'obj-' + util.Platform() + '-' + p.target_arch -prep.Configure() \ No newline at end of file +builder = run.BuildParser(sourcePath = sys.path[0], api=API_VERSION) +builder.default_arch = 'x86' +builder.default_build_folder = make_objdir_name +# builder.options.add_argument('--hl1sdk', type=str, dest='hl1sdk_path', default=None, + # help='Half-Life 1 SDK source tree folder') +# builder.options.add_argument('--mm-path', type=str, dest='mm_path', default=None, + # help='Metamod source tree folder') +builder.options.add_argument('--enable-optimize', action='store_const', const='1', dest='optimize', + help='Enable optimization') +builder.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', + help='Enable debug') +builder.options.add_argument('--enable-static-lib', action='store_const', const='1', dest='staticlib', + help='Enable statically link the sanitizer runtime') +builder.options.add_argument('--enable-shared-lib', action='store_const', const='1', dest='sharedlib', + help='Enable dynamically link the sanitizer runtime') +builder.Configure() \ No newline at end of file From ce9bf89cc43f3c46a463be9894a5859274dea75a Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 16 Jul 2023 16:05:50 +0100 Subject: [PATCH 078/114] Standard C++ refactoring and small optimisations --- NodeMachine.cpp | 4 +- dependencies/hlsdk/dlls/extdll.h | 24 +- dll.cpp | 6 +- realbot_mm.vcxproj | 3 +- util.cpp | 1466 +++++++++++++++--------------- 5 files changed, 759 insertions(+), 744 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 8d57f5c..775fa64 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2960,7 +2960,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_walk", msg); const bool isStuck = distanceMoved < expectedMoveDistance && pBot->shouldBeAbleToMove() && notStuckForAWhile; // also did not evaluate this logic for 0.5 second - Vector &vector = Nodes[currentNodeToHeadFor].origin; + const Vector &vector = Nodes[currentNodeToHeadFor].origin; if (isStuck) { pBot->rprint_trace("cNodeMachine::path_walk", "!!!STUCK STUCK STUCK STUCK STUCK STUCK STUCK!!!"); @@ -3451,7 +3451,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { // not a bot - cBot *botPointer = &bots[botIndex]; + const cBot *botPointer = &bots[botIndex]; if (botPointer == nullptr || !botPointer->bIsUsed || botPointer == pBot) { // skip self diff --git a/dependencies/hlsdk/dlls/extdll.h b/dependencies/hlsdk/dlls/extdll.h index 2e75d54..a92a582 100644 --- a/dependencies/hlsdk/dlls/extdll.h +++ b/dependencies/hlsdk/dlls/extdll.h @@ -56,6 +56,10 @@ #define NOMCX #define NOIME #include "windows.h" + +#undef max +#undef min + #else // _WIN32 #ifndef FALSE #define FALSE 0 @@ -69,18 +73,22 @@ typedef int BOOL; #define MAX_PATH PATH_MAX #include #include -#include // memset +#include // memset +//Fix for GCC 8 - [APG]RoboCop[CL] #include -using namespace std; -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif + #ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) #endif -#ifndef _vsnprintf -#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) #endif + +#undef max +#undef min + +#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d) #endif //_WIN32 // Misc C-runtime library headers diff --git a/dll.cpp b/dll.cpp index 429868c..2723dc8 100644 --- a/dll.cpp +++ b/dll.cpp @@ -987,12 +987,12 @@ void StartFrame() { spawn_time_reset = TRUE; if (respawn_time >= 1.0f) - respawn_time = min(respawn_time, gpGlobals->time + (float) 1.0f); + respawn_time = std::min(respawn_time, gpGlobals->time + 1.0f); if (bot_cfg_pause_time >= 1.0f) bot_cfg_pause_time = - min(bot_cfg_pause_time, - gpGlobals->time + (float) 1.0f); + std::min(bot_cfg_pause_time, + gpGlobals->time + 1.0f); } } } diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 3373d9f..8953233 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -61,10 +61,11 @@ .\Release/ true .\Release/ - Level2 + Level4 false true ProgramDatabase + stdcpp17 NDEBUG;%(PreprocessorDefinitions) diff --git a/util.cpp b/util.cpp index 9f7c75f..8521214 100644 --- a/util.cpp +++ b/util.cpp @@ -21,7 +21,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -33,9 +33,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -69,284 +69,285 @@ int gmsgTextMsg = 0; int gmsgSayText = 0; int gmsgShowMenu = 0; -Vector UTIL_VecToAngles(const Vector &vec) { - float rgflVecOut[3]; - VEC_TO_ANGLES(vec, rgflVecOut); - return {rgflVecOut}; +Vector UTIL_VecToAngles(const Vector& vec) { + float rgflVecOut[3]; + VEC_TO_ANGLES(vec, rgflVecOut); + return { rgflVecOut }; } // Overloaded to add IGNORE_GLASS void -UTIL_TraceLine(const Vector &vecStart, const Vector &vecEnd, - IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, - edict_t *pentIgnore, TraceResult *ptr) { - TRACE_LINE(vecStart, vecEnd, - (igmon == - ignore_monsters ? TRUE : FALSE) | (ignoreGlass ? 0x100 : 0), - pentIgnore, ptr); +UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, + edict_t* pentIgnore, TraceResult* ptr) { + TRACE_LINE(vecStart, vecEnd, + (igmon == + ignore_monsters ? TRUE : FALSE) | (ignoreGlass ? 0x100 : 0), + pentIgnore, ptr); } void -UTIL_TraceLine(const Vector &vecStart, const Vector &vecEnd, - IGNORE_MONSTERS igmon, edict_t *pentIgnore, - TraceResult *ptr) { - TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), - pentIgnore, ptr); +UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, edict_t* pentIgnore, + TraceResult* ptr) { + TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), + pentIgnore, ptr); } void -UTIL_TraceHull(const Vector &vecStart, const Vector &vecEnd, - IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, - TraceResult *ptr) { - TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), hullNumber, pentIgnore, ptr); +UTIL_TraceHull(const Vector& vecStart, const Vector& vecEnd, + IGNORE_MONSTERS igmon, int hullNumber, edict_t* pentIgnore, + TraceResult* ptr) { + TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), hullNumber, pentIgnore, ptr); } -void UTIL_MakeVectors(const Vector &vecAngles) { - MAKE_VECTORS(vecAngles); +void UTIL_MakeVectors(const Vector& vecAngles) { + MAKE_VECTORS(vecAngles); } -edict_t *UTIL_FindEntityInSphere(edict_t *pentStart, - const Vector &vecCenter, float flRadius) { +edict_t* UTIL_FindEntityInSphere(edict_t* pentStart, + const Vector& vecCenter, float flRadius) { edict_t* pentEntity = FIND_ENTITY_IN_SPHERE(pentStart, vecCenter, flRadius); - if (!FNullEnt(pentEntity)) - return pentEntity; + if (!FNullEnt(pentEntity)) + return pentEntity; - return nullptr; + return nullptr; } -edict_t *UTIL_FindEntityByString(edict_t *pentStart, - const char *szKeyword, - const char *szValue) { +edict_t* UTIL_FindEntityByString(edict_t* pentStart, + const char* szKeyword, + const char* szValue) { edict_t* pentEntity = FIND_ENTITY_BY_STRING(pentStart, szKeyword, szValue); - if (!FNullEnt(pentEntity)) - return pentEntity; - return nullptr; + if (!FNullEnt(pentEntity)) + return pentEntity; + return nullptr; } -edict_t *UTIL_FindEntityByClassname(edict_t *pentStart, - const char *szName) { - return UTIL_FindEntityByString(pentStart, "classname", szName); +edict_t* UTIL_FindEntityByClassname(edict_t* pentStart, + const char* szName) { + return UTIL_FindEntityByString(pentStart, "classname", szName); } -edict_t *UTIL_FindEntityByTargetname(edict_t *pentStart, - const char *szName) { - return UTIL_FindEntityByString(pentStart, "targetname", szName); +edict_t* UTIL_FindEntityByTargetname(edict_t* pentStart, + const char* szName) { + return UTIL_FindEntityByString(pentStart, "targetname", szName); } -int UTIL_PointContents(const Vector &vec) { - return POINT_CONTENTS(vec); +int UTIL_PointContents(const Vector& vec) { + return POINT_CONTENTS(vec); } void -UTIL_SetSize(entvars_t *pev, const Vector &vecMin, const Vector &vecMax) { - SET_SIZE(ENT(pev), vecMin, vecMax); +UTIL_SetSize(entvars_t* pev, const Vector& vecMin, const Vector& vecMax) { + SET_SIZE(ENT(pev), vecMin, vecMax); } -void UTIL_SetOrigin(entvars_t *pev, const Vector &vecOrigin) { - SET_ORIGIN(ENT(pev), vecOrigin); +void UTIL_SetOrigin(entvars_t* pev, const Vector& vecOrigin) { + SET_ORIGIN(ENT(pev), vecOrigin); } -void ClientPrint(edict_t *pEntity, int msg_dest, const char *msg_name) { +void ClientPrint(edict_t* pEntity, int msg_dest, const char* msg_name) { - if (gmsgTextMsg == 0) - gmsgTextMsg = REG_USER_MSG("TextMsg", -1); + if (gmsgTextMsg == 0) + gmsgTextMsg = REG_USER_MSG("TextMsg", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgTextMsg, nullptr, pEntity); + MESSAGE_BEGIN(MSG_ONE, gmsgTextMsg, nullptr, pEntity); - WRITE_BYTE(msg_dest); - WRITE_STRING(msg_name); - MESSAGE_END(); + WRITE_BYTE(msg_dest); + WRITE_STRING(msg_name); + MESSAGE_END(); } -void UTIL_ClientPrintAll(int msg_dest, const char *msg_name, const char *param1, - const char *param2, const char *param3, - const char *param4) { - if (gmsgTextMsg == 0) - gmsgTextMsg = REG_USER_MSG("TextMsg", -1); - - MESSAGE_BEGIN(MSG_ALL, gmsgTextMsg); - WRITE_BYTE(msg_dest); - WRITE_STRING(msg_name); - - if (param1) - WRITE_STRING(param1); - if (param2) - WRITE_STRING(param2); - if (param3) - WRITE_STRING(param3); - if (param4) - WRITE_STRING(param4); - - MESSAGE_END(); +void UTIL_ClientPrintAll(int msg_dest, const char* msg_name, const char* param1, + const char* param2, const char* param3, + const char* param4) { + if (gmsgTextMsg == 0) + gmsgTextMsg = REG_USER_MSG("TextMsg", -1); + + MESSAGE_BEGIN(MSG_ALL, gmsgTextMsg); + WRITE_BYTE(msg_dest); + WRITE_STRING(msg_name); + + if (param1) + WRITE_STRING(param1); + if (param2) + WRITE_STRING(param2); + if (param3) + WRITE_STRING(param3); + if (param4) + WRITE_STRING(param4); + + MESSAGE_END(); } -void UTIL_SayText(const char *pText, edict_t *pEdict) { - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG("SayText", -1); +void UTIL_SayText(const char* pText, edict_t* pEdict) { + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEdict); - WRITE_BYTE(ENTINDEX(pEdict)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING(pText); - MESSAGE_END(); + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEdict); + WRITE_BYTE(ENTINDEX(pEdict)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(pText); + MESSAGE_END(); } -void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message) { +void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { char text[128]; - char *pc; + char* pc; // make sure the text has content - for (pc = message; pc != nullptr && *pc != 0; pc++) { - if (isprint(*pc) && !isspace(*pc)) { - pc = nullptr; // we've found an alphanumeric character, so text is valid - break; - } - } - - if (pc != nullptr) - return; // no character found, so say nothing - - // turn on color set 2 (color on, no sound) - if (teamonly) - sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); - else - sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); + for (pc = message; pc != nullptr && *pc != 0; pc++) { + if (isprint(*pc) && !isspace(*pc)) { + pc = nullptr; // we've found an alphanumeric character, so text is valid + break; + } + } + + if (pc != nullptr) + return; // no character found, so say nothing + + // turn on color set 2 (color on, no sound) + if (teamonly) + sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); + else + sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); const int j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator - if (static_cast(strlen(message)) > j) - message[j] = 0; + if (static_cast(strlen(message)) > j) + message[j] = 0; - strcat(text, message); - strcat(text, "\n"); + strcat(text, message); + strcat(text, "\n"); - // loop through all players - // Start with the first player. - // This may return the world in single player if the client types something between levels or during spawn - // so check it, or it will infinite loop + // loop through all players + // Start with the first player. + // This may return the world in single player if the client types something between levels or during spawn + // so check it, or it will infinite loop - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG("SayText", -1); + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); const int sender_team = UTIL_GetTeam(pEntity); - edict_t* client = nullptr; - while (((client = UTIL_FindEntityByClassname(client, "player")) != nullptr) - && (!FNullEnt(client))) { - if (client == pEntity) // skip sender of message - continue; - - const int player_team = UTIL_GetTeam(client); - - if (teamonly && (sender_team != player_team)) - continue; - - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, client); - WRITE_BYTE(ENTINDEX(pEntity)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING(text); - MESSAGE_END(); - } - - // print to the sending client - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEntity); - WRITE_BYTE(ENTINDEX(pEntity)); - //if (mod_id == FRONTLINE_DLL) - // WRITE_SHORT(0); - WRITE_STRING(text); - MESSAGE_END(); - - // echo to server console - g_engfuncs.pfnServerPrint(text); + edict_t* client = nullptr; + while (((client = UTIL_FindEntityByClassname(client, "player")) != nullptr) + && (!FNullEnt(client))) { + if (client == pEntity) // skip sender of message + continue; + + const int player_team = UTIL_GetTeam(client); + + if (teamonly && (sender_team != player_team)) + continue; + + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, client); + WRITE_BYTE(ENTINDEX(pEntity)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(text); + MESSAGE_END(); + } + + // print to the sending client + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pEntity); + WRITE_BYTE(ENTINDEX(pEntity)); + //if (mod_id == FRONTLINE_DLL) + // WRITE_SHORT(0); + WRITE_STRING(text); + MESSAGE_END(); + + // echo to server console + g_engfuncs.pfnServerPrint(text); } #ifdef DEBUG -edict_t *DBG_EntOfVars(const entvars_t * pev) { - if (pev->pContainingEntity != NULL) - return pev->pContainingEntity; - ALERT(at_console, - "entvars_t pContainingEntity is NULL, calling into engine"); - edict_t *pent = (*g_engfuncs.pfnFindEntityByVars) ((entvars_t *) pev); - if (pent == NULL) - ALERT(at_console, - "DAMN! Even the engine couldn't FindEntityByVars!"); - ((entvars_t *) pev)->pContainingEntity = pent; - return pent; +edict_t* DBG_EntOfVars(const entvars_t* pev) { + if (pev->pContainingEntity != NULL) + return pev->pContainingEntity; + ALERT(at_console, + "entvars_t pContainingEntity is NULL, calling into engine"); + edict_t* pent = (*g_engfuncs.pfnFindEntityByVars) ((entvars_t*)pev); + if (pent == NULL) + ALERT(at_console, + "DAMN! Even the engine couldn't FindEntityByVars!"); + ((entvars_t*)pev)->pContainingEntity = pent; + return pent; } #endif //DEBUG // Is the edict a vip or not? -bool UTIL_IsVip(edict_t *pEntity) { - if (mod_id != CSTRIKE_DLL) - return false; - else { - char model_name[32]; +bool UTIL_IsVip(edict_t* pEntity) { + if (mod_id != CSTRIKE_DLL) + return false; + else { + char model_name[32]; - char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - if (strcmp(model_name, "vip") == 0) // VIP - return true; - } + if (strcmp(model_name, "vip") == 0) // VIP + return true; + } - return false; + return false; } // return team number 0 through 3 based what MOD uses for team numbers -int UTIL_GetTeam(edict_t *pEntity) { - if (mod_id == CSTRIKE_DLL) { - char model_name[32]; - - char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, - (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - - if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion - (strcmp(model_name, "arab") == 0) || // old L337 Krew - (strcmp(model_name, "leet") == 0) || // L337 Krew - (strcmp(model_name, "artic") == 0) || // Artic Avenger - (strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? - (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare +int UTIL_GetTeam(edict_t* pEntity) { + if (mod_id == CSTRIKE_DLL) { + char model_name[32]; + + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + strcpy(model_name, + (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + + if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion + (strcmp(model_name, "arab") == 0) || // old L337 Krew + (strcmp(model_name, "leet") == 0) || // L337 Krew + (strcmp(model_name, "artic") == 0) || // Artic Avenger + (strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? + (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare //(strcmp(model_name, "militia") == 0)) // CZ Militia - { - return 0; // team Terrorists - } else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 - (strcmp(model_name, "gsg9") == 0) || // German GSG-9 - (strcmp(model_name, "sas") == 0) || // UK SAS - (strcmp(model_name, "gign") == 0) || // French GIGN - (strcmp(model_name, "vip") == 0) || // VIP - (strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz - { - return 1; // team Counter-Terrorists - } - - return -1; // unknown team - } - - return -2; // unknown mod + { + return 0; // team Terrorists + } + else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 + (strcmp(model_name, "gsg9") == 0) || // German GSG-9 + (strcmp(model_name, "sas") == 0) || // UK SAS + (strcmp(model_name, "gign") == 0) || // French GIGN + (strcmp(model_name, "vip") == 0) || // VIP + (strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz + { + return 1; // team Counter-Terrorists + } + + return -1; // unknown team + } + + return -2; // unknown mod } // return class number 0 through N -int UTIL_GetClass(edict_t *pEntity) { +int UTIL_GetClass(edict_t* pEntity) { char model_name[32]; - char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - return 0; + return 0; } -int UTIL_GetBotIndex(edict_t *pEdict) { +int UTIL_GetBotIndex(edict_t* pEdict) { for (int index = 0; index < 32; index++) { - if (bots[index].pEdict == pEdict) { - return index; - } - } + if (bots[index].pEdict == pEdict) { + return index; + } + } - return -1; // return -1 if edict is not a bot + return -1; // return -1 if edict is not a bot } /** @@ -354,122 +355,125 @@ int UTIL_GetBotIndex(edict_t *pEdict) { * @param pEdict * @return */ -cBot *UTIL_GetBotPointer(edict_t *pEdict) { +cBot* UTIL_GetBotPointer(edict_t* pEdict) { for (int index = 0; index < 32; index++) { - if (bots[index].pEdict == pEdict) { - return (&bots[index]); - } - } + if (bots[index].pEdict == pEdict) { + return (&bots[index]); + } + } - return nullptr; // return NULL if edict is not a bot + return nullptr; // return NULL if edict is not a bot } -bool IsAlive(edict_t *pEdict) { - // FIX: Make sure the edict is valid and such, else return false: - return ((pEdict != nullptr) && // VALID - (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD - (pEdict->v.health > 0) && // ENOUGHT HEALTH - !(pEdict->v.flags & FL_NOTARGET) && // ? - (pEdict->v.takedamage != 0)); // CAN TAKE DAMAGE +bool IsAlive(edict_t* pEdict) { + // FIX: Make sure the edict is valid and such, else return false: + return ((pEdict != nullptr) && // VALID + (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD + (pEdict->v.health > 0) && // ENOUGHT HEALTH + !(pEdict->v.flags & FL_NOTARGET) && // ? + (pEdict->v.takedamage != 0)); // CAN TAKE DAMAGE } -bool FInViewCone(Vector *pOrigin, edict_t *pEdict) { +bool FInViewCone(Vector* pOrigin, edict_t* pEdict) { UTIL_MakeVectors(pEdict->v.angles); - Vector2D vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); - vec2LOS = vec2LOS.Normalize(); + Vector2D vec2LOS = (*pOrigin - pEdict->v.origin).Make2D(); + vec2LOS = vec2LOS.Normalize(); const float flDot = DotProduct(vec2LOS, gpGlobals->v_forward.Make2D()); - if (flDot > 0.50f) // 60 degree field of view - { - return TRUE; - } else { - return FALSE; - } + if (flDot > 0.50f) // 60 degree field of view + { + return TRUE; + } + else { + return FALSE; + } } // FVisible() -bool FVisible(const Vector &vecOrigin, edict_t *pEdict) { - TraceResult tr; +bool FVisible(const Vector& vecOrigin, edict_t* pEdict) { + TraceResult tr; - // look through caller's eyes - const Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; + // look through caller's eyes + const Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; - const int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); - const int bLookerInWater = - (UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER); + const int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); + const int bLookerInWater = + (UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER); - // don't look through water - if (bInWater != bLookerInWater) - return FALSE; + // don't look through water + if (bInWater != bLookerInWater) + return FALSE; - UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, - ignore_glass, pEdict, &tr); + UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, + ignore_glass, pEdict, &tr); - if (tr.flFraction != 1.0f) { - return FALSE; // Line of sight is not established - } else { - return TRUE; // line of sight is valid. - } + if (tr.flFraction != 1.0f) { + return FALSE; // Line of sight is not established + } + else { + return TRUE; // line of sight is valid. + } } -Vector GetGunPosition(edict_t *pEdict) { - return (pEdict->v.origin + pEdict->v.view_ofs); +Vector GetGunPosition(edict_t* pEdict) { + return (pEdict->v.origin + pEdict->v.view_ofs); } -void UTIL_SelectItem(edict_t *pEdict, char *item_name) { - /*BotDebug( item_name); */ - FakeClientCommand(pEdict, item_name, nullptr, nullptr); +void UTIL_SelectItem(edict_t* pEdict, char* item_name) { + /*BotDebug( item_name); */ + FakeClientCommand(pEdict, item_name, nullptr, nullptr); } -Vector VecBModelOrigin(edict_t *pEdict) { - return pEdict->v.absmin + (pEdict->v.size * 0.5); +Vector VecBModelOrigin(edict_t* pEdict) { + return pEdict->v.absmin + (pEdict->v.size * 0.5); } void -UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, - char *pText) { - if (gmsgShowMenu == 0) - gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); +UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, + char* pText) { + if (gmsgShowMenu == 0) + gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); - MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, nullptr, pEdict); + MESSAGE_BEGIN(MSG_ONE, gmsgShowMenu, nullptr, pEdict); - WRITE_SHORT(slots); - WRITE_CHAR(displaytime); - WRITE_BYTE(needmore); - WRITE_STRING(pText); + WRITE_SHORT(slots); + WRITE_CHAR(displaytime); + WRITE_BYTE(needmore); + WRITE_STRING(pText); - MESSAGE_END(); + MESSAGE_END(); } -void UTIL_BuildFileName(char *filename, char *arg1, char *arg2) { +void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { - if (mod_id == VALVE_DLL) - strcpy(filename, "valve/"); + if (mod_id == VALVE_DLL) + strcpy(filename, "valve/"); - else if (mod_id == CSTRIKE_DLL) - strcpy(filename, "cstrike/"); + else if (mod_id == CSTRIKE_DLL) + strcpy(filename, "cstrike/"); - else { - filename[0] = 0; - return; - } + else { + filename[0] = 0; + return; + } - if ((arg1) && (*arg1) && (arg2) && (*arg2)) { - strcat(filename, arg1); - strcat(filename, "/"); - strcat(filename, arg2); - } else if ((arg1) && (*arg1)) { - strcat(filename, arg1); - } + if ((arg1) && (*arg1) && (arg2) && (*arg2)) { + strcat(filename, arg1); + strcat(filename, "/"); + strcat(filename, arg2); + } + else if ((arg1) && (*arg1)) { + strcat(filename, arg1); + } } // added by Tub // copies subdir/file to filename -void UTIL_BuildFileNameRB(char *subdir, char *filename) { +void UTIL_BuildFileNameRB(char* subdir, char* filename) { #if DO_DEBUG != 0 - char *filenamedebug = filename; + char* filenamedebug = filename; #endif #ifdef _WIN32 #define S '\\' @@ -477,15 +481,15 @@ void UTIL_BuildFileNameRB(char *subdir, char *filename) { #define S '/' #endif - strcpy(filename, "realbot/"); - strcat(filename, subdir); - while (*filename) { - if ((*filename == '/') || (*filename == '\\')) - *filename = S; - filename++; - } + strcpy(filename, "realbot/"); + strcat(filename, subdir); + while (*filename) { + if ((*filename == '/') || (*filename == '\\')) + *filename = S; + filename++; + } #if DO_DEBUG != 0 - DebugOut(filenamedebug); + DebugOut(filenamedebug); #endif #undef S } @@ -494,523 +498,525 @@ void UTIL_BuildFileNameRB(char *subdir, char *filename) { // UTIL_LogPrintf - Prints a logged message to console. // Preceded by LOG: ( timestamp ) < message > //========================================================= -void UTIL_LogPrintf(char *fmt, ...) { - va_list argptr; - static char string[1024]; +void UTIL_LogPrintf(char* fmt, ...) { + va_list argptr; + static char string[1024]; - va_start(argptr, fmt); - vsprintf(string, fmt, argptr); - va_end(argptr); + va_start(argptr, fmt); + vsprintf(string, fmt, argptr); + va_end(argptr); - // Print to server console - ALERT(at_logged, "%s", string); + // Print to server console + ALERT(at_logged, "%s", string); } -void UTIL_BotPressKey(cBot *pBot, int type) { - if (type == IN_JUMP || type == IN_DUCK) { - if (pBot->isFreezeTime()) { - pBot->rprint_trace("UTIL_BotPressKey", "IN_JUMP or IN_DUCK press requested, but in freezetime - IGNORING"); - return; // do nothing when in freezetime - } - } - - if (type == IN_JUMP) { - if (pBot->f_may_jump_time > gpGlobals->time || // do nothing when we may not jump - pBot->f_camp_time > gpGlobals->time || // when camping do not jump - FUNC_IsOnLadder(pBot->pEdict) // don't jump from ladder - ) { - pBot->rprint_trace("UTIL_BotPressKey", - "IN_JUMP requested, but either camping, still jumping or on ladder - IGNORING"); - return; - } - } - - // KEY: Reload - if (type == IN_RELOAD) // when reloading, there is NO zooming (when holding a zoomable weapon or a sniper gun) - { - pBot->rprint_trace("UTIL_BotPressKey", "IN_RELOAD"); - if (FUNC_BotHoldsZoomWeapon(pBot) || UTIL_GiveWeaponType(pBot->current_weapon.iId) == SNIPER) - //pBot->zoomed = ZOOM_NONE; // not zoomed anymore - - // FIX: Do not let bots do anything with this weapon for 0.7 second. So the engine can - // update the information. - pBot->f_update_weapon_time = gpGlobals->time + 0.7f; - } - // KEY: End - - switch (type) { - case IN_DUCK: - pBot->rprint_trace("UTIL_BotPressKey", "IN_DUCK"); - break; - case IN_JUMP: - pBot->rprint_trace("UTIL_BotPressKey", "IN_JUMP"); - break; - case IN_USE: - pBot->rprint_trace("UTIL_BotPressKey", "IN_USE"); - break; - case IN_RELOAD: - pBot->rprint_trace("UTIL_BotPressKey", "IN_RELOAD"); - break; - case IN_ATTACK: - pBot->rprint_trace("UTIL_BotPressKey", "IN_ATTACK"); - break; - case IN_RUN: - pBot->rprint_trace("UTIL_BotPressKey", "IN_RUN"); - break; - case IN_MOVELEFT: - pBot->rprint_trace("UTIL_BotPressKey", "IN_MOVELEFT"); - break; - case IN_MOVERIGHT: - pBot->rprint_trace("UTIL_BotPressKey", "IN_MOVERIGHT"); - break; - default: - char msg[255]; - sprintf(msg, "unknown key to print [%d]", type); - pBot->rprint_trace("UTIL_BotPressKey", msg); - break; - } - - pBot->pEdict->v.button |= type; +void UTIL_BotPressKey(cBot* pBot, int type) { + if (type == IN_JUMP || type == IN_DUCK) { + if (pBot->isFreezeTime()) { + pBot->rprint_trace("UTIL_BotPressKey", "IN_JUMP or IN_DUCK press requested, but in freezetime - IGNORING"); + return; // do nothing when in freezetime + } + } + + if (type == IN_JUMP) { + if (pBot->f_may_jump_time > gpGlobals->time || // do nothing when we may not jump + pBot->f_camp_time > gpGlobals->time || // when camping do not jump + FUNC_IsOnLadder(pBot->pEdict) // don't jump from ladder + ) { + pBot->rprint_trace("UTIL_BotPressKey", + "IN_JUMP requested, but either camping, still jumping or on ladder - IGNORING"); + return; + } + } + + // KEY: Reload + if (type == IN_RELOAD) // when reloading, there is NO zooming (when holding a zoomable weapon or a sniper gun) + { + pBot->rprint_trace("UTIL_BotPressKey", "IN_RELOAD"); + if (FUNC_BotHoldsZoomWeapon(pBot) || UTIL_GiveWeaponType(pBot->current_weapon.iId) == SNIPER) + //pBot->zoomed = ZOOM_NONE; // not zoomed anymore + + // FIX: Do not let bots do anything with this weapon for 0.7 second. So the engine can + // update the information. + pBot->f_update_weapon_time = gpGlobals->time + 0.7f; + } + // KEY: End + + switch (type) { + case IN_DUCK: + pBot->rprint_trace("UTIL_BotPressKey", "IN_DUCK"); + break; + case IN_JUMP: + pBot->rprint_trace("UTIL_BotPressKey", "IN_JUMP"); + break; + case IN_USE: + pBot->rprint_trace("UTIL_BotPressKey", "IN_USE"); + break; + case IN_RELOAD: + pBot->rprint_trace("UTIL_BotPressKey", "IN_RELOAD"); + break; + case IN_ATTACK: + pBot->rprint_trace("UTIL_BotPressKey", "IN_ATTACK"); + break; + case IN_RUN: + pBot->rprint_trace("UTIL_BotPressKey", "IN_RUN"); + break; + case IN_MOVELEFT: + pBot->rprint_trace("UTIL_BotPressKey", "IN_MOVELEFT"); + break; + case IN_MOVERIGHT: + pBot->rprint_trace("UTIL_BotPressKey", "IN_MOVERIGHT"); + break; + default: + char msg[255]; + sprintf(msg, "unknown key to print [%d]", type); + pBot->rprint_trace("UTIL_BotPressKey", msg); + break; + } + + pBot->pEdict->v.button |= type; } int UTIL_GiveWeaponType(int weapon_id) { - int kind = NONE; - // 30/07/04 by Josh - // Use switch instead of multiple if - switch (weapon_id) { - case CS_WEAPON_KNIFE: - kind = KNIFE; - break; // Check1. Is it a knife? - case CS_WEAPON_FLASHBANG: - case CS_WEAPON_HEGRENADE: - case CS_WEAPON_SMOKEGRENADE: - kind = GRENADE; - break; // Check 2, is it a 'tool'? - case CS_WEAPON_P228: - case CS_WEAPON_ELITE: - case CS_WEAPON_USP: - case CS_WEAPON_GLOCK18: - case CS_WEAPON_DEAGLE: - case CS_WEAPON_FIVESEVEN: - kind = SECONDARY; - break; // Check 3, is it a secondary gun? - case CS_WEAPON_SCOUT: - case CS_WEAPON_SG550: - case CS_WEAPON_AWP: - case CS_WEAPON_G3SG1: - kind = SNIPER; - break; // Check 4, is it a sniper gun? - //31.08.04 Frashman: added to switch construct - case CS_WEAPON_SHIELD: - kind = SHIELD; // 08/07/04 - Also take shield into account - } - - // When the kind of weapon is still not found, its a primary (in CS) - if (kind == NONE) - kind = PRIMARY; - - if (weapon_id < 1) - kind = NONE; - - return kind; + int kind = NONE; + // 30/07/04 by Josh + // Use switch instead of multiple if + switch (weapon_id) { + case CS_WEAPON_KNIFE: + kind = KNIFE; + break; // Check1. Is it a knife? + case CS_WEAPON_FLASHBANG: + case CS_WEAPON_HEGRENADE: + case CS_WEAPON_SMOKEGRENADE: + kind = GRENADE; + break; // Check 2, is it a 'tool'? + case CS_WEAPON_P228: + case CS_WEAPON_ELITE: + case CS_WEAPON_USP: + case CS_WEAPON_GLOCK18: + case CS_WEAPON_DEAGLE: + case CS_WEAPON_FIVESEVEN: + kind = SECONDARY; + break; // Check 3, is it a secondary gun? + case CS_WEAPON_SCOUT: + case CS_WEAPON_SG550: + case CS_WEAPON_AWP: + case CS_WEAPON_G3SG1: + kind = SNIPER; + break; // Check 4, is it a sniper gun? + //31.08.04 Frashman: added to switch construct + case CS_WEAPON_SHIELD: + kind = SHIELD; // 08/07/04 - Also take shield into account + } + + // When the kind of weapon is still not found, its a primary (in CS) + if (kind == NONE) + kind = PRIMARY; + + if (weapon_id < 1) + kind = NONE; + + return kind; } // Return weapon ID (depended on mod) -int UTIL_GiveWeaponId(const char *name) { - if (mod_id == CSTRIKE_DLL) { - if (strcmp(name, "weapon_knife") == 0) - return CS_WEAPON_KNIFE; - if (strcmp(name, "weapon_c4") == 0) - return CS_WEAPON_C4; - if (strcmp(name, "weapon_mp5navy") == 0) - return CS_WEAPON_MP5NAVY; - if (strcmp(name, "weapon_ak47") == 0) - return CS_WEAPON_AK47; - if (strcmp(name, "weapon_m3") == 0) - return CS_WEAPON_M3; - if (strcmp(name, "weapon_aug") == 0) - return CS_WEAPON_AUG; - if (strcmp(name, "weapon_sg552") == 0) - return CS_WEAPON_SG552; - if (strcmp(name, "weapon_m249") == 0) - return CS_WEAPON_M249; - if (strcmp(name, "weapon_xm1014") == 0) - return CS_WEAPON_XM1014; - if (strcmp(name, "weapon_p90") == 0) - return CS_WEAPON_P90; - if (strcmp(name, "weapon_tmp") == 0) - return CS_WEAPON_TMP; - if (strcmp(name, "weapon_m4a1") == 0) - return CS_WEAPON_M4A1; - if (strcmp(name, "weapon_awp") == 0) - return CS_WEAPON_AWP; - if (strcmp(name, "weapon_fiveseven") == 0) - return CS_WEAPON_FIVESEVEN; - if (strcmp(name, "weapon_ump45") == 0) - return CS_WEAPON_UMP45; - if (strcmp(name, "weapon_sg550") == 0) - return CS_WEAPON_SG550; - if (strcmp(name, "weapon_scout") == 0) - return CS_WEAPON_SCOUT; - if (strcmp(name, "weapon_mac10") == 0) - return CS_WEAPON_MAC10; - if (strcmp(name, "weapon_g3sg1") == 0) - return CS_WEAPON_G3SG1; - if (strcmp(name, "weapon_elite") == 0) - return CS_WEAPON_ELITE; - if (strcmp(name, "weapon_p228") == 0) - return CS_WEAPON_P228; - if (strcmp(name, "weapon_deagle") == 0) - return CS_WEAPON_DEAGLE; - if (strcmp(name, "weapon_usp") == 0) - return CS_WEAPON_USP; - if (strcmp(name, "weapon_glock18") == 0) - return CS_WEAPON_GLOCK18; - // Counter-Strike 1.6 - if (strcmp(name, "weapon_famas") == 0) - return CS_WEAPON_FAMAS; - if (strcmp(name, "weapon_galil") == 0) - return CS_WEAPON_GALIL; - - // TODO: Detect shield carrying. - // 06/07/04 - // Unconfirmed for handling shield - // 31.08.04 Frashman: moved shield string before unknown weapon, not after it - if (strcmp(name, "weapon_shield") == 0) - return CS_WEAPON_SHIELD; - - char buffer[80]; - _snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); - rblog(buffer); - } - - return -1; +int UTIL_GiveWeaponId(const char* name) { + if (mod_id == CSTRIKE_DLL) { + if (strcmp(name, "weapon_knife") == 0) + return CS_WEAPON_KNIFE; + if (strcmp(name, "weapon_c4") == 0) + return CS_WEAPON_C4; + if (strcmp(name, "weapon_mp5navy") == 0) + return CS_WEAPON_MP5NAVY; + if (strcmp(name, "weapon_ak47") == 0) + return CS_WEAPON_AK47; + if (strcmp(name, "weapon_m3") == 0) + return CS_WEAPON_M3; + if (strcmp(name, "weapon_aug") == 0) + return CS_WEAPON_AUG; + if (strcmp(name, "weapon_sg552") == 0) + return CS_WEAPON_SG552; + if (strcmp(name, "weapon_m249") == 0) + return CS_WEAPON_M249; + if (strcmp(name, "weapon_xm1014") == 0) + return CS_WEAPON_XM1014; + if (strcmp(name, "weapon_p90") == 0) + return CS_WEAPON_P90; + if (strcmp(name, "weapon_tmp") == 0) + return CS_WEAPON_TMP; + if (strcmp(name, "weapon_m4a1") == 0) + return CS_WEAPON_M4A1; + if (strcmp(name, "weapon_awp") == 0) + return CS_WEAPON_AWP; + if (strcmp(name, "weapon_fiveseven") == 0) + return CS_WEAPON_FIVESEVEN; + if (strcmp(name, "weapon_ump45") == 0) + return CS_WEAPON_UMP45; + if (strcmp(name, "weapon_sg550") == 0) + return CS_WEAPON_SG550; + if (strcmp(name, "weapon_scout") == 0) + return CS_WEAPON_SCOUT; + if (strcmp(name, "weapon_mac10") == 0) + return CS_WEAPON_MAC10; + if (strcmp(name, "weapon_g3sg1") == 0) + return CS_WEAPON_G3SG1; + if (strcmp(name, "weapon_elite") == 0) + return CS_WEAPON_ELITE; + if (strcmp(name, "weapon_p228") == 0) + return CS_WEAPON_P228; + if (strcmp(name, "weapon_deagle") == 0) + return CS_WEAPON_DEAGLE; + if (strcmp(name, "weapon_usp") == 0) + return CS_WEAPON_USP; + if (strcmp(name, "weapon_glock18") == 0) + return CS_WEAPON_GLOCK18; + // Counter-Strike 1.6 + if (strcmp(name, "weapon_famas") == 0) + return CS_WEAPON_FAMAS; + if (strcmp(name, "weapon_galil") == 0) + return CS_WEAPON_GALIL; + + // TODO: Detect shield carrying. + // 06/07/04 + // Unconfirmed for handling shield + // 31.08.04 Frashman: moved shield string before unknown weapon, not after it + if (name != nullptr && strcmp(name, "weapon_shield") == 0) + return CS_WEAPON_SHIELD; + + char buffer[80]; + _snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); + rblog(buffer); + } + + return -1; } // Return weapon ID (depended on mod) -char *UTIL_GiveWeaponName(int id) { - if (mod_id == CSTRIKE_DLL) { - switch (id) { - case CS_WEAPON_C4: - return "weapon_c4"; - break; - case CS_WEAPON_MP5NAVY: - return "weapon_mp5navy"; - break; - case CS_WEAPON_AK47: - return "weapon_ak47"; - break; - case CS_WEAPON_M3: - return "weapon_m3"; - break; - case CS_WEAPON_AUG: - return "weapon_aug"; - break; - case CS_WEAPON_SG552: - return "weapon_sg552"; - break; - case CS_WEAPON_M249: - return "weapon_m249"; - break; - case CS_WEAPON_XM1014: - return "weapon_xm1014"; - break; - case CS_WEAPON_P90: - return "weapon_p90"; - break; - case CS_WEAPON_TMP: - return "weapon_tmp"; - break; - case CS_WEAPON_M4A1: - return "weapon_m4a1"; - break; - case CS_WEAPON_AWP: - return "weapon_awp"; - break; - case CS_WEAPON_FIVESEVEN: - return "weapon_fiveseven"; - break; - case CS_WEAPON_UMP45: - return "weapon_ump45"; - break; - case CS_WEAPON_SG550: - return "weapon_ag550"; - break; - case CS_WEAPON_SCOUT: - return "weapon_scout"; - break; - case CS_WEAPON_MAC10: - return "weapon_mac10"; - break; - case CS_WEAPON_G3SG1: - return "weapon_g3sg1"; - break; - case CS_WEAPON_ELITE: - return "weapon_elite"; - break; - case CS_WEAPON_P228: - return "weapon_p228"; - break; - case CS_WEAPON_DEAGLE: - return "weapon_deagle"; - break; - case CS_WEAPON_USP: - return "weapon_usp"; - break; - case CS_WEAPON_GLOCK18: - return "weapon_glock18"; - break; - - // Counter-Strike 1.6 - case CS_WEAPON_FAMAS: - return "weapon_famas"; - break; - case CS_WEAPON_GALIL: - return "weapon_galil"; - break; - - // Unconfirmed shield - case CS_WEAPON_SHIELD: - return "weapon_shield"; - break; - } - } - - return "weapon_knife"; // return knife, always good ;) +char* UTIL_GiveWeaponName(int id) { + if (mod_id == CSTRIKE_DLL) { + switch (id) { + case CS_WEAPON_C4: + return "weapon_c4"; + break; + case CS_WEAPON_MP5NAVY: + return "weapon_mp5navy"; + break; + case CS_WEAPON_AK47: + return "weapon_ak47"; + break; + case CS_WEAPON_M3: + return "weapon_m3"; + break; + case CS_WEAPON_AUG: + return "weapon_aug"; + break; + case CS_WEAPON_SG552: + return "weapon_sg552"; + break; + case CS_WEAPON_M249: + return "weapon_m249"; + break; + case CS_WEAPON_XM1014: + return "weapon_xm1014"; + break; + case CS_WEAPON_P90: + return "weapon_p90"; + break; + case CS_WEAPON_TMP: + return "weapon_tmp"; + break; + case CS_WEAPON_M4A1: + return "weapon_m4a1"; + break; + case CS_WEAPON_AWP: + return "weapon_awp"; + break; + case CS_WEAPON_FIVESEVEN: + return "weapon_fiveseven"; + break; + case CS_WEAPON_UMP45: + return "weapon_ump45"; + break; + case CS_WEAPON_SG550: + return "weapon_ag550"; + break; + case CS_WEAPON_SCOUT: + return "weapon_scout"; + break; + case CS_WEAPON_MAC10: + return "weapon_mac10"; + break; + case CS_WEAPON_G3SG1: + return "weapon_g3sg1"; + break; + case CS_WEAPON_ELITE: + return "weapon_elite"; + break; + case CS_WEAPON_P228: + return "weapon_p228"; + break; + case CS_WEAPON_DEAGLE: + return "weapon_deagle"; + break; + case CS_WEAPON_USP: + return "weapon_usp"; + break; + case CS_WEAPON_GLOCK18: + return "weapon_glock18"; + break; + + // Counter-Strike 1.6 + case CS_WEAPON_FAMAS: + return "weapon_famas"; + break; + case CS_WEAPON_GALIL: + return "weapon_galil"; + break; + + // Unconfirmed shield + case CS_WEAPON_SHIELD: + return "weapon_shield"; + break; + } + } + + return "weapon_knife"; // return knife, always good ;) } // Thanks Botman for this code (from forum). -void UTIL_BotSprayLogo(edict_t *pEntity, char *logo_name) { +void UTIL_BotSprayLogo(edict_t* pEntity, char* logo_name) { TraceResult pTrace; UTIL_MakeVectors(pEntity->v.v_angle); const Vector v_src = pEntity->v.origin + pEntity->v.view_ofs; const Vector v_dest = v_src + gpGlobals->v_forward * 80; - UTIL_TraceLine(v_src, v_dest, ignore_monsters, - pEntity->v.pContainingEntity, &pTrace); + UTIL_TraceLine(v_src, v_dest, ignore_monsters, + pEntity->v.pContainingEntity, &pTrace); - int index = DECAL_INDEX(logo_name); + int index = DECAL_INDEX(logo_name); - if (index < 0) - return; + if (index < 0) + return; - if ((pTrace.pHit) && (pTrace.flFraction < 1.0f)) { - if (pTrace.pHit->v.solid != SOLID_BSP) - return; + if ((pTrace.pHit) && (pTrace.flFraction < 1.0f)) { + if (pTrace.pHit->v.solid != SOLID_BSP) + return; - MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); + MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY); - if (index > 255) { - WRITE_BYTE(TE_WORLDDECALHIGH); - index -= 256; - } else - WRITE_BYTE(TE_WORLDDECAL); + if (index > 255) { + WRITE_BYTE(TE_WORLDDECALHIGH); + index -= 256; + } + else + WRITE_BYTE(TE_WORLDDECAL); - WRITE_COORD(pTrace.vecEndPos.x); - WRITE_COORD(pTrace.vecEndPos.y); - WRITE_COORD(pTrace.vecEndPos.z); - WRITE_BYTE(index); + WRITE_COORD(pTrace.vecEndPos.x); + WRITE_COORD(pTrace.vecEndPos.y); + WRITE_COORD(pTrace.vecEndPos.z); + WRITE_BYTE(index); - MESSAGE_END(); + MESSAGE_END(); - EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0, - ATTN_NORM, 0, 100); - } + EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0, + ATTN_NORM, 0, 100); + } } // Give a radio message botty boy! -void UTIL_BotRadioMessage(cBot *pBot, int radio, char *arg1, char *arg2) { - // To be sure the console will only change when we MAY change. - // The values will only be changed when console_nr is 0 - if (pBot->console_nr == 0) { - switch (radio) { - case 1: - strcpy(pBot->arg1, "radio1"); - break; - case 2: - strcpy(pBot->arg1, "radio2"); - break; - case 3: - strcpy(pBot->arg1, "radio3"); - break; - } - - strcpy(pBot->arg2, arg1); - strcpy(pBot->arg3, arg2); - pBot->console_nr = 1; // Begin message - - // 02/07/04 - pointed out, eliminate any possible 'devide by zero' - int iExtra = (100 / (pBot->ipCreateRadio + 1)); - if (iExtra > 30) - iExtra = 30; - pBot->fDoRadio = gpGlobals->time + iExtra; - } +void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { + // To be sure the console will only change when we MAY change. + // The values will only be changed when console_nr is 0 + if (pBot->console_nr == 0) { + switch (radio) { + case 1: + strcpy(pBot->arg1, "radio1"); + break; + case 2: + strcpy(pBot->arg1, "radio2"); + break; + case 3: + strcpy(pBot->arg1, "radio3"); + break; + } + + strcpy(pBot->arg2, arg1); + strcpy(pBot->arg3, arg2); + pBot->console_nr = 1; // Begin message + + // 02/07/04 - pointed out, eliminate any possible 'devide by zero' + int iExtra = (100 / (pBot->ipCreateRadio + 1)); + if (iExtra > 30) + iExtra = 30; + pBot->fDoRadio = gpGlobals->time + iExtra; + } } ////////////////////////////////// // UTIL_getGrenadeType function // - Stefan ////////////////////////////////// -int UTIL_GetGrenadeType(edict_t *pEntity) { +int UTIL_GetGrenadeType(edict_t* pEntity) { - const int length = 32; + const int length = 32; - char model_name[length]; - memset(model_name, 0, sizeof(model_name)); + char model_name[length]; + memset(model_name, 0, sizeof(model_name)); - strncpy(model_name, STRING(pEntity->v.model), length - 1); - model_name[length - 1] = 0; // Make sure it is NULL terminated + strncpy(model_name, STRING(pEntity->v.model), length - 1); + model_name[length - 1] = 0; // Make sure it is NULL terminated - if (strcmp(model_name, "models/w_hegrenade.mdl") == 0) return 1; // He grenade - if (strcmp(model_name, "models/w_flashbang.mdl") == 0) return 2; // FlashBang - if (strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade - if (strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive + if (strcmp(model_name, "models/w_hegrenade.mdl") == 0) return 1; // He grenade + if (strcmp(model_name, "models/w_flashbang.mdl") == 0) return 2; // FlashBang + if (strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade + if (strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive - char msg[512]; - memset(msg, 0, sizeof(msg)); + char msg[512]; + memset(msg, 0, sizeof(msg)); - // when non empty string, let us know we missed something - if (!strlen(model_name) == 0) { - sprintf(msg, "UTIL_GetGrenadeType unknown grenade model : %s\n", model_name); - } + // when non empty string, let us know we missed something + if (!strlen(model_name) == 0) { + sprintf(msg, "UTIL_GetGrenadeType unknown grenade model : %s\n", model_name); + } - rblog(msg); + rblog(msg); - return 0; + return 0; } // 2 functions from podbot source unsigned short fixed_unsigned16(float value, float scale) { int output = static_cast(value * scale); - if (output < 0) - output = 0; - if (output > 0xFFFF) - output = 0xFFFF; + if (output < 0) + output = 0; + if (output > 0xFFFF) + output = 0xFFFF; - return static_cast(output); + return static_cast(output); } short fixed_signed16(float value, float scale) { int output = static_cast(value * scale); - if (output > 32767) - output = 32767; + if (output > 32767) + output = 32767; - if (output < -32768) - output = -32768; + if (output < -32768) + output = -32768; - return static_cast(output); + return static_cast(output); } // Using POD/SDK source to print nice messages on the client machine -void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict) { - // FROM PODBOT SOURCE - // Hacked together Version of HUD_DrawString - MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); - WRITE_BYTE(TE_TEXTMESSAGE); - WRITE_BYTE(1); - WRITE_SHORT(fixed_signed16(-1, 1 << 13)); - WRITE_SHORT(fixed_signed16(0, 1 << 13)); - WRITE_BYTE(2); - WRITE_BYTE(r); //r - WRITE_BYTE(g); //g - WRITE_BYTE(b); //b - WRITE_BYTE(0); - WRITE_BYTE(255); - WRITE_BYTE(255); - WRITE_BYTE(255); - WRITE_BYTE(200); - WRITE_SHORT(fixed_unsigned16(0.0078125, 1 << 8)); - WRITE_SHORT(fixed_unsigned16(2, 1 << 8)); - WRITE_SHORT(fixed_unsigned16(6, 1 << 8)); - WRITE_SHORT(fixed_unsigned16(0.1f, 1 << 8)); - WRITE_STRING(static_cast(&msg[0])); - MESSAGE_END(); +void HUD_DrawString(int r, int g, int b, char* msg, edict_t* edict) { + // FROM PODBOT SOURCE + // Hacked together Version of HUD_DrawString + MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); + WRITE_BYTE(TE_TEXTMESSAGE); + WRITE_BYTE(1); + WRITE_SHORT(fixed_signed16(-1, 1 << 13)); + WRITE_SHORT(fixed_signed16(0, 1 << 13)); + WRITE_BYTE(2); + WRITE_BYTE(r); //r + WRITE_BYTE(g); //g + WRITE_BYTE(b); //b + WRITE_BYTE(0); + WRITE_BYTE(255); + WRITE_BYTE(255); + WRITE_BYTE(255); + WRITE_BYTE(200); + WRITE_SHORT(fixed_unsigned16(0.0078125, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(2, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(6, 1 << 8)); + WRITE_SHORT(fixed_unsigned16(0.1f, 1 << 8)); + WRITE_STRING(static_cast(&msg[0])); + MESSAGE_END(); } -void UTIL_FixAngles(Vector *Angles) { - if (Angles->x > 180.0f) - Angles->x -= 360.0f; - if (Angles->x < -180.0f) - Angles->x += 360.0f; - if (Angles->y > 180.0f) - Angles->y -= 360.0f; - if (Angles->y < -180.0f) - Angles->y += 360.0f; +void UTIL_FixAngles(Vector* Angles) { + if (Angles->x > 180.0f) + Angles->x -= 360.0f; + if (Angles->x < -180.0f) + Angles->x += 360.0f; + if (Angles->y > 180.0f) + Angles->y -= 360.0f; + if (Angles->y < -180.0f) + Angles->y += 360.0f; - Angles->z = 0.0f; + Angles->z = 0.0f; } -void UTIL_SayTextBot(const char *pText, cBot *pBot) { - if (gmsgSayText == 0) - gmsgSayText = REG_USER_MSG("SayText", -1); - - char szTemp[160]; - char szName[BOT_NAME_LEN + 1]; - int i; - - // clear out - memset(szTemp, 0, sizeof(szTemp)); - memset(szName, 0, sizeof(szName)); - - // init - szTemp[0] = 2; - - const int entind = ENTINDEX(pBot->pEdict); - - if (IsAlive(pBot->pEdict)) { - strcpy(szName, pBot->name); - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - - // valid - if (pPlayer) - if (IsAlive(pPlayer)) // alive - { - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); - WRITE_BYTE(entind); - sprintf(&szTemp[1], "%s : %s", szName, pText); - WRITE_STRING(&szTemp[0]); - MESSAGE_END(); - } - } - } else { - strcpy(szName, pBot->name); - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - if (pPlayer) - if (!IsAlive(pPlayer)) { - MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); - WRITE_BYTE(entind); - sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); - WRITE_STRING(&szTemp[0]); - MESSAGE_END(); - } - } - } - - - // pass through on ChatEngine (not always) - if (RANDOM_LONG(0, 100) < 90) { - char chSentence[80]; - memset(chSentence, 0, sizeof(chSentence)); - - // copy pText to chSentence - strcpy(chSentence, pText); - - // pass through - ChatEngine.set_sentence(pBot->name, chSentence); - } +void UTIL_SayTextBot(const char* pText, cBot* pBot) { + if (gmsgSayText == 0) + gmsgSayText = REG_USER_MSG("SayText", -1); + + char szTemp[160]; + char szName[BOT_NAME_LEN + 1]; + int i; + + // clear out + memset(szTemp, 0, sizeof(szTemp)); + memset(szName, 0, sizeof(szName)); + + // init + szTemp[0] = 2; + + const int entind = ENTINDEX(pBot->pEdict); + + if (IsAlive(pBot->pEdict)) { + strcpy(szName, pBot->name); + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + + // valid + if (pPlayer) + if (IsAlive(pPlayer)) // alive + { + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); + WRITE_BYTE(entind); + sprintf(&szTemp[1], "%s : %s", szName, pText); + WRITE_STRING(&szTemp[0]); + MESSAGE_END(); + } + } + } + else { + strcpy(szName, pBot->name); + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + if (pPlayer) + if (!IsAlive(pPlayer)) { + MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); + WRITE_BYTE(entind); + sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); + WRITE_STRING(&szTemp[0]); + MESSAGE_END(); + } + } + } + + + // pass through on ChatEngine (not always) + if (RANDOM_LONG(0, 100) < 90) { + char chSentence[80]; + memset(chSentence, 0, sizeof(chSentence)); + + // copy pText to chSentence + strcpy(chSentence, pText); + + // pass through + ChatEngine.set_sentence(pBot->name, chSentence); + } } // This UTIL_SpeechSynth() is taken from the POD source. -void UTIL_SpeechSynth(edict_t *pEdict, char *szMessage) { - if (Game.bSpeechBroadcasting == false) - return; +void UTIL_SpeechSynth(edict_t* pEdict, char* szMessage) { + if (Game.bSpeechBroadcasting == false) + return; - char szSpeak[128]; + char szSpeak[128]; - sprintf(szSpeak, "speak \"%s\"\n", szMessage); - CLIENT_COMMAND(pEdict, szSpeak); + sprintf(szSpeak, "speak \"%s\"\n", szMessage); + CLIENT_COMMAND(pEdict, szSpeak); } // $Log: util.cpp,v $ From 2f2e27958b6e11a9fc283f15dbcda4ca36079577 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sun, 30 Jul 2023 21:33:31 +0100 Subject: [PATCH 079/114] Using newer C++ Standard functions --- AMBuildScript | 2 +- NodeMachine.cpp | 2 +- bot_func.cpp | 16 ++++++++++++++++ dependencies/hlsdk/dlls/extdll.h | 6 +++--- dependencies/hlsdk/dlls/vector.h | 8 +++++--- realbot_mm.vcxproj | 2 +- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index 3516fb6..1151fc1 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -92,7 +92,7 @@ if builder.options.optimize == '1': builder.cxx.cflags += ['-O2'] elif builder.cxx.target.platform == 'windows': # Windows optimization flags - builder.cxx.cflags += ['/O2', '/Zo'] + builder.cxx.cflags += ['/Ox', '/Zo'] # Windows optimization link flags builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 775fa64..57a09bd 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -722,7 +722,7 @@ int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) { // Compute the horizontal distance between A and B (ignoring z coordinate) static float horizontal_distance(const Vector& a, const Vector& b) { - return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); + return std::sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } #define STEP 20 //Incremental move diff --git a/bot_func.cpp b/bot_func.cpp index 5256b87..525fa78 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -890,6 +890,22 @@ void FUNC_FindBreakable(edict_t* pEntity) //TODO: not functioning, bots won't sh } } +/*bool IsShootableBreakable(edict_t* pent) // KWo - 08.02.2006 +{ + if (pent == nullptr) + return false; + + return (FStrEq("func_breakable", STRING(pent->v.classname)) + && (pent->v.playerclass == 1 || pent->v.health == 0 + || pent->v.health > 1 && pent->v.health < 1000 + || pent->v.rendermode == 4) // KWo - 21.02.2006 - br. crates has rendermode 4 + || FStrEq("func_pushable", STRING(pent->v.classname)) + && pent->v.health < 1000 && pent->v.spawnflags & SF_PUSH_BREAKABLE) // KWo - 03.02.2007 + && pent->v.impulse == 0 + && pent->v.takedamage > 0 + && !(pent->v.spawnflags & SF_BREAK_TRIGGER_ONLY); +}*/ + void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] { // Check if the bot has a bomb planted. diff --git a/dependencies/hlsdk/dlls/extdll.h b/dependencies/hlsdk/dlls/extdll.h index a92a582..342dccc 100644 --- a/dependencies/hlsdk/dlls/extdll.h +++ b/dependencies/hlsdk/dlls/extdll.h @@ -92,9 +92,9 @@ typedef int BOOL; #endif //_WIN32 // Misc C-runtime library headers -#include "stdio.h" -#include "stdlib.h" -#include "math.h" +#include +#include +#include // Header file containing definition of globalvars_t and entvars_t typedef unsigned int func_t; // diff --git a/dependencies/hlsdk/dlls/vector.h b/dependencies/hlsdk/dlls/vector.h index 08148de..58c441e 100644 --- a/dependencies/hlsdk/dlls/vector.h +++ b/dependencies/hlsdk/dlls/vector.h @@ -15,6 +15,8 @@ #ifndef VECTOR_H #define VECTOR_H +#include + //========================================================= // 2DVector - used for many pathfinding and many other // operations that are treated as planar rather than 3d. @@ -29,7 +31,7 @@ class Vector2D inline Vector2D operator*(float fl) const { return Vector2D(x*fl, y*fl); } inline Vector2D operator/(float fl) const { return Vector2D(x/fl, y/fl); } - inline float Length(void) const { return sqrt(x*x + y*y ); } + inline float Length(void) const { return std::sqrt(x*x + y*y ); } inline Vector2D Normalize ( void ) const { @@ -77,7 +79,7 @@ class Vector // same data-layout as engine's vec3_t, // Methods inline void CopyToArray(float* rgfl) const { rgfl[0] = x, rgfl[1] = y, rgfl[2] = z; } - inline float Length(void) const { return sqrt(x*x + y*y + z*z); } + inline float Length(void) const { return std::sqrt(x*x + y*y + z*z); } operator float *() { return &x; } // Vectors will now automatically convert to float * when needed operator const float *() const { return &x; } // Vectors will now automatically convert to float * when needed inline Vector Normalize(void) const @@ -97,7 +99,7 @@ class Vector // same data-layout as engine's vec3_t, return Vec2; } - inline float Length2D(void) const { return sqrt(x*x + y*y); } + inline float Length2D(void) const { return std::sqrt(x*x + y*y); } // Members vec_t x, y, z; diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 8953233..444d140 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -61,7 +61,7 @@ .\Release/ true .\Release/ - Level4 + EnableAllWarnings false true ProgramDatabase From d8a67cbbb4e0732c613c7e88de711590c6e3226b Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 22 Dec 2023 15:09:03 +0000 Subject: [PATCH 080/114] Reduced redundancy --- .gitignore | 1 + bot.cpp | 39 +++++++++++++++++++++++---------------- bot_navigate.cpp | 5 ++++- util.cpp | 9 +++------ 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 7a6332f..ab58d96 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ x64/ x86/ build/ +build_linux/ bld/ [Bb]in/ [Oo]bj/ diff --git a/bot.cpp b/bot.cpp index 565f01c..760e40a 100644 --- a/bot.cpp +++ b/bot.cpp @@ -230,8 +230,8 @@ void cBot::SpawnInit() { bWalkKnife = false; buy_ammo_primary = true; buy_ammo_secondary = true; - buy_primary = (Game.bPistols ? false : true); //30/07/04: Josh, handle the pistols only mode - buy_secondary = (Game.bPistols ? true : false); + buy_primary = !Game.bPistols; //30/07/04: Josh, handle the pistols only mode + buy_secondary = Game.bPistols; buy_armor = false; buy_defusekit = false; bFirstOutOfSight = false; @@ -401,11 +401,11 @@ void cBot::NewRound() { // Buying buy_ammo_primary = true; buy_ammo_secondary = true; - buy_primary = (Game.bPistols ? false : true); + buy_primary = !Game.bPistols; buy_grenade = false; buy_smokegrenade = false; buy_flashbang = 0; - buy_secondary = (Game.bPistols ? true : false); + buy_secondary = Game.bPistols; buy_armor = false; buy_defusekit = false; @@ -535,26 +535,33 @@ int cBot::FindEnemy() { // if bot can see the player... if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) { - const int player_team = UTIL_GetTeam(pPlayer); - const int bot_team = UTIL_GetTeam(pEdict); - if (player_team == bot_team) - continue; // do not target teammates - - // Its not a friend, track enemy - const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); + const int player_team = UTIL_GetTeam(pPlayer); + const int bot_team = UTIL_GetTeam(pEdict); + + if (player_team == bot_team) { + // do not target teammates + continue; + } + + // It's not a friend, track enemy + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); bool bCanSee = true; // The further away, the less chance we see this enemy - //if (RANDOM_FLOAT(0,1.0) < (fDistance/4096)) - // bCanSee=false; - if (CarryWeaponType() == SNIPER) + // Uncomment the following lines if you want to add distance-based visibility check + // if (RANDOM_FLOAT(0, 1.0) < (fDistance / 4096)) { + // bCanSee = false; + // } + + // If the bot carries a sniper, always consider the enemy visible + if (CarryWeaponType() == SNIPER) { bCanSee = true; + } + if (fDistance < fNearestDistance && bCanSee) { fNearestDistance = fDistance; pNewEnemy = pPlayer; } - continue; } } // valid player } // FOR diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 65eccb9..20652ab 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -43,7 +43,10 @@ extern int mod_id; extern edict_t *pHostEdict; -#define SCAN_RADIUS 60 // Radius to scan to prevent blocking with players +enum +{ + SCAN_RADIUS = 60 // Radius to scan to prevent blocking with players +}; /** * Given an angle, makes sure it wraps around properly diff --git a/util.cpp b/util.cpp index 8521214..93e74e4 100644 --- a/util.cpp +++ b/util.cpp @@ -855,7 +855,6 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { // UTIL_getGrenadeType function // - Stefan ////////////////////////////////// int UTIL_GetGrenadeType(edict_t* pEntity) { - const int length = 32; char model_name[length]; @@ -872,13 +871,11 @@ int UTIL_GetGrenadeType(edict_t* pEntity) { char msg[512]; memset(msg, 0, sizeof(msg)); - // when non empty string, let us know we missed something - if (!strlen(model_name) == 0) { - sprintf(msg, "UTIL_GetGrenadeType unknown grenade model : %s\n", model_name); + // when an empty string, let us know we missed something + if (model_name[0] == '\0') { + snprintf(msg, sizeof(msg), "UTIL_GetGrenadeType unknown grenade model: %s\n", model_name); } - rblog(msg); - return 0; } From eb94991816fa07fd42ee76cafa6f687b543ff5d7 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 25 Dec 2023 20:39:13 +0000 Subject: [PATCH 081/114] C++ Modernisation --- ChatEngine.cpp | 58 ++++---- IniParser.cpp | 202 +++++++++++++-------------- NodeMachine.cpp | 305 ++++++++++++++++++++-------------------- bot.cpp | 174 +++++++++++------------ bot_buycode.cpp | 6 +- bot_client.cpp | 54 ++++---- bot_func.cpp | 50 +++---- dll.cpp | 362 ++++++++++++++++++++++++------------------------ engine.cpp | 60 ++++---- game.cpp | 96 ++++++------- util.cpp | 158 ++++++++++----------- 11 files changed, 764 insertions(+), 761 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index a09fff6..25c481f 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -70,8 +70,8 @@ cChatEngine::init() { iLastSentence = -1; // init sentence - memset(sentence, 0, sizeof(sentence)); - memset(sender, 0, sizeof(sender)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(sender, 0, sizeof(sender)); } // load @@ -103,14 +103,14 @@ void cChatEngine::think() { if (pPlayer && (!pPlayer->free)) { char name[30], name2[30]; // clear - memset(name, 0, sizeof(name)); - memset(name2, 0, sizeof(name2)); + std::memset(name, 0, sizeof(name)); + std::memset(name2, 0, sizeof(name2)); // copy - strcpy(name, STRING(pPlayer->v.netname)); - strcpy(name2, sender); + std::strcpy(name, STRING(pPlayer->v.netname)); + std::strcpy(name2, sender); - if (strcmp(name, name2) == 0) { + if (std::strcmp(name, name2) == 0) { pSender = pPlayer; break; } @@ -120,20 +120,20 @@ void cChatEngine::think() { // Scan the message so we know in what block we should be to reply: char word[20]; - memset(word, 0, sizeof(word)); + std::memset(word, 0, sizeof(word)); int c = 0; int wc = 0; - const int sentenceLength = static_cast(strlen(sentence)); + const int sentenceLength = static_cast(std::strlen(sentence)); // When length is not valid, get out. // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? // how did we allow for this to happen? if (sentenceLength == 0 || sentenceLength >= (MAX_SENTENCE_LENGTH-1)) { // clear out sentence and sender - memset(sentence, 0, sizeof(sentence)); - memset(sender, 0, sizeof(sender)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(sender, 0, sizeof(sender)); // reset timer fThinkTimer = gpGlobals->time; @@ -169,7 +169,7 @@ void cChatEngine::think() { word[wc] = sentence[c]; // not a good word (too small) - if (strlen(word) <= 0) { + if (std::strlen(word) <= 0) { //SERVER_PRINT("This is not a good word!\n"); } else { for (int iB = 0; iB < MAX_BLOCKS; iB++) { @@ -179,12 +179,12 @@ void cChatEngine::think() { if (ReplyBlock[iB].word[iBw][0] == '\0') continue; // not filled in - if (strlen(ReplyBlock[iB].word[iBw]) <= 0) + if (std::strlen(ReplyBlock[iB].word[iBw]) <= 0) continue; // not long enough (a space?) // 03/07/04 // add score to matching word (evy: ignoring case) - if (strcmp(ReplyBlock[iB].word[iBw], word) == 0) + if (std::strcmp(ReplyBlock[iB].word[iBw], word) == 0) WordBlockScore[iB]++; } // all words in this block } // any used block @@ -194,7 +194,7 @@ void cChatEngine::think() { // clear out entire word. //for (int cw=0; cw < 20; cw++) // word[cw] = '\0'; - memset(word, 0, sizeof(word)); + std::memset(word, 0, sizeof(word)); wc = 0; // reset WC position (start writing 'word[WC]' at 0 again) c++; // next position in sentence @@ -279,12 +279,12 @@ void cChatEngine::think() { char chSentence[128]; char temp[80]; - memset(chSentence, 0, sizeof(chSentence)); - memset(temp, 0, sizeof(temp)); + std::memset(chSentence, 0, sizeof(chSentence)); + std::memset(temp, 0, sizeof(temp)); // get character position const char *name_pos = - strstr(ReplyBlock[iTheBlock]. + std::strstr(ReplyBlock[iTheBlock]. sentence[the_c], "%n"); // when name_pos var is found, fill it in. @@ -307,19 +307,19 @@ void cChatEngine::think() { temp[nC] = ' '; // copy senders name to chSentence - strcat(temp, sender); + std::strcat(temp, sender); // Skip %n part in ReplyBlock nC = name_offset + 3; // we just copied a name to chSentence // set our cursor after the name now (name length + 1) - int tc = static_cast(strlen(temp)); + int tc = static_cast(std::strlen(temp)); // now finish the sentence // get entire length of ReplyBlock and go until we reach the end const int length = - static_cast(strlen(ReplyBlock[iTheBlock]. + static_cast(std::strlen(ReplyBlock[iTheBlock]. sentence[the_c])); @@ -339,11 +339,11 @@ void cChatEngine::think() { // terminate temp[tc] = '\n'; - sprintf(chSentence, "%s \n", temp); + std::sprintf(chSentence, "%s \n", temp); } // when no name pos is found, we just copy the string and say that (works ok) else - sprintf(chSentence, "%s \n", + std::sprintf(chSentence, "%s \n", ReplyBlock[iTheBlock]. sentence[the_c]); @@ -364,8 +364,8 @@ void cChatEngine::think() { } // clear sentence and such - memset(sentence, 0, sizeof(sentence)); - memset(sender, 0, sizeof(sender)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(sender, 0, sizeof(sender)); fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); @@ -395,8 +395,8 @@ void cChatEngine::handle_sentence() //Experimental implementation [APG]RoboCop[C } // clear sentence and such - memset(sentence, 0, sizeof(sentence)); - memset(sender, 0, sizeof(sender)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(sender, 0, sizeof(sender)); fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); } @@ -411,7 +411,7 @@ void cChatEngine::set_sentence(char csender[30], char csentence[MAX_SENTENCE_LEN // SERVER_PRINT(csentence); // SERVER_PRINT("--\n"); - strcpy(sender, csender); + std::strcpy(sender, csender); #ifdef _WIN32 _strupr(csentence); @@ -427,7 +427,7 @@ void cChatEngine::set_sentence(char csender[30], char csentence[MAX_SENTENCE_LEN pString++; } #endif - strcpy(sentence, csentence); + std::strcpy(sentence, csentence); } } diff --git a/IniParser.cpp b/IniParser.cpp index 88736f4..1031dc0 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -120,120 +120,120 @@ void INI_Word(char input[80], char word[25]) { int INI_WordType(char word[25], int section) { if (word[0] != '\0') { - if (strcmp(word, "Word") == 0) + if (std::strcmp(word, "Word") == 0) return WORD_WORD; - if (strcmp(word, "Sentence") == 0) + if (std::strcmp(word, "Sentence") == 0) return WORD_SENTENCE; - if (strcmp(word, "X") == 0) + if (std::strcmp(word, "X") == 0) return WORD_AREAX; - if (strcmp(word, "Y") == 0) + if (std::strcmp(word, "Y") == 0) return WORD_AREAY; - if (strcmp(word, "Z") == 0) + if (std::strcmp(word, "Z") == 0) return WORD_AREAZ; // ------ personality stuff ------ - if (strcmp(word, "PrimaryWeapon") == 0) + if (std::strcmp(word, "PrimaryWeapon") == 0) return WORD_PRIWEAPON; - if (strcmp(word, "SecondaryWeapon") == 0) + if (std::strcmp(word, "SecondaryWeapon") == 0) return WORD_SECWEAPON; - if (strcmp(word, "SaveForWeapon") == 0) + if (std::strcmp(word, "SaveForWeapon") == 0) return WORD_SAVEFORWEAP; - if (strcmp(word, "Grenade") == 0) + if (std::strcmp(word, "Grenade") == 0) return WORD_GRENADE; - if (strcmp(word, "FlashBang") == 0) + if (std::strcmp(word, "FlashBang") == 0) return WORD_FLASHBANG; - if (strcmp(word, "SmokeGrenade") == 0) + if (std::strcmp(word, "SmokeGrenade") == 0) return WORD_SMOKEGREN; - if (strcmp(word, "DefuseKit") == 0) + if (std::strcmp(word, "DefuseKit") == 0) return WORD_DEFUSEKIT; - if (strcmp(word, "Armour") == 0) + if (std::strcmp(word, "Armour") == 0) return WORD_ARMOUR; // ---- skill - if (strcmp(word, "XOffset") == 0) + if (std::strcmp(word, "XOffset") == 0) return WORD_XOFFSET; - if (strcmp(word, "YOffset") == 0) + if (std::strcmp(word, "YOffset") == 0) return WORD_YOFFSET; - if (strcmp(word, "ZOffset") == 0) + if (std::strcmp(word, "ZOffset") == 0) return WORD_ZOFFSET; - if (strcmp(word, "BotSkill") == 0) + if (std::strcmp(word, "BotSkill") == 0) return WORD_BOTSKILL; - if (strcmp(word, "MaxReactionTime") == 0) + if (std::strcmp(word, "MaxReactionTime") == 0) return WORD_MAXREACTTIME; - if (strcmp(word, "MinReactionTime") == 0) + if (std::strcmp(word, "MinReactionTime") == 0) return WORD_MINREACTTIME; - if (strcmp(word, "Turnspeed") == 0) + if (std::strcmp(word, "Turnspeed") == 0) return WORD_TURNSPEED; // ---- Game - if (strcmp(word, "Hostage") == 0) + if (std::strcmp(word, "Hostage") == 0) return WORD_HOSTAGERATE; - if (strcmp(word, "BompSpot") == 0) + if (std::strcmp(word, "BompSpot") == 0) return WORD_BOMBSPOTRATE; - if (strcmp(word, "Random") == 0) + if (std::strcmp(word, "Random") == 0) return WORD_RANDOMRATE; - if (strcmp(word, "DroppedBomb") == 0) + if (std::strcmp(word, "DroppedBomb") == 0) return WORD_DROPPEDBOMB; // ---- Radio - if (strcmp(word, "Reply") == 0) + if (std::strcmp(word, "Reply") == 0) return WORD_REPLYRADIO; - if (strcmp(word, "Create") == 0) + if (std::strcmp(word, "Create") == 0) return WORD_CREATERADIO; // ---- Team - if (strcmp(word, "HelpTeammate") == 0) + if (std::strcmp(word, "HelpTeammate") == 0) return WORD_HELPTEAM; // ---- person - if (strcmp(word, "WalkWithKnife") == 0) + if (std::strcmp(word, "WalkWithKnife") == 0) return WORD_WALKKNIFE; - if (strcmp(word, "FearRate") == 0) + if (std::strcmp(word, "FearRate") == 0) return WORD_FEARRATE; - if (strcmp(word, "HearRate") == 0) + if (std::strcmp(word, "HearRate") == 0) return WORD_HEARRATE; - if (strcmp(word, "ChatRate") == 0) + if (std::strcmp(word, "ChatRate") == 0) return WORD_CHATRATE; - if (strcmp(word, "CampRate") == 0) + if (std::strcmp(word, "CampRate") == 0) return WORD_CAMPRATE; // ------ buy table stuff ------- - if (strcmp(word, "Price") == 0) + if (std::strcmp(word, "Price") == 0) return WORD_PRICE; - if (strcmp(word, "Priority") == 0) + if (std::strcmp(word, "Priority") == 0) return WORD_PRIORITY; - if (strcmp(word, "Ammo1Index") == 0) + if (std::strcmp(word, "Ammo1Index") == 0) return WORD_INDEX1; - if (strcmp(word, "Ammo2Index") == 0) + if (std::strcmp(word, "Ammo2Index") == 0) return WORD_INDEX2; - if (strcmp(word, "Ammo1Max") == 0) + if (std::strcmp(word, "Ammo1Max") == 0) return WORD_MAXAMMO1; - if (strcmp(word, "Ammo2Max") == 0) + if (std::strcmp(word, "Ammo2Max") == 0) return WORD_MAXAMMO2; } @@ -268,34 +268,34 @@ void INI_Sentence(FILE * f, char result[80]) { // Reads out section[], does a string compare and returns type id int INI_SectionType(char section[30], int last) { - if (strcmp(section, "BLOCK") == 0) + if (std::strcmp(section, "BLOCK") == 0) return INI_BLOCK; - if (strcmp(section, "DEATH") == 0) + if (std::strcmp(section, "DEATH") == 0) return INI_DEATHS; - if (strcmp(section, "WELCOME") == 0) + if (std::strcmp(section, "WELCOME") == 0) return INI_WELCOME; - if (strcmp(section, "AREA") == 0) + if (std::strcmp(section, "AREA") == 0) return INI_AREA; - if (strcmp(section, "WEAPON") == 0) + if (std::strcmp(section, "WEAPON") == 0) return INI_WEAPON; - if (strcmp(section, "SKILL") == 0) + if (std::strcmp(section, "SKILL") == 0) return INI_SKILL; - if (strcmp(section, "GAME") == 0) + if (std::strcmp(section, "GAME") == 0) return INI_GAME; - if (strcmp(section, "RADIO") == 0) + if (std::strcmp(section, "RADIO") == 0) return INI_RADIO; - if (strcmp(section, "TEAM") == 0) + if (std::strcmp(section, "TEAM") == 0) return INI_TEAM; - if (strcmp(section, "PERSON") == 0) + if (std::strcmp(section, "PERSON") == 0) return INI_PERSON; // When nothing found; we assume its just a new ID tag for some unit or structure @@ -307,69 +307,69 @@ int INI_SectionType(char section[30], int last) { // BUYTABLE.INI SPECIFIC! int INI_SectionType_BUYTABLE(char section[30], int last) { - if (strcmp(section, "P228") == 0) + if (std::strcmp(section, "P228") == 0) return CS_WEAPON_P228; - if (strcmp(section, "HEGRENADE") == 0) + if (std::strcmp(section, "HEGRENADE") == 0) return CS_WEAPON_HEGRENADE; - if (strcmp(section, "AK47") == 0) + if (std::strcmp(section, "AK47") == 0) return CS_WEAPON_AK47; - if (strcmp(section, "DEAGLE") == 0) + if (std::strcmp(section, "DEAGLE") == 0) return CS_WEAPON_DEAGLE; - if (strcmp(section, "MAC10") == 0) + if (std::strcmp(section, "MAC10") == 0) return CS_WEAPON_MAC10; - if (strcmp(section, "AUG") == 0) + if (std::strcmp(section, "AUG") == 0) return CS_WEAPON_AUG; - if (strcmp(section, "SG552") == 0) + if (std::strcmp(section, "SG552") == 0) return CS_WEAPON_SG552; - if (strcmp(section, "ELITE") == 0) + if (std::strcmp(section, "ELITE") == 0) return CS_WEAPON_ELITE; - if (strcmp(section, "FIVESEVEN") == 0) + if (std::strcmp(section, "FIVESEVEN") == 0) return CS_WEAPON_FIVESEVEN; - if (strcmp(section, "UMP45") == 0) + if (std::strcmp(section, "UMP45") == 0) return CS_WEAPON_UMP45; - if (strcmp(section, "SG550") == 0) + if (std::strcmp(section, "SG550") == 0) return CS_WEAPON_SG550; - if (strcmp(section, "USP") == 0) + if (std::strcmp(section, "USP") == 0) return CS_WEAPON_USP; - if (strcmp(section, "GLOCK18") == 0) + if (std::strcmp(section, "GLOCK18") == 0) return CS_WEAPON_GLOCK18; - if (strcmp(section, "AWP") == 0) + if (std::strcmp(section, "AWP") == 0) return CS_WEAPON_AWP; - if (strcmp(section, "MP5") == 0) + if (std::strcmp(section, "MP5") == 0) return CS_WEAPON_MP5NAVY; - if (strcmp(section, "M249") == 0) + if (std::strcmp(section, "M249") == 0) return CS_WEAPON_M249; - if (strcmp(section, "M3") == 0) + if (std::strcmp(section, "M3") == 0) return CS_WEAPON_M3; - if (strcmp(section, "M4A1") == 0) + if (std::strcmp(section, "M4A1") == 0) return CS_WEAPON_M4A1; - if (strcmp(section, "TMP") == 0) + if (std::strcmp(section, "TMP") == 0) return CS_WEAPON_TMP; - if (strcmp(section, "G3SG1") == 0) + if (std::strcmp(section, "G3SG1") == 0) return CS_WEAPON_G3SG1; - if (strcmp(section, "SCOUT") == 0) + if (std::strcmp(section, "SCOUT") == 0) return CS_WEAPON_SCOUT; - if (strcmp(section, "FLASHBANG") == 0) + if (std::strcmp(section, "FLASHBANG") == 0) return CS_WEAPON_FLASHBANG; - if (strcmp(section, "C4") == 0) + if (std::strcmp(section, "C4") == 0) return CS_WEAPON_C4; - if (strcmp(section, "SMOKEGRENADE") == 0) + if (std::strcmp(section, "SMOKEGRENADE") == 0) return CS_WEAPON_SMOKEGRENADE; - if (strcmp(section, "XM1014") == 0) + if (std::strcmp(section, "XM1014") == 0) return CS_WEAPON_XM1014; - if (strcmp(section, "KNIFE") == 0) + if (std::strcmp(section, "KNIFE") == 0) return CS_WEAPON_KNIFE; - if (strcmp(section, "P90") == 0) + if (std::strcmp(section, "P90") == 0) return CS_WEAPON_P90; // Counter-Strike 1.6 - if (strcmp(section, "FAMAS") == 0) + if (std::strcmp(section, "FAMAS") == 0) return CS_WEAPON_FAMAS; - if (strcmp(section, "GALIL") == 0) + if (std::strcmp(section, "GALIL") == 0) return CS_WEAPON_GALIL; // Unconfirmed - if (strcmp(section, "SHIELD") == 0) + if (std::strcmp(section, "SHIELD") == 0) return CS_WEAPON_SHIELD; // When nothing found; we assume its just a new ID tag for some unit or structure @@ -430,7 +430,7 @@ int INI_WordValueINT(char result[80]) { DebugOut(aa); */ - return atoi(number); + return std::atoi(number); } // nothing here, so we return NULL at the end } @@ -484,7 +484,7 @@ float INI_WordValueFLOAT(char result[80]) { if (c > 9) break; } - return static_cast(atof(number)); + return static_cast(std::atof(number)); } // nothing here, so we return NULL at the end } @@ -551,7 +551,7 @@ void INI_PARSE_CHATFILE() { // Set Directory name + file - strcpy(dirname, "data/cstrike/chat.ini"); + std::strcpy(dirname, "data/cstrike/chat.ini"); // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -583,7 +583,7 @@ void INI_PARSE_CHATFILE() { // Every line is checked for a new section. INI_Section(linefeed, linesection); - if (linesection[0] != '\0' && strlen(linesection) > 1) { + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { section = INI_SectionType(linesection, section); if (section == INI_BLOCK) { @@ -625,7 +625,7 @@ void INI_PARSE_CHATFILE() { // write the word in the block char chWord[25]; - memset(chWord, 0, sizeof(chWord)); + std::memset(chWord, 0, sizeof(chWord)); INI_WordValueCHAR(linefeed, chWord); // lower case //chWord = _strlwr( _strdup( chWord ) ); @@ -645,7 +645,7 @@ void INI_PARSE_CHATFILE() { pString++; } #endif - strcpy(ChatEngine.ReplyBlock[iBlockId].word[iBlockWord], + std::strcpy(ChatEngine.ReplyBlock[iBlockId].word[iBlockWord], chWord); } @@ -656,9 +656,9 @@ void INI_PARSE_CHATFILE() { // write the word in the block char chSentence[80]; - memset(chSentence, 0, sizeof(chSentence)); + std::memset(chSentence, 0, sizeof(chSentence)); INI_WordValueCHAR(linefeed, chSentence); - strcpy(ChatEngine.ReplyBlock[iBlockId]. + std::strcpy(ChatEngine.ReplyBlock[iBlockId]. sentence[iBlockSentence], chSentence); // here we say it is used @@ -682,10 +682,10 @@ void INI_PARSE_IAD() { int section = INI_NONE; // Set Directory name - strcpy(dirname, "data/cstrike/ini/"); + std::strcpy(dirname, "data/cstrike/ini/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".ini"); // nodes file + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".ini"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -714,7 +714,7 @@ void INI_PARSE_IAD() { // Every line is checked for a new section. INI_Section(linefeed, linesection); - if (linesection[0] != '\0' && strlen(linesection) > 1) { + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { section = INI_SectionType(linesection, section); continue; // next line } @@ -768,11 +768,11 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Set Directory name if (mod_id == CSTRIKE_DLL) - strcpy(dirname, "data/cstrike/bots/"); + std::strcpy(dirname, "data/cstrike/bots/"); //strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, cBotName); - strcat(dirname, ".ini"); + std::strcat(dirname, cBotName); + std::strcat(dirname, ".ini"); // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -797,7 +797,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Every line is checked for a new section. INI_Section(linefeed, linesection); - if (linesection[0] != '\0' && strlen(linesection) > 1) { + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { section = INI_SectionType(linesection, section); continue; // next line } @@ -934,7 +934,7 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); // Reaction Time delay added for realistic gameplay [APG]RoboCop[CL] fMinReact = - RANDOM_FLOAT((pBot->bot_skill / 20) + 0.3f, + RANDOM_FLOAT(pBot->bot_skill / 20 + 0.3f, (pBot->bot_skill / 5) + 0.3f); const float fMaxReact = fMinReact + RANDOM_FLOAT(0.2f, 0.4f); @@ -977,10 +977,10 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Set Directory name if (mod_id == CSTRIKE_DLL) - strcpy(dirname, "data/cstrike/bots/"); + std::strcpy(dirname, "data/cstrike/bots/"); - strcat(dirname, cBotName); - strcat(dirname, ".ini"); + std::strcat(dirname, cBotName); + std::strcat(dirname, ".ini"); // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1072,10 +1072,10 @@ void INI_PARSE_BUYTABLE() { // Set Directory name if (mod_id == CSTRIKE_DLL) - strcpy(dirname, "data/cstrike/"); + std::strcpy(dirname, "data/cstrike/"); //strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, "buytable.ini"); + std::strcat(dirname, "buytable.ini"); // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1106,7 +1106,7 @@ void INI_PARSE_BUYTABLE() { INI_Section(linefeed, linesection); // Found a new section - if (linesection[0] != '\0' && strlen(linesection) > 1) { + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { section = INI_SectionType_BUYTABLE(linesection, section); // Check if its the same as the previous section if (section != prev_section) { diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 57a09bd..c4e209f 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -121,15 +121,13 @@ void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { void cNodeMachine::ClearVisibilityTable() const { if (cVisTable) { - memset(cVisTable, 0, g_iMaxVisibilityByte); + std::memset(cVisTable, 0, g_iMaxVisibilityByte); } } void cNodeMachine::FreeVisibilityTable() const { - if (cVisTable) { - free(cVisTable); - } + free(cVisTable); } //--------------------------------------------------------- @@ -178,7 +176,7 @@ void cNodeMachine::init() { //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first cVisTable = static_cast(malloc(iSize)); - memset(cVisTable, 0, iSize); + std::memset(cVisTable, 0, iSize); ClearVisibilityTable(); // END: @@ -205,7 +203,7 @@ void cNodeMachine::initGoal(int g) { Goals[g].index = g; Goals[g].iChecked = 0; Goals[g].iBadScore = 0; // no bad score at init - memset(Goals[g].name, 0, sizeof(Goals[g].name)); + std::memset(Goals[g].name, 0, sizeof(Goals[g].name)); } int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const @@ -226,8 +224,8 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const if (Troubles[index].iFrom == iFrom && Troubles[index].iTo == iTo) { char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); rblog(msg); // found troubled connection, return its index return index; @@ -279,7 +277,7 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) { const tTrouble &trouble = Troubles[index]; char msg[255]; - sprintf(msg, "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); + std::sprintf(msg, "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); if (trouble.iTries > 2) { @@ -322,27 +320,27 @@ void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) { if (index < 0 || index >= MAX_TROUBLE) return; char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Increasing trouble for connection [%d]\n", index); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Increasing trouble for connection [%d]\n", index); rblog(msg); Troubles[index].iTries++; const tTrouble &trouble = Troubles[index]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); } bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) { char msg[255]; - sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); + std::sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); rblog(msg); const int index = GetTroubleIndexForConnection(iFrom, iTo); - memset(msg, 0, sizeof(msg)); - sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d has index %d\n", iFrom, iTo, index); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d has index %d\n", iFrom, iTo, index); rblog(msg); if (index < 0) { @@ -640,11 +638,11 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { } char msg[255]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); tNode *node = getNode(iFrom); if (!node) { - sprintf(msg, "(trouble) cNodeMachine::removeConnection | From %d, to %d has no node! (error)\n", iFrom, iTo); + std::sprintf(msg, "(trouble) cNodeMachine::removeConnection | From %d, to %d has no node! (error)\n", iFrom, iTo); rblog(msg); return false; } @@ -654,7 +652,7 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { for (int i = 0; i < MAX_NEIGHBOURS; i++) { const int neighbourNode = node->iNeighbour[i]; - sprintf(msg, + std::sprintf(msg, "(trouble) removeConnection(from->%d, to->%d), evaluating neighbour [%d] = node %d\n", iFrom, iTo, @@ -1203,7 +1201,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { && (bNeighbourWater == false && bIsInWater == false) && Nodes[currentIndex].origin.z >= Nodes[nodeIndex].origin.z) { char msg[80]; - sprintf(msg, "J.Z = %f, INDEX.Z = %f\n", Nodes[nodeIndex].origin.z, + std::sprintf(msg, "J.Z = %f, INDEX.Z = %f\n", Nodes[nodeIndex].origin.z, Nodes[currentIndex].origin.z); // UTIL_ClientPrintAll( HUD_PRINTNOTIFY, msg); bCanConnect = false; // cannot connect @@ -1302,29 +1300,29 @@ void cNodeMachine::connections(edict_t *pEntity) { int closeNode; char msg[75]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); if (draw_nodepath > -1 && draw_nodepath < 32) { cBot botPointer = bots[draw_nodepath]; if (botPointer.bIsUsed) { closeNode = botPointer.determineCurrentNodeWithTwoAttempts(); if (closeNode > -1) { const Vector &vector = Nodes[closeNode].origin; - sprintf(msg, "Bot [%s|%d] is at node %d (%f,%f,%f)\n", botPointer.name, draw_nodepath, closeNode, vector.x, vector.y, vector.z); + std::sprintf(msg, "Bot [%s|%d] is at node %d (%f,%f,%f)\n", botPointer.name, draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { - sprintf(msg, "Bot [%s|%d] is at node %d\n", botPointer.name, draw_nodepath, closeNode); + std::sprintf(msg, "Bot [%s|%d] is at node %d\n", botPointer.name, draw_nodepath, closeNode); } } else { closeNode = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); if (closeNode > -1) { const Vector &vector = Nodes[closeNode].origin; - sprintf(msg, "No bot used for slot [%d], YOU are at node %d (%f,%f,%f)\n", draw_nodepath, closeNode, vector.x, vector.y, vector.z); + std::sprintf(msg, "No bot used for slot [%d], YOU are at node %d (%f,%f,%f)\n", draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { - sprintf(msg, "No bot used for slot [%d], YOU are at node %d\n", draw_nodepath, closeNode); + std::sprintf(msg, "No bot used for slot [%d], YOU are at node %d\n", draw_nodepath, closeNode); } } } else { closeNode = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); - sprintf(msg, "YOU are at node %d\n", closeNode); + std::sprintf(msg, "YOU are at node %d\n", closeNode); } CenterMessage(msg); @@ -1375,26 +1373,29 @@ void cNodeMachine::connections(edict_t *pEntity) { } // Draw -void cNodeMachine::draw(edict_t *pEntity) { - //DebugOut("waypoint: waypoint_draw()\n"); +void cNodeMachine::draw(edict_t* pEntity) { + // DebugOut("waypoint: waypoint_draw()\n"); int max_drawn = 0; + // Declare 'start' vector outside the loop + Vector start; + for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin != Vector(9999, 9999, 9999)) { - const Vector start = Nodes[i].origin - Vector(0, 0, 36); + start = Nodes[i].origin - Vector(0, 0, 36); Vector end = Nodes[i].origin; - const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); + const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); - const int angle_to_waypoint = - FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); + const int angle_to_waypoint = + FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); if (good && angle_to_waypoint < 65) { int g, b, l; int r = g = b = l = 250; l = 250; - //l = 250; // Normally light is 250 + // l = 250; // Normally light is 250 if (Nodes[i].iNodeBits & BIT_LADDER) b = g = 0; @@ -1402,15 +1403,15 @@ void cNodeMachine::draw(edict_t *pEntity) { if (Nodes[i].iNodeBits & BIT_WATER) r = g = 0; - if (Nodes[i].iNodeBits & BIT_DUCK) + if (Nodes[i].iNodeBits & BIT_DUCK) r = b = 50; - // Jump and DuckJump was missing for those nodes? [APG]RoboCop[CL] + // Jump and DuckJump were missing for those nodes? [APG]RoboCop[CL] if (Nodes[i].iNodeBits & BIT_JUMP) r = b = 100; if (Nodes[i].iNodeBits & BIT_DUCKJUMP) r = b = 150; - + if (Nodes[i].iNeighbour[0] < 0) r = 0; @@ -1419,8 +1420,9 @@ void cNodeMachine::draw(edict_t *pEntity) { max_drawn++; } } - } // for + } // for } + const int iNodeClose = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); char msg[50]; @@ -1429,26 +1431,26 @@ void cNodeMachine::draw(edict_t *pEntity) { Flags[0] = 0; if (Nodes[iNodeClose].iNodeBits & BIT_LADDER) - strcat(Flags, "L"); + std::strcat(Flags, "L"); if (Nodes[iNodeClose].iNodeBits & BIT_WATER) - strcat(Flags, "W"); + std::strcat(Flags, "W"); if (Nodes[iNodeClose].iNodeBits & BIT_JUMP) - strcat(Flags, "J"); + std::strcat(Flags, "J"); if (Nodes[iNodeClose].iNodeBits & BIT_DUCK) - strcat(Flags, "D"); + std::strcat(Flags, "D"); // Experimental DuckJump added for this new node [APG]RoboCop[CL] if (Nodes[iNodeClose].iNodeBits & BIT_DUCKJUMP) - strcat(Flags, "h"); + std::strcat(Flags, "h"); - sprintf(msg, "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", - iNodeClose, (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.x, - (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.y, - (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.z, Flags, - pEntity->v.origin.x, pEntity->v.origin.y, pEntity->v.origin.z); + std::sprintf(msg, "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", + iNodeClose, (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.x, + (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.y, + (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.z, Flags, + pEntity->v.origin.x, pEntity->v.origin.y, pEntity->v.origin.z); CenterMessage(msg); } @@ -1458,9 +1460,9 @@ void cNodeMachine::experience_save() { char filename[256]; // Set Directory name - strcpy(dirname, "data/cstrike/exp/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".rbx"); // nodes file + std::strcpy(dirname, "data/cstrike/exp/"); + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".rbx"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1529,9 +1531,9 @@ void cNodeMachine::experience_load() { char filename[256]; // Set Directory name - strcpy(dirname, "data/cstrike/exp/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".rbx"); // nodes file + std::strcpy(dirname, "data/cstrike/exp/"); + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".rbx"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1620,9 +1622,9 @@ void cNodeMachine::save() const char filename[256]; // Set Directory name - strcpy(dirname, "data/cstrike/maps/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".rbn"); // nodes file + std::strcpy(dirname, "data/cstrike/maps/"); + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".rbn"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1653,9 +1655,9 @@ void cNodeMachine::save_important() const char filename[256]; // Set Directory name - strcpy(dirname, "data/cstrike/ini/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".ini"); // nodes file + std::strcpy(dirname, "data/cstrike/ini/"); + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".ini"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1691,10 +1693,10 @@ void cNodeMachine::load() { char filename[256]; // Set Directory name - strcpy(dirname, "data/cstrike/maps/"); + std::strcpy(dirname, "data/cstrike/maps/"); - strcat(dirname, STRING(gpGlobals->mapname)); - strcat(dirname, ".rbn"); // nodes file + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".rbn"); // nodes file // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); @@ -1739,7 +1741,7 @@ void cNodeMachine::load() { rblog("!!! Nodes table is full\n"); char msg[80]; - sprintf(msg, "After NodeMachine::load iMaxUsedNodes=%d\n", + std::sprintf(msg, "After NodeMachine::load iMaxUsedNodes=%d\n", iMaxUsedNodes); rblog(msg); SERVER_PRINT("Going to load IAD file : "); @@ -1757,7 +1759,7 @@ void cNodeMachine::ClearImportantGoals() { Goals[iGn].iType = -1; Goals[iGn].iNode = -1; Goals[iGn].pGoalEdict = nullptr; - memset(Goals[iGn].name, 0, sizeof(Goals[iGn].name)); + std::memset(Goals[iGn].name, 0, sizeof(Goals[iGn].name)); } } } @@ -1766,6 +1768,7 @@ void cNodeMachine::ClearImportantGoals() { void cNodeMachine::path_draw(edict_t *pEntity) { //DebugOut("waypoint: waypoint_draw()\n"); int max_drawn = 0; + Vector start; for (int i = 0; i < MAX_NODES; i++) { // TODO: iPath appears to be out of bounds [APG]RoboCop[CL] @@ -1773,7 +1776,7 @@ void cNodeMachine::path_draw(edict_t *pEntity) { const int iNextNode = iPath[draw_nodepath][(i + 1)]; if (iNode > -1 && iNextNode > -1) { - const Vector start = Nodes[iNode].origin; + start = Nodes[iNode].origin; Vector end = Nodes[iNextNode].origin; const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); @@ -1938,8 +1941,8 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { //strcpy(goal->name, getGoalTypeAsText(*goal)); //That appears to trigger crash [APG]RoboCop[CL] char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Adding goal at index %d of type %s, with nearby node %d\n", index, goal->name, nNode); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Adding goal at index %d of type %s, with nearby node %d\n", index, goal->name, nNode); rblog(msg); } @@ -2157,7 +2160,7 @@ tGoal *cNodeMachine::getRandomGoalByType(int goalType) { const int randomGoalIndex = RANDOM_LONG(0, (possibleCandidateIndex - 1)); char msg[255]; - sprintf(msg, "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", + std::sprintf(msg, "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", possibleCandidateIndex, goalType, randomGoalIndex); rblog(msg); @@ -2230,8 +2233,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn if (pBot) { char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "createPath(from->%d, to->%d, botIndex->%d)", nodeStartIndex, nodeTargetIndex, botIndex); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "createPath(from->%d, to->%d, botIndex->%d)", nodeStartIndex, nodeTargetIndex, botIndex); pBot->rprint("cNodeMachine::createPath", msg); } @@ -2393,8 +2396,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // print out full path so we know what the order is if (pBot != nullptr) { char pathMsg[255]; - memset(pathMsg, 0, sizeof(pathMsg)); - sprintf(pathMsg, "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); + std::memset(pathMsg, 0, sizeof(pathMsg)); + std::sprintf(pathMsg, "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); pBot->rprint("cNodeMachine::createPath", pathMsg); } @@ -2558,7 +2561,7 @@ void cNodeMachine::vis_calculate(int iFrom) { for (int i = 0; i < MAX_NODES; i++) if ((i != iFrom) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { - const float fClosest = 1024; + const float fClosest = 1024.0f; const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { TraceResult tr; @@ -2633,7 +2636,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, } } char msg[255]; - sprintf(msg, "Found best node to camp at %d\n", iBestNode); + std::sprintf(msg, "Found best node to camp at %d\n", iBestNode); rblog(msg); return iBestNode; } @@ -2693,7 +2696,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { float fDistance = 90; bool bTrigger = false; - if (strcmp(STRING(pBot->pButtonEdict->v.classname), "trigger_multiple") == 0) { + if (std::strcmp(STRING(pBot->pButtonEdict->v.classname), "trigger_multiple") == 0) { fDistance = 32; bTrigger = true; } @@ -2802,7 +2805,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { tGoal *goalData = pBot->getGoalData(); if (goalData) { char msg[255]; - sprintf(msg, "Heading for goal node of type [%s]", goalData->name); + std::sprintf(msg, "Heading for goal node of type [%s]", goalData->name); pBot->rprint_trace("cNodeMachine::path_walk (bNear)", msg); if (goalData->iType == GOAL_HOSTAGE) { pBot->rprint_normal("cNodeMachine::path_walk (bNear)", "next node is destination and GOAL_HOSTAGE, so need to get really close"); @@ -2818,7 +2821,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } char msg[255]; - sprintf(msg, "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", + std::sprintf(msg, "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", pBot->getCurrentPathNodeToHeadFor(), requiredDistance, pBot->getDistanceToNextNode(), pBot->getMoveToNodeTimeRemaining()); pBot->rprint_trace("cNodeMachine::path_walk (bNear)", msg); @@ -2904,7 +2907,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { !isEntityWorldspawn(pEntityHit)) // and it is not worldspawn (ie, the map itself) { char msg[255]; - sprintf(msg, "Entity [%s] between me and next node.", STRING(pEntityHit->v.classname)); + std::sprintf(msg, "Entity [%s] between me and next node.", STRING(pEntityHit->v.classname)); pBot->rprint_trace("cNodeMachine::path_walk", msg); // hit by a door? @@ -2921,7 +2924,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { return; } - if (strcmp(STRING(pEntityHit->v.classname), "player") == 0) { + if (std::strcmp(STRING(pEntityHit->v.classname), "player") == 0) { pBot->rprint_trace("cNodeMachine::path_walk", "Another player between me and next node."); if (pBot->hasTimeToMoveToNode()) { pBot->strafeRight(0.2f); @@ -2954,8 +2957,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // no need for 'is walking' because walking time influence `f_move_speed` hence it is already taken care of char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, expectedMoveDistance, notStuckForAWhile); pBot->rprint_trace("cNodeMachine::path_walk", msg); @@ -3030,9 +3033,9 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "No need to duck or to jump"); char msg[255]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); const float timeRemaining = pBot->getMoveToNodeTimeRemaining(); - sprintf(msg, "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); + std::sprintf(msg, "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); const cBot *pBotStuck = getCloseFellowBot(pBot); @@ -3043,19 +3046,19 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con edict_t *hostageNearbyInFOV = nullptr; if (entityNearbyInFOV) { - if (strcmp(STRING(entityNearbyInFOV->v.classname), "player") == 0) { + if (std::strcmp(STRING(entityNearbyInFOV->v.classname), "player") == 0) { playerNearbyInFOV = entityNearbyInFOV; pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "A player is in front of me"); } - if (strcmp(STRING(entityNearbyInFOV->v.classname), "hostage_entity") == 0) { + if (std::strcmp(STRING(entityNearbyInFOV->v.classname), "hostage_entity") == 0) { hostageNearbyInFOV = entityNearbyInFOV; pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "A hostage is in front of me"); } } - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", playerNearbyInFOV != nullptr, hostageNearbyInFOV != nullptr, pBotStuck != nullptr, timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); @@ -3173,7 +3176,7 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { if (!isHeadingForGoalNode) { char msg[255]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); const int currentPathNode = pBot->getCurrentPathNodeToHeadFor(); @@ -3181,12 +3184,12 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { const int troubleIndex = GetTroubleIndexForConnection(pBot->getPreviousPathNodeToHeadFor(), currentNodeToHeadFor); if (troubleIndex > -1) { const tTrouble &trouble = Troubles[troubleIndex]; - sprintf(msg, "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); + std::sprintf(msg, "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); } else { - sprintf(msg, "Heading to next node: %d - with no trouble", currentPathNode); + std::sprintf(msg, "Heading to next node: %d - with no trouble", currentPathNode); } } else { - sprintf(msg, "Heading to next node: %d", currentPathNode); + std::sprintf(msg, "Heading to next node: %d", currentPathNode); } pBot->rprint("cNodeMachine::path_walk()", msg); } @@ -3275,19 +3278,19 @@ bool cNodeMachine::isDoorThatOpensWhenPressingUseButton(const edict_t *pEntityHi bool cNodeMachine::isEntityDoor(const edict_t *pEntityHit) { - return strcmp(STRING(pEntityHit->v.classname), "func_door") == 0 || // normal door (can be used as an elevator) - strcmp(STRING(pEntityHit->v.classname), "func_wall") == 0 || // I am not 100% sure about func_wall, but include it anyway - strcmp(STRING(pEntityHit->v.classname), "func_door_rotating") == 0; // rotating door + return std::strcmp(STRING(pEntityHit->v.classname), "func_door") == 0 || // normal door (can be used as an elevator) + std::strcmp(STRING(pEntityHit->v.classname), "func_wall") == 0 || // I am not 100% sure about func_wall, but include it anyway + std::strcmp(STRING(pEntityHit->v.classname), "func_door_rotating") == 0; // rotating door } bool cNodeMachine::isEntityHostage(const edict_t *pEntityHit) { - return strcmp(STRING(pEntityHit->v.classname), "hostage_entity") == 0; // hostage + return std::strcmp(STRING(pEntityHit->v.classname), "hostage_entity") == 0; // hostage } bool cNodeMachine::isEntityWorldspawn(const edict_t *pEntityHit) { - return strcmp(STRING(pEntityHit->v.classname), "worldspawn") == 0; // the world + return std::strcmp(STRING(pEntityHit->v.classname), "worldspawn") == 0; // the world } // Think about path creation here @@ -3440,7 +3443,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { score += weight; // Take into consideration how many times this goal has been selected - score = (score + (1.0f - Goals[goalIndex].iChecked / maxCheckedScore)) / 2.0f; + score = (score + (1.0f - static_cast(Goals[goalIndex].iChecked) / static_cast(maxCheckedScore))) / 2.0f; // Danger (is important) score = (score + InfoNodes[Goals[goalIndex].iNode].fDanger[UTIL_GetTeam(pBot->pEdict)]) / 1.5f; @@ -3543,8 +3546,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (Game.isPlantedC4Discovered()) { pBot->rprint_trace("path_think/determine goal", "I know where the C4 is planted, evaluating if this is the closest bombspot."); char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "C4 is located at %f, %f, %f", Game.vPlantedC4.x, Game.vPlantedC4.y, Game.vPlantedC4.z); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "C4 is located at %f, %f, %f", Game.vPlantedC4.x, Game.vPlantedC4.y, Game.vPlantedC4.z); pBot->rprint_trace("path_think/determine goal", msg); // find a node close to the C4 @@ -3564,8 +3567,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { const float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; goalscore = 1.5f + score; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", distanceToC4FromCloseNode, distanceToC4FromThisGoalNode, goalscore); @@ -3655,8 +3658,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // even though its float comparison, it can h appen since we hard-set it to 2.0 at some places, making // some scores the same char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Evaluating goal %s gives a score of %f, highest score so far is %f", + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Evaluating goal %s gives a score of %f, highest score so far is %f", Goals[goalIndex].name, score, highestScore); @@ -3726,10 +3729,10 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { tGoal *goalData = pBot->getGoalData(); char msg[255]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); if (goalData != nullptr) { - sprintf(msg, "I have chosen a goal: Node [%d], Goal type [%s], checked [%d], score [%f], distance [%f]", + std::sprintf(msg, "I have chosen a goal: Node [%d], Goal type [%s], checked [%d], score [%f], distance [%f]", iFinalGoalNode, goalData->name, goalData->iChecked, @@ -3737,7 +3740,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->getDistanceTo(iFinalGoalNode) ); } else { - sprintf(msg, "I have chosen a goal: Node [%d], - NO GOAL DATA - score [%f], distance [%f]", + std::sprintf(msg, "I have chosen a goal: Node [%d], - NO GOAL DATA - score [%f], distance [%f]", iFinalGoalNode, highestScore, pBot->getDistanceTo(iFinalGoalNode) @@ -3790,50 +3793,50 @@ tNode *cNodeMachine::getNode(int index) { char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) { char typeAsText[32]; - memset(typeAsText, 0, sizeof(typeAsText)); + std::memset(typeAsText, 0, sizeof(typeAsText)); switch (goal.iType) { case GOAL_SPAWNT: - sprintf(typeAsText, "GOAL_SPAWNT"); + std::sprintf(typeAsText, "GOAL_SPAWNT"); break; case GOAL_SPAWNCT: - sprintf(typeAsText, "GOAL_SPAWNCT"); + std::sprintf(typeAsText, "GOAL_SPAWNCT"); break; case GOAL_BOMBSPOT: - sprintf(typeAsText, "GOAL_BOMBSPOT"); + std::sprintf(typeAsText, "GOAL_BOMBSPOT"); break; case GOAL_BOMB: - sprintf(typeAsText, "GOAL_BOMB"); + std::sprintf(typeAsText, "GOAL_BOMB"); break; case GOAL_HOSTAGE: - sprintf(typeAsText, "GOAL_HOSTAGE"); + std::sprintf(typeAsText, "GOAL_HOSTAGE"); break; case GOAL_RESCUEZONE: - sprintf(typeAsText, "GOAL_RESCUEZONE"); + std::sprintf(typeAsText, "GOAL_RESCUEZONE"); break; case GOAL_CONTACT: - sprintf(typeAsText, "GOAL_CONTACT"); + std::sprintf(typeAsText, "GOAL_CONTACT"); break; case GOAL_IMPORTANT: - sprintf(typeAsText, "GOAL_IMPORTANT"); + std::sprintf(typeAsText, "GOAL_IMPORTANT"); break; case GOAL_VIP: - sprintf(typeAsText, "GOAL_VIP"); + std::sprintf(typeAsText, "GOAL_VIP"); break; case GOAL_VIPSAFETY: - sprintf(typeAsText, "GOAL_VIPSAFETY"); + std::sprintf(typeAsText, "GOAL_VIPSAFETY"); break; case GOAL_ESCAPEZONE: - sprintf(typeAsText, "GOAL_ESCAPEZONE"); + std::sprintf(typeAsText, "GOAL_ESCAPEZONE"); break; case GOAL_WEAPON: - sprintf(typeAsText, "GOAL_WEAPON"); + std::sprintf(typeAsText, "GOAL_WEAPON"); break; case GOAL_NONE: - sprintf(typeAsText, "GOAL_NONE"); + std::sprintf(typeAsText, "GOAL_NONE"); break; default: - sprintf(typeAsText, "GOAL UNKNOWN"); + std::sprintf(typeAsText, "GOAL UNKNOWN"); } return typeAsText; //TODO: local variable invalid [APG]RoboCop[CL] } @@ -3990,53 +3993,53 @@ void cNodeMachine::dump_goals() const for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { char buffer[100]; const Vector v = Nodes[Goals[i].iNode].origin; - sprintf(buffer, + std::sprintf(buffer, "Goal#%d is at node %d (%.0f, %.0f, %.0f), iChecked= %d, ", i + 1, Goals[i].iNode, v.x, v.y, v.z, Goals[i].iChecked); switch (Goals[i].iType) { case GOAL_SPAWNCT: - strcat(buffer, "GOAL_SPAWNCT"); + std::strcat(buffer, "GOAL_SPAWNCT"); break; case GOAL_SPAWNT: - strcat(buffer, "GOAL_SPAWNT"); + std::strcat(buffer, "GOAL_SPAWNT"); break; case GOAL_BOMBSPOT: - strcat(buffer, "GOAL_BOMBSPOT"); + std::strcat(buffer, "GOAL_BOMBSPOT"); break; case GOAL_BOMB: - strcat(buffer, "GOAL_BOMB"); + std::strcat(buffer, "GOAL_BOMB"); break; case GOAL_HOSTAGE: - strcat(buffer, "GOAL_HOSTAGE"); + std::strcat(buffer, "GOAL_HOSTAGE"); break; case GOAL_RESCUEZONE: - strcat(buffer, "GOAL_RESCUEZONE"); + std::strcat(buffer, "GOAL_RESCUEZONE"); break; case GOAL_CONTACT: - strcat(buffer, "GOAL_CONTACT"); + std::strcat(buffer, "GOAL_CONTACT"); break; case GOAL_IMPORTANT: - strcat(buffer, "GOAL_IMPORTANT"); + std::strcat(buffer, "GOAL_IMPORTANT"); break; case GOAL_VIP: - strcat(buffer, "GOAL_VIP"); + std::strcat(buffer, "GOAL_VIP"); break; case GOAL_VIPSAFETY: - strcat(buffer, "GOAL_VIPSAFETY"); + std::strcat(buffer, "GOAL_VIPSAFETY"); break; case GOAL_ESCAPEZONE: - strcat(buffer, "GOAL_ESCAPEZONE"); + std::strcat(buffer, "GOAL_ESCAPEZONE"); break; case GOAL_WEAPON: - strcat(buffer, "GOAL_WEAPON"); + std::strcat(buffer, "GOAL_WEAPON"); break; case GOAL_NONE: - strcat(buffer, "GOAL_NONE"); + std::strcat(buffer, "GOAL_NONE"); break; default: - strcat(buffer, "unknown type"); + std::strcat(buffer, "unknown type"); } - strcat(buffer, "\n"); + std::strcat(buffer, "\n"); rblog(buffer); } @@ -4054,9 +4057,9 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { rblog(" Path is: "); for (i = 0; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { if (i == CurrentPath) - sprintf(buffer, "<%d> ", iPath[iBot][i]); + std::sprintf(buffer, "<%d> ", iPath[iBot][i]); else - sprintf(buffer, "%d ", iPath[iBot][i]); + std::sprintf(buffer, "%d ", iPath[iBot][i]); rblog(buffer); } rblog("\n"); @@ -4067,7 +4070,7 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { if (Nodes[CurrentNode].iNeighbour[i] >= 0) { const int j = Nodes[CurrentNode].iNeighbour[i]; const Vector v = Nodes[j].origin; - sprintf(buffer, " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, + std::sprintf(buffer, " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, v.z); rblog(buffer); } @@ -4100,7 +4103,7 @@ static void InitDebugBitmap() { exit(1); } - memset(bmp_buffer, 14, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // Set all to all white (and allow for darker palette) + std::memset(bmp_buffer, 14, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // Set all to all white (and allow for darker palette) } // Draw a small cross @@ -4552,7 +4555,7 @@ void cNodeMachine::Draw() { PlotNodes(0, 5); // 0 = black, 5 = blue PlotPaths(11, 7); // 11 = Red 7 = light blue ? PlotGoals(9); // 9 = green - sprintf(Filename, "%s%4.4d.bmp", STRING(gpGlobals->mapname), Count++); + std::sprintf(Filename, "%s%4.4d.bmp", STRING(gpGlobals->mapname), Count++); WriteDebugBitmap(Filename); } @@ -4583,8 +4586,8 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) if (doorButtonToLookFor) { char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "There is a target button , named %s, to open this door [%s] - going to search for it.", doorButtonToLookFor, STRING(pEntityHit->v.classname)); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "There is a target button , named %s, to open this door [%s] - going to search for it.", doorButtonToLookFor, STRING(pEntityHit->v.classname)); pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", msg); // find this entity @@ -4598,7 +4601,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) if (pent == pEntityHit) continue; // found button entity matching target - if (strcmp(STRING(pent->v.target), doorButtonToLookFor) == 0) { + if (std::strcmp(STRING(pent->v.target), doorButtonToLookFor) == 0) { Vector buttonVector = VecBModelOrigin(pent); UTIL_TraceLine(pBot->pEdict->v.origin, buttonVector, @@ -4633,7 +4636,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) continue; // found button entity - if (strcmp(STRING(pent->v.target), doorButtonToLookFor) == 0) { + if (std::strcmp(STRING(pent->v.target), doorButtonToLookFor) == 0) { // get vectr Vector vPentVector = VecBModelOrigin(pent); @@ -4661,7 +4664,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // as most doors have 2 buttons to access it (ie prodigy) // hits by worldspawn here - if (strcmp(STRING(trb.pHit->v.classname), "worldspawn") == 0) { + if (std::strcmp(STRING(trb.pHit->v.classname), "worldspawn") == 0) { // DE_PRODIGY FIX: // Somehow the button is not detectable. Find a node, that is close to it. @@ -4692,7 +4695,7 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // We have found a button to go to if (pButtonEdict) { - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); // Get its vector const Vector vButtonVector = VecBModelOrigin(pButtonEdict); @@ -4701,13 +4704,13 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // When node found, create path to it if (pBot->createPath(iButtonNode, PATH_NONE)) { - sprintf(msg, "Found a button at node %d and created a path to it.", iButtonNode); + std::sprintf(msg, "Found a button at node %d and created a path to it.", iButtonNode); pBot->pButtonEdict = pButtonEdict; } else { if (iButtonNode > -1) { - sprintf(msg, "Found a button at node %d but failed to create a path to it.", iButtonNode); + std::sprintf(msg, "Found a button at node %d but failed to create a path to it.", iButtonNode); } else { - sprintf(msg, "Found a button, but there is no nearby node :/"); + std::sprintf(msg, "Found a button, but there is no nearby node :/"); } } pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", msg); diff --git a/bot.cpp b/bot.cpp index 760e40a..29e6015 100644 --- a/bot.cpp +++ b/bot.cpp @@ -191,7 +191,7 @@ void cBot::SpawnInit() { pEnemyEdict = nullptr; // chat - memset(chChatSentence, 0, sizeof(chChatSentence)); + std::memset(chChatSentence, 0, sizeof(chChatSentence)); // ------------------------ @@ -290,8 +290,8 @@ void cBot::SpawnInit() { arg1[0] = 0; arg2[0] = 0; arg3[0] = 0; - memset(&(current_weapon), 0, sizeof(current_weapon)); - memset(&(m_rgAmmo), 0, sizeof(m_rgAmmo)); + std::memset(&(current_weapon), 0, sizeof(current_weapon)); + std::memset(&(m_rgAmmo), 0, sizeof(m_rgAmmo)); rprint_trace("SpawnInit()", "END"); } @@ -388,7 +388,7 @@ void cBot::NewRound() { // ------------------------ // chat - memset(chChatSentence, 0, sizeof(chChatSentence)); + std::memset(chChatSentence, 0, sizeof(chChatSentence)); vip = UTIL_IsVip(pEdict); @@ -467,8 +467,8 @@ void cBot::NewRound() { if (the_c > -1 && iMax > -1) { char chSentence[80]; - memset(chSentence, 0, sizeof(chSentence)); - sprintf(chSentence, "%s ", + std::memset(chSentence, 0, sizeof(chSentence)); + std::sprintf(chSentence, "%s ", ChatEngine.ReplyBlock[98].sentence[the_c]); PrepareChat(chSentence); } @@ -488,7 +488,7 @@ void cBot::PrepareChat(char sentence[128]) { if (Game.iProducedSentences <= Game.iMaxSentences) { // makes bot chat away fChatTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); - strcpy(chChatSentence, sentence); // copy this + std::strcpy(chChatSentence, sentence); // copy this Game.iProducedSentences++; } } @@ -500,7 +500,7 @@ float cBot::ReactionTime(int iSkill) { const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); if (Game.messageVerbosity > 1) { char msg[255]; - sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); + std::sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); rprint_trace("ReactionTime()", msg); } return time; @@ -883,7 +883,7 @@ void cBot::PickBestWeapon() { // Distance to enemy const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - const float knifeDistance = 300; + const float knifeDistance = 300.0f; // ---------------------------- // In this function all we do is decide what weapon to pick @@ -913,10 +913,10 @@ void cBot::PickBestWeapon() { func_distance(pEdict->v.origin, lastSeenEnemyVector) > 200 && // but not to close RANDOM_LONG(0, 100) < 10 && // only randomly we pick a grenade in the heat of the battle current_weapon.iId != CS_WEAPON_HEGRENADE && current_weapon.iId != CS_WEAPON_FLASHBANG && - f_gren_time + 15 < gpGlobals->time) // and dont hold it yet + f_gren_time + 15.0f < gpGlobals->time) // and dont hold it yet { UTIL_SelectItem(pEdict, "weapon_hegrenade"); // select grenade - f_wait_time = gpGlobals->time + 1; // wait 1 second (stand still 1 sec) + f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) f_gren_time = gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon @@ -931,7 +931,7 @@ void cBot::PickBestWeapon() { f_gren_time + 15 < gpGlobals->time) // and dont hold it yet { UTIL_SelectItem(pEdict, "weapon_flashbang"); // select grenade - f_wait_time = gpGlobals->time + 1; // wait 1 second (stand still 1 sec) + f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) f_gren_time = gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon @@ -1167,9 +1167,9 @@ void cBot::Combat() { const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { - sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); + std::sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); } else { - sprintf(msg, "A RealBot named %s has killed you!", name); + std::sprintf(msg, "A RealBot named %s has killed you!", name); } HUD_DrawString(r, g, b, msg, pEnemyEdict); @@ -1629,11 +1629,11 @@ void cBot::JoinTeam() { // select the team the bot wishes to join... if (iTeam == 1) { - strcpy(c_team, "1"); + std::strcpy(c_team, "1"); } else if (iTeam == 2) { - strcpy(c_team, "2"); + std::strcpy(c_team, "2"); } else { - strcpy(c_team, "5"); + std::strcpy(c_team, "5"); } // choose @@ -1657,15 +1657,15 @@ void cBot::JoinTeam() { // select the class the bot wishes to use... if (bot_class == 1) - strcpy(c_class, "1"); + std::strcpy(c_class, "1"); else if (bot_class == 2) - strcpy(c_class, "2"); + std::strcpy(c_class, "2"); else if (bot_class == 3) - strcpy(c_class, "3"); + std::strcpy(c_class, "3"); else if (bot_class == 4) - strcpy(c_class, "4"); + std::strcpy(c_class, "4"); else - strcpy(c_class, "5"); // random + std::strcpy(c_class, "5"); // random FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); @@ -1689,15 +1689,15 @@ void cBot::JoinTeam() { // select the class the bot wishes to use... if (bot_class == 1) - strcpy(c_class, "1"); + std::strcpy(c_class, "1"); else if (bot_class == 2) - strcpy(c_class, "2"); + std::strcpy(c_class, "2"); else if (bot_class == 3) - strcpy(c_class, "3"); + std::strcpy(c_class, "3"); else if (bot_class == 4) - strcpy(c_class, "4"); + std::strcpy(c_class, "4"); else - strcpy(c_class, "5"); // random + std::strcpy(c_class, "5"); // random FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); @@ -1898,7 +1898,7 @@ void cBot::Act() { if (fChatTime < gpGlobals->time) { if (chChatSentence[0] != '\0') { UTIL_SayTextBot(chChatSentence, this); - memset(chChatSentence, 0, sizeof(chChatSentence)); + std::memset(chChatSentence, 0, sizeof(chChatSentence)); } } @@ -2023,7 +2023,7 @@ void cBot::Act() { // Button usage, change vBody to a 'trigger multiple' because we have to touch these if (pButtonEdict) { - if (strcmp(STRING(pButtonEdict->v.classname), "trigger_multiple") == 0) { + if (std::strcmp(STRING(pButtonEdict->v.classname), "trigger_multiple") == 0) { if (func_distance(pEdict->v.origin, VecBModelOrigin(pButtonEdict)) < 60) { vBody = VecBModelOrigin(pButtonEdict); } @@ -2153,7 +2153,7 @@ void cBot::CheckAround() { char msg[255]; - sprintf(msg, "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); + std::sprintf(msg, "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); rprint_trace("CheckAround", msg); // Set 'act' properties @@ -2191,10 +2191,10 @@ void cBot::CheckAround() { edict_t *pent = nullptr; while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { char item_name[40]; - strcpy(item_name, STRING(pent->v.classname)); + std::strcpy(item_name, STRING(pent->v.classname)); // See if it matches our object name - if (strcmp("func_breakable", item_name) == 0) { + if (std::strcmp("func_breakable", item_name) == 0) { // Found a func_breakable const Vector vBreakableOrigin = VecBModelOrigin(pent); @@ -2305,8 +2305,8 @@ bool cBot::hasEnemy(edict_t * pEdict) const bool cBot::shouldBeWandering() { if (this->fWanderTime > gpGlobals->time) { char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); rprint(msg); return true; } @@ -2322,7 +2322,7 @@ void cBot::setMoveSpeed(float value) { void cBot::setStrafeSpeed(float value, float time) { char msg[255]; - sprintf(msg, "%f for %f seconds.", value, time); + std::sprintf(msg, "%f for %f seconds.", value, time); rprint_trace("setStrafeSpeed", msg); // if (f_strafe_time > gpGlobals->time) { // @@ -2344,8 +2344,8 @@ void cBot::startWandering(float time) { this->fWanderTime = gpGlobals->time + time; setMoveSpeed(f_max_speed); char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Start wandering for %f seconds", time); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Start wandering for %f seconds", time); rprint("startWandering", msg); } @@ -2398,17 +2398,17 @@ void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { tGoal *goalPtr = getGoalData(); char msg[255]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); if (goalPtr != nullptr) { - sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", + std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", nodeIndex, goalIndex, goalPtr->name, goalPtr->iChecked ); } else { - sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); + std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); } rprint("setGoalNode()", msg); } @@ -2510,10 +2510,10 @@ void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { if (this->console_nr == 0) { // set up first command and argument - strcpy(this->arg1, "buy"); - strcpy(this->arg2, menuItem); + std::strcpy(this->arg1, "buy"); + std::strcpy(this->arg2, menuItem); - if (subMenuItem != nullptr) strcpy(this->arg3, subMenuItem); + if (subMenuItem != nullptr) std::strcpy(this->arg3, subMenuItem); this->console_nr = 1; // start console command sequence } @@ -2913,7 +2913,7 @@ void cBot::Memory() { } } else { - fMemoryTime = gpGlobals->time + 5; + fMemoryTime = gpGlobals->time + 5.0f; } /* @@ -3082,7 +3082,7 @@ edict_t * cBot::findHostageToRescue() { if (getDistanceTo(pent->v.origin) > (NODE_ZONE * 2.5f)) continue; char msg[255]; - sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); + std::sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); this->rprint_trace("findHostageToRescue()", msg); return pent; } @@ -3216,11 +3216,11 @@ void cBot::Think() { const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - sprintf(msg, + std::sprintf(msg, "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", name, bot_skill); else - sprintf(msg, "You have killed a RealBot named %s!", + std::sprintf(msg, "You have killed a RealBot named %s!", name); HUD_DrawString(r, g, b, msg, killer_edict); @@ -3259,8 +3259,8 @@ void cBot::Think() { if (the_c > -1 && iMax > -1) { char chSentence[80]; - memset(chSentence, 0, sizeof(chSentence)); - sprintf(chSentence, "%s ", + std::memset(chSentence, 0, sizeof(chSentence)); + std::sprintf(chSentence, "%s ", ChatEngine.ReplyBlock[99].sentence[the_c]); //strcpy(chSentence, ChatEngine.ReplyBlock[99].sentence[the_c]); PrepareChat(chSentence); @@ -3297,7 +3297,7 @@ void cBot::Think() { rprint("Played enough rounds"); bIsUsed = FALSE; // no longer used char cmd[80]; - sprintf(cmd, "kick \"%s\"\n", name); + std::sprintf(cmd, "kick \"%s\"\n", name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") return; } @@ -3311,9 +3311,9 @@ void cBot::Think() { // prevent division by zero if (movedTwoTimes > 0.0f) { - distanceMoved = movedTwoTimes / 2; + distanceMoved = movedTwoTimes / 2.0f; } else { - distanceMoved = 0; + distanceMoved = 0.0f; } // save current position as previous @@ -3372,7 +3372,7 @@ void cBot::Think() { // NEW: When round time is over and still busy playing, kill bots - const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60; + const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60.0f; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); if (Game.getRoundStartedTime() + 10.0f + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { end_round = true; @@ -3437,11 +3437,11 @@ void cBot::Think() { bool bMayFromGame = true; - if (Game.fWalkWithKnife > 0) + if (Game.fWalkWithKnife > 0.0f) if (Game.getRoundStartedTime() + Game.fWalkWithKnife < gpGlobals->time) bMayFromGame = false; - if (Game.fWalkWithKnife == 0) + if (Game.fWalkWithKnife == 0.0f) bMayFromGame = false; if (hasShield()) { @@ -3593,7 +3593,7 @@ void cBot::CheckGear() { void cBot::UpdateStatus() { // name filled in yet? if (name[0] == 0) - strcpy(name, STRING(pEdict->v.netname)); + std::strcpy(name, STRING(pEdict->v.netname)); // Set thirdpartybot flag pEdict->v.flags |= FL_THIRDPARTYBOT; @@ -3646,7 +3646,7 @@ bool BotRadioAction() { int team = -1; int i; int radios = 0; // Hold amount of replies here, so we don't flood :) - strcpy(name, radio_messenger); + std::strcpy(name, radio_messenger); // First find the team messager name for (i = 1; i <= gpGlobals->maxClients; i++) { @@ -3654,8 +3654,8 @@ bool BotRadioAction() { if (pPlayer) // If player exists { char netname[64]; - strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname - if (strcmp(netname, name) == 0) // If + std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname + if (std::strcmp(netname, name) == 0) // If { plr = pPlayer; team = UTIL_GetTeam(pPlayer); @@ -3669,9 +3669,9 @@ bool BotRadioAction() { if (pPlayer) { char netname[64]; - strcpy(netname, STRING(pPlayer->v.netname)); + std::strcpy(netname, STRING(pPlayer->v.netname)); - if ((strcmp(netname, name) != 0) && // When not the same name + if ((std::strcmp(netname, name) != 0) && // When not the same name (team == UTIL_GetTeam(pPlayer)) && // .. the same team... (pPlayer->v.deadflag == DEAD_NO) && // .. not dead .. ((UTIL_GetBotPointer(pPlayer) != nullptr))) // and a RealBot @@ -3682,7 +3682,7 @@ bool BotRadioAction() { if (BotPointer == nullptr) continue; // somehow this fucked up, bail out - const auto distance = func_distance(plr->v.origin, + const float distance = func_distance(plr->v.origin, BotPointer->pEdict->v.origin); // distance between the 2 // Same team, randomly, do we even listen to the radio? @@ -3703,12 +3703,12 @@ bool BotRadioAction() { bool can_do_negative = false; // Report in team! - if (strstr(message, "#Report_in_team") != nullptr) { + if (std::strstr(message, "#Report_in_team") != nullptr) { // gives human knowledge who is on his team } // Regroup team! - if (strstr(message, "#Regroup_team") != nullptr) { + if (std::strstr(message, "#Regroup_team") != nullptr) { // regroup now! unstood = true; @@ -3719,21 +3719,21 @@ bool BotRadioAction() { } // Hold this position - if (strstr(message, "#Hold_this_position") != nullptr || - strstr(message, "#Get_in_position_and_wait") != nullptr) { + if (std::strstr(message, "#Hold_this_position") != nullptr || + std::strstr(message, "#Get_in_position_and_wait") != nullptr) { // do nothing } // Follow me!! - if (strstr(message, "#Follow_me") != nullptr) {} + if (std::strstr(message, "#Follow_me") != nullptr) {} // You take the point! // 23/06/04 - Stefan - Here the leader should break up his position? // ie, the leader will be assigned to the bot this human/bot is facing? - if (strstr(message, "#You_take_the_point") != nullptr) { + if (std::strstr(message, "#You_take_the_point") != nullptr) { can_do_negative = false; } // Enemy Sotted! - if (strstr(message, "#Enemy_spotted") != nullptr) { + if (std::strstr(message, "#Enemy_spotted") != nullptr) { can_do_negative = false; // Find player who issues this message and go to it @@ -3753,14 +3753,14 @@ bool BotRadioAction() { } } // Enemy Down! - if (strstr(message, "#Enemy_down") != nullptr) { + if (std::strstr(message, "#Enemy_down") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); unstood = true; can_do_negative = false; } // Stick together team! - if (strstr(message, "#Stick_together_team") != nullptr) { + if (std::strstr(message, "#Stick_together_team") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); unstood = true; can_do_negative = false; @@ -3768,7 +3768,7 @@ bool BotRadioAction() { // cover me|| strstr (message, "#Cover_me") != NULL // Need backup / taking fire... - if (strstr(message, "#Need_backup") != nullptr || strstr(message, "#Taking_fire") != nullptr) { + if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); unstood = true; @@ -3786,7 +3786,7 @@ bool BotRadioAction() { } // Taking fire! - if (strstr(message, "#Taking_fire") != nullptr) { + if (std::strstr(message, "#Taking_fire") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); unstood = true; @@ -3804,11 +3804,11 @@ bool BotRadioAction() { } // Team fall back! - if (strstr(message, "#Team_fall_back") != nullptr) { + if (std::strstr(message, "#Team_fall_back") != nullptr) { } // Go Go Go, stop camping, stop following, get the heck out of there! - if (strstr(message, "#Go_go_go") != nullptr) { + if (std::strstr(message, "#Go_go_go") != nullptr) { BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); unstood = true; BotPointer->f_camp_time = gpGlobals->time - 30; @@ -4066,7 +4066,7 @@ void BotThink(cBot *pBot) { const double upMove = 0.0; char msg[255]; - sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); + std::sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, upMove, pBot->pEdict->v.button, 0, msecval); @@ -4093,21 +4093,21 @@ void cBot::Dump() { iGoalNode, iCurrentNode); switch (iPathFlags) { case PATH_NONE: - strncat(buffer, "PATH_NONE ", 180); + std::strncat(buffer, "PATH_NONE ", 180); break; case PATH_DANGER: - strncat(buffer, "PATH_DANGER ", 180); + std::strncat(buffer, "PATH_DANGER ", 180); break; case PATH_CONTACT: - strncat(buffer, "PATH_CONTACT ", 180); + std::strncat(buffer, "PATH_CONTACT ", 180); break; case PATH_CAMP: - strncat(buffer, "PATH_CAMP ", 180); + std::strncat(buffer, "PATH_CAMP ", 180); break; default: - strncat(buffer, "???", 180); + std::strncat(buffer, "???", 180); } - strncat(buffer, "\n", 180); + std::strncat(buffer, "\n", 180); rblog(buffer); if (iGoalNode >= 0) NodeMachine.dump_path(iBotIndex, pathIndex); @@ -4255,7 +4255,7 @@ void cBot::lookAtNode(int nodeIndex) { void cBot::setTimeToMoveToNode(float timeInSeconds) { char msg[255]; const float endTime = gpGlobals->time + timeInSeconds; - sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); + std::sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); rprint_trace("setTimeToMoveToNode", msg); this->nodeTimeIncreasedAmount = 0; @@ -4272,8 +4272,8 @@ void cBot::increaseTimeToMoveToNode(float timeInSeconds) { this->fMoveToNodeTime += timeInSeconds; const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); rprint_trace("increaseTimeToMoveToNode", msg); } else { @@ -4345,8 +4345,8 @@ bool cBot::createPath(int destinationNode, int flags) { forgetPath(); char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); rprint("createPath()", msg); return NodeMachine.createPath(currentNode, destinationNode, iBotIndex, this, flags); diff --git a/bot_buycode.cpp b/bot_buycode.cpp index c2512b7..31c232c 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -70,12 +70,12 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const ch if (pBot->console_nr == 0) { // set up first command and argument - strcpy(pBot->arg1, "buy"); - strcpy(pBot->arg2, arg1); + std::strcpy(pBot->arg1, "buy"); + std::strcpy(pBot->arg2, arg1); // add argument if (arg2 != nullptr) - strcpy(pBot->arg3, arg2); + std::strcpy(pBot->arg3, arg2); pBot->console_nr = 1; // start console command sequence } diff --git a/bot_client.cpp b/bot_client.cpp index 83d8bae..21e5c46 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -76,18 +76,18 @@ void BotClient_CS_ShowMenu(void *p, int bot_index) { return; } - if (strcmp(static_cast(p), "#Team_Select") == 0 || - strcmp(static_cast(p), "#Team_Select_Spect") == 0 || - strcmp(static_cast(p), "#IG_Team_Select_Spect") == 0 || - strcmp(static_cast(p), "#IG_Team_Select") == 0 || - strcmp(static_cast(p), "#IG_VIP_Team_Select") == 0 || - strcmp(static_cast(p), "#IG_VIP_Team_Select_Spect") == 0) { + if (std::strcmp(static_cast(p), "#Team_Select") == 0 || + std::strcmp(static_cast(p), "#Team_Select_Spect") == 0 || + std::strcmp(static_cast(p), "#IG_Team_Select_Spect") == 0 || + std::strcmp(static_cast(p), "#IG_Team_Select") == 0 || + std::strcmp(static_cast(p), "#IG_VIP_Team_Select") == 0 || + std::strcmp(static_cast(p), "#IG_VIP_Team_Select_Spect") == 0) { // team select menu? bots[bot_index].start_action = MSG_CS_TEAM_SELECT; - } else if (strcmp(static_cast(p), "#Terrorist_Select") == 0) { + } else if (std::strcmp(static_cast(p), "#Terrorist_Select") == 0) { // T model select? bots[bot_index].start_action = MSG_CS_T_SELECT; - } else if (strcmp(static_cast(p), "#CT_Select") == 0) { + } else if (std::strcmp(static_cast(p), "#CT_Select") == 0) { // CT model select menu? bots[bot_index].start_action = MSG_CS_CT_SELECT; } @@ -104,7 +104,7 @@ void BotClient_Valve_WeaponList(void *p, int bot_index) { if (state == 0) { state++; - strcpy(bot_weapon.szClassname, static_cast(p)); + std::strcpy(bot_weapon.szClassname, static_cast(p)); } else if (state == 1) { state++; bot_weapon.iAmmo1 = *static_cast(p); // ammo index 1 @@ -487,7 +487,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { // face the attacker... edict_t *damageInflictor = pBot->pEdict->v.dmg_inflictor; if (damageInflictor) { - if (strcmp(STRING(damageInflictor->v.classname), "player") == 0) { + if (std::strcmp(STRING(damageInflictor->v.classname), "player") == 0) { // Face danger vector pBot->vHead = damage_origin; pBot->vBody = damage_origin; @@ -497,7 +497,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { pBot->rprint("BotClient_Valve_Damage", "Damage taken, by player, change goal to damage origin."); char msg[255]; - sprintf(msg, "damage_origin (x,y,z) => (%f,%f,%f) | damageInflictor->v.origin (x,y,z) => (%f,%f,%f)", + std::sprintf(msg, "damage_origin (x,y,z) => (%f,%f,%f) | damageInflictor->v.origin (x,y,z) => (%f,%f,%f)", damage_origin.x, damage_origin.y, damage_origin.z, @@ -513,7 +513,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { pBot->forgetPath(); } else { char msg[255]; - sprintf(msg, "I have a damage inflictor! -> %s", STRING(damageInflictor->v.classname)); + std::sprintf(msg, "I have a damage inflictor! -> %s", STRING(damageInflictor->v.classname)); pBot->rprint("BotClient_Valve_Damage", msg); } } else { @@ -571,17 +571,17 @@ void BotClient_CS_SayText(void *p, int bot_index) { char chSentence[MAX_SENTENCE_LENGTH]; char netname[30]; - memset(sentence, 0, sizeof(sentence)); - memset(chSentence, 0, sizeof(chSentence)); - memset(netname, 0, sizeof(netname)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(chSentence, 0, sizeof(chSentence)); + std::memset(netname, 0, sizeof(netname)); - strcpy(sentence, static_cast(p)); // the actual sentence + std::strcpy(sentence, static_cast(p)); // the actual sentence int length = 0; // FIXED: In any case that this might return NULL, do not crash the server - if (strstr(sentence, " : ")) - length = strlen(sentence) - strlen(strstr(sentence, " : ")); + if (std::strstr(sentence, " : ")) + length = std::strlen(sentence) - std::strlen(std::strstr(sentence, " : ")); int tc = 0; @@ -591,7 +591,7 @@ void BotClient_CS_SayText(void *p, int bot_index) { } const edict_t *pPlayer = INDEXENT(ucEntIndex); - strcpy(netname, STRING(pPlayer->v.netname)); + std::strcpy(netname, STRING(pPlayer->v.netname)); ChatEngine.set_sentence(netname, chSentence); state = -1; @@ -622,15 +622,15 @@ void BotClient_CS_SayText(void *p, int bot_index) { char netname[30]; // init - memset(sentence, 0, sizeof(sentence)); - memset(netname, 0, sizeof(netname)); + std::memset(sentence, 0, sizeof(sentence)); + std::memset(netname, 0, sizeof(netname)); // copy in memory - strcpy(sentence, static_cast(p)); + std::strcpy(sentence, static_cast(p)); // copy netname const edict_t *pPlayer = INDEXENT(ucEntIndex); - strcpy(netname, STRING(pPlayer->v.netname)); + std::strcpy(netname, STRING(pPlayer->v.netname)); // and give chatengine something to do ChatEngine.set_sentence(netname, sentence); @@ -673,7 +673,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { EnableIcon = *static_cast(p); // check the byte break; case 1: // Which icon - if (strcmp(static_cast(p), "buyzone") == 0) { + if (std::strcmp(static_cast(p), "buyzone") == 0) { switch (EnableIcon) { case 0: // Not in buy zone state = 0; @@ -683,7 +683,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp(static_cast(p), "c4") == 0) { + } else if (std::strcmp(static_cast(p), "c4") == 0) { switch (EnableIcon) { case 0: // No C4 bots[bot_index].bHUD_C4_plantable = false; @@ -698,7 +698,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp(static_cast(p), "defuser") == 0) { + } else if (std::strcmp(static_cast(p), "defuser") == 0) { switch (EnableIcon) { case 0: // No defuser state = 0; @@ -708,7 +708,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { default: break; } - } else if (strcmp(static_cast(p), "rescue") == 0) { + } else if (std::strcmp(static_cast(p), "rescue") == 0) { switch (EnableIcon) { case 0: // Not in rescue zone state = 0; diff --git a/bot_func.cpp b/bot_func.cpp index 525fa78..0e8172a 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -64,13 +64,13 @@ bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkna pEdict->v.pContainingEntity, &tr); // When our check string is not "none" and the traceline has a hit... - if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { + if (std::strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; const edict_t *pent = tr.pHit; // Ok now retrieve the entity - strcpy(entity_blocker, STRING(pent->v.classname)); // the classname + std::strcpy(entity_blocker, STRING(pent->v.classname)); // the classname - if (strcmp(entity_blocker, checkname) == 0) + if (std::strcmp(entity_blocker, checkname) == 0) return true; // We are blocked by our string, this means its ok. else { return false; // We are blocked, but by something differernt then 'checkname' its not ok @@ -95,13 +95,13 @@ bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { UTIL_TraceLine(start, dest, dont_ignore_monsters, nullptr, &tr); // Als we geblokt worden EN we checken voor een naam - if (strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { + if (std::strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. char entity_blocker[128]; const edict_t *pent = tr.pHit; // Ok now retrieve the entity - strcpy(entity_blocker, STRING(pent->v.classname)); // the classname + std::strcpy(entity_blocker, STRING(pent->v.classname)); // the classname - if (strcmp(entity_blocker, checkname) == 0) + if (std::strcmp(entity_blocker, checkname) == 0) return false; // We worden geblokt door die naam.. else return true; // We worden NIET geblokt door die naam (dus we worden niet geblokt). @@ -123,7 +123,7 @@ float func_distance(Vector v1, Vector v2) { if (v1 && v2) return (v1 - v2).Length(); else - return 0.0; + return 0.0f; } /** @@ -155,7 +155,7 @@ int FUNC_InFieldOfView(edict_t *pEntity, const Vector& dest) { // 45 degrees to the right is the limit of the normal view angle // rsm - START angle bug fix - int angle = abs(static_cast(view_angle) - static_cast(entity_angles.y)); + int angle = std::abs(static_cast(view_angle) - static_cast(entity_angles.y)); if (angle > 180) angle = 360 - angle; @@ -364,7 +364,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { if (pBot->iJumpTries > 5) { char msg[255]; - sprintf(msg, "Returning false because jumped too many times (%d)", pBot->iJumpTries); + std::sprintf(msg, "Returning false because jumped too many times (%d)", pBot->iJumpTries); pBot->rprint_trace("BotShouldJumpIfStuck", msg); return false; } @@ -378,7 +378,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { // should not jump, perhaps its a func_illusionary causing that we're stuck? const edict_t *entityInFov = getEntityNearbyBotInFOV(pBot); - if (entityInFov && strcmp("func_illusionary", STRING(entityInFov->v.classname)) == 0) { + if (entityInFov && std::strcmp("func_illusionary", STRING(entityInFov->v.classname)) == 0) { return true; // yes it is the case } @@ -480,7 +480,7 @@ bool BotShouldJump(cBot *pBot) { // "func_illusionary" - although on cs_italy this is not detected, and probably in a lot of other cases as well if (tr.pHit) { pBot->rprint_trace("trace pHit", STRING(tr.pHit->v.classname)); - if (strcmp("func_illusionary", STRING(tr.pHit->v.classname)) == 0) { + if (std::strcmp("func_illusionary", STRING(tr.pHit->v.classname)) == 0) { pBot->rprint_trace("BotShouldJump", "#1 Hit a func_illusionary, its a hit as well! (even though trace hit results no)"); return true; } @@ -663,23 +663,23 @@ int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { // sniper guns //if (strcmp("models/p_awp.mdl", STRING(pEdict->v.weaponmodel)) == 0) //Excluded for high prices and accuracy [APG]RoboCop[CL] // return CS_WEAPON_AWP; - if (strcmp("models/p_scout.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_scout.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_SCOUT; // good weapons (ak, m4a1, mp5) - if (strcmp("models/p_ak47.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_ak47.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_AK47; - if (strcmp("models/p_m4a1.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_m4a1.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_M4A1; - if (strcmp("models/p_mp5navy.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_mp5navy.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_MP5NAVY; // grenade types - if (strcmp("models/p_smokegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_smokegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_SMOKEGRENADE; - if (strcmp("models/p_hegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_hegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_HEGRENADE; - if (strcmp("models/p_flashbang.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (std::strcmp("models/p_flashbang.mdl", STRING(pEdict->v.weaponmodel)) == 0) return CS_WEAPON_FLASHBANG; // shield types //Most CS Veterans dislikes the shield [APG]RoboCop[CL] @@ -709,8 +709,8 @@ int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest) //Experim if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { if (farthest == -1) { farthest = i; farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); @@ -755,8 +755,8 @@ int FUNC_FindCover(const cBot* pBot) //Experimental [APG]RoboCop[CL] if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { if (farthest == -1) { farthest = i; farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); @@ -879,8 +879,8 @@ void FUNC_FindBreakable(edict_t* pEntity) //TODO: not functioning, bots won't sh if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { - if (strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { + if (std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { if (pEdict->v.origin == pEntity->v.origin) { pEntity->v.enemy = pEdict; return; @@ -913,7 +913,7 @@ void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] // If not, then we need to go to the waypoint. // "models/w_c4.mdl" needed for CTs to see the bomb? [APG]RoboCop[CL] - if (pEntity->v.model != 0 && strcmp(STRING(pEntity->v.model), "models/w_c4.mdl") == 0) { + if (pEntity->v.model != 0 && std::strcmp(STRING(pEntity->v.model), "models/w_c4.mdl") == 0) { // Bot has a bomb planted. // Go to the bomb site. pEntity->v.button |= IN_USE; diff --git a/dll.cpp b/dll.cpp index 2723dc8..d36d35e 100644 --- a/dll.cpp +++ b/dll.cpp @@ -161,7 +161,7 @@ C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, *pPlugInfo = &Plugin_info; // check for interface version compatibility - if (strcmp(ifvers, Plugin_info.ifvers) != 0) { + if (std::strcmp(ifvers, Plugin_info.ifvers) != 0) { int mmajor = 0, mminor = 0, pmajor = 0, pminor = 0; LOG_CONSOLE(PLID, "%s: meta-interface version mismatch (metamod: %s, %s: %s)", @@ -213,7 +213,7 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, } // keep track of the pointers to engine function tables metamod gives us gpMetaGlobals = pMGlobals; - memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); + std::memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); gpGamedllFuncs = pGamedllFuncs; // print a message to notify about plugin attaching @@ -264,7 +264,7 @@ GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals) { // get the engine functions from the engine... - memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t)); + std::memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t)); gpGlobals = pGlobals; mod_id = CSTRIKE_DLL; // so far RealBot works only for CS, eh Stefan ? :) // @PMB -> Yes so far it does ;) working on this MOD-GAME independent structure... grmbl @@ -289,7 +289,7 @@ void GameDLLInit() { // initialize the bots array of structures... rblog("Initializing memory for bots array.."); - memset(bots, 0.0f, sizeof(bots)); + std::memset(bots, 0.0f, sizeof(bots)); rblog("OK\n"); rblog("Verifying realbot is installed correctly.."); @@ -370,7 +370,7 @@ int Spawn(edict_t *pent) { if (gpGlobals->deathmatch) { const char *pClassname = const_cast(STRING(pent->v.classname)); - if (strcmp(pClassname, "worldspawn") == 0) { + if (std::strcmp(pClassname, "worldspawn") == 0) { // do level initialization stuff here... draw_nodes = false; draw_nodepath = -1; @@ -401,7 +401,7 @@ int Spawn(edict_t *pent) { NodeMachine.experience_load(); ChatEngine.fThinkTimer = gpGlobals->time; - } else if (strcmp(pClassname, "trigger_multiple") == 0) { + } else if (std::strcmp(pClassname, "trigger_multiple") == 0) { // make it a func_button? //sprintf(STRING(pent->v.classname), "func_button"); @@ -416,7 +416,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) { if (gpGlobals->deathmatch) { // check if this client is the listen server client - if (strcmp(pszAddress, "loopback") == 0) { + if (std::strcmp(pszAddress, "loopback") == 0) { // save the edict of the listen server client... pHostEdict = pEntity; } @@ -426,7 +426,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, // check if this is NOT a bot joining the server... - if (strcmp(pszAddress, "127.0.0.1") != 0) { + if (std::strcmp(pszAddress, "127.0.0.1") != 0) { int count = 0; int i; @@ -446,7 +446,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, { char cmd[80]; - sprintf(cmd, "kick \"%s\"\n", bots[i].name); + std::sprintf(cmd, "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; @@ -574,7 +574,7 @@ void StartFrame() { { if (bots[i].iTeam == kicking_team) { char cmd[80]; - sprintf(cmd, "kick \"%s\"\n", bots[i].name); + std::sprintf(cmd, "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; } @@ -667,7 +667,7 @@ void StartFrame() { if ((welcome_time > 0.0f) && (welcome_time < gpGlobals->time)) { // let's send a welcome message to this client... char total_welcome[256]; - sprintf(total_welcome, "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); + std::sprintf(total_welcome, "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); int r, g, b; /* r = RANDOM_LONG(30, 255); @@ -705,7 +705,7 @@ void StartFrame() { } welcome_sent = true; // clear this so we only do it once - welcome_time = 0.0; + welcome_time = 0.0f; } } @@ -714,7 +714,7 @@ void StartFrame() { for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) { - memset(&cd, 0, sizeof(cd)); + std::memset(&cd, 0, sizeof(cd)); MDLL_UpdateClientData(bots[i].pEdict, 1, &cd); @@ -934,14 +934,14 @@ void StartFrame() { // respawn 1 bot then wait a while (otherwise engine crashes) // 01/07/04 - Stefan - Thanks Evy for pointing out this one: On skill 10 - // the c_skill (was [2]) would be messed up (perhaps this is some memory related bug later on?) + // the c_skill (was [2]) would be messed up (perhaps this is some memory related bug later on?) char c_skill[3]; char c_team[2]; char c_class[3]; - sprintf(c_skill, "%d", bots[index].bot_skill); - sprintf(c_team, "%d", bots[index].iTeam); - sprintf(c_class, "%d", bots[index].bot_class); + std::sprintf(c_skill, "%d", bots[index].bot_skill); + std::sprintf(c_team, "%d", bots[index].iTeam); + std::sprintf(c_class, "%d", bots[index].bot_class); Game.createBot(nullptr, c_team, c_skill, c_class, bots[index].name); @@ -967,7 +967,7 @@ void StartFrame() { UTIL_BuildFileNameRB("bot.cfg", filename); - sprintf(msg, "Executing %s\n", filename); + std::sprintf(msg, "Executing %s\n", filename); ALERT(at_console, msg); bot_cfg_fp = fopen(filename, "r"); @@ -1015,7 +1015,7 @@ void StartFrame() { void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { int length; - memset(g_argv, 0, sizeof(g_argv)); + std::memset(g_argv, 0, sizeof(g_argv)); isFakeClientCommand = TRUE; @@ -1023,25 +1023,25 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { return; if ((arg2 == nullptr) || (*arg2 == 0)) { - length = sprintf(&g_argv[0], "%s", arg1); + length = std::sprintf(&g_argv[0], "%s", arg1); fake_arg_count = 1; } else if ((arg3 == nullptr) || (*arg3 == 0)) { - length = sprintf(&g_argv[0], "%s %s", arg1, arg2); + length = std::sprintf(&g_argv[0], "%s %s", arg1, arg2); fake_arg_count = 2; } else { - length = sprintf(&g_argv[0], "%s %s %s", arg1, arg2, arg3); + length = std::sprintf(&g_argv[0], "%s %s %s", arg1, arg2, arg3); fake_arg_count = 3; } g_argv[length] = 0; // null terminate just in case - strcpy(&g_argv[64], arg1); + std::strcpy(&g_argv[64], arg1); if (arg2) - strcpy(&g_argv[128], arg2); + std::strcpy(&g_argv[128], arg2); if (arg3) - strcpy(&g_argv[192], arg3); + std::strcpy(&g_argv[192], arg3); // allow the MOD DLL to execute the ClientCommand... MDLL_ClientCommand(pBot); @@ -1166,8 +1166,8 @@ void ProcessBotCfgFile() { cmd_line[cmd_index] = 0; // terminate the command line // copy the command line to a server command buffer... - strcpy(server_cmd, cmd_line); - strcat(server_cmd, "\n"); + std::strcpy(server_cmd, cmd_line); + std::strcat(server_cmd, "\n"); cmd_index = 0; const char* cmd = cmd_line; @@ -1214,15 +1214,15 @@ void ProcessBotCfgFile() { if ((cmd_line[0] == '#') || (cmd_line[0] == 0)) return; // return if comment or blank line - if (strcmp(cmd, "pause") == 0) { - bot_cfg_pause_time = gpGlobals->time + atoi(arg1); + if (std::strcmp(cmd, "pause") == 0) { + bot_cfg_pause_time = gpGlobals->time + std::atoi(arg1); return; } // 07/02/04 - This gives a user theoreticly the power as in the console // use 'realbot addbot' to add a bot, etc. I dont think we need more // it would double the work. - sprintf(msg, "BOT.CFG >> Executing command: %s", server_cmd); // removed \n + std::sprintf(msg, "BOT.CFG >> Executing command: %s", server_cmd); // removed \n ALERT(at_console, msg); if (IS_DEDICATED_SERVER()) @@ -1263,17 +1263,17 @@ void RealBot_ServerCommand() { SERVER_PRINT("=====================================\n"); } else if (FStrEq(pcmd, "chatrate")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - Game.iMaxSentences = atoi(arg1); + Game.iMaxSentences = std::atoi(arg1); if (Game.iMaxSentences < -1) Game.iMaxSentences = -1; if (Game.iMaxSentences > 10) Game.iMaxSentences = 10; - sprintf(cMessage, "REALBOT: Chat-rate set to %d", + std::sprintf(cMessage, "REALBOT: Chat-rate set to %d", Game.iMaxSentences); } else { - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: No argument given, current chat-rate is %d", Game.iMaxSentences); @@ -1285,13 +1285,13 @@ void RealBot_ServerCommand() { const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); bot_check_time = gpGlobals->time + 8.0f; if (iStatus == GAME_MSG_SUCCESS) - sprintf(cMessage, "REALBOT: Successfully created bot."); + std::sprintf(cMessage, "REALBOT: Successfully created bot."); else if (iStatus == GAME_MSG_FAILURE) - sprintf(cMessage, "REALBOT: Failed creating bot."); + std::sprintf(cMessage, "REALBOT: Failed creating bot."); else if (iStatus == GAME_MSG_FAIL_SERVERFULL) - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { if ((arg1 != nullptr) && (*arg1 != 0)) { @@ -1306,27 +1306,27 @@ void RealBot_ServerCommand() { // Show amount set if (Game.fWalkWithKnife > 0) - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Bots may walk with knife for %f seconds.", Game.fWalkWithKnife); else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Bots may not walk with knife (value=0)"); } else - sprintf(cMessage, "REALBOT: No valid argument given."); + std::sprintf(cMessage, "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "max")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - max_bots = atoi(arg1); + max_bots = std::atoi(arg1); if ((max_bots < 0) || (max_bots > 31)) max_bots = -1; // Show amount set - sprintf(cMessage, "REALBOT: Max amount of bots is set to %d.", + std::sprintf(cMessage, "REALBOT: Max amount of bots is set to %d.", max_bots); } else { // sprintf (cMessage, "REALBOT: No valid argument given."); - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Max amount of bots is %d -- no valid argument given.", max_bots); } @@ -1335,73 +1335,73 @@ void RealBot_ServerCommand() { if (FStrEq(arg1, "add")) { if (pHostEdict != nullptr) { NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, pHostEdict->v.origin); - sprintf(cMessage, "REALBOT: Added important area/goal."); + std::sprintf(cMessage, "REALBOT: Added important area/goal."); } else - sprintf(cMessage, "REALBOT: Only a listen server can execute this command!"); + std::sprintf(cMessage, "REALBOT: Only a listen server can execute this command!"); } else if (FStrEq(arg1, "save")) { NodeMachine.save_important(); - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Important Area Definitions written to INI file"); } else if (FStrEq(arg1, "init")) { // clear all goals that are 'goal_important' NodeMachine.ClearImportantGoals(); - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: All important goals have been removed."); } else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: 'important' sub-commands are: add, save, init"); } else if (FStrEq(pcmd, "killall")) { - sprintf(cMessage, "REALBOT: Killing all bots."); + std::sprintf(cMessage, "REALBOT: Killing all bots."); end_round = true; } else if (FStrEq(pcmd, "csversion")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); if (temp <= 0) counterstrike = 0; // cs 1.5 else counterstrike = 1; // cs 1.6 if (counterstrike == 0) - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Set bot-rules for Counter-Strike 1.5."); else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Set bot-rules for Counter-Strike 1.6."); } else { if (counterstrike == 0) - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: bot-rules are set for Counter-Strike 1.5."); else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: bot-rules are set for Counter-Strike 1.6."); } } else if (FStrEq(pcmd, "internet")) { if ((arg1 != nullptr) && (*arg1 != 0)) { // switch on/off internet mode - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); if (temp == 0) internet_play = false; else internet_play = true; if (internet_play) - sprintf(cMessage, "REALBOT: Internet simulation - enabled."); + std::sprintf(cMessage, "REALBOT: Internet simulation - enabled."); else - sprintf(cMessage, "REALBOT: Internet simulation - disabled."); + std::sprintf(cMessage, "REALBOT: Internet simulation - disabled."); } else - sprintf(cMessage, "REALBOT: No valid argument given."); + std::sprintf(cMessage, "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "internet_interval")) { // 1st argument if ((arg1 != nullptr) && (*arg1 != 0)) { // switch on/off internet mode - int temp = atoi(arg1); + int temp = std::atoi(arg1); if (temp > -1) { if (temp < 1) temp = 1; @@ -1412,7 +1412,7 @@ void RealBot_ServerCommand() { if ((arg2 != nullptr) && (*arg2 != 0)) { // switch on/off internet mode - int temp = atoi(arg2); + int temp = std::atoi(arg2); if (temp > -1) { if (temp < internet_min_interval) temp = internet_min_interval; @@ -1420,7 +1420,7 @@ void RealBot_ServerCommand() { } } // Create message - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Internet simulation - Interval set to, MIN %d - MAX %d", internet_min_interval, internet_max_interval); } else if (FStrEq(pcmd, "remove") && kick_amount_bots == 0) { @@ -1429,7 +1429,7 @@ void RealBot_ServerCommand() { if ((arg1 != nullptr) && (*arg1 != 0)) { // get amount - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); kick_amount_bots = temp; if (kick_amount_bots > 31) kick_amount_bots = 31; @@ -1441,7 +1441,7 @@ void RealBot_ServerCommand() { // get team int team = 0; - const int temp = atoi(arg2); + const int temp = std::atoi(arg2); if (temp == 1) team = 1; if (temp == 2) @@ -1449,16 +1449,16 @@ void RealBot_ServerCommand() { kick_bots_team = team; } if (kick_bots_team < 1) - sprintf(cMessage, "REALBOT: Removing randomly %d bots.", + std::sprintf(cMessage, "REALBOT: Removing randomly %d bots.", kick_amount_bots); else { if (kick_bots_team == 1) - sprintf(cMessage, "REALBOT: Removing %d terrorist bots.", + std::sprintf(cMessage, "REALBOT: Removing %d terrorist bots.", kick_amount_bots); else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Removing %d counter-terrorist bots.", kick_amount_bots); } @@ -1471,32 +1471,32 @@ void RealBot_ServerCommand() { // argument 1 if ((arg1 != nullptr) && (*arg1 != 0)) - s1 = atoi(arg1); + s1 = std::atoi(arg1); // argument 2 if ((arg2 != nullptr) && (*arg2 != 0)) - s2 = atoi(arg2); + s2 = std::atoi(arg2); Game.SetPlayingRounds(s1, s2); - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Bots play at minimum %d and at maximum %d rounds.\n", Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); } else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: No(t) (enough) valid arguments given."); } else if (FStrEq(pcmd, "setrandom")) { int s1 = -2, s2 = -2; // argument 1 if ((arg1 != nullptr) && (*arg1 != 0)) - s1 = atoi(arg1); + s1 = std::atoi(arg1); // argument 2 if ((arg2 != nullptr) && (*arg2 != 0)) - s2 = atoi(arg2); + s2 = std::atoi(arg2); // When first argument is invalid if (s1 < -1) { - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: No valid argument(s) given. (minimum random skill=%d, maximum random skill=%d).", Game.iRandomMinSkill, Game.iRandomMaxSkill); } else { @@ -1514,13 +1514,13 @@ void RealBot_ServerCommand() { s2 = s1; Game.iRandomMinSkill = s1; Game.iRandomMaxSkill = s2; - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: minimum random skill=%d, maximum random skill=%d.", Game.iRandomMinSkill, Game.iRandomMaxSkill); } } else if (FStrEq(pcmd, "autoskill")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); if (temp == 1) autoskill = true; @@ -1528,13 +1528,13 @@ void RealBot_ServerCommand() { autoskill = false; } if (autoskill) - sprintf(cMessage, "REALBOT: Auto adjust skill - enabled."); + std::sprintf(cMessage, "REALBOT: Auto adjust skill - enabled."); else - sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); + std::sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); if (temp == 1) Game.iOverrideBotSkill = GAME_YES; @@ -1542,26 +1542,26 @@ void RealBot_ServerCommand() { Game.iOverrideBotSkill = GAME_NO; } if (Game.iOverrideBotSkill == GAME_YES) - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Using personality skill (if present) instead of default bot skill."); else - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - const int temp = atoi(arg1); + const int temp = std::atoi(arg1); if ((temp < -1) || (temp > 10)) { - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Invalid argument given - default skill = %d.", Game.iDefaultBotSkill); } else { Game.iDefaultBotSkill = temp; - sprintf(cMessage, "REALBOT: Default skill = %d", + std::sprintf(cMessage, "REALBOT: Default skill = %d", Game.iDefaultBotSkill); } } else { - sprintf(cMessage, "REALBOT: Default skill = %d", + std::sprintf(cMessage, "REALBOT: Default skill = %d", Game.iDefaultBotSkill); } } @@ -1572,7 +1572,7 @@ void RealBot_ServerCommand() { // Minimum amount of playing players... bots or not if (FStrEq(arg1, "players")) { if ((arg2 != nullptr) && (*arg2 != 0)) { - int temp = atoi(arg2); // argument + int temp = std::atoi(arg2); // argument if (temp > 31) temp = 31; if (temp < -1) @@ -1582,7 +1582,7 @@ void RealBot_ServerCommand() { f_minplayers_think = gpGlobals->time; } - sprintf(cMessage, "RBSERVER: Minimum playing forced to %d.", + std::sprintf(cMessage, "RBSERVER: Minimum playing forced to %d.", min_players); } // Broadcast @@ -1591,37 +1591,37 @@ void RealBot_ServerCommand() { if (FStrEq(arg2, "version")) { // How do we broadcast version message? if ((arg3 != nullptr) && (*arg3 != 0)) { - int temp = atoi(arg3); // argument + int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; if (temp >= 1) temp = 1; Game.iVersionBroadcasting = temp; if (Game.iVersionBroadcasting == BROADCAST_ROUND) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting RealBot version every round and map change.\n"); else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting RealBot version every map change only.\n"); } } else if (FStrEq(arg2, "speech")) { if (arg2 != nullptr) { - if (atoi(arg2) == 1) + if (std::atoi(arg2) == 1) Game.bSpeechBroadcasting = true; else Game.bSpeechBroadcasting = false; } if (Game.bSpeechBroadcasting) - sprintf(cMessage, "RBSERVER: Broadcasting speech is ON"); + std::sprintf(cMessage, "RBSERVER: Broadcasting speech is ON"); else - sprintf(cMessage, "RBSERVER: Broadcasting speech is OFF"); + std::sprintf(cMessage, "RBSERVER: Broadcasting speech is OFF"); } else if (FStrEq(arg2, "kills")) { // How do we broadcast kills by bots? if ((arg3 != nullptr) && (*arg3 != 0)) { - int temp = atoi(arg3); // argument + int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; if (temp >= 2) @@ -1633,30 +1633,30 @@ void RealBot_ServerCommand() { if (temp == 2) Game.iKillsBroadcasting = BROADCAST_KILLS_NONE; if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Nothing will be sent to player.\n"); } } else if (FStrEq(arg2, "deaths")) { // How do we broadcast deaths by bots. if ((arg3 != nullptr) && (*arg3 != 0)) { - int temp = atoi(arg3); // argument + int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; if (temp >= 2) @@ -1668,31 +1668,31 @@ void RealBot_ServerCommand() { if (temp == 2) Game.iDeathsBroadcasting = BROADCAST_DEATHS_NONE; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Nothing will be sent to player.\n"); } } else { - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Broadcast what?\nversion\nspeech\nkills\ndeaths"); } } else - sprintf(cMessage, + std::sprintf(cMessage, "RBSERVER: Invalid sub-command.\nValid commands are:\nbroadcast (version/kill)\nplayers (keep ## player slots full)"); } // ----------------------------------------- @@ -1712,7 +1712,7 @@ void RealBot_ServerCommand() { // check for valid argument if ((arg2 != nullptr) && (*arg2 != 0)) { - const int iTo = atoi(arg2); // add connection TO + const int iTo = std::atoi(arg2); // add connection TO // Add this connection if (iTo > -1) { @@ -1720,11 +1720,11 @@ void RealBot_ServerCommand() { NodeMachine.add_neighbour_node(iOnNode, iTo); if (bSuccess) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Added connection from node %d to node %d.", iOnNode, iTo); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); bValidArg = true; @@ -1732,7 +1732,7 @@ void RealBot_ServerCommand() { } if (bValidArg == false) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeto")) { // removes connection TO @@ -1740,7 +1740,7 @@ void RealBot_ServerCommand() { // check for valid argument if ((arg2 != nullptr) && (*arg2 != 0)) { - const int iTo = atoi(arg2); // remove connection TO + const int iTo = std::atoi(arg2); // remove connection TO // remove this connection if (iTo > -1) { @@ -1748,11 +1748,11 @@ void RealBot_ServerCommand() { NodeMachine.removeConnection(iOnNode, iTo); if (bSuccess) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Removed connection from node %d to node %d.", iOnNode, iTo); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Could not remove connection, connection does not exist."); bValidArg = true; @@ -1760,14 +1760,14 @@ void RealBot_ServerCommand() { } if (bValidArg == false) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeall")) { const bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); if (bSuccess) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Removed all connections from node %d.", iOnNode); } else if (FStrEq(arg1, "draw")) { @@ -1776,9 +1776,9 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) @@ -1787,22 +1787,22 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes connections - enabled."); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); - sprintf(cMessage, "NODES EDITOR: Nodes initialized."); + std::sprintf(cMessage, "NODES EDITOR: Nodes initialized."); } else if (FStrEq(arg1, "save")) { NodeMachine.save(); - sprintf(cMessage, "NODES EDITOR: Nodes saved."); + std::sprintf(cMessage, "NODES EDITOR: Nodes saved."); } else if (FStrEq(arg1, "load")) { NodeMachine.load(); - sprintf(cMessage, "NODES EDITOR: Nodes loaded."); + std::sprintf(cMessage, "NODES EDITOR: Nodes loaded."); } else { - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Unknown command\n Valid commands are:\naddto,removeto,removeall,draw,connections,init,save,load."); } } else { @@ -1814,9 +1814,9 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) @@ -1825,22 +1825,22 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes connections - enabled."); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); - sprintf(cMessage, "NODES EDITOR: Nodes initialized."); + std::sprintf(cMessage, "NODES EDITOR: Nodes initialized."); } else if (FStrEq(arg1, "save")) { NodeMachine.save(); - sprintf(cMessage, "NODES EDITOR: Nodes saved."); + std::sprintf(cMessage, "NODES EDITOR: Nodes saved."); } else if (FStrEq(arg1, "load")) { NodeMachine.load(); - sprintf(cMessage, "NODES EDITOR: Nodes loaded."); + std::sprintf(cMessage, "NODES EDITOR: Nodes loaded."); } else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Not close enough to a node to edit."); } // commands not needed for a node to be close @@ -1851,35 +1851,35 @@ void RealBot_ServerCommand() { // check for valid argument if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) && (*arg3 != 0)) { - const int Node1 = atoi(arg2); // add connection TO - const int Node2 = atoi(arg3); // add connection TO + const int Node1 = std::atoi(arg2); // add connection TO + const int Node2 = std::atoi(arg3); // add connection TO if ((Node1 >= 0) && (Node2 >= 0) && NodeMachine.add_neighbour_node(Node1, Node2)) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Added connection from node %d to node %d.", Node1, Node2); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); } else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: this command requires TWO numeric arguments!"); } else if (FStrEq(arg1, "disconnect")) { // check for valid argument if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) && (*arg3 != 0)) { - const int Node1 = atoi(arg2); - const int Node2 = atoi(arg3); + const int Node1 = std::atoi(arg2); + const int Node2 = std::atoi(arg3); if ((Node1 >= 0) && (Node2 >= 0) && NodeMachine.removeConnection(Node1, Node2)) - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Removed connection from node %d to node %d.", Node1, Node2); else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: Connection could not be removed..."); } else - sprintf(cMessage, + std::sprintf(cMessage, "NODES EDITOR: this command requires TWO numeric arguments!"); } } @@ -1892,7 +1892,7 @@ void RealBot_ServerCommand() { if (FStrEq(arg1, "dontshoot")) { // realbot debug dontshoot [1/0] // check for valid argument if ((arg2 != nullptr) && (*arg2 != 0)) { - const int temp = atoi(arg2); + const int temp = std::atoi(arg2); if (temp) Game.bDoNotShoot = true; else @@ -1900,14 +1900,14 @@ void RealBot_ServerCommand() { } if (Game.bDoNotShoot) - sprintf(cMessage, "RBDEBUG: Bots will not shoot."); + std::sprintf(cMessage, "RBDEBUG: Bots will not shoot."); else - sprintf(cMessage, "RBDEBUG: Bots will shoot."); + std::sprintf(cMessage, "RBDEBUG: Bots will shoot."); } // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] if ((arg2 != nullptr) && (*arg2 != 0)) { - const int temp = atoi(arg2); + const int temp = std::atoi(arg2); if (temp) Game.bPistols = true; else @@ -1915,13 +1915,13 @@ void RealBot_ServerCommand() { } if (Game.bPistols) - sprintf(cMessage, "RBDEBUG: Bots will only use pistols."); + std::sprintf(cMessage, "RBDEBUG: Bots will only use pistols."); else - sprintf(cMessage, "RBDEBUG: Bots will use all weapons."); + std::sprintf(cMessage, "RBDEBUG: Bots will use all weapons."); } else if (FStrEq(arg1, "goals")) // Print all current goals { NodeMachine.dump_goals(); - strcpy(cMessage, "RBDEBUG: Dumping goals."); + std::strcpy(cMessage, "RBDEBUG: Dumping goals."); } else if (FStrEq(arg1, "bots")) // realbot debug bots // Print information about all current bots { @@ -1931,37 +1931,37 @@ void RealBot_ServerCommand() { } NodeMachine.dump_goals(); - strcpy(cMessage, "RBDEBUG: Dumping bots' information."); + std::strcpy(cMessage, "RBDEBUG: Dumping bots' information."); } else if (FStrEq(arg1, "print")) { // realbot debug print (toggles, and last argument is bot index) if (Game.bDebug > -2) { Game.bDebug = -2; - sprintf(cMessage, "RBDEBUG: Debug messages off."); + std::sprintf(cMessage, "RBDEBUG: Debug messages off."); } else { if ((arg2 != nullptr) && (*arg2 != 0)) { - const int temp = atoi(arg2); + const int temp = std::atoi(arg2); Game.bDebug = temp; - sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); + std::sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); } else { Game.bDebug = -1; - sprintf(cMessage, "RBDEBUG: Debug messages on for all bots"/*, Game.bDebug*/); + std::sprintf(cMessage, "RBDEBUG: Debug messages on for all bots"/*, Game.bDebug*/); } } } else if (FStrEq(arg1, "verbosity")) { // realbot verbosity if (FStrEq(arg2, "low")) { - sprintf(cMessage, "RBDEBUG: Message verbosity low."); + std::sprintf(cMessage, "RBDEBUG: Message verbosity low."); Game.messageVerbosity = 0; } else if (FStrEq(arg2, "normal")) { - sprintf(cMessage, "RBDEBUG: Message verbosity normal."); + std::sprintf(cMessage, "RBDEBUG: Message verbosity normal."); Game.messageVerbosity = 1; } else if (FStrEq(arg2, "trace")) { - sprintf(cMessage, "RBDEBUG: Message verbosity trace."); + std::sprintf(cMessage, "RBDEBUG: Message verbosity trace."); Game.messageVerbosity = 2; // extreme verbose } else { - sprintf(cMessage, "RBDEBUG: Usage: realbot debug verbosity [low][normal][trace]"); + std::sprintf(cMessage, "RBDEBUG: Usage: realbot debug verbosity [low][normal][trace]"); } } else if (FStrEq(arg1, "nodes")) { // realbot debug nodes if (FStrEq(arg2, "dumpbmp")) { // realbot debug nodes dumpbmp - sprintf(cMessage, "RBDEBUG: Dumping Nodes information into bitmap file"); + std::sprintf(cMessage, "RBDEBUG: Dumping Nodes information into bitmap file"); NodeMachine.Draw(); } else if (FStrEq(arg2, "draw")) { if (draw_nodes == false) @@ -1969,15 +1969,15 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - sprintf(cMessage, "RBDEBUG: Drawing nodes - enabled."); + std::sprintf(cMessage, "RBDEBUG: Drawing nodes - enabled."); else - sprintf(cMessage, "RBDEBUG: Drawing nodes - disabled."); + std::sprintf(cMessage, "RBDEBUG: Drawing nodes - disabled."); } else if (FStrEq(arg2, "path")) { int iFrom = -1, iTo = -1; if ((arg3 != nullptr) && (*arg3 != 0)) - iFrom = atoi(arg3); + iFrom = std::atoi(arg3); if ((arg4 != nullptr) && (*arg4 != 0)) - iTo = atoi(arg4); + iTo = std::atoi(arg4); if (iFrom > -1) { if (iTo < 0) { @@ -1985,18 +1985,18 @@ void RealBot_ServerCommand() { if (ptr) iTo = ptr->iNode; } - sprintf(cMessage, "RBDEBUG: Creating path from [%d] to [%d].", iFrom, iTo); + std::sprintf(cMessage, "RBDEBUG: Creating path from [%d] to [%d].", iFrom, iTo); NodeMachine.createPath(iFrom, iTo, 0, nullptr, PATH_DANGER); } else { - sprintf(cMessage, "RBDEBUG: Usage: realbot debug nodes path "); + std::sprintf(cMessage, "RBDEBUG: Usage: realbot debug nodes path "); } } else if (FStrEq(arg2, "drawpath")) { if ((arg3 != nullptr) && (*arg3 != 0)) - draw_nodepath = atoi(arg3); + draw_nodepath = std::atoi(arg3); if (draw_nodepath > -1) { - sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); + std::sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); } else - sprintf(cMessage, + std::sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d] - no better or valid argument given.", draw_nodepath); } else if (FStrEq(arg2, "connections")) { @@ -2006,30 +2006,30 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - sprintf(cMessage, + std::sprintf(cMessage, "RBDEBUG: Drawing nodes connections - enabled."); else - sprintf(cMessage, + std::sprintf(cMessage, "RBDEBUG: Drawing nodes connections - disabled."); } else if (FStrEq(arg2, "init")) { NodeMachine.init(); - sprintf(cMessage, "RBDEBUG: Nodes initialized."); + std::sprintf(cMessage, "RBDEBUG: Nodes initialized."); } else if (FStrEq(arg2, "save")) { NodeMachine.save(); - sprintf(cMessage, "RBDEBUG: Nodes saved."); + std::sprintf(cMessage, "RBDEBUG: Nodes saved."); } else if (FStrEq(arg2, "load")) { NodeMachine.load(); - sprintf(cMessage, "RBDEBUG: Nodes loaded."); + std::sprintf(cMessage, "RBDEBUG: Nodes loaded."); } else - sprintf(cMessage, "RBDEBUG: No argument given."); + std::sprintf(cMessage, "RBDEBUG: No argument given."); } else { - sprintf(cMessage, + std::sprintf(cMessage, "RBDEBUG: Unknown debug command.\n\nKnown commands are:\ndontshoot, pistols, nodes, print"); } } else { // Not a valid command - sprintf(cMessage, + std::sprintf(cMessage, "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); bool bValidCommand = false; //Unused variable boolean [APG]RoboCop[CL] } @@ -2037,7 +2037,7 @@ void RealBot_ServerCommand() { // Send message if (bSendMessage) { // Adding return carriage - strcat(cMessage, "\n"); + std::strcat(cMessage, "\n"); // Put a carriage return when using dedicated server. if (IS_DEDICATED_SERVER()) { @@ -2079,11 +2079,11 @@ int Spawn_Post(edict_t *pent) { } char msg[255]; - sprintf(msg, "Found an entity %s - %s - %s with rendermode %d!\n", STRING(pent->v.classname), STRING(pent->v.netname), STRING(pent->v.model), pent->v.rendermode); + std::sprintf(msg, "Found an entity %s - %s - %s with rendermode %d!\n", STRING(pent->v.classname), STRING(pent->v.netname), STRING(pent->v.model), pent->v.rendermode); rblog(msg); // is this a trigger_multiple ? - if (strcmp(STRING(pent->v.classname), "trigger_multiple") == 0) { + if (std::strcmp(STRING(pent->v.classname), "trigger_multiple") == 0) { //pent->v.flags &= ~FL_WORLDBRUSH; // then clear the FL_WORLDBRUSH flag pent->v.flags |= FL_WORLDBRUSH; // make it detectable! pent->v.rendermode = kRenderNormal; @@ -2112,7 +2112,7 @@ GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable.pfnClientPutInServer = ClientPutInServer; gFunctionTable.pfnClientCommand = ClientCommand; gFunctionTable.pfnStartFrame = StartFrame; - memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); + std::memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); return (TRUE); } @@ -2120,7 +2120,7 @@ GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable_post.pfnSpawn = Spawn_Post; // need to declare another gFunctionTable_post in the top of the dll.cpp file - memcpy(pFunctionTable, &gFunctionTable_post, sizeof(DLL_FUNCTIONS)); + std::memcpy(pFunctionTable, &gFunctionTable_post, sizeof(DLL_FUNCTIONS)); return (TRUE); } diff --git a/engine.cpp b/engine.cpp index ca4189a..2e34767 100644 --- a/engine.cpp +++ b/engine.cpp @@ -73,7 +73,7 @@ void pfnChangeLevel(const char *s1, const char *s2) { { char cmd[40]; - sprintf(cmd, "kick \"%s\"\n", bots[index].name); + std::sprintf(cmd, "kick \"%s\"\n", bots[index].name); bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN; @@ -91,7 +91,7 @@ edict_t *pfnFindEntityByString(edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue) { // Counter-Strike - New Round Started - if (strcmp(pszValue, "info_map_parameters") == 0) { + if (std::strcmp(pszValue, "info_map_parameters") == 0) { rblog("pfnFindEntityByString: Game new round\n"); // New round started. @@ -121,7 +121,7 @@ void pfnRemoveEntity(edict_t *e) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnRemoveEntity() - model -> '%s'\n", + std::sprintf(msg, "ENGINE: pfnRemoveEntity() - model -> '%s'\n", STRING(e->v.model)); rblog(msg); } @@ -145,7 +145,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict if (Game.bEngineDebug) { char dmsg[256]; - sprintf(dmsg, "ENGINE: pfnMessageBegin(), dest=%d, msg_type=%d\n", msg_dest, msg_type); + std::sprintf(dmsg, "ENGINE: pfnMessageBegin(), dest=%d, msg_type=%d\n", msg_dest, msg_type); rblog(dmsg); } @@ -294,7 +294,7 @@ void pfnWriteByte(int iValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteByte() - '%d'\n", iValue); + std::sprintf(msg, "ENGINE: pfnWriteByte() - '%d'\n", iValue); rblog(msg); } @@ -310,7 +310,7 @@ void pfnWriteChar(int iValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteChar() - '%d'\n", iValue); + std::sprintf(msg, "ENGINE: pfnWriteChar() - '%d'\n", iValue); rblog(msg); } RETURN_META(MRES_IGNORED); @@ -325,7 +325,7 @@ void pfnWriteShort(int iValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteShort() - '%d'\n", iValue); + std::sprintf(msg, "ENGINE: pfnWriteShort() - '%d'\n", iValue); rblog(msg); } @@ -341,7 +341,7 @@ void pfnWriteLong(int iValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteLong() - '%d'\n", iValue); + std::sprintf(msg, "ENGINE: pfnWriteLong() - '%d'\n", iValue); rblog(msg); } @@ -358,7 +358,7 @@ void pfnWriteAngle(float flValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteAngle() - '%f'\n", flValue); + std::sprintf(msg, "ENGINE: pfnWriteAngle() - '%f'\n", flValue); rblog(msg); } @@ -375,7 +375,7 @@ void pfnWriteCoord(float flValue) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteCoord() - '%f'\n", flValue); + std::sprintf(msg, "ENGINE: pfnWriteCoord() - '%f'\n", flValue); rblog(msg); } @@ -386,41 +386,41 @@ void pfnWriteCoord(float flValue) { void pfnWriteString(const char *sz) { if (Game.bEngineDebug) { char msg[256]; - sprintf(msg, "ENGINE: pfnWriteByte() - '%s'\n", sz); + std::sprintf(msg, "ENGINE: pfnWriteByte() - '%s'\n", sz); rblog(msg); } if (gpGlobals->deathmatch) { // Ditlew's Radio - if ((strstr(sz, "(RADIO):") != nullptr) && !radio_message) { + if ((std::strstr(sz, "(RADIO):") != nullptr) && !radio_message) { // We found an old radio message, we should convert the strings... radio_message = true; // we found a radio message // Thank god Ditlew you already coded this... - const unsigned length = strlen(sz) - strlen(strstr(sz, " (RADIO)")); - strncpy(radio_messenger, sz, length); + const unsigned length = std::strlen(sz) - std::strlen(std::strstr(sz, " (RADIO)")); + std::strncpy(radio_messenger, sz, length); // Now search for any compatible radio command (old string). // if found then convert the message in the new way so the code // thinks its CS 1.1 and thus every version lower then CS 1.1 should work too... - if ((strstr(sz, "Follow Me") != nullptr)) { + if ((std::strstr(sz, "Follow Me") != nullptr)) { // convert string - strcpy(message, "#Follow me"); - } else if ((strstr(sz, "You Take the Point") != nullptr)) { + std::strcpy(message, "#Follow me"); + } else if ((std::strstr(sz, "You Take the Point") != nullptr)) { // convert string - strcpy(message, "#You_take_the_point"); - } else if ((strstr(sz, "Need backup") != nullptr)) { + std::strcpy(message, "#You_take_the_point"); + } else if ((std::strstr(sz, "Need backup") != nullptr)) { // convert string - strcpy(message, "#Need_backup"); - } else if ((strstr(sz, "Taking Fire.. Need Assistance!") != nullptr)) { + std::strcpy(message, "#Need_backup"); + } else if ((std::strstr(sz, "Taking Fire.. Need Assistance!") != nullptr)) { // convert string - strcpy(message, "#Taking_fire"); - } else if ((strstr(sz, "Team, fall back!") != nullptr)) { + std::strcpy(message, "#Taking_fire"); + } else if ((std::strstr(sz, "Team, fall back!") != nullptr)) { // convert string - strcpy(message, "#Team_fall_back"); - } else if ((strstr(sz, "Go go go") != nullptr)) { + std::strcpy(message, "#Team_fall_back"); + } else if ((std::strstr(sz, "Go go go") != nullptr)) { // convert string - strcpy(message, "#Go_go_go"); + std::strcpy(message, "#Go_go_go"); } } @@ -497,14 +497,14 @@ void pfnWriteString(const char *sz) { } */ if (radio_message_start) { - strcpy(radio_messenger, sz); // the messenger of the radio + std::strcpy(radio_messenger, sz); // the messenger of the radio radio_message_start = false; radio_message_from = true; } else if (radio_message_from) { - strcpy(message, sz); // copy message and handle at bot.cpp radio routine. + std::strcpy(message, sz); // copy message and handle at bot.cpp radio routine. radio_message = true; radio_message_from = false; - } else if (strcmp(sz, "#Game_radio") == 0) { + } else if (std::strcmp(sz, "#Game_radio") == 0) { radio_message_start = true; } @@ -628,6 +628,6 @@ GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, meta_engfuncs.pfnCmd_Argc = pfnCmd_Argc; meta_engfuncs.pfnSetClientMaxspeed = pfnSetClientMaxspeed; meta_engfuncs.pfnGetPlayerUserId = pfnGetPlayerUserId; - memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t)); + std::memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t)); return TRUE; } diff --git a/game.cpp b/game.cpp index 0a6be08..22488a7 100644 --- a/game.cpp +++ b/game.cpp @@ -93,22 +93,22 @@ void cGame::Init() { bPistols = false; // pistols only mode // Speech sentences (from POD and a *few* own made) - strcpy(cSpeechSentences[0], "hello user,communication is acquired"); - strcpy(cSpeechSentences[1], "your presence is acknowledged"); - strcpy(cSpeechSentences[2], "high man, your in command now"); - strcpy(cSpeechSentences[3], "blast your hostile for good"); - strcpy(cSpeechSentences[4], "high man, kill some idiot here"); - strcpy(cSpeechSentences[5], "is there a doctor in the area"); - strcpy(cSpeechSentences[6], "warning, experimental materials detected"); - strcpy(cSpeechSentences[7], "high amigo, shoot some but"); - strcpy(cSpeechSentences[8], "attention, hours of work software, detected"); - strcpy(cSpeechSentences[9], "time for some bad ass explosion"); - strcpy(cSpeechSentences[10], "bad ass son of a breach device activated"); - strcpy(cSpeechSentences[11], "high, do not question this great service"); - strcpy(cSpeechSentences[12], "engine is operative, hello and goodbye"); - strcpy(cSpeechSentences[13], "high amigo, your administration has been great last day"); - strcpy(cSpeechSentences[14], "attention, expect experimental armed hostile presence"); - strcpy(cSpeechSentences[15], "warning,medical attention required"); + std::strcpy(cSpeechSentences[0], "hello user,communication is acquired"); + std::strcpy(cSpeechSentences[1], "your presence is acknowledged"); + std::strcpy(cSpeechSentences[2], "high man, your in command now"); + std::strcpy(cSpeechSentences[3], "blast your hostile for good"); + std::strcpy(cSpeechSentences[4], "high man, kill some idiot here"); + std::strcpy(cSpeechSentences[5], "is there a doctor in the area"); + std::strcpy(cSpeechSentences[6], "warning, experimental materials detected"); + std::strcpy(cSpeechSentences[7], "high amigo, shoot some but"); + std::strcpy(cSpeechSentences[8], "attention, hours of work software, detected"); + std::strcpy(cSpeechSentences[9], "time for some bad ass explosion"); + std::strcpy(cSpeechSentences[10], "bad ass son of a breach device activated"); + std::strcpy(cSpeechSentences[11], "high, do not question this great service"); + std::strcpy(cSpeechSentences[12], "engine is operative, hello and goodbye"); + std::strcpy(cSpeechSentences[13], "high amigo, your administration has been great last day"); + std::strcpy(cSpeechSentences[14], "attention, expect experimental armed hostile presence"); + std::strcpy(cSpeechSentences[15], "warning,medical attention required"); InitNewRound(); } // Init() @@ -171,8 +171,8 @@ void cGame::DetermineMapGoal() const } char msg[255]; - memset(msg, 0, sizeof(msg)); - sprintf(msg, "DetermineMapGoal: There are %d hostages found to rescue\n", hostagesFound); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "DetermineMapGoal: There are %d hostages found to rescue\n", hostagesFound); rblog(msg); Game.bHostageRescueMap = hostagesFound > 0; @@ -187,8 +187,8 @@ void cGame::DetermineMapGoal() const rescueZonesFound++; } - memset(msg, 0, sizeof(msg)); - sprintf(msg, "DetermineMapGoal: There are %d rescue zones found\n", rescueZonesFound); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "DetermineMapGoal: There are %d rescue zones found\n", rescueZonesFound); rblog(msg); Game.bHostageRescueZoneFound = rescueZonesFound > 0; @@ -203,8 +203,8 @@ void cGame::DetermineMapGoal() const while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_bomb_target")) != nullptr) { bombSpots++; } - memset(msg, 0, sizeof(msg)); - sprintf(msg, "DetermineMapGoal: There are %d bomb spots in this level\n", bombSpots); + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "DetermineMapGoal: There are %d bomb spots in this level\n", bombSpots); Game.bBombPlantMap = bombSpots > 0; rblog(msg); } @@ -295,7 +295,7 @@ void cGame::LoadNames() { char name_buffer[80]; while ((iAmountNames < MAX_BOT_NAMES) && (fgets(name_buffer, 80, bot_name_fp) != nullptr)) { - int length = static_cast(strlen(name_buffer)); + int length = static_cast(std::strlen(name_buffer)); if (name_buffer[length - 1] == '\n') { name_buffer[length - 1] = 0; // remove '\n' length--; @@ -311,7 +311,7 @@ void cGame::LoadNames() { } if (name_buffer[0] != 0) { - strncpy(cBotNames[iAmountNames], name_buffer, BOT_NAME_LEN); + std::strncpy(cBotNames[iAmountNames], name_buffer, BOT_NAME_LEN); iAmountNames++; } } @@ -360,7 +360,7 @@ void cGame::SelectName(char *name) const // when we are back to where we came from, get the fuck outta here if (iNameIndex == iLimit) { - strcpy(name, "RealBot"); + std::strcpy(name, "RealBot"); return; } } @@ -372,7 +372,7 @@ void cGame::SelectName(char *name) const for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { const edict_t* pPlayer = INDEXENT(iIndex); if (pPlayer && !pPlayer->free) { - if (strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) + if (std::strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) == 0) { // atten tion, this namehas been used. bUsed = true; @@ -387,7 +387,7 @@ void cGame::SelectName(char *name) const } // copy name into the name_buffer - strcpy(name, cBotNames[iNameIndex]); + std::strcpy(name, cBotNames[iNameIndex]); } // SelectName() // GAME: Load BUYTABLE.INI file @@ -478,21 +478,21 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // NAME char botName[BOT_NAME_LEN + 1]; - memset(botName, 0, sizeof(botName)); + std::memset(botName, 0, sizeof(botName)); // if name given, use that if ((nameArg != nullptr) && (*nameArg != 0)) { - strncpy(botName, nameArg, BOT_NAME_LEN - 1); + std::strncpy(botName, nameArg, BOT_NAME_LEN - 1); botName[BOT_NAME_LEN] = 0; // make sure botName is null terminated } else { // else pick random one or fallback to default "RealBot" if (NamesAvailable()) { SelectName(botName); } else { - strcpy(botName, "RealBot"); + std::strcpy(botName, "RealBot"); } } // length of name - int lengthOfBotName = static_cast(strlen(botName)); + int lengthOfBotName = static_cast(std::strlen(botName)); for (int i = 0; i < lengthOfBotName; i++) { if ((botName[i] <= ' ') || (botName[i] > '~') || (botName[i] == '"')) { @@ -508,7 +508,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // Skill argument provided if ((skillArg != nullptr) && (*skillArg != 0)) { - botSkill = atoi(skillArg); // set to given skill + botSkill = std::atoi(skillArg); // set to given skill } // when not valid (-2), it has default skill @@ -593,8 +593,8 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // clear char c_skin[BOT_SKIN_LEN + 1]; - memset(c_skin, 0, sizeof(c_skin)); - strcpy(pBot->skin, c_skin); + std::memset(c_skin, 0, sizeof(c_skin)); + std::strcpy(pBot->skin, c_skin); pBot->pEdict = pBotEdict; pBot->hasJoinedTeam = false; // hasn't joined game yet @@ -638,11 +638,11 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // here we set team if ((teamArg != nullptr) && (teamArg[0] != 0)) { - pBot->iTeam = atoi(teamArg); + pBot->iTeam = std::atoi(teamArg); // and class if ((modelArg != nullptr) && (modelArg[0] != 0)) { - pBot->bot_class = atoi(modelArg); + pBot->bot_class = std::atoi(modelArg); } } @@ -669,28 +669,28 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { char mapName[32]; int botIndex = -1; - memset(team, 0, sizeof(team)); // clear - memset(name, 0, sizeof(name)); // clear - memset(mapName, 0, sizeof(mapName)); // clear + std::memset(team, 0, sizeof(team)); // clear + std::memset(name, 0, sizeof(name)); // clear + std::memset(mapName, 0, sizeof(mapName)); // clear - strcpy(team, "NONE"); - strcpy(name, "FUNCTION"); + std::strcpy(team, "NONE"); + std::strcpy(name, "FUNCTION"); if (gpGlobals->mapname) { - strcpy(mapName, STRING(gpGlobals->mapname)); + std::strcpy(mapName, STRING(gpGlobals->mapname)); } else { - strcpy(mapName, "NA"); + std::strcpy(mapName, "NA"); } if (pBot) { botIndex = pBot->iBotIndex; - memset(name, 0, sizeof(name)); // clear - strcpy(name, pBot->name); // copy name + std::memset(name, 0, sizeof(name)); // clear + std::strcpy(name, pBot->name); // copy name if (pBot->isCounterTerrorist()) { - strcpy(team, "COUNTER"); + std::strcpy(team, "COUNTER"); } else if (pBot->isTerrorist()) { - strcpy(team, "TERROR"); + std::strcpy(team, "TERROR"); } } @@ -705,7 +705,7 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { const int minutesLeft = static_cast(roundTimeRemaining) / 60; const int secondsLeft = static_cast(roundTimeRemaining) % 60; - sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); + std::sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); // print in console only when on debug print if (Game.bDebug > -2) { diff --git a/util.cpp b/util.cpp index 93e74e4..ae443d2 100644 --- a/util.cpp +++ b/util.cpp @@ -211,16 +211,16 @@ void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { // turn on color set 2 (color on, no sound) if (teamonly) - sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); + std::sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); else - sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); + std::sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); - const int j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator - if (static_cast(strlen(message)) > j) + const int j = sizeof(text) - 2 - std::strlen(text); // -2 for /n and null terminator + if (static_cast(std::strlen(message)) > j) message[j] = 0; - strcat(text, message); - strcat(text, "\n"); + std::strcat(text, message); + std::strcat(text, "\n"); // loop through all players // Start with the first player. @@ -286,9 +286,9 @@ bool UTIL_IsVip(edict_t* pEntity) { char model_name[32]; char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + std::strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - if (strcmp(model_name, "vip") == 0) // VIP + if (std::strcmp(model_name, "vip") == 0) // VIP return true; } @@ -301,25 +301,25 @@ int UTIL_GetTeam(edict_t* pEntity) { char model_name[32]; char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, + std::strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - if ((strcmp(model_name, "terror") == 0) || // Phoenix Connektion - (strcmp(model_name, "arab") == 0) || // old L337 Krew - (strcmp(model_name, "leet") == 0) || // L337 Krew - (strcmp(model_name, "artic") == 0) || // Artic Avenger - (strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? - (strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare + if ((std::strcmp(model_name, "terror") == 0) || // Phoenix Connektion + (std::strcmp(model_name, "arab") == 0) || // old L337 Krew + (std::strcmp(model_name, "leet") == 0) || // L337 Krew + (std::strcmp(model_name, "artic") == 0) || // Artic Avenger + (std::strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? + (std::strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare //(strcmp(model_name, "militia") == 0)) // CZ Militia { return 0; // team Terrorists } - else if ((strcmp(model_name, "urban") == 0) || // Seal Team 6 - (strcmp(model_name, "gsg9") == 0) || // German GSG-9 - (strcmp(model_name, "sas") == 0) || // UK SAS - (strcmp(model_name, "gign") == 0) || // French GIGN - (strcmp(model_name, "vip") == 0) || // VIP - (strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz + else if ((std::strcmp(model_name, "urban") == 0) || // Seal Team 6 + (std::strcmp(model_name, "gsg9") == 0) || // German GSG-9 + (std::strcmp(model_name, "sas") == 0) || // UK SAS + (std::strcmp(model_name, "gign") == 0) || // French GIGN + (std::strcmp(model_name, "vip") == 0) || // VIP + (std::strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz { return 1; // team Counter-Terrorists } @@ -335,7 +335,7 @@ int UTIL_GetClass(edict_t* pEntity) { char model_name[32]; char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + std::strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); return 0; } @@ -449,10 +449,10 @@ UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { if (mod_id == VALVE_DLL) - strcpy(filename, "valve/"); + std::strcpy(filename, "valve/"); else if (mod_id == CSTRIKE_DLL) - strcpy(filename, "cstrike/"); + std::strcpy(filename, "cstrike/"); else { filename[0] = 0; @@ -460,12 +460,12 @@ void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { } if ((arg1) && (*arg1) && (arg2) && (*arg2)) { - strcat(filename, arg1); - strcat(filename, "/"); - strcat(filename, arg2); + std::strcat(filename, arg1); + std::strcat(filename, "/"); + std::strcat(filename, arg2); } else if ((arg1) && (*arg1)) { - strcat(filename, arg1); + std::strcat(filename, arg1); } } @@ -481,8 +481,8 @@ void UTIL_BuildFileNameRB(char* subdir, char* filename) { #define S '/' #endif - strcpy(filename, "realbot/"); - strcat(filename, subdir); + std::strcpy(filename, "realbot/"); + std::strcat(filename, subdir); while (*filename) { if ((*filename == '/') || (*filename == '\\')) *filename = S; @@ -569,7 +569,7 @@ void UTIL_BotPressKey(cBot* pBot, int type) { break; default: char msg[255]; - sprintf(msg, "unknown key to print [%d]", type); + std::sprintf(msg, "unknown key to print [%d]", type); pBot->rprint_trace("UTIL_BotPressKey", msg); break; } @@ -622,65 +622,65 @@ int UTIL_GiveWeaponType(int weapon_id) { // Return weapon ID (depended on mod) int UTIL_GiveWeaponId(const char* name) { if (mod_id == CSTRIKE_DLL) { - if (strcmp(name, "weapon_knife") == 0) + if (std::strcmp(name, "weapon_knife") == 0) return CS_WEAPON_KNIFE; - if (strcmp(name, "weapon_c4") == 0) + if (std::strcmp(name, "weapon_c4") == 0) return CS_WEAPON_C4; - if (strcmp(name, "weapon_mp5navy") == 0) + if (std::strcmp(name, "weapon_mp5navy") == 0) return CS_WEAPON_MP5NAVY; - if (strcmp(name, "weapon_ak47") == 0) + if (std::strcmp(name, "weapon_ak47") == 0) return CS_WEAPON_AK47; - if (strcmp(name, "weapon_m3") == 0) + if (std::strcmp(name, "weapon_m3") == 0) return CS_WEAPON_M3; - if (strcmp(name, "weapon_aug") == 0) + if (std::strcmp(name, "weapon_aug") == 0) return CS_WEAPON_AUG; - if (strcmp(name, "weapon_sg552") == 0) + if (std::strcmp(name, "weapon_sg552") == 0) return CS_WEAPON_SG552; - if (strcmp(name, "weapon_m249") == 0) + if (std::strcmp(name, "weapon_m249") == 0) return CS_WEAPON_M249; - if (strcmp(name, "weapon_xm1014") == 0) + if (std::strcmp(name, "weapon_xm1014") == 0) return CS_WEAPON_XM1014; - if (strcmp(name, "weapon_p90") == 0) + if (std::strcmp(name, "weapon_p90") == 0) return CS_WEAPON_P90; - if (strcmp(name, "weapon_tmp") == 0) + if (std::strcmp(name, "weapon_tmp") == 0) return CS_WEAPON_TMP; - if (strcmp(name, "weapon_m4a1") == 0) + if (std::strcmp(name, "weapon_m4a1") == 0) return CS_WEAPON_M4A1; - if (strcmp(name, "weapon_awp") == 0) + if (std::strcmp(name, "weapon_awp") == 0) return CS_WEAPON_AWP; - if (strcmp(name, "weapon_fiveseven") == 0) + if (std::strcmp(name, "weapon_fiveseven") == 0) return CS_WEAPON_FIVESEVEN; - if (strcmp(name, "weapon_ump45") == 0) + if (std::strcmp(name, "weapon_ump45") == 0) return CS_WEAPON_UMP45; - if (strcmp(name, "weapon_sg550") == 0) + if (std::strcmp(name, "weapon_sg550") == 0) return CS_WEAPON_SG550; - if (strcmp(name, "weapon_scout") == 0) + if (std::strcmp(name, "weapon_scout") == 0) return CS_WEAPON_SCOUT; - if (strcmp(name, "weapon_mac10") == 0) + if (std::strcmp(name, "weapon_mac10") == 0) return CS_WEAPON_MAC10; - if (strcmp(name, "weapon_g3sg1") == 0) + if (std::strcmp(name, "weapon_g3sg1") == 0) return CS_WEAPON_G3SG1; - if (strcmp(name, "weapon_elite") == 0) + if (std::strcmp(name, "weapon_elite") == 0) return CS_WEAPON_ELITE; - if (strcmp(name, "weapon_p228") == 0) + if (std::strcmp(name, "weapon_p228") == 0) return CS_WEAPON_P228; - if (strcmp(name, "weapon_deagle") == 0) + if (std::strcmp(name, "weapon_deagle") == 0) return CS_WEAPON_DEAGLE; - if (strcmp(name, "weapon_usp") == 0) + if (std::strcmp(name, "weapon_usp") == 0) return CS_WEAPON_USP; - if (strcmp(name, "weapon_glock18") == 0) + if (std::strcmp(name, "weapon_glock18") == 0) return CS_WEAPON_GLOCK18; // Counter-Strike 1.6 - if (strcmp(name, "weapon_famas") == 0) + if (std::strcmp(name, "weapon_famas") == 0) return CS_WEAPON_FAMAS; - if (strcmp(name, "weapon_galil") == 0) + if (std::strcmp(name, "weapon_galil") == 0) return CS_WEAPON_GALIL; // TODO: Detect shield carrying. // 06/07/04 // Unconfirmed for handling shield // 31.08.04 Frashman: moved shield string before unknown weapon, not after it - if (name != nullptr && strcmp(name, "weapon_shield") == 0) + if (name != nullptr && std::strcmp(name, "weapon_shield") == 0) return CS_WEAPON_SHIELD; char buffer[80]; @@ -829,18 +829,18 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { if (pBot->console_nr == 0) { switch (radio) { case 1: - strcpy(pBot->arg1, "radio1"); + std::strcpy(pBot->arg1, "radio1"); break; case 2: - strcpy(pBot->arg1, "radio2"); + std::strcpy(pBot->arg1, "radio2"); break; case 3: - strcpy(pBot->arg1, "radio3"); + std::strcpy(pBot->arg1, "radio3"); break; } - strcpy(pBot->arg2, arg1); - strcpy(pBot->arg3, arg2); + std::strcpy(pBot->arg2, arg1); + std::strcpy(pBot->arg3, arg2); pBot->console_nr = 1; // Begin message // 02/07/04 - pointed out, eliminate any possible 'devide by zero' @@ -858,18 +858,18 @@ int UTIL_GetGrenadeType(edict_t* pEntity) { const int length = 32; char model_name[length]; - memset(model_name, 0, sizeof(model_name)); + std::memset(model_name, 0, sizeof(model_name)); - strncpy(model_name, STRING(pEntity->v.model), length - 1); + std::strncpy(model_name, STRING(pEntity->v.model), length - 1); model_name[length - 1] = 0; // Make sure it is NULL terminated - if (strcmp(model_name, "models/w_hegrenade.mdl") == 0) return 1; // He grenade - if (strcmp(model_name, "models/w_flashbang.mdl") == 0) return 2; // FlashBang - if (strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade - if (strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive + if (std::strcmp(model_name, "models/w_hegrenade.mdl") == 0) return 1; // He grenade + if (std::strcmp(model_name, "models/w_flashbang.mdl") == 0) return 2; // FlashBang + if (std::strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade + if (std::strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive char msg[512]; - memset(msg, 0, sizeof(msg)); + std::memset(msg, 0, sizeof(msg)); // when an empty string, let us know we missed something if (model_name[0] == '\0') { @@ -951,8 +951,8 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { int i; // clear out - memset(szTemp, 0, sizeof(szTemp)); - memset(szName, 0, sizeof(szName)); + std::memset(szTemp, 0, sizeof(szTemp)); + std::memset(szName, 0, sizeof(szName)); // init szTemp[0] = 2; @@ -960,7 +960,7 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { const int entind = ENTINDEX(pBot->pEdict); if (IsAlive(pBot->pEdict)) { - strcpy(szName, pBot->name); + std::strcpy(szName, pBot->name); for (i = 1; i <= gpGlobals->maxClients; i++) { edict_t* pPlayer = INDEXENT(i); @@ -970,21 +970,21 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { { MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); - sprintf(&szTemp[1], "%s : %s", szName, pText); + std::sprintf(&szTemp[1], "%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } } } else { - strcpy(szName, pBot->name); + std::strcpy(szName, pBot->name); for (i = 1; i <= gpGlobals->maxClients; i++) { edict_t* pPlayer = INDEXENT(i); if (pPlayer) if (!IsAlive(pPlayer)) { MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); - sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); + std::sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } @@ -995,10 +995,10 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { // pass through on ChatEngine (not always) if (RANDOM_LONG(0, 100) < 90) { char chSentence[80]; - memset(chSentence, 0, sizeof(chSentence)); + std::memset(chSentence, 0, sizeof(chSentence)); // copy pText to chSentence - strcpy(chSentence, pText); + std::strcpy(chSentence, pText); // pass through ChatEngine.set_sentence(pBot->name, chSentence); @@ -1012,7 +1012,7 @@ void UTIL_SpeechSynth(edict_t* pEdict, char* szMessage) { char szSpeak[128]; - sprintf(szSpeak, "speak \"%s\"\n", szMessage); + std::sprintf(szSpeak, "speak \"%s\"\n", szMessage); CLIENT_COMMAND(pEdict, szSpeak); } From 8ef8a58edccfae55bc87491df1ddb9be40433bcc Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 29 Dec 2023 20:55:30 +0000 Subject: [PATCH 082/114] Converting doubles into floats --- IniParser.cpp | 8 ++++---- NodeMachine.cpp | 2 +- bot.cpp | 6 +++--- dll.cpp | 2 +- game.cpp | 4 ++-- util.cpp | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/IniParser.cpp b/IniParser.cpp index 1031dc0..19738b7 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -934,8 +934,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); // Reaction Time delay added for realistic gameplay [APG]RoboCop[CL] fMinReact = - RANDOM_FLOAT(pBot->bot_skill / 20 + 0.3f, - (pBot->bot_skill / 5) + 0.3f); + RANDOM_FLOAT(pBot->bot_skill / 20.0f + 0.3f, + (pBot->bot_skill / 5.0f) + 0.3f); const float fMaxReact = fMinReact + RANDOM_FLOAT(0.2f, 0.4f); @@ -946,8 +946,8 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { // Set Offsets (note, they are extra upon current aiming code) // 30.8.04 redefined by frashman // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); - const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5) + 0.05f, - (pBot->bot_skill / 2) + 0.05f); + const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5.0f) + 0.05f, + (pBot->bot_skill / 2.0f) + 0.05f); // SET pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index c4e209f..d74e84b 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2773,7 +2773,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (pBot->isOnLadder()) { pBot->rprint("Bot is on ladder"); // Set touch radius - pBot->f_strafe_speed = 0.0; // we may not strafe + pBot->f_strafe_speed = 0.0f; // we may not strafe pBot->setMoveSpeed(pBot->f_max_speed / 2); //pBot->pEdict->v.button |= IN_DUCK; // duck diff --git a/bot.cpp b/bot.cpp index 29e6015..1ca2117 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1977,7 +1977,7 @@ void cBot::Act() { } if (f_strafe_time < gpGlobals->time) { - f_strafe_speed = 0; + f_strafe_speed = 0.0f; } // walk only when NOT holding duck (is same as walking, combination makes bot super slow) @@ -1987,7 +1987,7 @@ void cBot::Act() { pEdict->v.button &= (~IN_RUN); // release IN_RUN rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed((f_max_speed) / 2 + (f_max_speed) / 50); + setMoveSpeed((f_max_speed) / 2.0f + (f_max_speed) / 50.0f); } // When we are at max speed, press IN_RUN to get a running animation @@ -3272,7 +3272,7 @@ void cBot::Think() { if (chChatSentence[0] == '\0') // we did not want to say anything if (RANDOM_LONG(0, 100) < ipChatRate) // rate fChatTime = gpGlobals->time + - RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + static_cast(1)) / 2)); // wait + RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + 1.0f) / 2.0f)); // wait } diff --git a/dll.cpp b/dll.cpp index d36d35e..e14ecb1 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1295,7 +1295,7 @@ void RealBot_ServerCommand() { "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { if ((arg1 != nullptr) && (*arg1 != 0)) { - const float fVar = atof(arg1); + const float fVar = std::atof(arg1); // Only set when valid if (fVar < 0) diff --git a/game.cpp b/game.cpp index 22488a7..3801e45 100644 --- a/game.cpp +++ b/game.cpp @@ -79,7 +79,7 @@ void cGame::Init() { vDroppedC4 = Vector(9999, 9999, 9999); // May we walk with knife (when bots want to), default = yes (3600 seconds) - fWalkWithKnife = 3600; + fWalkWithKnife = 3600.0f; // Chat related iMaxSentences = 1; // max sentences produced by chatengine per second (1=default) @@ -134,7 +134,7 @@ void cGame::InitNewRound() { } iProducedSentences = RANDOM_LONG(0, Game.iMaxSentences); - ChatEngine.fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0, 0.5); + ChatEngine.fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); } /** diff --git a/util.cpp b/util.cpp index ae443d2..61ec5c3 100644 --- a/util.cpp +++ b/util.cpp @@ -371,7 +371,7 @@ bool IsAlive(edict_t* pEdict) { (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD (pEdict->v.health > 0) && // ENOUGHT HEALTH !(pEdict->v.flags & FL_NOTARGET) && // ? - (pEdict->v.takedamage != 0)); // CAN TAKE DAMAGE + (pEdict->v.takedamage != 0.0f)); // CAN TAKE DAMAGE } bool FInViewCone(Vector* pOrigin, edict_t* pEdict) { From 48c1f538a033e6f31e2c9460938acc9ad2eb0b2e Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 19 Feb 2024 02:39:25 +0000 Subject: [PATCH 083/114] Version 4.0.5-beta4 released Minor refactoring for modernisation and less redundant coding --- ChatEngine.cpp | 15 +- IniParser.cpp | 1952 +++-- NodeDataTypes.h | 75 +- NodeMachine.cpp | 543 +- NodeMachine.h | 30 +- bot.cpp | 9102 +++++++++++----------- bot_buycode.cpp | 29 +- bot_client.cpp | 30 +- bot_func.cpp | 175 +- bot_navigate.cpp | 18 +- bot_weapons.h | 4 +- build.cpp | 2 +- dependencies/hlsdk/dlls/util.h | 2 +- dependencies/metamod-hl1/metamod/osdep.h | 2 +- dll.cpp | 244 +- engine.cpp | 57 +- game.cpp | 31 +- realbot_mm.vcxproj | 1 + todo.txt | 1 + util.cpp | 184 +- 20 files changed, 6233 insertions(+), 6264 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 25c481f..6e75f23 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -100,7 +100,7 @@ void cChatEngine::think() { for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); - if (pPlayer && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { char name[30], name2[30]; // clear std::memset(name, 0, sizeof(name)); @@ -130,7 +130,7 @@ void cChatEngine::think() { // When length is not valid, get out. // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? // how did we allow for this to happen? - if (sentenceLength == 0 || sentenceLength >= (MAX_SENTENCE_LENGTH-1)) { + if (sentenceLength == 0 || sentenceLength >= MAX_SENTENCE_LENGTH-1) { // clear out sentence and sender std::memset(sentence, 0, sizeof(sentence)); std::memset(sender, 0, sizeof(sender)); @@ -163,7 +163,7 @@ void cChatEngine::think() { if (sentence[c] == ' ' || sentence[c] == '\n' || sentence[c] == '.' || sentence[c] == '?' || sentence[c] == '!' || c == sentenceLength) { - // Now find the word and add up scors on the proper score blocks. + // Now find the word and add up scores on the proper score blocks. if (c == sentenceLength) word[wc] = sentence[c]; @@ -242,7 +242,7 @@ void cChatEngine::think() { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && pSender != pPlayer) { + if (pPlayer && !pPlayer->free && pSender != pPlayer) { const bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here const bool bPlayerAlive = IsAlive(pPlayer); @@ -253,7 +253,7 @@ void cChatEngine::think() { if (pBotPointer != nullptr) if (RANDOM_LONG(0, 100) < - (pBotPointer->ipChatRate + 25)) { + pBotPointer->ipChatRate + 25) { // When we have at least 1 sentence... if (iMax > -1) { // choose randomly a reply @@ -343,9 +343,8 @@ void cChatEngine::think() { } // when no name pos is found, we just copy the string and say that (works ok) else - std::sprintf(chSentence, "%s \n", - ReplyBlock[iTheBlock]. - sentence[the_c]); + snprintf(chSentence, sizeof(chSentence), "%s \n", + ReplyBlock[iTheBlock].sentence[the_c]); // reply: pBotPointer->PrepareChat(chSentence); diff --git a/IniParser.cpp b/IniParser.cpp index 19738b7..b3a6f79 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -6,7 +6,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -18,19 +18,19 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. * **/ -/** - * INI PARSER - * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 - **/ + /** + * INI PARSER + * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 + **/ #include #include @@ -49,1008 +49,988 @@ #include extern int mod_id; -extern edict_t *pHostEdict; +extern edict_t* pHostEdict; extern cNodeMachine NodeMachine; extern int m_spriteTexture; extern cGame Game; extern cChatEngine ChatEngine; - // Reads out INPUT , will check for a [ at [0] and then checks till ], it will fill section[] // with the chars in between. So : [MAP] -> section = 'MAP'. Use function INI_SectionType(..) // to get the correct ID for that. void INI_Section(char input[80], char section[30]) { int end_pos = -1; - // clear out entire string - for (int i = 0; i < 30; i++) - section[i] = '\0'; - - // check if the first character is a '[' - if (input[0] == '[') { - int pos = 1; // Begin at character 1 - - while (pos < 79) { - if (input[pos] == ']') { - end_pos = pos - 1; - break; - } - pos++; - } - - if (end_pos > 1 && end_pos < 29) { - for (int wc = 0; wc < end_pos; wc++) - section[wc] = input[wc + 1]; - - section[end_pos] = '\0'; // terminate string - } - } - + // clear out entire string + for (int i = 0; i < 30; i++) + section[i] = '\0'; + + // check if the first character is a '[' + if (input[0] == '[') { + int pos = 1; // Begin at character 1 + + while (pos < 79) { + if (input[pos] == ']') { + end_pos = pos - 1; + break; + } + pos++; + } + + if (end_pos > 1 && end_pos < 29) { + for (int wc = 0; wc < end_pos; wc++) + section[wc] = input[wc + 1]; + + section[end_pos] = '\0'; // terminate string + } + } } // Reads out INPUT and will check for an '=' Everything at the left of the // '=' IS a word and will be put in 'word[]'. Use function INI_WordType(char word[25]) to get // the correct ID tag. void INI_Word(char input[80], char word[25]) { - int pos = 0; - int word_pos = -1; - - // clear out entire string - for (int i = 0; i < 25; i++) - word[i] = '\0'; - - while (pos < 79) { - if (input[pos] == '=') { - word_pos = pos; - break; - } - pos++; - } - - if (word_pos > -1 && word_pos < 23) { - for (int wc = 0; wc < word_pos; wc++) - word[wc] = input[wc]; - - word[word_pos] = '\0'; // terminate string - } + int pos = 0; + int word_pos = -1; + + // clear out entire string + for (int i = 0; i < 25; i++) + word[i] = '\0'; + + while (pos < 79) { + if (input[pos] == '=') { + word_pos = pos; + break; + } + pos++; + } + + if (word_pos > -1 && word_pos < 23) { + for (int wc = 0; wc < word_pos; wc++) + word[wc] = input[wc]; + + word[word_pos] = '\0'; // terminate string + } } // Reads out word[], does a string compare and returns type id int INI_WordType(char word[25], int section) { - if (word[0] != '\0') { + if (word[0] != '\0') { + if (std::strcmp(word, "Word") == 0) + return WORD_WORD; + if (std::strcmp(word, "Sentence") == 0) + return WORD_SENTENCE; - if (std::strcmp(word, "Word") == 0) - return WORD_WORD; - if (std::strcmp(word, "Sentence") == 0) - return WORD_SENTENCE; + if (std::strcmp(word, "X") == 0) + return WORD_AREAX; + if (std::strcmp(word, "Y") == 0) + return WORD_AREAY; + if (std::strcmp(word, "Z") == 0) + return WORD_AREAZ; + // ------ personality stuff ------ + if (std::strcmp(word, "PrimaryWeapon") == 0) + return WORD_PRIWEAPON; - if (std::strcmp(word, "X") == 0) - return WORD_AREAX; - if (std::strcmp(word, "Y") == 0) - return WORD_AREAY; - if (std::strcmp(word, "Z") == 0) - return WORD_AREAZ; + if (std::strcmp(word, "SecondaryWeapon") == 0) + return WORD_SECWEAPON; - // ------ personality stuff ------ - if (std::strcmp(word, "PrimaryWeapon") == 0) - return WORD_PRIWEAPON; + if (std::strcmp(word, "SaveForWeapon") == 0) + return WORD_SAVEFORWEAP; - if (std::strcmp(word, "SecondaryWeapon") == 0) - return WORD_SECWEAPON; + if (std::strcmp(word, "Grenade") == 0) + return WORD_GRENADE; - if (std::strcmp(word, "SaveForWeapon") == 0) - return WORD_SAVEFORWEAP; + if (std::strcmp(word, "FlashBang") == 0) + return WORD_FLASHBANG; - if (std::strcmp(word, "Grenade") == 0) - return WORD_GRENADE; + if (std::strcmp(word, "SmokeGrenade") == 0) + return WORD_SMOKEGREN; - if (std::strcmp(word, "FlashBang") == 0) - return WORD_FLASHBANG; + if (std::strcmp(word, "DefuseKit") == 0) + return WORD_DEFUSEKIT; - if (std::strcmp(word, "SmokeGrenade") == 0) - return WORD_SMOKEGREN; + if (std::strcmp(word, "Armour") == 0) + return WORD_ARMOUR; - if (std::strcmp(word, "DefuseKit") == 0) - return WORD_DEFUSEKIT; + // ---- skill - if (std::strcmp(word, "Armour") == 0) - return WORD_ARMOUR; + if (std::strcmp(word, "XOffset") == 0) + return WORD_XOFFSET; - // ---- skill + if (std::strcmp(word, "YOffset") == 0) + return WORD_YOFFSET; - if (std::strcmp(word, "XOffset") == 0) - return WORD_XOFFSET; + if (std::strcmp(word, "ZOffset") == 0) + return WORD_ZOFFSET; - if (std::strcmp(word, "YOffset") == 0) - return WORD_YOFFSET; + if (std::strcmp(word, "BotSkill") == 0) + return WORD_BOTSKILL; - if (std::strcmp(word, "ZOffset") == 0) - return WORD_ZOFFSET; + if (std::strcmp(word, "MaxReactionTime") == 0) + return WORD_MAXREACTTIME; - if (std::strcmp(word, "BotSkill") == 0) - return WORD_BOTSKILL; + if (std::strcmp(word, "MinReactionTime") == 0) + return WORD_MINREACTTIME; - if (std::strcmp(word, "MaxReactionTime") == 0) - return WORD_MAXREACTTIME; + if (std::strcmp(word, "Turnspeed") == 0) + return WORD_TURNSPEED; - if (std::strcmp(word, "MinReactionTime") == 0) - return WORD_MINREACTTIME; + // ---- Game + if (std::strcmp(word, "Hostage") == 0) + return WORD_HOSTAGERATE; - if (std::strcmp(word, "Turnspeed") == 0) - return WORD_TURNSPEED; + if (std::strcmp(word, "BompSpot") == 0) + return WORD_BOMBSPOTRATE; - // ---- Game - if (std::strcmp(word, "Hostage") == 0) - return WORD_HOSTAGERATE; + if (std::strcmp(word, "Random") == 0) + return WORD_RANDOMRATE; + if (std::strcmp(word, "DroppedBomb") == 0) + return WORD_DROPPEDBOMB; - if (std::strcmp(word, "BompSpot") == 0) - return WORD_BOMBSPOTRATE; + // ---- Radio + if (std::strcmp(word, "Reply") == 0) + return WORD_REPLYRADIO; - if (std::strcmp(word, "Random") == 0) - return WORD_RANDOMRATE; - if (std::strcmp(word, "DroppedBomb") == 0) - return WORD_DROPPEDBOMB; + if (std::strcmp(word, "Create") == 0) + return WORD_CREATERADIO; - // ---- Radio - if (std::strcmp(word, "Reply") == 0) - return WORD_REPLYRADIO; + // ---- Team + if (std::strcmp(word, "HelpTeammate") == 0) + return WORD_HELPTEAM; - if (std::strcmp(word, "Create") == 0) - return WORD_CREATERADIO; + // ---- person + if (std::strcmp(word, "WalkWithKnife") == 0) + return WORD_WALKKNIFE; + if (std::strcmp(word, "FearRate") == 0) + return WORD_FEARRATE; + if (std::strcmp(word, "HearRate") == 0) + return WORD_HEARRATE; + if (std::strcmp(word, "ChatRate") == 0) + return WORD_CHATRATE; - // ---- Team - if (std::strcmp(word, "HelpTeammate") == 0) - return WORD_HELPTEAM; + if (std::strcmp(word, "CampRate") == 0) + return WORD_CAMPRATE; - // ---- person - if (std::strcmp(word, "WalkWithKnife") == 0) - return WORD_WALKKNIFE; - if (std::strcmp(word, "FearRate") == 0) - return WORD_FEARRATE; - if (std::strcmp(word, "HearRate") == 0) - return WORD_HEARRATE; - if (std::strcmp(word, "ChatRate") == 0) - return WORD_CHATRATE; + // ------ buy table stuff ------- + if (std::strcmp(word, "Price") == 0) + return WORD_PRICE; - if (std::strcmp(word, "CampRate") == 0) - return WORD_CAMPRATE; + if (std::strcmp(word, "Priority") == 0) + return WORD_PRIORITY; - // ------ buy table stuff ------- - if (std::strcmp(word, "Price") == 0) - return WORD_PRICE; + if (std::strcmp(word, "Ammo1Index") == 0) + return WORD_INDEX1; - if (std::strcmp(word, "Priority") == 0) - return WORD_PRIORITY; + if (std::strcmp(word, "Ammo2Index") == 0) + return WORD_INDEX2; - if (std::strcmp(word, "Ammo1Index") == 0) - return WORD_INDEX1; + if (std::strcmp(word, "Ammo1Max") == 0) + return WORD_MAXAMMO1; - if (std::strcmp(word, "Ammo2Index") == 0) - return WORD_INDEX2; + if (std::strcmp(word, "Ammo2Max") == 0) + return WORD_MAXAMMO2; + } - if (std::strcmp(word, "Ammo1Max") == 0) - return WORD_MAXAMMO1; - - if (std::strcmp(word, "Ammo2Max") == 0) - return WORD_MAXAMMO2; - - } - - return WORD_NONE; + return WORD_NONE; } // Reads out an entire sentence and returns it -void INI_Sentence(FILE * f, char result[80]) { - - char ch; - int pos = 0; - - // clear out entire string - for (int i = 0; i < 80; i++) - result[i] = '\0'; - - while ((feof(f) == 0) && ((ch = fgetc(f)) != '\n')) { - result[pos] = ch; - pos++; - - // do not allow strings greater then 80 characters. This check prevents a crash for - // users who do exceed the limit. - if (pos > 79) - break; - - // remove dedicated server garbage - //putchar (ch); - } +void INI_Sentence(FILE* f, char result[80]) { + char ch; + int pos = 0; + + // clear out entire string + for (int i = 0; i < 80; i++) + result[i] = '\0'; + + while (feof(f) == 0 && (ch = fgetc(f)) != '\n') { + result[pos] = ch; + pos++; + + // do not allow strings greater then 80 characters. This check prevents a crash for + // users who do exceed the limit. + if (pos > 79) + break; + + // remove dedicated server garbage + //putchar (ch); + } } // Reads out section[], does a string compare and returns type id int INI_SectionType(char section[30], int last) { + if (std::strcmp(section, "BLOCK") == 0) + return INI_BLOCK; - if (std::strcmp(section, "BLOCK") == 0) - return INI_BLOCK; + if (std::strcmp(section, "DEATH") == 0) + return INI_DEATHS; - if (std::strcmp(section, "DEATH") == 0) - return INI_DEATHS; + if (std::strcmp(section, "WELCOME") == 0) + return INI_WELCOME; - if (std::strcmp(section, "WELCOME") == 0) - return INI_WELCOME; + if (std::strcmp(section, "AREA") == 0) + return INI_AREA; - if (std::strcmp(section, "AREA") == 0) - return INI_AREA; + if (std::strcmp(section, "WEAPON") == 0) + return INI_WEAPON; - if (std::strcmp(section, "WEAPON") == 0) - return INI_WEAPON; + if (std::strcmp(section, "SKILL") == 0) + return INI_SKILL; - if (std::strcmp(section, "SKILL") == 0) - return INI_SKILL; + if (std::strcmp(section, "GAME") == 0) + return INI_GAME; - if (std::strcmp(section, "GAME") == 0) - return INI_GAME; + if (std::strcmp(section, "RADIO") == 0) + return INI_RADIO; - if (std::strcmp(section, "RADIO") == 0) - return INI_RADIO; + if (std::strcmp(section, "TEAM") == 0) + return INI_TEAM; - if (std::strcmp(section, "TEAM") == 0) - return INI_TEAM; + if (std::strcmp(section, "PERSON") == 0) + return INI_PERSON; - if (std::strcmp(section, "PERSON") == 0) - return INI_PERSON; - - // When nothing found; we assume its just a new ID tag for some unit or structure - // Therefor we return the last known SECTION ID so we can assign the proper WORD ID's - return last; + // When nothing found; we assume its just a new ID tag for some unit or structure + // Therefor we return the last known SECTION ID so we can assign the proper WORD ID's + return last; } // Reads out section[], does a string compare and returns type id // BUYTABLE.INI SPECIFIC! int INI_SectionType_BUYTABLE(char section[30], int last) { - - if (std::strcmp(section, "P228") == 0) - return CS_WEAPON_P228; - if (std::strcmp(section, "HEGRENADE") == 0) - return CS_WEAPON_HEGRENADE; - if (std::strcmp(section, "AK47") == 0) - return CS_WEAPON_AK47; - if (std::strcmp(section, "DEAGLE") == 0) - return CS_WEAPON_DEAGLE; - if (std::strcmp(section, "MAC10") == 0) - return CS_WEAPON_MAC10; - if (std::strcmp(section, "AUG") == 0) - return CS_WEAPON_AUG; - if (std::strcmp(section, "SG552") == 0) - return CS_WEAPON_SG552; - if (std::strcmp(section, "ELITE") == 0) - return CS_WEAPON_ELITE; - if (std::strcmp(section, "FIVESEVEN") == 0) - return CS_WEAPON_FIVESEVEN; - if (std::strcmp(section, "UMP45") == 0) - return CS_WEAPON_UMP45; - if (std::strcmp(section, "SG550") == 0) - return CS_WEAPON_SG550; - if (std::strcmp(section, "USP") == 0) - return CS_WEAPON_USP; - if (std::strcmp(section, "GLOCK18") == 0) - return CS_WEAPON_GLOCK18; - if (std::strcmp(section, "AWP") == 0) - return CS_WEAPON_AWP; - if (std::strcmp(section, "MP5") == 0) - return CS_WEAPON_MP5NAVY; - if (std::strcmp(section, "M249") == 0) - return CS_WEAPON_M249; - if (std::strcmp(section, "M3") == 0) - return CS_WEAPON_M3; - if (std::strcmp(section, "M4A1") == 0) - return CS_WEAPON_M4A1; - if (std::strcmp(section, "TMP") == 0) - return CS_WEAPON_TMP; - if (std::strcmp(section, "G3SG1") == 0) - return CS_WEAPON_G3SG1; - if (std::strcmp(section, "SCOUT") == 0) - return CS_WEAPON_SCOUT; - if (std::strcmp(section, "FLASHBANG") == 0) - return CS_WEAPON_FLASHBANG; - if (std::strcmp(section, "C4") == 0) - return CS_WEAPON_C4; - if (std::strcmp(section, "SMOKEGRENADE") == 0) - return CS_WEAPON_SMOKEGRENADE; - if (std::strcmp(section, "XM1014") == 0) - return CS_WEAPON_XM1014; - if (std::strcmp(section, "KNIFE") == 0) - return CS_WEAPON_KNIFE; - if (std::strcmp(section, "P90") == 0) - return CS_WEAPON_P90; - - // Counter-Strike 1.6 - if (std::strcmp(section, "FAMAS") == 0) - return CS_WEAPON_FAMAS; - if (std::strcmp(section, "GALIL") == 0) - return CS_WEAPON_GALIL; - - // Unconfirmed - if (std::strcmp(section, "SHIELD") == 0) - return CS_WEAPON_SHIELD; - - // When nothing found; we assume its just a new ID tag for some unit or structure - // Therefor we return the last known SECTION ID so we can assign the proper WORD ID's - return last; + if (std::strcmp(section, "P228") == 0) + return CS_WEAPON_P228; + if (std::strcmp(section, "HEGRENADE") == 0) + return CS_WEAPON_HEGRENADE; + if (std::strcmp(section, "AK47") == 0) + return CS_WEAPON_AK47; + if (std::strcmp(section, "DEAGLE") == 0) + return CS_WEAPON_DEAGLE; + if (std::strcmp(section, "MAC10") == 0) + return CS_WEAPON_MAC10; + if (std::strcmp(section, "AUG") == 0) + return CS_WEAPON_AUG; + if (std::strcmp(section, "SG552") == 0) + return CS_WEAPON_SG552; + if (std::strcmp(section, "ELITE") == 0) + return CS_WEAPON_ELITE; + if (std::strcmp(section, "FIVESEVEN") == 0) + return CS_WEAPON_FIVESEVEN; + if (std::strcmp(section, "UMP45") == 0) + return CS_WEAPON_UMP45; + if (std::strcmp(section, "SG550") == 0) + return CS_WEAPON_SG550; + if (std::strcmp(section, "USP") == 0) + return CS_WEAPON_USP; + if (std::strcmp(section, "GLOCK18") == 0) + return CS_WEAPON_GLOCK18; + if (std::strcmp(section, "AWP") == 0) + return CS_WEAPON_AWP; + if (std::strcmp(section, "MP5") == 0) + return CS_WEAPON_MP5NAVY; + if (std::strcmp(section, "M249") == 0) + return CS_WEAPON_M249; + if (std::strcmp(section, "M3") == 0) + return CS_WEAPON_M3; + if (std::strcmp(section, "M4A1") == 0) + return CS_WEAPON_M4A1; + if (std::strcmp(section, "TMP") == 0) + return CS_WEAPON_TMP; + if (std::strcmp(section, "G3SG1") == 0) + return CS_WEAPON_G3SG1; + if (std::strcmp(section, "SCOUT") == 0) + return CS_WEAPON_SCOUT; + if (std::strcmp(section, "FLASHBANG") == 0) + return CS_WEAPON_FLASHBANG; + if (std::strcmp(section, "C4") == 0) + return CS_WEAPON_C4; + if (std::strcmp(section, "SMOKEGRENADE") == 0) + return CS_WEAPON_SMOKEGRENADE; + if (std::strcmp(section, "XM1014") == 0) + return CS_WEAPON_XM1014; + if (std::strcmp(section, "KNIFE") == 0) + return CS_WEAPON_KNIFE; + if (std::strcmp(section, "P90") == 0) + return CS_WEAPON_P90; + + // Counter-Strike 1.6 + if (std::strcmp(section, "FAMAS") == 0) + return CS_WEAPON_FAMAS; + if (std::strcmp(section, "GALIL") == 0) + return CS_WEAPON_GALIL; + + if (std::strcmp(section, "SHIELD") == 0) + return CS_WEAPON_SHIELD; + + // When nothing found; we assume its just a new ID tag for some unit or structure + // Therefor we return the last known SECTION ID so we can assign the proper WORD ID's + return last; } // Reads out 'result' and will return the value after the '='. Returns integer. // For CHAR returns see "INI_WordValueCHAR(char result[80]); int INI_WordValueINT(char result[80]) { - int pos = 0; - int is_pos = -1; - - while (pos < 79) { - if (result[pos] == '=') { - is_pos = pos; - break; - } - pos++; - } - - if (is_pos > -1) { - // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty - // space. - int end_pos = -1; - - while (pos < 79) { - if (result[pos] == '\0') { - end_pos = pos; - break; - } - pos++; - } - - // End position found! - if (end_pos > -1) { - // We know the END position. We will use that piece of string to read out a number. - char number[10]; - - // clear out entire string - for (int i = 0; i < 10; i++) - number[i] = '\0'; - - // Copy the part to 'number', Make sure we won't get outside the array of the character. - int cp = is_pos + 1; - int c = 0; - while (cp < end_pos) { - number[c] = result[cp]; - c++; - cp++; - if (c > 9) - break; - } - - /* - char aa[80]; - sprintf(aa, "Original %s, atoi %d\n", number, atoi(number)); - DebugOut(aa); - */ - - return std::atoi(number); - } - // nothing here, so we return NULL at the end - } - - return 0; // No value, return 0 (was NULL) + int pos = 0; + int is_pos = -1; + + while (pos < 79) { + if (result[pos] == '=') { + is_pos = pos; + break; + } + pos++; + } + + if (is_pos > -1) { + // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty + // space. + int end_pos = -1; + + while (pos < 79) { + if (result[pos] == '\0') { + end_pos = pos; + break; + } + pos++; + } + + // End position found! + if (end_pos > -1) { + // We know the END position. We will use that piece of string to read out a number. + char number[10]; + + // clear out entire string + for (int i = 0; i < 10; i++) + number[i] = '\0'; + + // Copy the part to 'number', Make sure we won't get outside the array of the character. + int cp = is_pos + 1; + int c = 0; + while (cp < end_pos) { + number[c] = result[cp]; + c++; + cp++; + if (c > 9) + break; + } + + /* + char aa[80]; + sprintf(aa, "Original %s, atoi %d\n", number, atoi(number)); + DebugOut(aa); + */ + + return std::atoi(number); + } + // nothing here, so we return NULL at the end + } + + return 0; // No value, return 0 (was NULL) } // Reads out 'result' and will return the value after the '='. Returns integer. // For CHAR returns see "INI_WordValueCHAR(char result[80]); float INI_WordValueFLOAT(char result[80]) { - int pos = 0; - int is_pos = -1; - - while (pos < 79) { - if (result[pos] == '=') { - is_pos = pos; - break; - } - pos++; - } - - if (is_pos > -1) { - // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty - // space. - int end_pos = -1; - - while (pos < 79) { - if (result[pos] == '\0') { - end_pos = pos; - break; - } - pos++; - } - - // End position found! - if (end_pos > -1) { - // We know the END position. We will use that piece of string to read out a number. - char number[10]; - - // clear out entire string - for (int i = 0; i < 10; i++) - number[i] = '\0'; - - // Copy the part to 'number', Make sure we won't get outside the array of the character. - int cp = is_pos + 1; - int c = 0; - while (cp < end_pos) { - number[c] = result[cp]; - c++; - cp++; - if (c > 9) - break; - } - return static_cast(std::atof(number)); - } - // nothing here, so we return NULL at the end - } - - return 0.0; // No value, return 0.0 was NULL + int pos = 0; + int is_pos = -1; + + while (pos < 79) { + if (result[pos] == '=') { + is_pos = pos; + break; + } + pos++; + } + + if (is_pos > -1) { + // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty + // space. + int end_pos = -1; + + while (pos < 79) { + if (result[pos] == '\0') { + end_pos = pos; + break; + } + pos++; + } + + // End position found! + if (end_pos > -1) { + // We know the END position. We will use that piece of string to read out a number. + char number[10]; + + // clear out entire string + for (int i = 0; i < 10; i++) + number[i] = '\0'; + + // Copy the part to 'number', Make sure we won't get outside the array of the character. + int cp = is_pos + 1; + int c = 0; + while (cp < end_pos) { + number[c] = result[cp]; + c++; + cp++; + if (c > 9) + break; + } + return static_cast(std::atof(number)); + } + // nothing here, so we return NULL at the end + } + + return 0.0; // No value, return 0.0 was NULL } // Reads out 'result' and will return the value after the '='. Returns nothing but will put // the result in 'value[25]'. Max argument may be 25 characters! void INI_WordValueCHAR(char result[80], char value[80]) { - int pos = 0; - int is_pos = -1; - - // clear out entire string - for (int i = 0; i < 25; i++) - value[i] = '\0'; - - while (pos < 79) { - if (result[pos] == '=') { - is_pos = pos; - break; - } - pos++; - } - - if (is_pos > -1) { - // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty - // space. - int end_pos = -1; - - while (pos < 79) { - if (result[pos] == '\0') { - end_pos = pos; - break; - } - pos++; - } - - // End position found! - if (end_pos > -1) { - // We know the END position. We will use that piece of string to read out a number. - - // Copy the part to 'value', Make sure we won't get outside the array of the character. - int cp = is_pos + 1; - int c = 0; - while (cp < end_pos) { - value[c] = result[cp]; - c++; - cp++; - if (c > 79) - break; - } - } - } + int pos = 0; + int is_pos = -1; + + // clear out entire string + for (int i = 0; i < 25; i++) + value[i] = '\0'; + + while (pos < 79) { + if (result[pos] == '=') { + is_pos = pos; + break; + } + pos++; + } + + if (is_pos > -1) { + // Whenever the IS (=) position is known, we make a number out of 'IS_POS' till the next empty + // space. + int end_pos = -1; + + while (pos < 79) { + if (result[pos] == '\0') { + end_pos = pos; + break; + } + pos++; + } + + // End position found! + if (end_pos > -1) { + // We know the END position. We will use that piece of string to read out a number. + + // Copy the part to 'value', Make sure we won't get outside the array of the character. + int cp = is_pos + 1; + int c = 0; + while (cp < end_pos) { + value[c] = result[cp]; + c++; + cp++; + if (c > 79) + break; + } + } + } } // parses the chat file (loads in blocks) void INI_PARSE_CHATFILE() { - char dirname[256]; - char filename[256]; - - FILE *stream; - int section = INI_NONE; - - - // Set Directory name + file - std::strcpy(dirname, "data/cstrike/chat.ini"); - - // writes whole path into "filename", Linux compatible - UTIL_BuildFileNameRB(dirname, filename); - - // make sure the engine knows... - REALBOT_PRINT(nullptr, "INI_PARSE_CHATFILE", "Loading CHAT.INI\n"); - - int iBlockId = -1; - int iBlockWord = -1; - int iBlockSentence = -1; - - // load it - if ((stream = fopen(filename, "r+t")) != nullptr) { - - // infinite loop baby - while (!feof(stream)) { - char linesection[30]; - char linefeed[80]; - INI_Sentence(stream, linefeed); - - // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary - // character (which is "//", ";" or "#"), or an empty line, then skip it - if (linefeed[0] == ';' || - linefeed[0] == '#' || - (linefeed[0] == '/' && linefeed[1] == '/') || - linefeed[0] == '\n' || linefeed[0] == '\0') - continue; // Skip - - // Every line is checked for a new section. - INI_Section(linefeed, linesection); - - if (linesection[0] != '\0' && std::strlen(linesection) > 1) { - section = INI_SectionType(linesection, section); - - if (section == INI_BLOCK) { - iBlockId++; - if (iBlockId > 97) - iBlockId = 97; - section = INI_NONE; - iBlockWord = -1; - iBlockSentence = -1; - } - - if (section == INI_DEATHS) { - iBlockId = 99; // 99 = death - iBlockWord = -1; - iBlockSentence = -1; - section = INI_NONE; - } - - if (section == INI_WELCOME) { - iBlockId = 98; // 98 = welcome - iBlockWord = -1; - iBlockSentence = -1; - section = INI_NONE; - } - - continue; // next line - } - - if (iBlockId > -1) { - char lineword[25]; - INI_Word(linefeed, lineword); - const int wordtype = INI_WordType(lineword, section); - - // We load in words - if (wordtype == WORD_WORD) { - iBlockWord++; - if (iBlockWord > 9) - iBlockWord = 9; - - // write the word in the block - char chWord[25]; - std::memset(chWord, 0, sizeof(chWord)); - INI_WordValueCHAR(linefeed, chWord); - // lower case - //chWord = _strlwr( _strdup( chWord ) ); + char dirname[256]; + char filename[256]; + + FILE* stream; + int section = INI_NONE; + + // Set Directory name + file + std::strcpy(dirname, "data/cstrike/chat.ini"); + + // writes whole path into "filename", Linux compatible + UTIL_BuildFileNameRB(dirname, filename); + + // make sure the engine knows... + REALBOT_PRINT(nullptr, "INI_PARSE_CHATFILE", "Loading CHAT.INI\n"); + + int iBlockId = -1; + int iBlockWord = -1; + int iBlockSentence = -1; + + // load it + if ((stream = std::fopen(filename, "r+t")) != nullptr) { + // infinite loop baby + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); + + // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary + // character (which is "//", ";" or "#"), or an empty line, then skip it + if (linefeed[0] == ';' || + linefeed[0] == '#' || + (linefeed[0] == '/' && linefeed[1] == '/') || + linefeed[0] == '\n' || linefeed[0] == '\0') + continue; // Skip + + // Every line is checked for a new section. + INI_Section(linefeed, linesection); + + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { + section = INI_SectionType(linesection, section); + + if (section == INI_BLOCK) { + iBlockId++; + if (iBlockId > 97) + iBlockId = 97; + section = INI_NONE; + iBlockWord = -1; + iBlockSentence = -1; + } + + if (section == INI_DEATHS) { + iBlockId = 99; // 99 = death + iBlockWord = -1; + iBlockSentence = -1; + section = INI_NONE; + } + + if (section == INI_WELCOME) { + iBlockId = 98; // 98 = welcome + iBlockWord = -1; + iBlockSentence = -1; + section = INI_NONE; + } + + continue; // next line + } + + if (iBlockId > -1) { + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); + + // We load in words + if (wordtype == WORD_WORD) { + iBlockWord++; + if (iBlockWord > 9) + iBlockWord = 9; + + // write the word in the block + char chWord[25]; + std::memset(chWord, 0, sizeof(chWord)); + INI_WordValueCHAR(linefeed, chWord); + // lower case + //chWord = _strlwr( _strdup( chWord ) ); #ifdef _WIN32 - _strupr(chWord); - // #elseif did not work for MSVC + _strupr(chWord); + // #elseif did not work for MSVC #else - //for linux by ok: - // transform removed by evyncke since it works only on strings and not char array - //further changed back by evyncke as these are normal string not CString - //Hence, hardcoding the strupr inline... - char *pString; - pString = chWord; - while (*pString) { - *pString = toupper(*pString); - pString++; - } + //for linux by ok: + // transform removed by evyncke since it works only on strings and not char array + //further changed back by evyncke as these are normal string not CString + //Hence, hardcoding the strupr inline... + char* pString; + pString = chWord; + while (*pString) { + *pString = toupper(*pString); + pString++; + } #endif - std::strcpy(ChatEngine.ReplyBlock[iBlockId].word[iBlockWord], - chWord); - } - - if (wordtype == WORD_SENTENCE) { - iBlockSentence++; - if (iBlockSentence > 49) - iBlockSentence = 49; - - // write the word in the block - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); - INI_WordValueCHAR(linefeed, chSentence); - std::strcpy(ChatEngine.ReplyBlock[iBlockId]. - sentence[iBlockSentence], chSentence); - - // here we say it is used - ChatEngine.ReplyBlock[iBlockId].bUsed = true; - } - } - - } // while - - fclose(stream); - } + std::strcpy(ChatEngine.ReplyBlock[iBlockId].word[iBlockWord], + chWord); + } + + if (wordtype == WORD_SENTENCE) { + iBlockSentence++; + if (iBlockSentence > 49) + iBlockSentence = 49; + + // write the word in the block + char chSentence[80]; + std::memset(chSentence, 0, sizeof(chSentence)); + INI_WordValueCHAR(linefeed, chSentence); + std::strcpy(ChatEngine.ReplyBlock[iBlockId]. + sentence[iBlockSentence], chSentence); + + // here we say it is used + ChatEngine.ReplyBlock[iBlockId].bUsed = true; + } + } + } // while + + std::fclose(stream); + } } // Parse IAD file: // Important Area Definition file void INI_PARSE_IAD() { - char dirname[256]; - char filename[256]; - - FILE *stream; - int section = INI_NONE; - - // Set Directory name - std::strcpy(dirname, "data/cstrike/ini/"); - - std::strcat(dirname, STRING(gpGlobals->mapname)); - std::strcat(dirname, ".ini"); // nodes file - - // writes whole path into "filename", Linux compatible - UTIL_BuildFileNameRB(dirname, filename); - - SERVER_PRINT(filename); - SERVER_PRINT("\n"); - - float AreaY, AreaZ; - float AreaX = AreaY = AreaZ = 9999; - - if ((stream = fopen(filename, "r+t")) != nullptr) { - - while (!feof(stream)) { - char linesection[30]; - char linefeed[80]; - INI_Sentence(stream, linefeed); - - // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary - // character (which is "//", ";" or "#"), or an empty line, then skip it - if (linefeed[0] == ';' || - linefeed[0] == '#' || - (linefeed[0] == '/' && linefeed[1] == '/') || - linefeed[0] == '\n' || linefeed[0] == '\0') - continue; // Skip - - // Every line is checked for a new section. - INI_Section(linefeed, linesection); - - if (linesection[0] != '\0' && std::strlen(linesection) > 1) { - section = INI_SectionType(linesection, section); - continue; // next line - } - - // Check word only when in a section - if (section != INI_NONE) { - char lineword[25]; - INI_Word(linefeed, lineword); - const int wordtype = INI_WordType(lineword, section); - - if (section == INI_AREA) { - if (wordtype == WORD_AREAX) - AreaX = static_cast(INI_WordValueINT(linefeed)); - if (wordtype == WORD_AREAY) - AreaY = static_cast(INI_WordValueINT(linefeed)); - if (wordtype == WORD_AREAZ) - AreaZ = static_cast(INI_WordValueINT(linefeed)); - - - if (AreaX != 9999 && AreaY != 9999 && AreaZ != 9999) { - // add this to goal - rblog("IAD: Adding an important area/goal\n"); - NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, Vector(AreaX, AreaY, AreaZ)); - - AreaX = AreaY = AreaZ = 9999; - } - } - } - - } // while - - fclose(stream); - } + char dirname[256]; + char filename[256]; + + FILE* stream; + int section = INI_NONE; + + // Set Directory name + std::strcpy(dirname, "data/cstrike/ini/"); + + std::strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, ".ini"); // nodes file + + // writes whole path into "filename", Linux compatible + UTIL_BuildFileNameRB(dirname, filename); + + SERVER_PRINT(filename); + SERVER_PRINT("\n"); + + float AreaY, AreaZ; + float AreaX = AreaY = AreaZ = 9999; + + if ((stream = std::fopen(filename, "r+t")) != nullptr) { + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); + + // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary + // character (which is "//", ";" or "#"), or an empty line, then skip it + if (linefeed[0] == ';' || + linefeed[0] == '#' || + (linefeed[0] == '/' && linefeed[1] == '/') || + linefeed[0] == '\n' || linefeed[0] == '\0') + continue; // Skip + + // Every line is checked for a new section. + INI_Section(linefeed, linesection); + + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { + section = INI_SectionType(linesection, section); + continue; // next line + } + + // Check word only when in a section + if (section != INI_NONE) { + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); + + if (section == INI_AREA) { + if (wordtype == WORD_AREAX) + AreaX = static_cast(INI_WordValueINT(linefeed)); + if (wordtype == WORD_AREAY) + AreaY = static_cast(INI_WordValueINT(linefeed)); + if (wordtype == WORD_AREAZ) + AreaZ = static_cast(INI_WordValueINT(linefeed)); + + if (AreaX != 9999 && AreaY != 9999 && AreaZ != 9999) { + // add this to goal + rblog("IAD: Adding an important area/goal\n"); + NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, Vector(AreaX, AreaY, AreaZ)); + + AreaX = AreaY = AreaZ = 9999; + } + } + } + } // while + + std::fclose(stream); + } } // Parse personality file -void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { - /* - Revisited: 02/07/05 - Stefan - Last bug/issue report: - - seems to overwrite personality file ? (loading does not work?) - RESULT: There is no bug. - - removed any messages sent by this function. - */ - - FILE *stream; - int section = INI_NONE; - - char dirname[256]; - char filename[256]; - - // Set Directory name - if (mod_id == CSTRIKE_DLL) - std::strcpy(dirname, "data/cstrike/bots/"); - - //strcat(dirname, STRING(gpGlobals->mapname)); - std::strcat(dirname, cBotName); - std::strcat(dirname, ".ini"); - - // writes whole path into "filename", Linux compatible - UTIL_BuildFileNameRB(dirname, filename); - - // we open the file here! - if ((stream = fopen(filename, "r+t")) != nullptr) { - - // infinite loop baby - while (!feof(stream)) { - char linesection[30]; - char linefeed[80]; - INI_Sentence(stream, linefeed); - - // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary - // character (which is "//", ";" or "#"), or an empty line, then skip it - if (linefeed[0] == ';' || - linefeed[0] == '#' || - (linefeed[0] == '/' && linefeed[1] == '/') || - linefeed[0] == '\n' || linefeed[0] == '\0') - continue; // Skip - - // Every line is checked for a new section. - INI_Section(linefeed, linesection); - - if (linesection[0] != '\0' && std::strlen(linesection) > 1) { - section = INI_SectionType(linesection, section); - continue; // next line - } - // Check word only when in a section - if (section != INI_NONE) { - char lineword[25]; - INI_Word(linefeed, lineword); - const int wordtype = INI_WordType(lineword, section); - - // WEAPON - if (section == INI_WEAPON) { - // 30/07/04 Josh - // Code optimization using a case instead of series of IF THEN - switch (wordtype) { - - case WORD_PRIWEAPON: - pBot->ipFavoPriWeapon = INI_WordValueINT(linefeed); - break; - case WORD_SECWEAPON: - pBot->ipFavoSecWeapon = INI_WordValueINT(linefeed); - break; - case WORD_GRENADE: - pBot->ipBuyGrenade = INI_WordValueINT(linefeed); - break; - case WORD_SAVEFORWEAP: - pBot->ipSaveForWeapon = INI_WordValueINT(linefeed); - break; - case WORD_FLASHBANG: - pBot->ipBuyFlashBang = INI_WordValueINT(linefeed); - break; - case WORD_SMOKEGREN: - pBot->ipBuySmokeGren = INI_WordValueINT(linefeed); - break; - case WORD_DEFUSEKIT: - pBot->ipBuyDefuseKit = INI_WordValueINT(linefeed); - break; - case WORD_ARMOUR: - pBot->ipBuyArmour = INI_WordValueINT(linefeed); - break; - } - } - // SKILL - if (section == INI_SKILL) { - switch (wordtype) { - case WORD_MINREACTTIME: - pBot->fpMinReactTime = INI_WordValueFLOAT(linefeed); - break; - case WORD_MAXREACTTIME: - pBot->fpMaxReactTime = INI_WordValueFLOAT(linefeed); - break; - case WORD_XOFFSET: - pBot->fpXOffset = INI_WordValueFLOAT(linefeed); - break; - case WORD_YOFFSET: - pBot->fpYOffset = INI_WordValueFLOAT(linefeed); - break; - case WORD_ZOFFSET: - pBot->fpZOffset = INI_WordValueFLOAT(linefeed); - break; - - } - // default we override bot skill with personality skill - if (Game.iOverrideBotSkill == GAME_YES) - if (wordtype == WORD_BOTSKILL) - pBot->bot_skill = INI_WordValueINT(linefeed); - } - // GAME - if (section == INI_GAME) { - if (wordtype == WORD_HOSTAGERATE) - pBot->ipHostage = INI_WordValueINT(linefeed); - if (wordtype == WORD_BOMBSPOTRATE) - pBot->ipBombspot = INI_WordValueINT(linefeed); - if (wordtype == WORD_RANDOMRATE) - pBot->ipRandom = INI_WordValueINT(linefeed); - if (wordtype == WORD_DROPPEDBOMB) - pBot->ipDroppedBomb = INI_WordValueINT(linefeed); - } - // RADIO - if (section == INI_RADIO) { - if (wordtype == WORD_REPLYRADIO) - pBot->ipReplyToRadio = INI_WordValueINT(linefeed); - if (wordtype == WORD_CREATERADIO) - pBot->ipCreateRadio = INI_WordValueINT(linefeed); - } - // TEAM - if (section == INI_TEAM) { - if (wordtype == WORD_HELPTEAM) - pBot->ipHelpTeammate = INI_WordValueINT(linefeed); - } - // PERSON - if (section == INI_PERSON) { - if (wordtype == WORD_TURNSPEED) - pBot->ipTurnSpeed = INI_WordValueINT(linefeed); - if (wordtype == WORD_WALKKNIFE) - pBot->ipWalkWithKnife = INI_WordValueINT(linefeed); - if (wordtype == WORD_FEARRATE) - pBot->ipFearRate = INI_WordValueINT(linefeed); - if (wordtype == WORD_HEARRATE) - pBot->ipHearRate = INI_WordValueINT(linefeed); - if (wordtype == WORD_CHATRATE) - pBot->ipChatRate = INI_WordValueINT(linefeed); - if (wordtype == WORD_CAMPRATE) - pBot->ipCampRate = INI_WordValueINT(linefeed); - } - } - } - fclose(stream); - } - // When we end up here, there is NO file? - else { - // Create new variables and save them into file. - - // Buy preferences - pBot->ipFavoPriWeapon = -1; - pBot->ipFavoSecWeapon = -1; - pBot->ipBuyFlashBang = RANDOM_LONG(20, 80); - pBot->ipBuyGrenade = RANDOM_LONG(20, 80); - pBot->ipBuySmokeGren = RANDOM_LONG(20, 80); - pBot->ipBuyDefuseKit = RANDOM_LONG(20, 80); - pBot->ipDroppedBomb = RANDOM_LONG(20, 80); - pBot->ipSaveForWeapon = RANDOM_LONG(0, 20); - pBot->ipBuyArmour = RANDOM_LONG(30, 100); - pBot->ipFearRate = RANDOM_LONG(20, 60); - - - // Skill, everything but botskill can change. - - // Determine reaction time based upon botskill here - float fMinReact; - if (pBot->bot_skill == 0) - fMinReact = 0.0f; - else - //30.8.04 redefined by frashman - // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); - // Reaction Time delay added for realistic gameplay [APG]RoboCop[CL] - fMinReact = - RANDOM_FLOAT(pBot->bot_skill / 20.0f + 0.3f, - (pBot->bot_skill / 5.0f) + 0.3f); - - const float fMaxReact = fMinReact + RANDOM_FLOAT(0.2f, 0.4f); - - // SET them - pBot->fpMinReactTime = fMinReact; - pBot->fpMaxReactTime = fMaxReact; - - // Set Offsets (note, they are extra upon current aiming code) - // 30.8.04 redefined by frashman - // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); - const float fOffset = RANDOM_FLOAT((pBot->bot_skill / 5.0f) + 0.05f, - (pBot->bot_skill / 2.0f) + 0.05f); - - // SET - pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; - - // Team - pBot->ipHelpTeammate = RANDOM_LONG(40, 80); - - // Game - pBot->ipHostage = RANDOM_LONG(25, 70); - pBot->ipBombspot = RANDOM_LONG(25, 70); - pBot->ipRandom = RANDOM_LONG(40, 80); - - // Radio - pBot->ipReplyToRadio = RANDOM_LONG(10, 20); - pBot->ipCreateRadio = RANDOM_LONG(10, 20); - pBot->ipHearRate = RANDOM_LONG(20, 60); - - // Person - pBot->ipTurnSpeed = RANDOM_LONG(20, 40); - pBot->ipCampRate = RANDOM_LONG(0, 40); - pBot->ipChatRate = RANDOM_LONG(10, 20); - pBot->ipWalkWithKnife = RANDOM_LONG(0, 30); - - // SAVE TO DISK: - //char dirname[256]; - //char filename[256]; - - // Set Directory name - if (mod_id == CSTRIKE_DLL) - std::strcpy(dirname, "data/cstrike/bots/"); - - std::strcat(dirname, cBotName); - std::strcat(dirname, ".ini"); - - // writes whole path into "filename", Linux compatible - UTIL_BuildFileNameRB(dirname, filename); - - // Only save if lock type is < 1 - FILE* rbl = fopen(filename, "w+t"); - - // Created file - if (rbl != nullptr) { - fprintf(rbl, "; RealBot\n"); - fprintf(rbl, "; \n"); - fprintf(rbl, - "; This personality is created with random values. You may\n; change this file to create your own personality.\n\n"); - - // WEAPON - fprintf(rbl, "[WEAPON]\n"); - fprintf(rbl, "PrimaryWeapon=%d\n", pBot->ipFavoPriWeapon); - fprintf(rbl, "SecondaryWeapon=%d\n", pBot->ipFavoSecWeapon); - fprintf(rbl, "SaveForWeapon=%d\n", pBot->ipSaveForWeapon); - fprintf(rbl, "Grenade=%d\n", pBot->ipBuyGrenade); - fprintf(rbl, "Flashbang=%d\n", pBot->ipBuyFlashBang); - fprintf(rbl, "SmokeGrenade=%d\n", pBot->ipBuySmokeGren); - fprintf(rbl, "DefuseKit=%d\n", pBot->ipBuyDefuseKit); - fprintf(rbl, "Armour=%d\n", pBot->ipBuyArmour); - fprintf(rbl, "\n"); - - - // SKILL - fprintf(rbl, "[SKILL]\n"); - fprintf(rbl, "XOffset=%f\n", pBot->fpXOffset); - fprintf(rbl, "YOffset=%f\n", pBot->fpYOffset); - fprintf(rbl, "ZOffset=%f\n", pBot->fpZOffset); - fprintf(rbl, "BotSkill=%d\n", pBot->bot_skill); - fprintf(rbl, "MaxReactionTime=%f\n", pBot->fpMaxReactTime); - fprintf(rbl, "MinReactionTime=%f\n", pBot->fpMinReactTime); - fprintf(rbl, "\n"); - - // GAME - fprintf(rbl, "[GAME]\n"); - fprintf(rbl, "Hostage=%d\n", pBot->ipHostage); - fprintf(rbl, "BombSpot=%d\n", pBot->ipBombspot); - fprintf(rbl, "DroppedBomb=%d\n", pBot->ipDroppedBomb); - fprintf(rbl, "Random=%d\n", pBot->ipRandom); - fprintf(rbl, "\n"); - - // RADIO - fprintf(rbl, "[RADIO]\n"); - fprintf(rbl, "Reply=%d\n", pBot->ipReplyToRadio); - fprintf(rbl, "Create=%d\n", pBot->ipCreateRadio); - fprintf(rbl, "\n"); - - // TEAM - fprintf(rbl, "[TEAM]\n"); - fprintf(rbl, "HelpTeammate=%d\n", pBot->ipHelpTeammate); - fprintf(rbl, "\n"); - - // PERSON - fprintf(rbl, "[PERSON]\n"); - fprintf(rbl, "Turnspeed=%d\n", pBot->ipTurnSpeed); - fprintf(rbl, "WalkWithKnife=%d\n", pBot->ipWalkWithKnife); - fprintf(rbl, "HearRate=%d\n", pBot->ipHearRate); - fprintf(rbl, "FearRate=%d\n", pBot->ipFearRate); - fprintf(rbl, "ChatRate=%d\n", pBot->ipChatRate); - fprintf(rbl, "CampRate=%d\n", pBot->ipCampRate); - fprintf(rbl, "\n"); - - // Close file - fclose(rbl); - } - } +void INI_PARSE_BOTS(char cBotName[33], cBot* pBot) { + /* + Revisited: 02/07/05 - Stefan + Last bug/issue report: + - seems to overwrite personality file ? (loading does not work?) + RESULT: There is no bug. + - removed any messages sent by this function. + */ + + FILE* stream; + int section = INI_NONE; + + char dirname[256]; + char filename[256]; + + // Set Directory name + if (mod_id == CSTRIKE_DLL) + std::strcpy(dirname, "data/cstrike/bots/"); + + //strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, cBotName); + std::strcat(dirname, ".ini"); + + // writes whole path into "filename", Linux compatible + UTIL_BuildFileNameRB(dirname, filename); + + // we open the file here! + if ((stream = std::fopen(filename, "r+t")) != nullptr) { + // infinite loop baby + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); + + // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary + // character (which is "//", ";" or "#"), or an empty line, then skip it + if (linefeed[0] == ';' || + linefeed[0] == '#' || + (linefeed[0] == '/' && linefeed[1] == '/') || + linefeed[0] == '\n' || linefeed[0] == '\0') + continue; // Skip + + // Every line is checked for a new section. + INI_Section(linefeed, linesection); + + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { + section = INI_SectionType(linesection, section); + continue; // next line + } + // Check word only when in a section + if (section != INI_NONE) { + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); + + // WEAPON + if (section == INI_WEAPON) { + // 30/07/04 Josh + // Code optimization using a case instead of series of IF THEN + switch (wordtype) { + case WORD_PRIWEAPON: + pBot->ipFavoPriWeapon = INI_WordValueINT(linefeed); + break; + case WORD_SECWEAPON: + pBot->ipFavoSecWeapon = INI_WordValueINT(linefeed); + break; + case WORD_GRENADE: + pBot->ipBuyGrenade = INI_WordValueINT(linefeed); + break; + case WORD_SAVEFORWEAP: + pBot->ipSaveForWeapon = INI_WordValueINT(linefeed); + break; + case WORD_FLASHBANG: + pBot->ipBuyFlashBang = INI_WordValueINT(linefeed); + break; + case WORD_SMOKEGREN: + pBot->ipBuySmokeGren = INI_WordValueINT(linefeed); + break; + case WORD_DEFUSEKIT: + pBot->ipBuyDefuseKit = INI_WordValueINT(linefeed); + break; + case WORD_ARMOUR: + pBot->ipBuyArmour = INI_WordValueINT(linefeed); + break; + } + } + // SKILL + if (section == INI_SKILL) { + switch (wordtype) { + case WORD_MINREACTTIME: + pBot->fpMinReactTime = INI_WordValueFLOAT(linefeed); + break; + case WORD_MAXREACTTIME: + pBot->fpMaxReactTime = INI_WordValueFLOAT(linefeed); + break; + case WORD_XOFFSET: + pBot->fpXOffset = INI_WordValueFLOAT(linefeed); + break; + case WORD_YOFFSET: + pBot->fpYOffset = INI_WordValueFLOAT(linefeed); + break; + case WORD_ZOFFSET: + pBot->fpZOffset = INI_WordValueFLOAT(linefeed); + break; + } + // default we override bot skill with personality skill + if (Game.iOverrideBotSkill == GAME_YES) + if (wordtype == WORD_BOTSKILL) + pBot->bot_skill = INI_WordValueINT(linefeed); + } + // GAME + if (section == INI_GAME) { + if (wordtype == WORD_HOSTAGERATE) + pBot->ipHostage = INI_WordValueINT(linefeed); + if (wordtype == WORD_BOMBSPOTRATE) + pBot->ipBombspot = INI_WordValueINT(linefeed); + if (wordtype == WORD_RANDOMRATE) + pBot->ipRandom = INI_WordValueINT(linefeed); + if (wordtype == WORD_DROPPEDBOMB) + pBot->ipDroppedBomb = INI_WordValueINT(linefeed); + } + // RADIO + if (section == INI_RADIO) { + if (wordtype == WORD_REPLYRADIO) + pBot->ipReplyToRadio = INI_WordValueINT(linefeed); + if (wordtype == WORD_CREATERADIO) + pBot->ipCreateRadio = INI_WordValueINT(linefeed); + } + // TEAM + if (section == INI_TEAM) { + if (wordtype == WORD_HELPTEAM) + pBot->ipHelpTeammate = INI_WordValueINT(linefeed); + } + // PERSON + if (section == INI_PERSON) { + if (wordtype == WORD_TURNSPEED) + pBot->ipTurnSpeed = INI_WordValueINT(linefeed); + if (wordtype == WORD_WALKKNIFE) + pBot->ipWalkWithKnife = INI_WordValueINT(linefeed); + if (wordtype == WORD_FEARRATE) + pBot->ipFearRate = INI_WordValueINT(linefeed); + if (wordtype == WORD_HEARRATE) + pBot->ipHearRate = INI_WordValueINT(linefeed); + if (wordtype == WORD_CHATRATE) + pBot->ipChatRate = INI_WordValueINT(linefeed); + if (wordtype == WORD_CAMPRATE) + pBot->ipCampRate = INI_WordValueINT(linefeed); + } + } + } + std::fclose(stream); + } + // When we end up here, there is NO file? + else { + // Create new variables and save them into file. + + // Buy preferences + pBot->ipFavoPriWeapon = -1; + pBot->ipFavoSecWeapon = -1; + pBot->ipBuyFlashBang = RANDOM_LONG(20, 80); + pBot->ipBuyGrenade = RANDOM_LONG(20, 80); + pBot->ipBuySmokeGren = RANDOM_LONG(20, 80); + pBot->ipBuyDefuseKit = RANDOM_LONG(20, 80); + pBot->ipDroppedBomb = RANDOM_LONG(20, 80); + pBot->ipSaveForWeapon = RANDOM_LONG(0, 20); + pBot->ipBuyArmour = RANDOM_LONG(30, 100); + pBot->ipFearRate = RANDOM_LONG(20, 60); + + // Skill, everything but botskill can change. + + // Determine reaction time based upon botskill here + float fMinReact; + if (pBot->bot_skill == 0) + fMinReact = 0.0f; + else + //30.8.04 redefined by frashman + // fMinReact = RANDOM_FLOAT (0.05, (pBot->bot_skill / 10)); + // Reaction Time delay added for realistic gameplay [APG]RoboCop[CL] + fMinReact = + RANDOM_FLOAT(pBot->bot_skill / 20.0f + 0.3f, + pBot->bot_skill / 5.0f + 0.3f); + + const float fMaxReact = fMinReact + RANDOM_FLOAT(0.2f, 0.4f); + + // SET them + pBot->fpMinReactTime = fMinReact; + pBot->fpMaxReactTime = fMaxReact; + + // Set Offsets (note, they are extra upon current aiming code) + // 30.8.04 redefined by frashman + // float fOffset = RANDOM_FLOAT ((pBot->bot_skill / 5), (pBot->bot_skill / 2)); + const float fOffset = RANDOM_FLOAT(pBot->bot_skill / 5.0f + 0.05f, + pBot->bot_skill / 2.0f + 0.05f); + + // SET + pBot->fpXOffset = pBot->fpYOffset = pBot->fpZOffset = fOffset; + + // Team + pBot->ipHelpTeammate = RANDOM_LONG(40, 80); + + // Game + pBot->ipHostage = RANDOM_LONG(25, 70); + pBot->ipBombspot = RANDOM_LONG(25, 70); + pBot->ipRandom = RANDOM_LONG(40, 80); + + // Radio + pBot->ipReplyToRadio = RANDOM_LONG(10, 20); + pBot->ipCreateRadio = RANDOM_LONG(10, 20); + pBot->ipHearRate = RANDOM_LONG(20, 60); + + // Person + pBot->ipTurnSpeed = RANDOM_LONG(20, 40); + pBot->ipCampRate = RANDOM_LONG(0, 40); + pBot->ipChatRate = RANDOM_LONG(10, 20); + pBot->ipWalkWithKnife = RANDOM_LONG(0, 30); + + // SAVE TO DISK: + //char dirname[256]; + //char filename[256]; + + // Set Directory name + if (mod_id == CSTRIKE_DLL) + std::strcpy(dirname, "data/cstrike/bots/"); + + std::strcat(dirname, cBotName); + std::strcat(dirname, ".ini"); + + // writes whole path into "filename", Linux compatible + UTIL_BuildFileNameRB(dirname, filename); + + // Only save if lock type is < 1 + FILE* rbl = std::fopen(filename, "w+t"); + + // Created file + if (rbl != nullptr) { + std::fprintf(rbl, "; RealBot\n"); + std::fprintf(rbl, "; \n"); + std::fprintf(rbl, + "; This personality is created with random values. You may\n; change this file to create your own personality.\n\n"); + + // WEAPON + std::fprintf(rbl, "[WEAPON]\n"); + std::fprintf(rbl, "PrimaryWeapon=%d\n", pBot->ipFavoPriWeapon); + std::fprintf(rbl, "SecondaryWeapon=%d\n", pBot->ipFavoSecWeapon); + std::fprintf(rbl, "SaveForWeapon=%d\n", pBot->ipSaveForWeapon); + std::fprintf(rbl, "Grenade=%d\n", pBot->ipBuyGrenade); + std::fprintf(rbl, "Flashbang=%d\n", pBot->ipBuyFlashBang); + std::fprintf(rbl, "SmokeGrenade=%d\n", pBot->ipBuySmokeGren); + std::fprintf(rbl, "DefuseKit=%d\n", pBot->ipBuyDefuseKit); + std::fprintf(rbl, "Armour=%d\n", pBot->ipBuyArmour); + std::fprintf(rbl, "\n"); + + // SKILL + std::fprintf(rbl, "[SKILL]\n"); + std::fprintf(rbl, "XOffset=%f\n", pBot->fpXOffset); + std::fprintf(rbl, "YOffset=%f\n", pBot->fpYOffset); + std::fprintf(rbl, "ZOffset=%f\n", pBot->fpZOffset); + std::fprintf(rbl, "BotSkill=%d\n", pBot->bot_skill); + std::fprintf(rbl, "MaxReactionTime=%f\n", pBot->fpMaxReactTime); + std::fprintf(rbl, "MinReactionTime=%f\n", pBot->fpMinReactTime); + std::fprintf(rbl, "\n"); + + // GAME + std::fprintf(rbl, "[GAME]\n"); + std::fprintf(rbl, "Hostage=%d\n", pBot->ipHostage); + std::fprintf(rbl, "BombSpot=%d\n", pBot->ipBombspot); + std::fprintf(rbl, "DroppedBomb=%d\n", pBot->ipDroppedBomb); + std::fprintf(rbl, "Random=%d\n", pBot->ipRandom); + std::fprintf(rbl, "\n"); + + // RADIO + std::fprintf(rbl, "[RADIO]\n"); + std::fprintf(rbl, "Reply=%d\n", pBot->ipReplyToRadio); + std::fprintf(rbl, "Create=%d\n", pBot->ipCreateRadio); + std::fprintf(rbl, "\n"); + + // TEAM + std::fprintf(rbl, "[TEAM]\n"); + std::fprintf(rbl, "HelpTeammate=%d\n", pBot->ipHelpTeammate); + std::fprintf(rbl, "\n"); + + // PERSON + std::fprintf(rbl, "[PERSON]\n"); + std::fprintf(rbl, "Turnspeed=%d\n", pBot->ipTurnSpeed); + std::fprintf(rbl, "WalkWithKnife=%d\n", pBot->ipWalkWithKnife); + std::fprintf(rbl, "HearRate=%d\n", pBot->ipHearRate); + std::fprintf(rbl, "FearRate=%d\n", pBot->ipFearRate); + std::fprintf(rbl, "ChatRate=%d\n", pBot->ipChatRate); + std::fprintf(rbl, "CampRate=%d\n", pBot->ipCampRate); + std::fprintf(rbl, "\n"); + + // Close file + std::fclose(rbl); + } + } } // INI parsing /** @@ -1062,89 +1042,89 @@ void INI_PARSE_BOTS(char cBotName[33], cBot * pBot) { * The buytable.ini is not in the source file, but in the binary downloads of REALBOT. */ void INI_PARSE_BUYTABLE() { - FILE *stream; - int section = INI_NONE; - int prev_section = section; - int weapon_id = -1; - - char dirname[256]; - char filename[256]; - - // Set Directory name - if (mod_id == CSTRIKE_DLL) - std::strcpy(dirname, "data/cstrike/"); - - //strcat(dirname, STRING(gpGlobals->mapname)); - std::strcat(dirname, "buytable.ini"); - - // writes whole path into "filename", Linux compatible - UTIL_BuildFileNameRB(dirname, filename); - - // clear out weapon table completely - for (int cl = 0; cl < 32; cl++) { - weapons_table[cl].iId = -1; - weapons_table[cl].price = -1; - weapons_table[cl].priority = -1; - weapons_table[cl].iIdIndex = -1; - } - - if ((stream = fopen(filename, "r+t")) != nullptr) { - while (!feof(stream)) { - char linesection[30]; - char linefeed[80]; - INI_Sentence(stream, linefeed); - - // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary - // character (which is "//", ";" or "#"), or an empty line, then skip it - if (linefeed[0] == ';' || - linefeed[0] == '#' || - (linefeed[0] == '/' && linefeed[1] == '/') || - linefeed[0] == '\n' || linefeed[0] == '\0') - continue; // Skip - - // Every line is checked for a new section. - INI_Section(linefeed, linesection); - - // Found a new section - if (linesection[0] != '\0' && std::strlen(linesection) > 1) { - section = INI_SectionType_BUYTABLE(linesection, section); - // Check if its the same as the previous section - if (section != prev_section) { - weapon_id++; // new weapon - if (weapon_id > MAX_WEAPONS - 1) { - // done - fclose(stream); - break; // out of the loop - } - - weapons_table[weapon_id].iId = section; - weapons_table[section].iIdIndex = weapon_id; - } - - prev_section = section; // Equal the sections now - continue; // next line - } - - // Check word only when in a section - if (section != INI_NONE) { - char lineword[25]; - INI_Word(linefeed, lineword); - const int wordtype = INI_WordType(lineword, section); - if (wordtype != WORD_NONE) { - if (wordtype == WORD_PRICE) { - //BotDebug("Loading price\n"); - weapons_table[weapon_id].price = - INI_WordValueINT(linefeed); - } else if (wordtype == WORD_PRIORITY) { - //BotDebug("Loading priority\n"); - weapons_table[weapons_table[weapon_id].iId].priority = - INI_WordValueINT(linefeed); - } - } - } - } - fclose(stream); - } + FILE* stream; + int section = INI_NONE; + int prev_section = section; + int weapon_id = -1; + + char dirname[256]; + char filename[256]; + + // Set Directory name + if (mod_id == CSTRIKE_DLL) + std::strcpy(dirname, "data/cstrike/"); + + //strcat(dirname, STRING(gpGlobals->mapname)); + std::strcat(dirname, "buytable.ini"); + + // writes whole path into "filename", Linux compatible + UTIL_BuildFileNameRB(dirname, filename); + + // clear out weapon table completely + for (int cl = 0; cl < 32; cl++) { + weapons_table[cl].iId = -1; + weapons_table[cl].price = -1; + weapons_table[cl].priority = -1; + weapons_table[cl].iIdIndex = -1; + } + + if ((stream = std::fopen(filename, "r+t")) != nullptr) { + while (!feof(stream)) { + char linesection[30]; + char linefeed[80]; + INI_Sentence(stream, linefeed); + + // Linefeed contains a string of 1 sentence. Whenever the first character is a commentary + // character (which is "//", ";" or "#"), or an empty line, then skip it + if (linefeed[0] == ';' || + linefeed[0] == '#' || + (linefeed[0] == '/' && linefeed[1] == '/') || + linefeed[0] == '\n' || linefeed[0] == '\0') + continue; // Skip + + // Every line is checked for a new section. + INI_Section(linefeed, linesection); + + // Found a new section + if (linesection[0] != '\0' && std::strlen(linesection) > 1) { + section = INI_SectionType_BUYTABLE(linesection, section); + // Check if its the same as the previous section + if (section != prev_section) { + weapon_id++; // new weapon + if (weapon_id > MAX_WEAPONS - 1) { + // done + //std::fclose(stream); + break; // out of the loop + } + + weapons_table[weapon_id].iId = section; + weapons_table[section].iIdIndex = weapon_id; + } + + prev_section = section; // Equal the sections now + continue; // next line + } + + // Check word only when in a section + if (section != INI_NONE) { + char lineword[25]; + INI_Word(linefeed, lineword); + const int wordtype = INI_WordType(lineword, section); + if (wordtype != WORD_NONE) { + if (wordtype == WORD_PRICE) { + //BotDebug("Loading price\n"); + weapons_table[weapon_id].price = + INI_WordValueINT(linefeed); + } else if (wordtype == WORD_PRIORITY) { + //BotDebug("Loading priority\n"); + weapons_table[weapons_table[weapon_id].iId].priority = + INI_WordValueINT(linefeed); + } + } + } + } + std::fclose(stream); + } } // INI parsing // $Log: IniParser.cpp,v $ @@ -1219,4 +1199,4 @@ void INI_PARSE_BUYTABLE() { // - Log() works properly now // - Clearing in dll.cpp of reallog.txt at dll init // - Logging works now, add REALBOT_PRINT() at every point you want to log something. -// +// \ No newline at end of file diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 0323a46..93253b1 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -6,7 +6,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -18,24 +18,24 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. * **/ -/** - * NODE MACHINE data types - * COPYRIGHTED BY STEFAN HENDRIKS (C) - **/ + /** + * NODE MACHINE data types + * COPYRIGHTED BY STEFAN HENDRIKS (C) + **/ #ifndef NODEDATATYPES_H #define NODEDATATYPES_H -// player sizes for path_connection_walkable + // player sizes for path_connection_walkable #define MAX_JUMPHEIGHT 60 // confirmed // 45 without crouching #define MAX_FALLHEIGHT 130 // not confirmed (200 is to high, adjusted) #define MAX_STAIRHEIGHT 18 // confirmed @@ -136,61 +136,60 @@ const unsigned long g_iMaxVisibilityByte = MAX_NODES * MAX_NODES / 8; #define SF_DOOR_NOMONSTERS 512 // Monster can't open #define SF_DOOR_SILENT 0x80000000 - // Player information on map typedef struct { - Vector vPrevPos; // Previous Position - int iNode; // Previous Node + Vector vPrevPos; // Previous Position + int iNode; // Previous Node } - tPlayer; +tPlayer; // Astar Node informaiton typedef struct { - int state; // OPEN/CLOSED - int parent; // Who opened this node? - float cost; // Cost - double danger; + int state; // OPEN/CLOSED + int parent; // Who opened this node? + float cost; // Cost + double danger; } - tNodestar; +tNodestar; // Additional Node Information typedef struct { - float fDanger[2]; // Danger information (0.0 - no danger, 1.0 dangerous). Indexed per team (T/CT) - float fContact[2]; // How many times have contact with enemy (0.0 none, 1.0 , a lot) + float fDanger[2]; // Danger information (0.0 - no danger, 1.0 dangerous). Indexed per team (T/CT) + float fContact[2]; // How many times have contact with enemy (0.0 none, 1.0 , a lot) } - tInfoNode; +tInfoNode; typedef struct { - int iNodes[MAX_NODES_IN_MEREDIANS]; + int iNodes[MAX_NODES_IN_MEREDIANS]; } - tMeredian; +tMeredian; // Trouble connections typedef struct { - int iFrom; // From NODE - int iTo; // To NODE - int iTries; // How many times we had trouble with this connection + int iFrom; // From NODE + int iTo; // To NODE + int iTries; // How many times we had trouble with this connection } - tTrouble; +tTrouble; // Node (stored in RBN file, do not change casually) typedef struct { - Vector origin; // Node origin - int iNeighbour[MAX_NEIGHBOURS]; // Reachable nodes for this node - int iNodeBits; + Vector origin; // Node origin + int iNeighbour[MAX_NEIGHBOURS]; // Reachable nodes for this node + int iNodeBits; } - tNode; +tNode; // Goal Node information typedef struct { - edict_t *pGoalEdict; // edict of goal - int iNode; // index of node attached to it - int iType; // type of goal - int iChecked; // many times checked/visited? - int iBadScore; // bad score for a node (when it seems to be unreachable?) - int index; // the index in the Goals[] array - char name[32]; // name of goal + edict_t* pGoalEdict; // edict of goal + int iNode; // index of node attached to it + int iType; // type of goal + int iChecked; // many times checked/visited? + int iBadScore; // bad score for a node (when it seems to be unreachable?) + int index; // the index in the Goals[] array + char name[32]; // name of goal } - tGoal; +tGoal; #endif // NODEDATATYPES_H diff --git a/NodeMachine.cpp b/NodeMachine.cpp index d74e84b..db47a2a 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -66,29 +66,30 @@ extern int draw_nodepath; int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const // BERKED { // prevent negative indexes on iVisChecked below -- BERKED - if (iFrom < 0 || iFrom > MAX_NODES || iTo < 0 || iTo > MAX_NODES) { - return VIS_INVALID; + if (iFrom >= 0 && iFrom < 4096 && iTo >= 0 && iTo < 4096) { + if (iVisChecked[iFrom] == 0) + return VIS_UNKNOWN; // we have no clue } - // -- BY STEFAN -- - if (iVisChecked[iFrom] == 0) - return VIS_UNKNOWN; // we have no clue - // -- END -- - + else { + rblog("ERROR: Negative or out of bound index on iFrom! Returning Visibility NULL\n"); + return 0; + } + // was int - + // work out the position - const long iPosition = (iFrom * MAX_NODES) + iTo; - + const long iPosition = iFrom * MAX_NODES + iTo; + const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; - + if (iByte < static_cast(g_iMaxVisibilityByte)) { // Get the Byte that this is in - const unsigned char *ToReturn = (cVisTable + iByte); + const unsigned char* ToReturn = cVisTable + iByte; // get the bit in the byte - return ((*ToReturn & (1 << iBit)) > 0) ? VIS_VISIBLE : VIS_BLOCKED; // BERKED + return (*ToReturn & 1 << iBit) > 0 ? VIS_VISIBLE : VIS_BLOCKED; // BERKED } - + return VIS_BLOCKED; // BERKED } @@ -98,21 +99,25 @@ void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { return; } - // -- STEFAN -- - iVisChecked[iFrom] = 1; // WE HAVE CHECKED THIS ONE - // -- END -- + if (iFrom >= 0 && iFrom < 4096) { + iVisChecked[iFrom] = 1; // WE HAVE CHECKED THIS ONE + } + else { + rblog("ERROR: Negative or out of bound index on iFrom! Returning Visibility NULL\n"); + return; + } // was int - const long iPosition = (iFrom * MAX_NODES) + iTo; + const long iPosition = iFrom * MAX_NODES + iTo; const long iByte = static_cast(iPosition / 8); const unsigned int iBit = iPosition % 8; if (iByte < static_cast(g_iMaxVisibilityByte)) { - unsigned char *ToChange = (cVisTable + iByte); + unsigned char *ToChange = cVisTable + iByte; if (bVisible) - *ToChange |= (1 << iBit); + *ToChange |= 1 << iBit; else *ToChange &= ~(1 << iBit); } @@ -148,7 +153,7 @@ void cNodeMachine::init() { // --- info nodes for (int d = 0; d < 2; d++) { - InfoNodes[i].fDanger[d] = 0.0; + InfoNodes[i].fDanger[d] = 0.0f; } } @@ -176,7 +181,13 @@ void cNodeMachine::init() { //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first cVisTable = static_cast(malloc(iSize)); - std::memset(cVisTable, 0, iSize); + if (cVisTable != nullptr) { + std::memset(cVisTable, 0, iSize); + } + else { + rblog("cNodeMachine::init() - ERROR: Could not allocate memory for visibility table\n"); + } + ClearVisibilityTable(); // END: @@ -243,7 +254,8 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const * @param iTo * @return index of newly created index */ -int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) { +int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) +{ const int existingIndex = GetTroubleIndexForConnection(iFrom, iTo); if (existingIndex > -1) return existingIndex; // already exists @@ -268,7 +280,8 @@ int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) { return iNew; } -bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) { +bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) const +{ if (index < 0) { rblog("(trouble) hasAttemptedConnectionTooManyTimes | invalid index for hasAttemptedConnectionTooManyTimes()\n"); // deal with invalid connection @@ -296,7 +309,8 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) { * @param iTo * @return */ -bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int iFrom, int iTo) { +bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int iFrom, int iTo) +{ const int index = AddTroubledConnection(iFrom, iTo); IncreaseAttemptsForTroubledConnection(index); if (hasAttemptedConnectionTooManyTimes(index)) { @@ -310,13 +324,13 @@ bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int i } return false; - } else { - rblog("(trouble) IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded | may attempt another time\n"); - return true; } + rblog("(trouble) IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded | may attempt another time\n"); + return true; } -void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) { +void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) +{ if (index < 0 || index >= MAX_TROUBLE) return; char msg[255]; @@ -332,7 +346,8 @@ void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) { rblog(msg); } -bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) { +bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) +{ char msg[255]; std::sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); rblog(msg); @@ -356,7 +371,8 @@ bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) { return true; } -void cNodeMachine::path_clear(int botIndex) { +void cNodeMachine::path_clear(int botIndex) +{ for (int nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { iPath[botIndex][nodeIndex] = -1; } @@ -373,7 +389,8 @@ Vector cNodeMachine::node_vector(int iNode) const } // Input: Vector, Output X and Y Meredians -void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) { +void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) +{ // Called for lookupt and for storing float iCoordX = vOrigin.x + 8192.0f; // map height (converts from - to +) float iCoordY = vOrigin.y + 8192.0f; // map width (converts from - to +) @@ -386,7 +403,8 @@ void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) { *iY = static_cast(iCoordY); } -void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { +void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) +{ int index = -1; for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) if (Meredians[iX][iY].iNodes[i] < 0) { @@ -401,9 +419,10 @@ void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) { } // Does the node float? -bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) +{ TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2f)); + const Vector tr_end = vOrigin - Vector(0, 0, ORIGIN_HEIGHT * 1.2f); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) //UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -433,9 +452,10 @@ bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { } // Does the node stand on a crate? or a steep slope? -bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { +bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) +{ TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, (ORIGIN_HEIGHT * 1.2f)); + const Vector tr_end = vOrigin - Vector(0, 0, ORIGIN_HEIGHT * 1.2f); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) if (pEdict) @@ -480,7 +500,8 @@ int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDis * @param pEdict * @return */ -int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) const +{ // REDO: Need faster method to find a node // TOADD: For secure results all nodes should be checked to figure out the real // 'closest' node. @@ -528,15 +549,9 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE } // if nothing hit: - if (tr.flFraction >= 1.0f) { - if (pEdict != nullptr) { - if (FInViewCone(&nodeVector, pEdict) // in FOV - && FVisible(nodeVector, pEdict)) { - iCloseNode = iNode; - } else { - iCloseNode = iNode; - } - } + if (tr.flFraction >= 1.0f && pEdict != nullptr) { + // Regardless of conditions, set iFarNode to iNode + iCloseNode = iNode; } } } @@ -550,7 +565,8 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE * @param pEdict * @return */ -int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) { +int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, const edict_t *pEdict) const +{ // Use Meredians to search for nodes // TODO: we should take care in the situation where we're at the 'edge' of such a meridian (subspace). So we should // basicly take edging meridians as well when too close to the edge. @@ -571,7 +587,7 @@ int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, edict_t *p const int iNode = Meredians[iX][iY].iNodes[i]; -// if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us + // if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us const float distanceFromTo = func_distance(vOrigin, Nodes[iNode].origin); if (distanceFromTo < fDist && // within range @@ -595,15 +611,9 @@ int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, edict_t *p } // if nothing hit: - if (tr.flFraction >= 1.0f) { - if (pEdict != nullptr) { - if (FInViewCone(&nodeVector, pEdict) // in FOV - && FVisible(nodeVector, pEdict)) { - iFarNode = iNode; - } else { - iFarNode = iNode; - } - } + if (tr.flFraction >= 1.0f && pEdict != nullptr) { + // Regardless of conditions, set iFarNode to iNode + iFarNode = iNode; } } } @@ -709,7 +719,8 @@ int cNodeMachine::is_neighbour_node(const tNode& node, int iNode) } // Return the node id from bot path on Index NR -int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) { +int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) const +{ if (botIndex > -1 && botIndex < MAX_BOTS && pathNodeIndex > -1 && pathNodeIndex < MAX_PATH_NODES) { return iPath[botIndex][pathNodeIndex]; @@ -810,8 +821,8 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const // If either start/end is on ladder, assume we can fly without falling // but still check whether a human hull can go through - if ((Nodes[iStart].iNodeBits & BIT_LADDER) || - (Nodes[iEnd].iNodeBits & BIT_LADDER)) + if (Nodes[iStart].iNodeBits & BIT_LADDER || + Nodes[iEnd].iNodeBits & BIT_LADDER) { UTIL_TraceHull(Start, End, ignore_monsters, human_hull, nullptr, &tr); return tr.flFraction >= 1.0f; @@ -990,7 +1001,7 @@ int cNodeMachine::getFreeNodeIndex() const for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin == INVALID_VECTOR) { return i; - break; + //break; } } return -1; // no free node found @@ -1085,7 +1096,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling (or walking a slope), the distance will be bigger. const float distanceBetweenVectorsWithoutZAxis = func_distance(vNormalizedOrigin, vNormalizedIndex); - if (distanceBetweenVectorsWithoutZAxis > (NODE_ZONE * 3)) { // allow up to 3 times the boundary we use normally + if (distanceBetweenVectorsWithoutZAxis > NODE_ZONE * 3) { // allow up to 3 times the boundary we use normally continue; } @@ -1121,7 +1132,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { const vec_t fallDistance = Nodes[currentIndex].origin.z - Nodes[nodeIndex].origin.z; if (indexNodeFloats - && (fallDistance > MAX_FALLHEIGHT) + && fallDistance > MAX_FALLHEIGHT && (!bNeighbourWater && !bIsInWater)) { // skip nodes that are not in water and too low (ie will cause fall damage) continue; @@ -1182,7 +1193,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // trace UTIL_TraceHull(Nodes[currentIndex].origin, Nodes[nodeIndex].origin, ignore_monsters, - hull_type, pEntity->v.pContainingEntity, &tr); + hull_type, pEntity->v.pContainingEntity, &tr); // if nothing hit: if (tr.flFraction >= 1.0f) { @@ -1197,7 +1208,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // Check if J is LOWER then Index, if so, the height should be jumpable! // When height does not differ to much we can add this connection. - if ((indexNodeFloats && bNeighbourFloats) + if (indexNodeFloats && bNeighbourFloats && (bNeighbourWater == false && bIsInWater == false) && Nodes[currentIndex].origin.z >= Nodes[nodeIndex].origin.z) { char msg[80]; @@ -1258,7 +1269,7 @@ void cNodeMachine::init_round() { const edict_t *pPlayer = INDEXENT(index); // skip invalid players - if ((pPlayer) && (!pPlayer->free)) + if (pPlayer && !pPlayer->free) Players[(index - 1)].vPrevPos = pPlayer->v.origin; } @@ -1280,7 +1291,7 @@ void cNodeMachine::addNodesForPlayers() { edict_t *pPlayer = INDEXENT(index); // skip invalid (dead, not playing) players - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { if (pPlayer->free) continue; if (!IsAlive(pPlayer)) continue; @@ -1296,8 +1307,8 @@ void cNodeMachine::addNodesForPlayers() { } // Draw connections of the node we are standing on -void cNodeMachine::connections(edict_t *pEntity) { - +void cNodeMachine::connections(edict_t *pEntity) const +{ int closeNode; char msg[75]; std::memset(msg, 0, sizeof(msg)); @@ -1346,7 +1357,7 @@ void cNodeMachine::connections(edict_t *pEntity) { const int tries = Troubles[troubleIndex].iTries; if (tries <= 1) { red = 255; - green = 255; + green = 250; blue = 0; } @@ -1357,7 +1368,7 @@ void cNodeMachine::connections(edict_t *pEntity) { } if (tries > 2) { - red = 128; + red = 150; green = 0; blue = 0; } @@ -1373,7 +1384,8 @@ void cNodeMachine::connections(edict_t *pEntity) { } // Draw -void cNodeMachine::draw(edict_t* pEntity) { +void cNodeMachine::draw(edict_t* pEntity) const +{ // DebugOut("waypoint: waypoint_draw()\n"); int max_drawn = 0; @@ -1388,13 +1400,13 @@ void cNodeMachine::draw(edict_t* pEntity) { const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); const int angle_to_waypoint = - FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); + FUNC_InFieldOfView(pEntity, end - pEntity->v.origin); if (good && angle_to_waypoint < 65) { int g, b, l; int r = g = b = l = 250; - l = 250; + // l = 250; // Normally light is 250 if (Nodes[i].iNodeBits & BIT_LADDER) @@ -1424,6 +1436,14 @@ void cNodeMachine::draw(edict_t* pEntity) { } const int iNodeClose = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); + if (iNodeClose >= static_cast(sizeof(Nodes) / sizeof(Nodes[0]))) { + char msg[50]; + std::sprintf(msg, "Node %d\nMe: (%.0f,%.0f,%.0f)\n", iNodeClose, + pEntity->v.origin.x, pEntity->v.origin.y, + pEntity->v.origin.z); + CenterMessage(msg); + return; + } char msg[50]; char Flags[10]; @@ -1447,9 +1467,9 @@ void cNodeMachine::draw(edict_t* pEntity) { std::strcat(Flags, "h"); std::sprintf(msg, "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", - iNodeClose, (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.x, - (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.y, - (iNodeClose < 0) ? -1 : Nodes[iNodeClose].origin.z, Flags, + iNodeClose, iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.x, + iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.y, + iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.z, Flags, pEntity->v.origin.x, pEntity->v.origin.y, pEntity->v.origin.z); CenterMessage(msg); } @@ -1468,27 +1488,28 @@ void cNodeMachine::experience_save() { UTIL_BuildFileNameRB(dirname, filename); // Only save if lock type is < 1 - FILE* rbl = fopen(filename, "wb"); + FILE* rbl = std::fopen(filename, "wb"); if (rbl != nullptr) { const int iVersion = FILE_EXP_VER2; - fwrite(&iVersion, sizeof(int), 1, rbl); + std::fwrite(&iVersion, sizeof(int), 1, rbl); + //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (int i = 0; i < MAX_NODES; i++) { - fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - fwrite(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - fwrite(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - fwrite(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fwrite(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + + std::fwrite(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fwrite(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; // Here write down the MAX amounts of nodes used from vis table! - const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; - fwrite(&iMaxUsedNodes, sizeof(int), 1, rbl); + std::fwrite(&iMaxUsedNodes, sizeof(int), 1, rbl); // Write down 512 bytes chunks, and when a remaining piece is left over // also write that down. Only when 'size' is 0 we quit the loop @@ -1503,7 +1524,7 @@ void cNodeMachine::experience_save() { // While we still have bytes remaining to write to disk. while (iRemaining > 0) { - fwrite(&cVisTable[iPos], iChunk, 1, rbl); + std::fwrite(&cVisTable[iPos], iChunk, 1, rbl); iChunk = 512; // keep the size 512 @@ -1519,10 +1540,10 @@ void cNodeMachine::experience_save() { } // write down the checked vis - fwrite(iVisChecked, sizeof(iVisChecked), 1, rbl); - fclose(rbl); + std::fwrite(iVisChecked, sizeof(iVisChecked), 1, rbl); + std::fclose(rbl); } else - fprintf(stderr, "Cannot write experience file %s\n", filename); + std::fprintf(stderr, "Cannot write experience file %s\n", filename); } // Load Danger @@ -1538,49 +1559,51 @@ void cNodeMachine::experience_load() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE* rbl = fopen(filename, "rb"); + FILE* rbl = std::fopen(filename, "rb"); if (rbl != nullptr) { int i; int iVersion = FILE_EXP_VER1; - fread(&iVersion, sizeof(int), 1, rbl); + std::fread(&iVersion, sizeof(int), 1, rbl); if (iVersion == FILE_EXP_VER1) { + //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + + std::fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } - - fread(&iMaxUsedNodes, sizeof(int), 1, rbl); + + std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); // make sure we never exceed the limit if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; - const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; // Read table from what we know - fread(cVisTable, iSize, 1, rbl); - fread(iVisChecked, sizeof(iVisChecked), 1, rbl); + std::fread(cVisTable, iSize, 1, rbl); + std::fread(iVisChecked, sizeof(iVisChecked), 1, rbl); } else if (iVersion == FILE_EXP_VER2) { + //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + + std::fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } - fread(&iMaxUsedNodes, sizeof(int), 1, rbl); + std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); // make sure we never exceed the limit if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; - const unsigned long iSize = (iMaxUsedNodes * MAX_NODES) / 8; + const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; // Now read the cVisTable from what we know ClearVisibilityTable(); // clear first @@ -1595,7 +1618,7 @@ void cNodeMachine::experience_load() { break; // Read table from what we know - fread(&cVisTable[iPos], iChunk, 1, rbl); + std::fread(&cVisTable[iPos], iChunk, 1, rbl); // When we exceed the size we make sure that the chunk is not to big if (iRemaining < iChunk) @@ -1608,10 +1631,10 @@ void cNodeMachine::experience_load() { break; // escape } - fread(iVisChecked, sizeof(iVisChecked), 1, rbl); + std::fread(iVisChecked, sizeof(iVisChecked), 1, rbl); } - fclose(rbl); + std::fclose(rbl); } } @@ -1630,23 +1653,23 @@ void cNodeMachine::save() const UTIL_BuildFileNameRB(dirname, filename); // Only save if lock type is < 1 - FILE* rbl = fopen(filename, "wb"); + FILE* rbl = std::fopen(filename, "wb"); if (rbl != nullptr) { // Write down version number const int iVersion = FILE_NODE_VER1; - fwrite(&iVersion, sizeof(int), 1, rbl); + std::fwrite(&iVersion, sizeof(int), 1, rbl); for (int i = 0; i < MAX_NODES; i++) { - fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); + std::fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); for (int n = 0; n < MAX_NEIGHBOURS; n++) - fwrite(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + std::fwrite(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); // save bit flags - fwrite(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); + std::fwrite(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); } - fclose(rbl); + std::fclose(rbl); } else - fprintf(stderr, "Cannot write file %s\n", filename); + std::fprintf(stderr, "Cannot write file %s\n", filename); } void cNodeMachine::save_important() const @@ -1663,27 +1686,27 @@ void cNodeMachine::save_important() const UTIL_BuildFileNameRB(dirname, filename); // Only save if lock type is < 1 - FILE *rbl = fopen(filename, "w+t"); + FILE *rbl = std::fopen(filename, "w+t"); if (rbl) { - fprintf(rbl, + std::fprintf(rbl, "; RealBot : Important Area Definition file\n; Do not hand-edit, this is _not_ an editable ini file!\n;\n\n"); // save important areas: for (int iGn = 0; iGn < MAX_GOALS; iGn++) { if (Goals[iGn].iType == GOAL_IMPORTANT) { // save this area - fprintf(rbl, "[AREA]\n"); + std::fprintf(rbl, "[AREA]\n"); const Vector iGoalVector = node_vector(Goals[iGn].iNode); - fprintf(rbl, "X=%f\n", iGoalVector.x); - fprintf(rbl, "Y=%f\n", iGoalVector.y); - fprintf(rbl, "Z=%f\n\n", iGoalVector.z); + std::fprintf(rbl, "X=%f\n", iGoalVector.x); + std::fprintf(rbl, "Y=%f\n", iGoalVector.y); + std::fprintf(rbl, "Z=%f\n\n", iGoalVector.z); } } - fprintf(rbl, "; Eof"); - fclose(rbl); + std::fprintf(rbl, "; Eof"); + std::fclose(rbl); } } @@ -1701,23 +1724,23 @@ void cNodeMachine::load() { // writes whole path into "filename", Linux compatible UTIL_BuildFileNameRB(dirname, filename); - FILE* rbl = fopen(filename, "rb"); + FILE* rbl = std::fopen(filename, "rb"); if (rbl != nullptr) { int i; int iVersion = FILE_NODE_VER1; - fread(&iVersion, sizeof(int), 1, rbl); + std::fread(&iVersion, sizeof(int), 1, rbl); // Version 1.0 if (iVersion == FILE_NODE_VER1) { for (i = 0; i < MAX_NODES; i++) { - fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); + std::fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); for (int n = 0; n < MAX_NEIGHBOURS; n++) { - fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + std::fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); } // save bit flags - fread(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); + std::fread(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); if (Nodes[i].origin != Vector(9999, 9999, 9999)) iMaxUsedNodes = i; @@ -1732,7 +1755,7 @@ void cNodeMachine::load() { AddToMeredian(iX, iY, i); } - fclose(rbl); + std::fclose(rbl); // 04/07/04 // Check for full nodes table @@ -1765,23 +1788,29 @@ void cNodeMachine::ClearImportantGoals() { } // Draw path 0 (user) -void cNodeMachine::path_draw(edict_t *pEntity) { +void cNodeMachine::path_draw(edict_t* pEntity) const +{ //DebugOut("waypoint: waypoint_draw()\n"); int max_drawn = 0; + + // Declare 'start' vector outside the loop Vector start; for (int i = 0; i < MAX_NODES; i++) { - // TODO: iPath appears to be out of bounds [APG]RoboCop[CL] - const int iNode = iPath[draw_nodepath][i]; - const int iNextNode = iPath[draw_nodepath][(i + 1)]; - + const int iNode = iPath[draw_nodepath][i]; + int iNextNode = -1; // Initialize to -1 + + if (i < MAX_NODES - 1) { // Check if i is less than MAX_NODES - 1 + iNextNode = iPath[draw_nodepath][(i + 1)]; + } + if (iNode > -1 && iNextNode > -1) { start = Nodes[iNode].origin; Vector end = Nodes[iNextNode].origin; const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); const int angle_to_waypoint = - FUNC_InFieldOfView(pEntity, (end - pEntity->v.origin)); + FUNC_InFieldOfView(pEntity, end - pEntity->v.origin); if (max_drawn < 39 && good && angle_to_waypoint < 50) { const int red = 255; @@ -1842,7 +1871,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { // within distance and 'reachable' if (tr.flFraction >= 1.0f) { - const double costIncrease = (fDist / NODE_CONTACT_DIST) * NODE_CONTACT_STEP; + const double costIncrease = fDist / NODE_CONTACT_DIST * NODE_CONTACT_STEP; InfoNodes[i].fContact[iTeam] += static_cast(costIncrease); } } @@ -1881,7 +1910,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { // within distance and reachable if (tr.flFraction >= 1.0f) { - const float costIncrease = (fDist / NODE_DANGER_DIST) * NODE_DANGER_STEP; + const float costIncrease = fDist / NODE_DANGER_DIST * NODE_DANGER_STEP; InfoNodes[i].fDanger[iTeam] += costIncrease; } } @@ -2041,17 +2070,16 @@ void cNodeMachine::updateGoals() { // SEARCH PLAYERS FOR ENEMIES for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - + edict_t* pPlayer = INDEXENT(i); + // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; - } - - if (UTIL_IsVip(pPlayer)) { - addGoal(pPlayer, GOAL_VIP, pPlayer->v.origin + Vector(0,0,32)); + if (UTIL_IsVip(pPlayer)) { + addGoal(pPlayer, GOAL_VIP, pPlayer->v.origin + Vector(0, 0, 32)); + } } } rblog("cNodeMachine::updateGoals - FINISHED\n"); @@ -2134,37 +2162,37 @@ void cNodeMachine::setUpInitialGoals() { } // Find a goal, and return the node close to it -tGoal *cNodeMachine::getRandomGoalByType(int goalType) { +tGoal* cNodeMachine::getRandomGoalByType(int goalType) { if (goalType == GOAL_NONE) return nullptr; - + int possibleGoalNodes[MAX_GOALS]; for (int c = 0; c < MAX_GOALS; c++) { possibleGoalNodes[c] = -1; } - + int possibleCandidateIndex = 0; for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { if (Goals[goalIndex].iType == goalType && // type equals requested type Goals[goalIndex].iNode > -1) { // and it has a node -// possibleGoalNodes[possibleCandidateIndex] = Goals[goalIndex].iNode; + // possibleGoalNodes[possibleCandidateIndex] = Goals[goalIndex].iNode; possibleGoalNodes[possibleCandidateIndex] = goalIndex; possibleCandidateIndex++; } } - + if (possibleCandidateIndex == 0) return nullptr; // nothing found :( - + // we have an amount of goals, pick one randomly - const int randomGoalIndex = RANDOM_LONG(0, (possibleCandidateIndex - 1)); - + const int randomGoalIndex = RANDOM_LONG(0, possibleCandidateIndex - 1); + char msg[255]; std::sprintf(msg, "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", - possibleCandidateIndex, goalType, randomGoalIndex); + possibleCandidateIndex, goalType, randomGoalIndex); rblog(msg); - - return getGoal(randomGoalIndex); + + return getGoal(possibleGoalNodes[randomGoalIndex]); } // Contact scaler (on round start) @@ -2274,7 +2302,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn bool pathFound = false; // is it still valid to loop through the lists for pathfinding? - int nodesEvaluated = 0; //Not used? [APG]RoboCop[CL] + int nodesEvaluated = 0; // INIT: End // PATHFINDER: Start while (!pathFound) { @@ -2283,7 +2311,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // go through all OPEN waypoints for (nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { - tNodestar &nodeStar = astar_list[nodeIndex]; + nodesEvaluated++; // increment nodesEvaluated each time a node is evaluated [APG]RoboCop[CL] + tNodestar &nodeStar = astar_list[nodeIndex]; if (nodeStar.state == CLOSED || nodeStar.state == AVAILABLE) continue; @@ -2386,7 +2415,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // INIT: End // Now set the path up correctly - for (nodeIndex = (MAX_NODES - 1); nodeIndex > -1; nodeIndex--) { + for (nodeIndex = MAX_NODES - 1; nodeIndex > -1; nodeIndex--) { const int node = temp_path[nodeIndex]; if (node < 0) continue; @@ -2445,7 +2474,8 @@ void cNodeMachine::closeNode(int nodeIndex, int parent, float cost) { * @param parent * @param cost */ -void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) { +void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) const +{ const tNode &startNode = Nodes[startNodeIndex]; // very start of path const tNode &destNode = Nodes[destinationNodeIndex]; // destination for path @@ -2505,7 +2535,8 @@ void cNodeMachine::makeAllWaypointsAvailable() } // Find a node which has almost no danger! -int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) { +int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const +{ // Use Meredians to search for nodes int iX, iY; VectorToMeredian(vOrigin, &iX, &iY); @@ -2560,7 +2591,7 @@ void cNodeMachine::vis_calculate(int iFrom) { // Check around your area to see what is visible for (int i = 0; i < MAX_NODES; i++) - if ((i != iFrom) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { + if (i != iFrom && Nodes[i].origin != Vector(9999, 9999, 9999)) { const float fClosest = 1024.0f; const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { @@ -2943,7 +2974,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - go back in path... const float timeEvaluatingMoveSpeed = 0.1f; - const bool notStuckForAWhile = (pBot->fNotStuckTime + timeEvaluatingMoveSpeed) < gpGlobals->time; + const bool notStuckForAWhile = pBot->fNotStuckTime + timeEvaluatingMoveSpeed < gpGlobals->time; const double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. // Else it would trigger stuck logic too soon, too often. @@ -2997,7 +3028,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con // JUMP & DUCK // TODO: Add a proper and reliable DuckJump Node [APG]RoboCop[CL] const tNode ¤tNode = Nodes[currentNodeToHeadFor]; - if (BotShouldJumpIfStuck(pBot) || (currentNode.iNodeBits & BIT_JUMP)) { + if (BotShouldJumpIfStuck(pBot) || currentNode.iNodeBits & BIT_JUMP) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Jump tries increased, increase node time - START"); pBot->doJump(vector); pBot->iJumpTries++; @@ -3005,7 +3036,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); return; } - if (BotShouldDuck(pBot) || (currentNode.iNodeBits & BIT_DUCK)) { + if (BotShouldDuck(pBot) || currentNode.iNodeBits & BIT_DUCK) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Duck tries increased, increase node time - START"); pBot->doDuck(); pBot->iDuckTries++; @@ -3013,7 +3044,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "Finished!"); return; } - if (BotShouldDuckJump(pBot) || (currentNode.iNodeBits & BIT_DUCKJUMP)) { + if (BotShouldDuckJump(pBot) || currentNode.iNodeBits & BIT_DUCKJUMP) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "DuckJump tries increased, increase node time - START"); pBot->doDuckJump(); pBot->iDuckJumpTries++; @@ -3316,9 +3347,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->canSeeHostageToRescue()) { pBot->rprint_trace("cNodeMachine::path_think", "has hostage and can see hostage, will not do anything"); return; // bot has hostage, can see hostage - } else { - pBot->rprint_trace("cNodeMachine::path_think", "has hostage to rescue, but can't see it"); } + pBot->rprint_trace("cNodeMachine::path_think", "has hostage to rescue, but can't see it"); } if (pBot->shouldActWithC4()) { @@ -3454,13 +3484,12 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { // not a bot - const cBot *botPointer = &bots[botIndex]; - if (botPointer == nullptr || - !botPointer->bIsUsed || + const cBot* botPointer = &bots[botIndex]; + if (!botPointer->bIsUsed || botPointer == pBot) { // skip self continue; } - + // real bots.. if (pBot->isOnSameTeamAs(botPointer)) { teamMembers++; @@ -3471,7 +3500,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } // add favoriteness - score = (score + (1.0f - (goalAlreadyUsedScore / teamMembers))) / 2.0f; + score = (score + (1.0f - goalAlreadyUsedScore / teamMembers)) / 2.0f; // Goals regardless of map/game type const int goalType = Goals[goalIndex].iType; @@ -3538,7 +3567,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { goalscore = 2.0f; // plant it! } else { const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; - goalscore = (0.7f * mul); + goalscore = 0.7f * mul; } } else if (pBot->isCounterTerrorist()) { @@ -3585,7 +3614,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { pBot->rprint_trace("path_think/determine goal", "Bomb is not planted"); const float mul = fDistanceToGoal / MAX_GOAL_DISTANCE; - goalscore = (0.7f * mul); + goalscore = 0.7f * mul; } } // this is weird? what? @@ -3602,24 +3631,24 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (pBot->isCounterTerrorist()) { if (pBot->vip) { // VIP wants to get out - score = 2.0; + score = 2.0f; } } else { // terrorists pick random score = (score + RANDOM_FLOAT(0.0f, 1.0f)) / 2.0f; } } - + if (goalType == GOAL_VIP) { if (pBot->isCounterTerrorist()) { if (pBot->vip) { score = 0; // do not chase yourself } else { score = 0; // don't care about VIP -// // if distance is too big, go to it. (guard the VIP) -// int maxDistanceWeKeepToVIP = 500; -// float goalScore = maxDistanceWeKeepToVIP / fDistanceToGoal; -// score = (score + goalScore) / 2.0; + // if distance is too big, go to it. (guard the VIP) + const int maxDistanceWeKeepToVIP = 500; + const float goalScore = maxDistanceWeKeepToVIP / fDistanceToGoal; + score = (score + goalScore) / 2.0f; } } } @@ -3872,7 +3901,7 @@ int cNodeMachine::node_cover(int iFrom, int iTo, edict_t *pEdict) { float fClosest = 512; int iClosest = -1; for (int i = 0; i < MAX_NODES; i++) - if ((i != iTo) && (Nodes[i].origin != Vector(9999, 9999, 9999))) { + if (i != iTo && Nodes[i].origin != Vector(9999, 9999, 9999)) { const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { @@ -3936,8 +3965,8 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, // we search for a node that can see the sound node (iFrom) and the origin node (iOrigin) for (int i = 0; i < MAX_NODES; i++) - if ((i != iOrigin && i != iFrom) - && (Nodes[i].origin != Vector(9999, 9999, 9999))) { + if (i != iOrigin && i != iFrom + && Nodes[i].origin != Vector(9999, 9999, 9999)) { if (func_distance(Nodes[i].origin, Nodes[iOrigin].origin) > BOT_HEARDISTANCE) continue; @@ -3990,7 +4019,7 @@ int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, void cNodeMachine::dump_goals() const { rblog("Dump of all goals\n"); - for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { + for (int i = 0; i < MAX_GOALS && Goals[i].iNode >= 0; i++) { char buffer[100]; const Vector v = Nodes[Goals[i].iNode].origin; std::sprintf(buffer, @@ -4046,7 +4075,8 @@ void cNodeMachine::dump_goals() const } // EVY: another dump -void cNodeMachine::dump_path(int iBot, int CurrentPath) { +void cNodeMachine::dump_path(int iBot, int CurrentPath) const +{ char buffer[80]; int i, CurrentNode; @@ -4055,7 +4085,7 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { else CurrentNode = -1; rblog(" Path is: "); - for (i = 0; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { + for (i = 0; i < MAX_NODES && iPath[iBot][i] >= 0; i++) { if (i == CurrentPath) std::sprintf(buffer, "<%d> ", iPath[iBot][i]); else @@ -4081,8 +4111,11 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) { // Graphs from PMB & Botman // width and height of the debug bitmap image -#define DEBUG_BMP_WIDTH 2048 -#define DEBUG_BMP_HEIGHT 2048 +enum +{ + DEBUG_BMP_WIDTH = 2048, + DEBUG_BMP_HEIGHT = 2048 +}; static char *bmp_buffer; static float maxx, maxy, minx, miny; @@ -4097,7 +4130,7 @@ static void InitDebugBitmap() { bmp_buffer = nullptr; bmp_buffer = static_cast(malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)); // allocate memory if (bmp_buffer == nullptr) { - fprintf(stderr, + std::fprintf(stderr, "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024); exit(1); @@ -4109,7 +4142,7 @@ static void InitDebugBitmap() { // Draw a small cross static void DrawPoint(const Vector& v, unsigned char color) { if (bmp_buffer == nullptr) { - fprintf(stderr, + std::fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } @@ -4118,8 +4151,8 @@ static void DrawPoint(const Vector& v, unsigned char color) { const int y0 = static_cast((v.y - miny) / scale); const int offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf(stderr, + if (offset < 0 || offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) { + std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); exit(1); @@ -4148,7 +4181,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsi int fraction; if (bmp_buffer == nullptr) { - fprintf(stderr, + std::fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } @@ -4172,8 +4205,8 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsi stepy = 1; int offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf(stderr, + if (offset < 0 || offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) { + std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); exit(1); @@ -4200,9 +4233,9 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsi // compute the offset in the BMP buffer corresponding to this point offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) - || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf(stderr, + if (offset < 0 + || offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) { + std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); exit(1); @@ -4228,9 +4261,9 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsi // compute the offset in the BMP buffer corresponding to this point offset = y0 * DEBUG_BMP_WIDTH + x0; - if ((offset < 0) - || (offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)) { - fprintf(stderr, + if (offset < 0 + || offset >= DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT) { + std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); exit(1); @@ -4238,7 +4271,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsi bmp_buffer[offset] = color; // set this point to have the specified color } } - return; // finished, segment has been printed into the BMP dot matrix + //return; // finished, segment has been printed into the BMP dot matrix } // from PMB & Botman code @@ -4248,15 +4281,15 @@ static void WriteDebugBitmap(const char *filename) { unsigned long dummy; if (bmp_buffer == nullptr) { - fprintf(stderr, + std::fprintf(stderr, "WriteDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // open (or create) the .bmp file for writing in binary mode... - FILE* fp = fopen(filename, "wb"); + FILE* fp = std::fopen(filename, "wb"); if (fp == nullptr) { - fprintf(stderr, "WriteDebugBitmap(): unable to open BMP file!\n"); -// if (bmp_buffer) + std::fprintf(stderr, "WriteDebugBitmap(): unable to open BMP file!\n"); + // if (bmp_buffer) free(bmp_buffer); // cannot open file, free DXF buffer bmp_buffer = nullptr; return; // cancel if error creating file @@ -4270,25 +4303,25 @@ static void WriteDebugBitmap(const char *filename) { // write the info header dummy = 40; - fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the info header size (does 40 bytes) + std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the info header size (does 40 bytes) dummy = DEBUG_BMP_WIDTH; - fwrite(&dummy, sizeof(long), 1, fp); // write the image width (2000 px) + std::fwrite(&dummy, sizeof(long), 1, fp); // write the image width (2000 px) dummy = DEBUG_BMP_HEIGHT; - fwrite(&dummy, sizeof(long), 1, fp); // write the image height (2000 px) + std::fwrite(&dummy, sizeof(long), 1, fp); // write the image height (2000 px) dummy = 1; - fwrite(&dummy, sizeof(short), 1, fp); // write the # of planes (1) + std::fwrite(&dummy, sizeof(short), 1, fp); // write the # of planes (1) dummy = 8; - fwrite(&dummy, sizeof(short), 1, fp); // write the bit count (8) + std::fwrite(&dummy, sizeof(short), 1, fp); // write the bit count (8) dummy = 0; - fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the compression id (no compression) + std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the compression id (no compression) dummy = DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT; - fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the image size (2000 * 2000) + std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the image size (2000 * 2000) dummy = 0; - fwrite(&dummy, sizeof(long), 1, fp); // write the X pixels per meter (not specified) - fwrite(&dummy, sizeof(long), 1, fp); // write the Y pixels per meter (not specified) + std::fwrite(&dummy, sizeof(long), 1, fp); // write the X pixels per meter (not specified) + std::fwrite(&dummy, sizeof(long), 1, fp); // write the Y pixels per meter (not specified) dummy = 256; - fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of colors used (all) - fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of important colors (wtf ?) + std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of colors used (all) + std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of important colors (wtf ?) // write the color palette (B, G, R, reserved byte) fputc(0x00, fp); @@ -4382,25 +4415,25 @@ static void WriteDebugBitmap(const char *filename) { // write the actual image data data_start = ftell(fp); // get the data start position (that's where we are now) - fwrite(bmp_buffer, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT, 1, fp); // write the image + std::fwrite(bmp_buffer, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT, 1, fp); // write the image file_size = ftell(fp); // get the file size now that the image is dumped // now that we've dumped our data, we know the file size and the data start position fseek(fp, 0, SEEK_SET); // rewind fseek(fp, 2, SEEK_CUR); // skip the BMP header tag "BM" - fwrite(&file_size, sizeof(unsigned long), 1, fp); // write the file size at its location + std::fwrite(&file_size, sizeof(unsigned long), 1, fp); // write the file size at its location fseek(fp, sizeof(short), SEEK_CUR); // skip the first reserved field fseek(fp, sizeof(short), SEEK_CUR); // skip the second reserved field - fwrite(&data_start, sizeof(unsigned long), 1, fp); // write the data start at its location + std::fwrite(&data_start, sizeof(unsigned long), 1, fp); // write the data start at its location - fclose(fp); // finished, close the BMP file + std::fclose(fp); // finished, close the BMP file -// if (bmp_buffer) + // if (bmp_buffer) free(bmp_buffer); // and free the BMP buffer bmp_buffer = nullptr; - return; // and return + //return; // and return } @@ -4411,7 +4444,7 @@ void cNodeMachine::FindMinMax() const minx = miny = 9999.0f; maxx = maxy = -9999.0f; for (int i = 0; - (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); + i < MAX_NODES && Nodes[i].origin != Vector(9999, 9999, 9999); i++) { if (Nodes[i].origin.x > maxx) maxx = Nodes[i].origin.x; @@ -4448,12 +4481,12 @@ void cNodeMachine::MarkAxis() { const int y0 = static_cast((0 - miny) / scale); // Mark X axis by keeping X to 0 and varying Y - if ((minx < 0) && (0 < maxx)) + if (minx < 0 && 0 < maxx) for (int y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x0] += 2; // Mark Y axis by keeping Y to 0 and varying X - if ((miny < 0) && (0 < maxy)) + if (miny < 0 && 0 < maxy) for (int x = 0; x < DEBUG_BMP_WIDTH; x++) bmp_buffer[y0 * DEBUG_BMP_WIDTH + x] += 2; } @@ -4490,21 +4523,22 @@ void cNodeMachine::MarkMeredians() { // Put a cross on all nodes in RBN + draw lines to all neighbours -void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) { +void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) const +{ int i; // Draw all neighbours for (i = 0; - (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); + i < MAX_NODES && Nodes[i].origin != Vector(9999, 9999, 9999); i++) - for (int j = 0; (j < MAX_NEIGHBOURS) && (Nodes[i].iNeighbour[j] >= 0); + for (int j = 0; j < MAX_NEIGHBOURS && Nodes[i].iNeighbour[j] >= 0; j++) DrawLineInDebugBitmap(Nodes[i].origin, Nodes[Nodes[i].iNeighbour[j]].origin, NeighbourColor); // Draw all nodes for (i = 0; - (i < MAX_NODES) && (Nodes[i].origin != Vector(9999, 9999, 9999)); + i < MAX_NODES && Nodes[i].origin != Vector(9999, 9999, 9999); i++) DrawPoint(Nodes[i].origin, NodeColor); } @@ -4513,25 +4547,26 @@ void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) { void cNodeMachine::PlotGoals(int color) const { - for (int i = 0; (i < MAX_GOALS) && (Goals[i].iNode >= 0); i++) { + for (int i = 0; i < MAX_GOALS && Goals[i].iNode >= 0; i++) { const Vector v = Nodes[Goals[i].iNode].origin; DrawPoint(v, color); } } // Plot the computed paths for all life bots -void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) { - for (int iBot = 0; (iBot < 32); iBot++) { +void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) const +{ + for (int iBot = 0; iBot < 32; iBot++) { if (bots[iBot].bIsUsed) { int From = iPath[iBot][0]; if (From < 0) continue; // This bot has not path - for (int i = 1; (i < MAX_NODES) && (iPath[iBot][i] >= 0); i++) { + for (int i = 1; i < MAX_NODES && iPath[iBot][i] >= 0; i++) { const int To = iPath[iBot][i]; DrawLineInDebugBitmap(Nodes[From].origin, Nodes[To].origin, - (bots[iBot].iTeam == - 1) ? Tcolor : CTcolor); + bots[iBot].iTeam == + 1 ? Tcolor : CTcolor); From = To; } } @@ -4544,7 +4579,8 @@ void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) { // 05/07/04 // Marking Axis, Meredians, other colors, other filenames (linked to map names) -void cNodeMachine::Draw() { +void cNodeMachine::Draw() const +{ static int Count = 0; // Static to create filenames like cs_siege0000.bmp, cs_siege0001.bmp, ... char Filename[80]; @@ -4559,7 +4595,8 @@ void cNodeMachine::Draw() { WriteDebugBitmap(Filename); } -void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) { +void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) const +{ pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", "Start"); // check if we have to 'use' it @@ -4613,13 +4650,12 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // Button found to head for! pButtonEdict = pent; break; - } else { - // we hit this button we check for - if (trb.pHit == pent) { - // Button found to head for! - pButtonEdict = pent; - break; - } + } + // we hit this button we check for + if (trb.pHit == pent) { + // Button found to head for! + pButtonEdict = pent; + break; } } } // while (func_button) @@ -4650,11 +4686,10 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) if (trb.flFraction >= 1.0f) { pButtonEdict = pent; break; - } else { - // we hit this button we check for - if (trb.pHit == pent) - isGood = true; } + // we hit this button we check for + if (trb.pHit == pent) + isGood = true; if (isGood) { // Button found to head for! diff --git a/NodeMachine.h b/NodeMachine.h index 3c8fe89..2cafc25 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -49,8 +49,8 @@ class cNodeMachine { int add2(const Vector& vOrigin, int iType, edict_t *pEntity); - int getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict); // returns a close node - int getFurthestNode(const Vector& vOrigin, float fDist, edict_t *pEdict); // returns a node within dist, but most far away + int getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) const; // returns a close node + int getFurthestNode(const Vector& vOrigin, float fDist, const edict_t *pEdict) const; // returns a node within dist, but most far away int getFreeNodeIndex() const; // ----------------- @@ -66,7 +66,7 @@ class cNodeMachine { // ----------------- void init(); // Init (info)nodes - void save() const; // Save nodes on disk + void save() const; // Save nodes on disk void load(); // Load nodes on disk void save_important() const; @@ -81,7 +81,7 @@ class cNodeMachine { bool IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int iFrom, int iTo); - bool hasAttemptedConnectionTooManyTimes(int index); + bool hasAttemptedConnectionTooManyTimes(int index) const; void IncreaseAttemptsForTroubledConnection(int index); bool ClearTroubledConnection(int iFrom, int iTo); @@ -127,28 +127,28 @@ class cNodeMachine { int node_look_at_hear(int iFrom, int iOrigin, edict_t* pEdict); - int node_camp(const Vector& vOrigin, int iTeam); + int node_camp(const Vector& vOrigin, int iTeam) const; void vis_calculate(int iFrom); // ----------------- bool createPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot *pBot, int iFlags); // know the path - void path_draw(edict_t *pEntity); // draw the path + void path_draw(edict_t *pEntity) const; // draw the path void path_walk(cBot *pBot, float distanceMoved); // walk the path void path_think(cBot *pBot, float distanceMoved); // think about paths void path_clear(int botIndex); void ExecuteNearNodeLogic(cBot *pBot); - int getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex); + int getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) const; // ----------------- static void VectorToMeredian(const Vector& vOrigin, int *iX, int *iY); // Input: origin, output X and Y Meredians void AddToMeredian(int iX, int iY, int iNode); // ----------------- - void draw(edict_t *pEntity); // Draw nodes - void connections(edict_t *pEntity); // Draw neighbours + void draw(edict_t *pEntity) const; // Draw nodes + void connections(edict_t *pEntity) const; // Draw neighbours // ----------------- void addNodesForPlayers(); // Players plot around! @@ -167,9 +167,9 @@ class cNodeMachine { // Some debugging by EVY void dump_goals() const; - void dump_path(int iBot, int CurrentPath); + void dump_path(int iBot, int CurrentPath) const; - void Draw(); + void Draw() const; tNode *getNode(int index); @@ -196,16 +196,16 @@ class cNodeMachine { static void MarkMeredians(); - void PlotNodes(int NeighbourColor, int NodeColor); + void PlotNodes(int NeighbourColor, int NodeColor) const; - void PlotPaths(int Tcolor, int CTcolor); + void PlotPaths(int Tcolor, int CTcolor) const; void PlotGoals(int GoalColor) const; static void makeAllWaypointsAvailable(); static void closeNode(int nodeIndex, int parent, float cost); - void openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam); + void openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) const; static char *getGoalTypeAsText(const tGoal &goal); @@ -223,7 +223,7 @@ class cNodeMachine { void ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, const Vector &vector); - void ExecuteDoorInteractionLogic(cBot* pBot, edict_t* pEntityHit); + void ExecuteDoorInteractionLogic(cBot* pBot, edict_t* pEntityHit) const; }; #endif // NODEMACHINE_H diff --git a/bot.cpp b/bot.cpp index 1ca2117..ed3b1af 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1,4547 +1,4557 @@ -/** - * RealBot : Artificial Intelligence - * Version : Work In Progress - * Author : Stefan Hendriks - * Url : http://realbot.bots-united.com - ** - * DISCLAIMER - * - * History, Information & Credits: - * RealBot is based partially upon the HPB-Bot Template #3 by Botman - * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) - * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And - * everybody else who helped me with this project. - * Storage of Visibility Table using BITS by Cheesemonster. - * - * Some portions of code are from other bots, special thanks (and credits) go - * to (in no specific order): - * - * Pierre Marie Baty - * Count - Floyd - * - * !! BOTS-UNITED FOREVER !! - * - * This project is open-source, it is protected under the GPL license; - * By using this source-code you agree that you will ALWAYS release the - * source-code with your project. - * - **/ - - -/* - -//========================================================= -// Returns if enemy can be shoot through some obstacle -//========================================================= -bool CBaseBot::IsShootableThruObstacle(Vector vecDest) -{ - if (!WeaponShootsThru(m_iCurrentWeapon)) - return FALSE; - - Vector vecSrc = EyePosition(); - Vector vecDir = (vecDest - vecSrc).Normalize(); // 1 unit long - Vector vecPoint = g_vecZero; - int iThickness = 0; - int iHits = 0; - - edict_t *pentIgnore = pev->pContainingEntity; - TraceResult tr; - UTIL_TraceLine(vecSrc, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); - - while (tr.flFraction != 1.0 && iHits < 3) - { - iHits++; - iThickness++; - vecPoint = tr.vecEndPos + vecDir; - while (POINT_CONTENTS(vecPoint) == CONTENTS_SOLID && iThickness < 64) - { - vecPoint = vecPoint + vecDir; - iThickness++; - } - UTIL_TraceLine(vecPoint, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); - } - - if (iHits < 3 && iThickness < 64) - { - if (LengthSquared(vecDest - vecPoint) < 12544) - return TRUE; - } - - return FALSE; -} - -*/ - -#include -#include -#include -#include -#include -#include - -#include "bot.h" -#include "bot_weapons.h" -#include "bot_func.h" - -#include "game.h" -#include "NodeMachine.h" -#include "ChatEngine.h" - -#include -#include - -extern edict_t *pHostEdict; -extern int mod_id; -extern bool internet_play; -extern cGame Game; -extern cNodeMachine NodeMachine; -extern cChatEngine ChatEngine; -extern int counterstrike; -//static FILE *fp; -extern bool autoskill; - -/* Radio issue - Credit by Ditlew (NNBOT - Rest In Peace) */ -bool radio_message = false; -char *message = static_cast(malloc(64 * sizeof(char))); -char radio_messenger[30]; - -// random boundries -extern int random_max_skill; -extern int random_min_skill; -cBot bots[32]; // max of 32 bots in a game - -// External added variables -extern bool end_round; // End round - -#ifndef _WIN32 -#define _snprintf snprintf -#endif - -cBot::cBot() { - pBotHostage = nullptr; - fMoveToNodeTime = -1; - clearHostages(); -} - -/****************************************************************************** - Function purpose: Initializes bot vars on spawn - ******************************************************************************/ -void cBot::SpawnInit() { - rprint_trace("SpawnInit()", "START"); - - // ------------------------ - // TIMERS - // ------------------------ - fUpdateTime = gpGlobals->time; - fLastRunPlayerMoveTime = gpGlobals->time - 0.1f; - fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); - fMemoryTime = gpGlobals->time; - fDoRadio = gpGlobals->time; - const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); - fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; - f_shoot_wait_time = gpGlobals->time; - f_goback_time = gpGlobals->time; - f_may_jump_time = gpGlobals->time; - fCheckHostageStatusTimer = gpGlobals->time; - f_defuse = gpGlobals->time; - f_allow_keypress = gpGlobals->time; - f_use_timer = gpGlobals->time; - f_light_time = gpGlobals->time; - f_sec_weapon = gpGlobals->time; - f_prim_weapon = gpGlobals->time; - f_gren_time = gpGlobals->time; - f_walk_time = gpGlobals->time; - f_hear_time = gpGlobals->time; - freezeTime = gpGlobals->time - 1; - f_cover_time = gpGlobals->time; - f_c4_time = gpGlobals->time; - f_update_weapon_time = gpGlobals->time; - f_follow_time = gpGlobals->time; - f_jump_time = 0.0f; - f_hold_duck = gpGlobals->time; - f_camp_time = gpGlobals->time; - f_wait_time = gpGlobals->time; - f_bot_see_enemy_time = gpGlobals->time; - f_bot_find_enemy_time = gpGlobals->time; - f_shoot_time = gpGlobals->time; - fMoveToNodeTime = -1; - nodeTimeIncreasedAmount = 0; - distanceMovedTimer = gpGlobals->time; - distanceMoved = 0; - fBlindedTime = gpGlobals->time; - f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); - fWanderTime = gpGlobals->time; - f_strafe_time = gpGlobals->time; - - // Personality Related (these gets changed when loading personality file) - fpXOffset = 0.0f; - fpYOffset = 0.0f; - fpZOffset = 0.0f; - fpMinReactTime = 0.0f; - fpMaxReactTime = 0.0f; - - // ------------------------ - // POINTERS - // ------------------------ - pButtonEdict = nullptr; - pBotHostage = nullptr; - clearHostages(); - pEnemyEdict = nullptr; - - // chat - std::memset(chChatSentence, 0, sizeof(chChatSentence)); - - - // ------------------------ - // INTEGERS - // ------------------------ - iGoalNode = -1; - goalIndex = -1; - iPreviousGoalNode = -1; - iCloseNode = -1; - iDiedNode = -1; - - iTeam = -1; - bot_class = -1; - i_camp_style = 0; - iPrimaryWeapon = -1; - iSecondaryWeapon = -1; - zoomed = ZOOM_NONE; - play_rounds = RANDOM_LONG(Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); - bot_health = 0; - prev_health = 0; - bot_armor = 0; - bot_weapons = 0; - bot_use_special = 0 + RANDOM_LONG(0, 2); - console_nr = 0; - pathIndex = -1; - iPathFlags = PATH_DANGER; - - // Smarter Stuck stuff - iDuckTries = 0; - iJumpTries = 0; - - // ------------------------ - // BOOLEANS - // ------------------------ - vip = UTIL_IsVip(pEdict); - bWalkKnife = false; - buy_ammo_primary = true; - buy_ammo_secondary = true; - buy_primary = !Game.bPistols; //30/07/04: Josh, handle the pistols only mode - buy_secondary = Game.bPistols; - buy_armor = false; - buy_defusekit = false; - bFirstOutOfSight = false; - buy_grenade = false; - buy_smokegrenade = false; - - buy_flashbang = 0; - if (RANDOM_LONG(0, 100) < ipWalkWithKnife) { - bWalkKnife = true; - } - - if (UTIL_GetTeam(pEdict) == 1) { - if (RANDOM_LONG(0, 100) < ipBuyDefuseKit) { - buy_defusekit = true; - } - } - - if (RANDOM_LONG(0, 100) < ipBuyGrenade) { - buy_grenade = true; - } - - // 31.08.04 Frashman added Support for Smoke Grenade - if (RANDOM_LONG(0, 100) < ipBuySmokeGren) { - buy_smokegrenade = true; - } - - if (RANDOM_LONG(0, 100) < ipBuyFlashBang) { - buy_flashbang = 2; - - } - - if (RANDOM_LONG(0, 100) < 15 || Game.bPistols) - buy_secondary = true; - - // ------------------------ - // HUD - // ------------------------ - bHUD_C4_plantable = false; // Get's init'ed anyway... // BERKED - - // ------------------------ - // FLOATS - // ------------------------ - f_strafe_speed = 0.0f; - f_max_speed = CVAR_GET_FLOAT("sv_maxspeed"); - - // ------------------------ - // VECTORS - // ------------------------ - prevOrigin = Vector(9999.0, 9999.0, 9999.0); - lastSeenEnemyVector = Vector(0, 0, 0); - vEar = Vector(9999, 9999, 9999); - - // ------------------------ - // CHAR - // ------------------------ - arg1[0] = 0; - arg2[0] = 0; - arg3[0] = 0; - std::memset(&(current_weapon), 0, sizeof(current_weapon)); - std::memset(&(m_rgAmmo), 0, sizeof(m_rgAmmo)); - - rprint_trace("SpawnInit()", "END"); -} - -/****************************************************************************** - Function purpose: Initializes bot vars on new round - ******************************************************************************/ -void cBot::NewRound() { - rprint_trace("NewRound()", "START"); - - // ------------------------ - // TIMERS - // ------------------------ - fUpdateTime = gpGlobals->time; - fLastRunPlayerMoveTime = gpGlobals->time; - fCheckHostageStatusTimer = gpGlobals->time; - fButtonTime = gpGlobals->time; - fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); - fMemoryTime = gpGlobals->time; - fDoRadio = gpGlobals->time; - const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); - fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; - f_shoot_wait_time = gpGlobals->time; - f_goback_time = gpGlobals->time; - f_may_jump_time = gpGlobals->time; - f_defuse = gpGlobals->time; - f_allow_keypress = gpGlobals->time; - f_use_timer = gpGlobals->time; - f_light_time = gpGlobals->time; - f_sec_weapon = gpGlobals->time; - f_prim_weapon = gpGlobals->time; - f_gren_time = gpGlobals->time; - f_walk_time = gpGlobals->time; - f_hear_time = gpGlobals->time; - freezeTime = gpGlobals->time - 1; - f_cover_time = gpGlobals->time; - f_c4_time = gpGlobals->time; - f_update_weapon_time = gpGlobals->time; - f_follow_time = gpGlobals->time; - f_jump_time = 0.0f; - f_hold_duck = gpGlobals->time - 1; - f_camp_time = gpGlobals->time; - f_wait_time = gpGlobals->time; - f_bot_see_enemy_time = gpGlobals->time; - f_bot_find_enemy_time = gpGlobals->time; - f_shoot_time = gpGlobals->time; - fMoveToNodeTime = -1; - nodeTimeIncreasedAmount = 0; - distanceMovedTimer = gpGlobals->time; - distanceMoved = 0; - fBlindedTime = gpGlobals->time; - f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); - fWanderTime = gpGlobals->time; - f_strafe_time = gpGlobals->time; - - // ------------------------ - // POINTERS - // ------------------------ - pButtonEdict = nullptr; - pBotHostage = nullptr; - clearHostages(); - pEnemyEdict = nullptr; - - // ------------------------ - // INTEGERS - // ------------------------ - i_camp_style = 0; - iPrimaryWeapon = -1; - iSecondaryWeapon = -1; - zoomed = ZOOM_NONE; - bot_health = 0; - prev_health = 0; - bot_armor = 0; -// bot_weapons = 0; // <- stefan: prevent from buying new stuff every round! - console_nr = 0; - pathIndex = -1; - iGoalNode = -1; - goalIndex = -1; - iPreviousGoalNode = -1; - iCloseNode = -1; - - - // Smarter Stuck stuff - iDuckTries = 0; - iJumpTries = 0; - - if (RANDOM_LONG(0, 100) < ipFearRate) - iPathFlags = PATH_DANGER; - else - iPathFlags = PATH_NONE; - - // ------------------------ - // BOOLEANS - // ------------------------ - - // chat - std::memset(chChatSentence, 0, sizeof(chChatSentence)); - - vip = UTIL_IsVip(pEdict); - - // Every round consider - bWalkKnife = false; - - if (RANDOM_LONG(0, 100) < ipWalkWithKnife) - bWalkKnife = true; - - // Buying - buy_ammo_primary = true; - buy_ammo_secondary = true; - buy_primary = !Game.bPistols; - buy_grenade = false; - buy_smokegrenade = false; - buy_flashbang = 0; - buy_secondary = Game.bPistols; - buy_armor = false; - buy_defusekit = false; - - if (UTIL_GetTeam(pEdict) == 1) - if (RANDOM_LONG(0, 100) < ipBuyDefuseKit) - buy_defusekit = true; - - if (RANDOM_LONG(0, 100) < ipBuyArmour) - buy_armor = true; - - if (RANDOM_LONG(0, 100) < ipBuyGrenade) - buy_grenade = true; - - if (RANDOM_LONG(0, 100) < ipBuySmokeGren) - buy_smokegrenade = true; - - if (RANDOM_LONG(0, 100) < ipBuyFlashBang) - buy_flashbang = 2; - - - bFirstOutOfSight = false; - - - f_strafe_speed = 0.0f; - - // ------------------------ - // VECTORS - // ------------------------ - prevOrigin = Vector(9999.0f, 9999.0f, 9999.0f); - lastSeenEnemyVector = Vector(0, 0, 0); - vEar = Vector(9999, 9999, 9999); - - // ------------------------ - // CHAR - // ------------------------ - arg1[0] = 0; - arg2[0] = 0; - arg3[0] = 0; - - // initalize a few other stuff - NodeMachine.path_clear(iBotIndex); - iPathFlags = PATH_NONE; - - played_rounds++; - - // hello dudes - if (played_rounds == 1) { - // do some chatting - if (RANDOM_LONG(0, 100) < (ipChatRate + 10)) { - // we should say something now? - int iMax = -1; - - for (int tc = 0; tc < 50; tc++) { - if (ChatEngine.ReplyBlock[98].sentence[tc][0] != '\0') - iMax++; - } - - const int the_c = RANDOM_LONG(0, iMax); - - if (the_c > -1 && iMax > -1) { - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); - std::sprintf(chSentence, "%s ", - ChatEngine.ReplyBlock[98].sentence[the_c]); - PrepareChat(chSentence); - } - } - } - - clearHostages(); - clearHostageToRescueTarget(); - - rprint("NewRound", "Initialization new round finished"); -} - -/****************************************************************************** - Function purpose: Returns a random chat sentence and stores it into 'sentence' - ******************************************************************************/ -void cBot::PrepareChat(char sentence[128]) { - if (Game.iProducedSentences <= Game.iMaxSentences) { - // makes bot chat away - fChatTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); - std::strcpy(chChatSentence, sentence); // copy this - Game.iProducedSentences++; - } -} - -/****************************************************************************** - Function purpose: Return reaction time based upon skill - ******************************************************************************/ -float cBot::ReactionTime(int iSkill) { - const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); - if (Game.messageVerbosity > 1) { - char msg[255]; - std::sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); - rprint_trace("ReactionTime()", msg); - } - return time; -} - -/****************************************************************************** - Function purpose: Finds a (new) enemy - ******************************************************************************/ -int cBot::FindEnemy() { - // When on ladder, do not search for enemies - if (isOnLadder()) - return -1; - - // When blinded we cannot search for enemies - if (fBlindedTime > gpGlobals->time) - return -1; - float fNearestDistance = 9999; // Nearest distance - edict_t *pNewEnemy = nullptr; // New enemy found - - // SEARCH PLAYERS FOR ENEMIES - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - - // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - - // skip this player if not alive (i.e. dead or dying) - if (!IsAlive(pPlayer)) - continue; - - Vector vVecEnd = pPlayer->v.origin + pPlayer->v.view_ofs; - - // if bot can see the player... - if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) { - const int player_team = UTIL_GetTeam(pPlayer); - const int bot_team = UTIL_GetTeam(pEdict); - - if (player_team == bot_team) { - // do not target teammates - continue; - } - - // It's not a friend, track enemy - const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); - bool bCanSee = true; - - // The further away, the less chance we see this enemy - // Uncomment the following lines if you want to add distance-based visibility check - // if (RANDOM_FLOAT(0, 1.0) < (fDistance / 4096)) { - // bCanSee = false; - // } - - // If the bot carries a sniper, always consider the enemy visible - if (CarryWeaponType() == SNIPER) { - bCanSee = true; - } - +/** + * RealBot : Artificial Intelligence + * Version : Work In Progress + * Author : Stefan Hendriks + * Url : http://realbot.bots-united.com + ** + * DISCLAIMER + * + * History, Information & Credits: + * RealBot is based partially upon the HPB-Bot Template #3 by Botman + * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) + * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And + * everybody else who helped me with this project. + * Storage of Visibility Table using BITS by Cheesemonster. + * + * Some portions of code are from other bots, special thanks (and credits) go + * to (in no specific order): + * + * Pierre Marie Baty + * Count - Floyd + * + * !! BOTS-UNITED FOREVER !! + * + * This project is open-source, it is protected under the GPL license; + * By using this source-code you agree that you will ALWAYS release the + * source-code with your project. + * + **/ + + +/* + +//========================================================= +// Returns if enemy can be shoot through some obstacle +//========================================================= +bool CBaseBot::IsShootableThruObstacle(Vector vecDest) +{ + if (!WeaponShootsThru(m_iCurrentWeapon)) + return FALSE; + + Vector vecSrc = EyePosition(); + Vector vecDir = (vecDest - vecSrc).Normalize(); // 1 unit long + Vector vecPoint = g_vecZero; + int iThickness = 0; + int iHits = 0; + + edict_t *pentIgnore = pev->pContainingEntity; + TraceResult tr; + UTIL_TraceLine(vecSrc, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); + + while (tr.flFraction != 1.0 && iHits < 3) + { + iHits++; + iThickness++; + vecPoint = tr.vecEndPos + vecDir; + while (POINT_CONTENTS(vecPoint) == CONTENTS_SOLID && iThickness < 64) + { + vecPoint = vecPoint + vecDir; + iThickness++; + } + UTIL_TraceLine(vecPoint, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); + } + + if (iHits < 3 && iThickness < 64) + { + if (LengthSquared(vecDest - vecPoint) < 12544) + return TRUE; + } + + return FALSE; +} + +*/ + +#include +#include +#include +#include +#include +#include + +#include "bot.h" +#include "bot_weapons.h" +#include "bot_func.h" + +#include "game.h" +#include "NodeMachine.h" +#include "ChatEngine.h" + +#include +#include + +extern edict_t *pHostEdict; +extern int mod_id; +extern bool internet_play; +extern cGame Game; +extern cNodeMachine NodeMachine; +extern cChatEngine ChatEngine; +extern int counterstrike; +//static FILE *fp; +extern bool autoskill; + +/* Radio issue + Credit by Ditlew (NNBOT - Rest In Peace) */ +bool radio_message = false; +char *message = static_cast(malloc(64 * sizeof(char))); +char radio_messenger[30]; + +// random boundries +extern int random_max_skill; +extern int random_min_skill; +cBot bots[32]; // max of 32 bots in a game + +// External added variables +extern bool end_round; // End round + +#ifndef _WIN32 +#define snprintf std::snprintf //-V1059 +#endif + +cBot::cBot() { + pBotHostage = nullptr; + fMoveToNodeTime = -1; + clearHostages(); +} + +/****************************************************************************** + Function purpose: Initializes bot vars on spawn + ******************************************************************************/ +void cBot::SpawnInit() { + rprint_trace("SpawnInit()", "START"); + + // ------------------------ + // TIMERS + // ------------------------ + fUpdateTime = gpGlobals->time; + fLastRunPlayerMoveTime = gpGlobals->time - 0.1f; + fButtonTime = gpGlobals->time; + fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); + fMemoryTime = gpGlobals->time; + fDoRadio = gpGlobals->time; + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; + f_shoot_wait_time = gpGlobals->time; + f_goback_time = gpGlobals->time; + f_may_jump_time = gpGlobals->time; + fCheckHostageStatusTimer = gpGlobals->time; + f_defuse = gpGlobals->time; + f_allow_keypress = gpGlobals->time; + f_use_timer = gpGlobals->time; + f_light_time = gpGlobals->time; + f_sec_weapon = gpGlobals->time; + f_prim_weapon = gpGlobals->time; + f_gren_time = gpGlobals->time; + f_walk_time = gpGlobals->time; + f_hear_time = gpGlobals->time; + freezeTime = gpGlobals->time - 1; + f_cover_time = gpGlobals->time; + f_c4_time = gpGlobals->time; + f_update_weapon_time = gpGlobals->time; + f_follow_time = gpGlobals->time; + f_jump_time = 0.0f; + f_hold_duck = gpGlobals->time; + f_camp_time = gpGlobals->time; + f_wait_time = gpGlobals->time; + f_bot_see_enemy_time = gpGlobals->time; + f_bot_find_enemy_time = gpGlobals->time; + f_shoot_time = gpGlobals->time; + fMoveToNodeTime = -1; + nodeTimeIncreasedAmount = 0; + distanceMovedTimer = gpGlobals->time; + distanceMoved = 0; + fBlindedTime = gpGlobals->time; + f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); + fWanderTime = gpGlobals->time; + f_strafe_time = gpGlobals->time; + + // Personality Related (these gets changed when loading personality file) + fpXOffset = 0.0f; + fpYOffset = 0.0f; + fpZOffset = 0.0f; + fpMinReactTime = 0.0f; + fpMaxReactTime = 0.0f; + + // ------------------------ + // POINTERS + // ------------------------ + pButtonEdict = nullptr; + pBotHostage = nullptr; + clearHostages(); + pEnemyEdict = nullptr; + + // chat + std::memset(chChatSentence, 0, sizeof(chChatSentence)); + + + // ------------------------ + // INTEGERS + // ------------------------ + iGoalNode = -1; + goalIndex = -1; + iPreviousGoalNode = -1; + iCloseNode = -1; + iDiedNode = -1; + + iTeam = -1; + bot_class = -1; + i_camp_style = 0; + iPrimaryWeapon = -1; + iSecondaryWeapon = -1; + zoomed = ZOOM_NONE; + play_rounds = RANDOM_LONG(Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); + bot_health = 0; + prev_health = 0; + bot_armor = 0; + bot_weapons = 0; + bot_use_special = 0 + RANDOM_LONG(0, 2); + console_nr = 0; + pathIndex = -1; + iPathFlags = PATH_DANGER; + + // Smarter Stuck stuff + iDuckTries = 0; + iJumpTries = 0; + + // ------------------------ + // BOOLEANS + // ------------------------ + vip = UTIL_IsVip(pEdict); + bWalkKnife = false; + buy_ammo_primary = true; + buy_ammo_secondary = true; + buy_primary = !Game.bPistols; //30/07/04: Josh, handle the pistols only mode + buy_secondary = Game.bPistols; + buy_armor = false; + buy_defusekit = false; + bFirstOutOfSight = false; + buy_grenade = false; + buy_smokegrenade = false; + + buy_flashbang = 0; + if (RANDOM_LONG(0, 100) < ipWalkWithKnife) { + bWalkKnife = true; + } + + if (UTIL_GetTeam(pEdict) == 1) { + if (RANDOM_LONG(0, 100) < ipBuyDefuseKit) { + buy_defusekit = true; + } + } + + if (RANDOM_LONG(0, 100) < ipBuyGrenade) { + buy_grenade = true; + } + + // 31.08.04 Frashman added Support for Smoke Grenade + if (RANDOM_LONG(0, 100) < ipBuySmokeGren) { + buy_smokegrenade = true; + } + + if (RANDOM_LONG(0, 100) < ipBuyFlashBang) { + buy_flashbang = 2; + + } + + if (RANDOM_LONG(0, 100) < 15 || Game.bPistols) + buy_secondary = true; + + // ------------------------ + // HUD + // ------------------------ + bHUD_C4_plantable = false; // Get's init'ed anyway... // BERKED + + // ------------------------ + // FLOATS + // ------------------------ + f_strafe_speed = 0.0f; + f_max_speed = CVAR_GET_FLOAT("sv_maxspeed"); + + // ------------------------ + // VECTORS + // ------------------------ + prevOrigin = Vector(9999.0, 9999.0, 9999.0); + lastSeenEnemyVector = Vector(0, 0, 0); + vEar = Vector(9999, 9999, 9999); + + // ------------------------ + // CHAR + // ------------------------ + arg1[0] = 0; + arg2[0] = 0; + arg3[0] = 0; + std::memset(&(current_weapon), 0, sizeof(current_weapon)); + std::memset(&(m_rgAmmo), 0, sizeof(m_rgAmmo)); + + rprint_trace("SpawnInit()", "END"); +} + +/****************************************************************************** + Function purpose: Initializes bot vars on new round + ******************************************************************************/ +void cBot::NewRound() { + rprint_trace("NewRound()", "START"); + + // ------------------------ + // TIMERS + // ------------------------ + fUpdateTime = gpGlobals->time; + fLastRunPlayerMoveTime = gpGlobals->time; + fCheckHostageStatusTimer = gpGlobals->time; + fButtonTime = gpGlobals->time; + fChatTime = gpGlobals->time + RANDOM_FLOAT(2.5f, 5.0f); + fMemoryTime = gpGlobals->time; + fDoRadio = gpGlobals->time; + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + fNotStuckTime = gpGlobals->time + freezeTimeCVAR + 0.5f; + f_shoot_wait_time = gpGlobals->time; + f_goback_time = gpGlobals->time; + f_may_jump_time = gpGlobals->time; + f_defuse = gpGlobals->time; + f_allow_keypress = gpGlobals->time; + f_use_timer = gpGlobals->time; + f_light_time = gpGlobals->time; + f_sec_weapon = gpGlobals->time; + f_prim_weapon = gpGlobals->time; + f_gren_time = gpGlobals->time; + f_walk_time = gpGlobals->time; + f_hear_time = gpGlobals->time; + freezeTime = gpGlobals->time - 1; + f_cover_time = gpGlobals->time; + f_c4_time = gpGlobals->time; + f_update_weapon_time = gpGlobals->time; + f_follow_time = gpGlobals->time; + f_jump_time = 0.0f; + f_hold_duck = gpGlobals->time - 1; + f_camp_time = gpGlobals->time; + f_wait_time = gpGlobals->time; + f_bot_see_enemy_time = gpGlobals->time; + f_bot_find_enemy_time = gpGlobals->time; + f_shoot_time = gpGlobals->time; + fMoveToNodeTime = -1; + nodeTimeIncreasedAmount = 0; + distanceMovedTimer = gpGlobals->time; + distanceMoved = 0; + fBlindedTime = gpGlobals->time; + f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.1f, 0.9f); + fWanderTime = gpGlobals->time; + f_strafe_time = gpGlobals->time; + + // ------------------------ + // POINTERS + // ------------------------ + pButtonEdict = nullptr; + pBotHostage = nullptr; + clearHostages(); + pEnemyEdict = nullptr; + + // ------------------------ + // INTEGERS + // ------------------------ + i_camp_style = 0; + iPrimaryWeapon = -1; + iSecondaryWeapon = -1; + zoomed = ZOOM_NONE; + bot_health = 0; + prev_health = 0; + bot_armor = 0; +// bot_weapons = 0; // <- stefan: prevent from buying new stuff every round! + console_nr = 0; + pathIndex = -1; + iGoalNode = -1; + goalIndex = -1; + iPreviousGoalNode = -1; + iCloseNode = -1; + + + // Smarter Stuck stuff + iDuckTries = 0; + iJumpTries = 0; + + if (RANDOM_LONG(0, 100) < ipFearRate) + iPathFlags = PATH_DANGER; + else + iPathFlags = PATH_NONE; + + // ------------------------ + // BOOLEANS + // ------------------------ + + // chat + std::memset(chChatSentence, 0, sizeof(chChatSentence)); + + vip = UTIL_IsVip(pEdict); + + // Every round consider + bWalkKnife = false; + + if (RANDOM_LONG(0, 100) < ipWalkWithKnife) + bWalkKnife = true; + + // Buying + buy_ammo_primary = true; + buy_ammo_secondary = true; + buy_primary = !Game.bPistols; + buy_grenade = false; + buy_smokegrenade = false; + buy_flashbang = 0; + buy_secondary = Game.bPistols; + buy_armor = false; + buy_defusekit = false; + + if (UTIL_GetTeam(pEdict) == 1) + if (RANDOM_LONG(0, 100) < ipBuyDefuseKit) + buy_defusekit = true; + + if (RANDOM_LONG(0, 100) < ipBuyArmour) + buy_armor = true; + + if (RANDOM_LONG(0, 100) < ipBuyGrenade) + buy_grenade = true; + + if (RANDOM_LONG(0, 100) < ipBuySmokeGren) + buy_smokegrenade = true; + + if (RANDOM_LONG(0, 100) < ipBuyFlashBang) + buy_flashbang = 2; + + + bFirstOutOfSight = false; + + + f_strafe_speed = 0.0f; + + // ------------------------ + // VECTORS + // ------------------------ + prevOrigin = Vector(9999.0f, 9999.0f, 9999.0f); + lastSeenEnemyVector = Vector(0, 0, 0); + vEar = Vector(9999, 9999, 9999); + + // ------------------------ + // CHAR + // ------------------------ + arg1[0] = 0; + arg2[0] = 0; + arg3[0] = 0; + + // initalize a few other stuff + NodeMachine.path_clear(iBotIndex); + iPathFlags = PATH_NONE; + + played_rounds++; + + // hello dudes + if (played_rounds == 1) { + // do some chatting + if (RANDOM_LONG(0, 100) < (ipChatRate + 10)) { + // we should say something now? + int iMax = -1; + + for (int tc = 0; tc < 50; tc++) { + if (ChatEngine.ReplyBlock[98].sentence[tc][0] != '\0') + iMax++; + } + + const int the_c = RANDOM_LONG(0, iMax); + + if (the_c > -1 && iMax > -1) { + char chSentence[80]; + std::memset(chSentence, 0, sizeof(chSentence)); + snprintf(chSentence, sizeof(chSentence), "%s ", ChatEngine.ReplyBlock[98].sentence[the_c]); + PrepareChat(chSentence); + } + } + } + + clearHostages(); + clearHostageToRescueTarget(); + + rprint("NewRound", "Initialization new round finished"); +} + +/****************************************************************************** + Function purpose: Returns a random chat sentence and stores it into 'sentence' + ******************************************************************************/ +void cBot::PrepareChat(char sentence[128]) { + if (Game.iProducedSentences <= Game.iMaxSentences) { + // makes bot chat away + fChatTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); + std::strcpy(chChatSentence, sentence); // copy this + Game.iProducedSentences++; + } +} + +/****************************************************************************** + Function purpose: Return reaction time based upon skill + ******************************************************************************/ +float cBot::ReactionTime(int iSkill) { + const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); + if (Game.messageVerbosity > 1) { + char msg[255]; + std::sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); + rprint_trace("ReactionTime()", msg); + } + return time; +} + +/****************************************************************************** + Function purpose: Finds a (new) enemy + ******************************************************************************/ +int cBot::FindEnemy() { + // When on ladder, do not search for enemies + if (isOnLadder()) + return -1; + + // When blinded we cannot search for enemies + if (fBlindedTime > gpGlobals->time) + return -1; + float fNearestDistance = 9999; // Nearest distance + edict_t *pNewEnemy = nullptr; // New enemy found + + // SEARCH PLAYERS FOR ENEMIES + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t *pPlayer = INDEXENT(i); + + // skip invalid players and skip self (i.e. this bot) + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { + + // skip this player if not alive (i.e. dead or dying) + if (!IsAlive(pPlayer)) + continue; + + Vector vVecEnd = pPlayer->v.origin + pPlayer->v.view_ofs; + + // if bot can see the player... + if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) { + const int player_team = UTIL_GetTeam(pPlayer); + const int bot_team = UTIL_GetTeam(pEdict); + + if (player_team == bot_team) { + // do not target teammates + continue; + } + + // It's not a friend, track enemy + const float fDistance = (pPlayer->v.origin - pEdict->v.origin).Length(); + bool bCanSee = true; + + // The further away, the less chance we see this enemy + // Uncomment the following lines if you want to add distance-based visibility check + // if (RANDOM_FLOAT(0, 1.0) < (fDistance / 4096)) { + // bCanSee = false; + // } + + // If the bot carries a sniper, always consider the enemy visible + if (CarryWeaponType() != SNIPER) { + // bCanSee = true; + } + if (fDistance < fNearestDistance && bCanSee) { - fNearestDistance = fDistance; - pNewEnemy = pPlayer; - } - } - } // valid player - } // FOR - - // We found a new enemy & the new enemy is different then previous pointer - if (pNewEnemy && pNewEnemy != pEnemyEdict) { - const int iCurrentNode = determineCurrentNode(); - - // Add 'contact' data - if (iCurrentNode > -1) { - NodeMachine.contact(iCurrentNode, UTIL_GetTeam(pEdict)); - } - - // We have a reaction time to this new enemy - rememberEnemyFound(); - f_shoot_time = gpGlobals->time + ReactionTime(bot_skill); - pEnemyEdict = pNewEnemy; // Update pointer - - // We did not have an enemy before - if (pEnemyEdict == nullptr) { - rprint_trace("FindEnemy()", "Found new enemy"); - - // RADIO: When we found a NEW enemy but NOT via a friend - if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "2", ""); - } - - // We found a new enemy - return 0; - } else { - // we found an enemy that is newer/more dangerous then previous - rprint_trace("FindEnemy()", "Found 'newer' enemy"); - return 3; - } - } - - // nothing found - return -1; // return result -} - -void cBot::rememberEnemyFound() { - f_bot_find_enemy_time = gpGlobals->time + REMEMBER_ENEMY_TIME; -} - -/****************************************************************************** - Function purpose: Sets vHead to aim at vector - ******************************************************************************/ -void cBot::setHeadAiming(const Vector& vTarget) { - vHead = vTarget; -} - -/** - * Returns true / false whether enemy is alive. - * @return - */ -bool cBot::isEnemyAlive() const -{ - return IsAlive(pEnemyEdict); -} - -bool cBot::isSeeingEnemy() { - if (!hasEnemy()) { - this->rprint("canSeeEnemy called without having enemy?"); - return false; - } - - if (isBlindedByFlashbang()) { - return false; - } - - Vector vBody = pEnemyEdict->v.origin; - Vector vHead = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs; - - const bool bodyInFOV = FInViewCone(&vBody, pEdict) && FVisible(vBody, pEdict); - const bool headInFOV = FInViewCone(&vHead, pEdict) && FVisible(vHead, pEdict); - if (bodyInFOV || headInFOV) { - return true; - } - return false; -} - -/****************************************************************************** - Function purpose: Aims at enemy, only when valid. Based upon skill how it 'aims' - ******************************************************************************/ -void cBot::AimAtEnemy() { - if (!hasEnemy()) - return; - - // We cannot see our enemy? -> bail out - if (isSeeingEnemy()) { - setHeadAiming(lastSeenEnemyVector); // look at last known vector of enemy - return; - } - - // Distance to enemy - const float fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero - - // factor in distance, the further away the more deviation - which is based on skill - const int skillReversed = (10 - bot_skill) + 1; - float fScale = 0.5f + (fDistance / static_cast(64 * - skillReversed)); // a good skilled bot is less impacted by distance than a bad skilled bot - - if (CarryWeaponType() == SNIPER) fScale *= 0.80f; // sniping improves aiming - - // Set target here - Vector vTarget; - if (bot_skill <= 1) - vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-0.5f, 1.1f); // aim for the head - else if (bot_skill > 1 && bot_skill < 4) - vTarget = pEnemyEdict->v.origin + - pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy - else - vTarget = pEnemyEdict->v.origin; // aim for body - - // Based upon how far, we make this fuzzy - float fDy, fDz; - float fDx = fDy = fDz = static_cast(bot_skill + 1) * fScale; - - // Example 1: - // Super skilled bot (bot_skill 1), with enemy of 2048 units away. Results into: - // skillReversed = (10 - 0 + 1) == 11 - // fScale = 2048 / (128 * 11) -> 2048 / 1408 => 1.454545 - // fd* = 0.5 + 1 * 1,95 - - // Example 2, less skilled bot (skill = 3) same enemy - // skillReversed = (10 - 3 + 1) == 8 - // fScale = 2048 / (128 * 8) -> 2048 / 1024 => 2 - // fd* = 3 * 2 - - vTarget = vTarget + Vector( - RANDOM_FLOAT(-fDx, fDx), - RANDOM_FLOAT(-fDy, fDy), - RANDOM_FLOAT(-fDz, fDz) - ); - - // Add Offset - fDx = fpXOffset; - fDy = fpYOffset; - fDz = fpZOffset; - - // increase offset with personality x,y,z offsets randomly - vTarget = vTarget + Vector( - RANDOM_FLOAT(-fDx, fDx), - RANDOM_FLOAT(-fDy, fDy), - RANDOM_FLOAT(-fDz, fDz) - ); - - if (isHoldingGrenadeOrFlashbang()) { - // aim a bit higher - vTarget = vTarget + Vector(0, 0, 50); - } - - setHeadAiming(vTarget); -} - -bool cBot::isBlindedByFlashbang() const { - return fBlindedTime > gpGlobals->time; -} - -bool cBot::isHoldingGrenadeOrFlashbang() const { - return current_weapon.iId == CS_WEAPON_HEGRENADE || current_weapon.iId == CS_WEAPON_FLASHBANG; -} - -/****************************************************************************** - Function purpose: Perform fighting actions - ******************************************************************************/ -void cBot::FightEnemy() { - // We can see our enemy - if (!isBlindedByFlashbang() && isSeeingEnemy()) { - - // GET OUT OF CAMP MODE - if (f_camp_time > gpGlobals->time) { - f_camp_time = gpGlobals->time; - } - - // Next time our enemy gets out of sight, it will be the 'first' time - // of all 'frame times'. - bFirstOutOfSight = false; - - // Remember last seen enemy position - lastSeenEnemyVector = pEnemyEdict->v.origin; // last seen enemy position - - // FIXME: Fix the darn zoom bug - // zoom in with sniper gun - if (CarryWeaponType() == SNIPER) { - if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - zoomed++; - - if (zoomed > ZOOM_TWICE) - zoomed = ZOOM_NONE; - } - } else if (FUNC_BotHoldsZoomWeapon(this)) { - if (zoomed < ZOOM_ONCE && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - zoomed++; - } - } - - // NOT blinded by flashbang, try to find cover? - if (f_cover_time < gpGlobals->time) { - // COVER: Not taking cover now, fight using fightstyles. - - // when vip, we always take cover. - if (vip) { - // Camp, take cover, etc. - BOT_DecideTakeCover(this); - - if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "3", ""); // need backup - } - } else { - // DECIDE: Should we take cover or not. - if (FUNC_ShouldTakeCover(this)) { - FindCover(); - } - } - } else { - - } - - // Keep timer updated for enemy - f_bot_find_enemy_time = gpGlobals->time + REMEMBER_ENEMY_TIME; - } - else // ---- CANNOT SEE ENEMY - { - if (f_bot_find_enemy_time < gpGlobals->time) { - pEnemyEdict = nullptr; - lastSeenEnemyVector = Vector(0, 0, 0); - rprint_trace("FightEnemy()", "Lost enemy out of sight, forgetting path and goal"); - forgetPath(); - forgetGoal(); - } else { - - // When we have the enemy for the first time out of sight - // we calculate a path to the last seen position - if (!bFirstOutOfSight) { - rprint_trace("FightEnemy()", "Enemy out of sight, calculating path towards it."); - // Only change path when we update our information here - const int iGoal = NodeMachine.getClosestNode(lastSeenEnemyVector, NODE_ZONE, pEdict); - if (iGoal > -1) { - setGoalNode(iGoal); - forgetPath(); - } - - bFirstOutOfSight = true; - } else { - if (!hasGoal()) { - rprint("Enemy out of sight and no goal, forgetting enemy"); - forgetEnemy(); - } - } - } - } // visible -} - -void cBot::pickWeapon(int weaponId) { - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(weaponId)); - f_c4_time = gpGlobals->time - 1; // reset C4 timer data - // give Counter-Strike time to switch weapon (animation, update state, etc) - f_update_weapon_time = gpGlobals->time + 0.7f; -} - -bool cBot::ownsFavoritePrimaryWeapon() const -{ - return hasFavoritePrimaryWeaponPreference() && isOwningWeapon(ipFavoPriWeapon); -} - -bool cBot::ownsFavoriteSecondaryWeapon() const -{ - return hasFavoriteSecondaryWeaponPreference() && isOwningWeapon(ipFavoSecWeapon); -} - -/** - * Returns true if bot has weapon (id) in possession - * @param weaponId - * @return - */ -bool cBot::isOwningWeapon(int weaponId) const -{ - return bot_weapons & (1 << weaponId); -} - -/** - * Returns true if bot carries weapon right now - * @param weaponId - * @return - */ -bool cBot::isHoldingWeapon(int weaponId) const -{ - return current_weapon.iId == weaponId; -} - -bool cBot::hasFavoritePrimaryWeaponPreference() const -{ - return ipFavoPriWeapon > -1; -} - -bool cBot::hasFavoriteSecondaryWeaponPreference() const -{ - return ipFavoSecWeapon > -1; -} - -bool cBot::canAfford(int price) const //price muddled with weaponId? [APG]RoboCop[CL] -{ - return this->bot_money > price; -} - -/****************************************************************************** - Function purpose: Based upon several events pick the best weapon - ******************************************************************************/ -void cBot::PickBestWeapon() { - // does Timer allow to change weapon? (only when f_update_weapon_time < gpGlobals->time - if (f_update_weapon_time > gpGlobals->time) - return; - - // Distance to enemy - const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - - const float knifeDistance = 300.0f; - - // ---------------------------- - // In this function all we do is decide what weapon to pick - // if we don't pick another weapon the current weapon is okay - // ---------------------------- - - // First we handle situations which are bad, no matter the distance - // or any other circumstance. - - // BAD: Carrying C4 or knife - if (CarryWeapon(CS_WEAPON_C4) || // carrying C4 - (CarryWeapon(CS_WEAPON_KNIFE) && fDistance > knifeDistance)) { // carrying knife and too far - if (hasPrimaryWeaponEquiped()) { - pickWeapon(iPrimaryWeapon); - return; - } else if (hasSecondaryWeaponEquiped()) { - pickWeapon(iSecondaryWeapon); - return; - } - } - - // At this point we do not update weapon information. And we did not 'switch back' to primary / secondary - if (hasEnemy() && !isSeeingEnemy()) { - // decision to pull HE grenade - if (isOwningWeapon(CS_WEAPON_HEGRENADE) && // we have a grenade - func_distance(pEdict->v.origin, lastSeenEnemyVector) < 900 && // we are close - func_distance(pEdict->v.origin, lastSeenEnemyVector) > 200 && // but not to close - RANDOM_LONG(0, 100) < 10 && // only randomly we pick a grenade in the heat of the battle - current_weapon.iId != CS_WEAPON_HEGRENADE && current_weapon.iId != CS_WEAPON_FLASHBANG && - f_gren_time + 15.0f < gpGlobals->time) // and dont hold it yet - { - UTIL_SelectItem(pEdict, "weapon_hegrenade"); // select grenade - f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) - f_gren_time = - gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it - zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon - return; - } - // OR we pull a flashbang? - if (isOwningWeapon(CS_WEAPON_FLASHBANG) && // we have a grenade - func_distance(pEdict->v.origin, lastSeenEnemyVector) < 200 && // we are close - func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300 && // but not to close - RANDOM_LONG(0, 100) < 15 && // only randomly we pick a grenade in the heat of the battle - current_weapon.iId != CS_WEAPON_FLASHBANG && current_weapon.iId != CS_WEAPON_HEGRENADE && - f_gren_time + 15 < gpGlobals->time) // and dont hold it yet - { - UTIL_SelectItem(pEdict, "weapon_flashbang"); // select grenade - f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) - f_gren_time = - gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it - zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon - return; - } - } - - // When we are here, we did not decide to switch to grenade/flashbang. Now we look - // if the bot has to reload or switch weapon based upon ammo. - - // ---------------------------------------- - // More complex bad things that can happen: - // ---------------------------------------- - const int iTotalAmmo = current_weapon.iAmmo1; - const int iCurrentAmmo = current_weapon.iClip; - - //char msg[80]; - //sprintf(msg, "BOT: ICLIP %d, TOTALAMMO %d\n", iCurrentAmmo, iTotalAmmo); - - // Clip is out of ammo - if (iCurrentAmmo < 1 - && (CarryWeaponType() == PRIMARY || CarryWeaponType() == SECONDARY)) { - // Camp, take cover, etc. - BOT_DecideTakeCover(this); - - // We still have ammo! - if (iTotalAmmo > 0) { - UTIL_BotPressKey(this, IN_RELOAD); - f_update_weapon_time = gpGlobals->time + 0.7f; // update timer - return; - } else { - // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code - // a bit though. Btw, distance 600 is too far for slashing :) - - // at here the bot does not have ammo of the current weapon, so - // switch to another weapon. - if (iPrimaryWeapon > -1 && // we have a primary - current_weapon.iId != iPrimaryWeapon && // that's not the current, empty gun - func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300) // and we are not close enough to knife - { - // select primary weapon - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); // select the primary - return; - } else { - - if (iSecondaryWeapon > -1 && current_weapon.iId != iSecondaryWeapon && - // that's not the current, empty gun - func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300) // and we are not close enough to knife - { - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); // select the secondary - return; - } else { - if (isOwningWeapon(CS_WEAPON_KNIFE) && // we have a knife (for non-knife maps) - !isHoldingWeapon(CS_WEAPON_KNIFE)) // but we do not carry it - { - UTIL_SelectItem(pEdict, "weapon_knife"); - return; - } - } - } // end if - } // no ammo - } -} - -/****************************************************************************** - Function purpose: Fire weapon (burst; or do not fire when not allowed) - ******************************************************************************/ -void cBot::FireWeapon() { - // We may not shoot! - if (f_shoot_time > gpGlobals->time || - f_update_weapon_time > gpGlobals->time) - return; - - if (!isSeeingEnemy()) { - return; - } - - // ------------------------------------------------------------ - float fDistance = 50.0f; - - if (hasEnemy()) { - fDistance = func_distance(pEdict->v.origin, pEnemyEdict->v.origin); - } - - // Depending on weapon type - if (CarryWeaponType() == SECONDARY) { - // We may shoot, use shooting rate. - // TODO TODO TODO; Add shooting rates in BUYTABLE.INI - - if (f_sec_weapon < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK); - f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05f, 0.2f); - } - - } else if (CarryWeaponType() == PRIMARY) { - // We may shoot, use shooting rate. - // TODO TODO TODO: Add shooting rates in BUYTABLE.INI - if (f_prim_weapon < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK); // Hold fire - // All other weapons, the more distance, the more time we add to holding weapon - if (f_shoot_wait_time < gpGlobals->time) { - // AK, COLT, STEYR AUG, SIG SG552 only when enough skill! - if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) - || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) - && (bot_skill < 3)) { - float f_burst = (2048 / fDistance) + 0.1f; - if (f_burst < 0.1f) - f_burst = 0.1f; - if (f_burst > 0.4f) - f_burst = 0.4f; - - // CS 1.6 less burst - if (counterstrike == 1) - if (f_burst > 0.3f) - f_burst = 0.3f; - - f_prim_weapon = gpGlobals->time + f_burst; - - f_shoot_wait_time = gpGlobals->time + (f_burst * 3); - } else // other weapons - { - float f_burst = 0.1f; - if (fDistance > 300 && bot_skill < 6) { - f_burst = ((fDistance - 300) / 550); - if (f_burst < 0.1f) - f_burst = 0.0f; - if (f_burst > 0.7f) - f_burst = 0.7f; - - // CS 1.6 less burst - if (counterstrike == 1) - if (f_burst > 0.2f) - f_burst = 0.2f; - if (f_prim_weapon < gpGlobals->time) - f_prim_weapon = gpGlobals->time + f_burst; - } - f_shoot_wait_time = - gpGlobals->time + f_burst + RANDOM_FLOAT(0.2f, 0.7f); - } - } - } // give the bot alteast 0.3 seconds to fire its weapon - } // PRIMARY - else if (CarryWeaponType() == GRENADE) { - if (f_gren_time > gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK); // Hold fire - setMoveSpeed(f_max_speed / 2); - - // Set new goal when holding flashbang! - if (current_weapon.iId == CS_WEAPON_FLASHBANG) { - - //tonode ? - // COVER: Take cover, using tracelines all the time! - FindCover(); - } - } else if (f_gren_time + 0.5f < gpGlobals->time) { - // NOTE: Should not happen, a bot cannot 'forget' this... - f_gren_time = gpGlobals->time + 1; - } - } // GRENADE - else if (CarryWeaponType() == KNIFE) { - setMoveSpeed(f_max_speed); - UTIL_BotPressKey(this, IN_ATTACK); // Hold fire - } // KNIFE - else if (CarryWeaponType() == SNIPER) { - setMoveSpeed(f_max_speed / 2); - UTIL_BotPressKey(this, IN_ATTACK); // Hold fire - f_shoot_time = gpGlobals->time + 1.0f; - } // SNIPER - else if (CarryWeaponType() == SHIELD) { - if (fDistance > 550) { - if (hasShieldDrawn()) { - // when the enemy is far away, we keep it - } else { - // draw shield! - UTIL_BotPressKey(this, IN_ATTACK2); // secondary attack makes shield draw - f_allow_keypress = gpGlobals->time + 0.7f; - } - } else { - // get weapon here. - if (hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { - rblog - ("BOT: Enemy is close enough, i should withdraw shield to attack this enemy\n"); - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - } - } - } else { - // debug print - REALBOT_PRINT(this, "FireWeapon()", "Unknown weapon"); - } -} - -/****************************************************************************** - Function purpose: The combat brain of the bot ( called by Think() ) - ******************************************************************************/ -void cBot::Combat() { - if (!hasEnemy()) { - rprint("Unexpected call to Combat because bot has no enemy!"); - return; - } - - // Bot is on ladder - if (isOnLadder()) { - // TODO: Bot fights when on ladder - - return; - } - - // We have an enemy and it is now dead - if (!isEnemyAlive()) { - - // radio (Enemy down) - if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "9", ""); - } - - // get bot pointer - const cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); - - // This bot killed a human; adjust skill when 'autoskill' is on. - if (checkpointer == nullptr) { - - // increase bot_skill value when autoskill enabled (making bot weaker) - if (autoskill && bot_skill < 10) { - bot_skill++; - } - - if (Game.iDeathsBroadcasting != BROADCAST_DEATHS_NONE) { - // This is a human, we will tell this human he has been killed - // by a bot. - const int r = RANDOM_LONG(150, 255); - const int g = RANDOM_LONG(30, 155); - const int b = RANDOM_LONG(30, 155); - char msg[128]; - if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { - std::sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); - } else { - std::sprintf(msg, "A RealBot named %s has killed you!", name); - } - - HUD_DrawString(r, g, b, msg, pEnemyEdict); - } - } - - // clear the pointer for this and other bots that might have the same pEnemyEdict - FUNC_ClearEnemyPointer(pEnemyEdict); - - // from here react after kill... - forgetGoal(); - forgetPath(); - - if (lastSeenEnemyVector != Vector(0, 0, 0)) { - vHead = lastSeenEnemyVector; - } - - lastSeenEnemyVector = Vector(0, 0, 0); - - // random waiting - f_wait_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 0.4f)); - - // keep on walking when afraid (perhaps there are more enemies) - if (RANDOM_LONG(0, 100) < ipFearRate) - f_walk_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 2.0f)); - - InteractWithPlayers(); // check any new enemy here immediately - - return; - } - - // ----------- combat - - // STEP 1: Pick best weapon to fight with - PickBestWeapon(); - - // STEP 2: Decide how to move to make us a harder target - FightEnemy(); - - // STEP 3: Aim at enemy (skill-based) - AimAtEnemy(); - - // STEP 4: Fire! - FireWeapon(); -} - -/****************************************************************************** - Function purpose: Find cover - Note: Using tracelines to get a cover node. - ******************************************************************************/ -void cBot::FindCover() { - TraceResult tr; - const Vector dest = lastSeenEnemyVector; - // Vector start = pEdict->v.origin; - // Vector end; - Vector cover_vect = Vector(9999, 9999, 9999); - - // TraceLines in 2 directions to find which way to go... - UTIL_MakeVectors(pEdict->v.v_angle); - const Vector v_src = pEdict->v.origin + pEdict->v.view_ofs; - Vector v_right = v_src + gpGlobals->v_right * 90; - Vector v_left = v_src + gpGlobals->v_right * -90; - - // We have now our first 'left' and 'right' - - // First check the right.. - UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction >= 1.0f) { - // We can see it - // Now trace from that vector to our threat - UTIL_TraceLine(v_right, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - - // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0f) - cover_vect = v_right; - } - - // Now check at the left - UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction >= 1.0f) { - // We can see it - // Now trace from that vector to our threat - UTIL_TraceLine(v_left, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); - - // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0f) { - // If we already found a wpt, then randomly pick this one - if (cover_vect != Vector(9999, 9999, 9999)) { - if (RANDOM_LONG(0, 100) < 50) - cover_vect = v_left; - } else - cover_vect = v_left; - } - } - // Now update the V_left and V_right and do the checks again. - // Vector old_right = v_right; - // Vector old_left = v_left; - v_right = v_src + gpGlobals->v_right * 180; - v_left = v_src + gpGlobals->v_right * -180; - - // Now check at the right again - UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction >= 1.0f) { - // We can see it - // Now trace from that vector to our threat - UTIL_TraceLine(v_right, dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0f) { - // If we already found a wpt, then randomly pick this one - if (cover_vect != Vector(9999, 9999, 9999)) { - if (RANDOM_LONG(0, 100) < 50) - cover_vect = v_right; - } else - cover_vect = v_right; - } - } - - // Now check at the left - UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - if (tr.flFraction >= 1.0f) { - // We can see it - // Now trace from that vector to our threat - UTIL_TraceLine(v_left, dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // If this is blocking.. then its a good wpt - if (tr.flFraction < 1.0f) { - // If we already found a wpt, then randomly pick this one - if (cover_vect != Vector(9999, 9999, 9999)) { - if (RANDOM_LONG(0, 100) < 50) - cover_vect = v_left; - } else - cover_vect = v_left; - } - } - - const int iNodeEnemy = NodeMachine.getClosestNode(pEnemyEdict->v.origin, 60, pEnemyEdict); - const int iNodeFrom = NodeMachine.getClosestNode(pEdict->v.origin, NODE_ZONE, pEdict); - - // -------------- - // TEST TEST TEST - // -------------- - const int iCoverNode = NodeMachine.node_cover(iNodeFrom, iNodeEnemy, pEdict); - bool bTakenCover = false; - - if (iCoverNode > -1) { - rprint("FindCover()", "cover node found (node based)"); - setGoalNode(iCoverNode); - forgetPath(); - - // Calculate a path to this position and get the heck there. - createPath(iCoverNode); - f_cover_time = gpGlobals->time + 8; - bTakenCover = true; - } else { - - // -------------------------------------------------- - // If cover_vect is found, we find a node close to it - // -------------------------------------------------- - if (cover_vect != Vector(9999, 9999, 9999)) { - rprint("FindCover()", "cover node found (cover_vect based)"); - const int iNodeCover = NodeMachine.getClosestNode(cover_vect, 60, pEdict); - if (iNodeCover > -1) { - setGoalNode(iNodeCover); - forgetPath(); - - // Calculate a path to this position and get the heck there. - rprint("createPath -> find cover node"); - NodeMachine.createPath(iNodeFrom, iNodeCover, iBotIndex, this, PATH_NONE); - f_cover_time = gpGlobals->time + 8; - bTakenCover = true; - } - } - } - - // when we have taken cover, and we are leader, command our team to get - // into our position to cover area - if (bTakenCover) { - // do something... - } - -} // FindCover() - -void cBot::InteractWithFriends() { - - - // TODO TODO TODO; make this thing really work - //return; - - // We interact with our players in some way - // - // When a bot is camping, another bot can choose to say 'go go go' for example. - // - // - - for (int i = 1; i <= gpGlobals->maxClients; i++) { - - edict_t *pPlayer = INDEXENT(i); - - // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - // skip this player if not alive (i.e. dead or dying) - if (!IsAlive(pPlayer)) - continue; - - // skip enemies - if (UTIL_GetTeam(pPlayer) != UTIL_GetTeam(pEdict)) - continue; - - bool bCanSeePlayer = false; - bool bClose = false; - - Vector vVecEnd = pPlayer->v.origin + pPlayer->v.view_ofs; - - if (func_distance(pPlayer->v.origin, pEdict->v.origin) < 450) - bClose = true; - - if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) - bCanSeePlayer = true; - - // there are tons of cases - const cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); - - // It is a fellow bot - if (pBotPointer != nullptr) { - if (bClose) { - if (pBotPointer->f_camp_time > gpGlobals->time - && pBotPointer->f_camp_time - 10 < gpGlobals->time - && pBotPointer->pEnemyEdict == nullptr - && (RANDOM_LONG(0, 100) < ipCampRate - && FUNC_DoRadio(this))) { - // issue go go go - UTIL_BotRadioMessage(this, 2, "1", ""); // go go go! - } - } - - if (bCanSeePlayer) {} - } else // it is a teammate, but it is human (or a different bot) - { - // when firing - - } - - // any player: - if (bClose) { - // some one is close, need backup? - if (RANDOM_LONG(0, 100) < ipFearRate && pEnemyEdict != nullptr) - if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "3", ""); // need backup - } - } - } - } - -} - -// BOT: Interact with Players ('find enemy, and how to react upon them') -void cBot::InteractWithPlayers() { - - // friends are important, we are a team dudes! - InteractWithFriends(); - - const int result = FindEnemy(); - - // ------------------------------- - // RESULT < 0; NO ENEMY FOUND - // ------------------------------- - - // No enemy found, unzoom - if (result < 0) { - // Keep f_prim_weapon updated, else we do burst immidiatly - if (CarryWeaponType() == SNIPER) { - - // Unzoom (for sniper guns) - if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - zoomed++; - } - if (zoomed > ZOOM_TWICE) - zoomed = ZOOM_NONE; - } else if (FUNC_BotHoldsZoomWeapon(this)) { - - // Unzoom (for other guns with only 1 zoom) - if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - zoomed = ZOOM_NONE; - } - } else { - - // For any weapon that has a silencer (the colt for example), use it if we want that. - if (isHoldingWeapon(CS_WEAPON_M4A1)) - if (bot_use_special == 0 && zoomed == ZOOM_NONE - && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - zoomed = ZOOM_ONCE; - } - } - } - // ------------------------------------------------ - // RESULT > -1 ; ENEMY FOUND / NO SPECIFIC REACTION - // ------------------------------------------------ - if (result > -1 && result < 4) { - - // VIP: When we found an enemy, we have a problem. - if (vip) { - - // We do not forget our enemy, but we will try to get the heck out of here. - // TODO TODO TODO: code something here? - - } - // Whenever we hold a knife, get our primary weapon - if (CarryWeapon(CS_WEAPON_KNIFE)) { - - // switch back to primary - if (iPrimaryWeapon > -1) - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); - - else // pick secondary - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); - - f_update_weapon_time = gpGlobals->time + 0.7f; - } - } - // ------------------------------------------------ - // RESULT = 1 ; ENEMY FOUND, VIA FRIEND! - // ------------------------------------------------ - - // When we have found an enemy via a friend, we simply build a path to it. - if (result == 1) { - - /* - f_prim_weapon = gpGlobals->time; - - // DECIDE: - // Do we go into battle, or do we wait first a few seconds? - - // HEALTH: The less we have, the more we want to wait - int vHealth = 100-bot_health; - - // CAMP: The more we want to camp, the more we want to wait. - int vCamp = ipCampRate; - - if (RANDOM_LONG(0,200) < (vHealth+vCamp)) - { - // depending on how much we want, the longer we wait - float fWaitTime = ((200/(vHealth+vCamp))*5); - f_wait_time = gpGlobals->time + fWaitTime; - - // TODO TODO TODO; we might not even want to wait, but also take 'cover'? - } - - // INITIALIZATION: - int iGoal = NodeMachine.getCloseNode(pBotEnemy->v.origin, NODE_ZONE, pBotEnemy); - if (iGoal > -1) - { - iGoalNode = iGoal; - pathNodeIndex = -1; - } - */ - } - // ------------------------------------------------ - // RESULT = 0 ; NEW ENEMY FOUND - // ------------------------------------------------ - if (result == 0) { - // First Encounter - //f_prim_weapon = gpGlobals->time; - if (CarryWeaponType() == SNIPER) { - if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); - f_allow_keypress = gpGlobals->time + 0.7f; - zoomed++; - } - } - - // INITIALIZATION: - const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); - if (iGoal > -1) { - rprint_trace("InteractWithPlayers()", "Found a new enemy, setting goal and forgetting path"); - setGoalNode(iGoal); - forgetPath(); - } - - // Speed our enemy runs - // int run_speed = FUNC_PlayerSpeed(pBot->pBotEnemy); - // Distance between Us and Enemy. - // float f_distance = func_distance(pBot->pEdict->v.origin, - // pBot->pBotEnemy->v.origin); - - // Does our enemy (when a bot) has focus on us? - bool focused; - const cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); - if (playerbot) { - if (playerbot->pEnemyEdict == pEdict) - focused = true; - } else // Its a human - { - - // When we are in his 'sight' of 25 degrees , we are pretty - // much focussed for a first encounter. - if (FUNC_InFieldOfView - (pEdict, (pEnemyEdict->v.origin - pEdict->v.origin)) < 25) - focused = true; - } - - /****************************** - At this moment we know: - - The distance between us and enemy - - The focus (are we targetted too?) - - The speed of the enemy (running, standing still? etc) - *******************************/ - } // We have a first encounter - - // ------------------------------------------------ - // RESULT = 3 ; NEWER ENEMY FOUND - // ------------------------------------------------ - if (result == 3) { - // - // Newer enemy found, update goals and such, but thats all! - // - - // INITIALIZATION: - const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); - - if (iGoal > -1) { - rprint_trace("InteractWithPlayers()", "Found a *newer* enemy, so picking goal node to that"); - setGoalNode(iGoal); - forgetPath(); - } - } -} - -// BOT: INTERACT WITH PLAYERS -void cBot::JoinTeam() { - if (mod_id != CSTRIKE_DLL) return; - // When bot plays Counter-Strike (only Counter-Strike is supported) - - char c_class[32]; - - // Choose team first - if (start_action == MSG_CS_TEAM_SELECT) { - char c_team[32]; - start_action = MSG_CS_IDLE; // switch back to idle - - // in case of bad state/input fall-back to 'pick one for me' - if ((iTeam != 1) && (iTeam != 2) && (iTeam != 5)) { - iTeam = 5; - } - - // select the team the bot wishes to join... - if (iTeam == 1) { - std::strcpy(c_team, "1"); - } else if (iTeam == 2) { - std::strcpy(c_team, "2"); - } else { - std::strcpy(c_team, "5"); - } - - // choose - FakeClientCommand(this->pEdict, "menuselect", c_team, nullptr); - - return; - } - - // counter terrorist menu, which class/outfit? - if (start_action == MSG_CS_CT_SELECT) { - start_action = MSG_CS_IDLE; // switch back to idle - - if ((bot_class < 1) || (bot_class > 4)) - bot_class = 5; // use random if invalid - - // Since cs 1.6 does not give us pretty random models - // we do it ourselves - if (bot_class == 5) { - bot_class = RANDOM_LONG(1, 4); - } - - // select the class the bot wishes to use... - if (bot_class == 1) - std::strcpy(c_class, "1"); - else if (bot_class == 2) - std::strcpy(c_class, "2"); - else if (bot_class == 3) - std::strcpy(c_class, "3"); - else if (bot_class == 4) - std::strcpy(c_class, "4"); - else - std::strcpy(c_class, "5"); // random - - FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); - - // bot has now joined a team - hasJoinedTeam = true; - - return; - } - - // terrorist select - if (start_action == MSG_CS_T_SELECT) { - start_action = MSG_CS_IDLE; // switch back to idle - - if ((bot_class < 1) || (bot_class > 4)) - bot_class = 5; // use random if invalid - - // Since cs 1.6 does not give us pretty random models - // we do it ourselves - if (bot_class == 5) - bot_class = RANDOM_LONG(1, 4); - - // select the class the bot wishes to use... - if (bot_class == 1) - std::strcpy(c_class, "1"); - else if (bot_class == 2) - std::strcpy(c_class, "2"); - else if (bot_class == 3) - std::strcpy(c_class, "3"); - else if (bot_class == 4) - std::strcpy(c_class, "4"); - else - std::strcpy(c_class, "5"); // random - - FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); - - // bot has now joined the game (doesn't need to be started) - hasJoinedTeam = true; - - return; - } -} - -int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { - - // hope this fix the unnescesary turning of bots. - // how? we save the values here, andc alculate the new value. - // this part is copied from botchangeyaw/pitch so it SHOULD work :) - float current_180; // current +/- 180 degrees - - // turn from the current v_angle pitch to the idealpitch by selecting - // the quickest way to turn to face that direction - - // find the difference in the current and ideal angle - const float diff = std::fabs(current - ideal); - - // check if the bot is already facing the idealpitch direction... - if (diff <= 1.0f) - return static_cast(current); // return number of degrees turned - - // check if difference is less than the max degrees per turn - if (diff < speed) - speed = diff; // just need to turn a little bit (less than max) - - // here we have four cases, both angle positive, one positive and - // the other negative, one negative and the other positive, or - // both negative. handle each case separately... - if ((current >= 0.0f) && (ideal >= 0.0f)) // both positive - { - if (current > ideal) - current -= speed; - - else - current += speed; - } else if ((current >= 0.0f) && (ideal < 0.0f)) { - current_180 = current - 180.0f; - if (current_180 > ideal) - current += speed; - - else - current -= speed; - } else if ((current < 0) && (ideal >= 0)) { - current_180 = current + 180; - if (current_180 > ideal) - current += speed; - - else - current -= speed; - } else // (current < 0) && (ideal < 0) both negative - { - if (current > ideal) - current -= speed; - - else - current += speed; - } - - // check for wrap around of angle... - if (current > 180) - current -= 360; - if (current < -180) - current += 360; - return static_cast(current); // return what it should be -} - -// BOT: sub-function (DEFUSE) for ACT() -bool cBot::Defuse() { - if (!isCounterTerrorist()) // non-Counter-Terrorists have no business here - return false; - - // this bot is defusing - if (shouldActWithC4() && keyPressed(IN_USE)) { - setTimeToMoveToNode(3); - return true; - } - - // What i do, i search for the c4 timer, store its origin and check - // if this bot is close. If so, the bot should be defusing the bomb - // if the timers are set. The above check makes sure that no other - // bot will be defusing the bomb. - edict_t *pent = nullptr; - bool c4Found = false; - while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != nullptr) { - if (UTIL_GetGrenadeType(pent) == 4) { // It is a C4 - c4Found = true; - break; - } - } - - if (!c4Found) { - rprint_normal("Defuse()", "No C4 planted yet"); - return false; - } - - rprint_normal("Defuse()", "C4 is planted!"); - - // A c4 has been found, oh dear. - // Remember, pent=c4 now! - - // Calculate the distance between our position to the c4 - const Vector vC4 = pent->v.origin; - const float distance = func_distance(pEdict->v.origin, vC4); - - // can see C4 - const bool canSeeC4 = canSeeVector(vC4); - - if (!canSeeC4) { - rprint_trace("Defuse()", "Cannot see planted C4 - bailing"); - return false; - } - - // it can be seen, so it has been discovered - if (!Game.isPlantedC4Discovered()) { - this->rprint_trace("Defuse()", "C4 is discovered, remembering its coordinates"); - Game.vPlantedC4 = vC4; - } - - // We can do 2 things now - // - If we are not close, we check if we can walk to it, and if so we face to the c4 - // - If we are close, we face it and (begin) defuse the bomb. - const int distanceForC4ToBeInReach = 70; - if (distance < distanceForC4ToBeInReach) { - vHead = vC4; - vBody = vC4; - - setTimeToMoveToNode(3); // we are going to do non-path-follow stuff, so keep timer updated - const int angle_to_c4 = FUNC_InFieldOfView(pEdict, (vC4 - pEdict->v.origin)); - - // if defusion timer has not been set (ie, the bot is not yet going to defuse the bomb) - if (f_defuse < gpGlobals->time && angle_to_c4 < 35) { - this->rprint("Defuse()", "I'll start defusing the bomb"); - // when we are 'about to' defuse, we simply set the timers - f_defuse = gpGlobals->time + 90; // hold as long as you can - f_allow_keypress = gpGlobals->time + 1.5f; // And stop any key pressing the first second - // ABOUT TO DEFUSE BOMB - } - - // Defusion timer is set and c4 is within vision - if (f_defuse > gpGlobals->time && angle_to_c4 < 35) { - this->rprint("Defuse()", "I'm defusing the bomb"); - setMoveSpeed(0.0); - f_c4_time = gpGlobals->time + 6; - UTIL_BotPressKey(this, IN_DUCK); - - if (func_distance(pEdict->v.origin, vC4) > 50 - && f_allow_keypress + 0.5f > gpGlobals->time) { - setMoveSpeed(f_max_speed / 2); - } - } - - if (f_allow_keypress < gpGlobals->time && f_defuse > gpGlobals->time) { - UTIL_BotPressKey(this, IN_USE); - } - - } else { - rprint_trace("Defuse()", "I can see C4, but it is out of reach."); - const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); - if (iGoalNode < 0) { - rprint_normal("Defuse()", "No node close, so just look at it/body face at it and move towards it."); - vHead = vC4; - vBody = vC4; - } - - if (iGoalNode > -1) { - // we are not heading for this goal yet - if (iGoalNode > -1 && getGoalNode() != iGoalNode) { - rprint_normal("Defuse()", "I don't have a goal towards the C4, overriding it now to C4 destination!"); - forgetPath(); - forgetGoal(); - setGoalNode(iGoalNode); - } else { - rprint_normal("Defuse()", "I already have a goal towards the C4!"); - } - } else { - rprint_normal("Defuse()", "C4 is somewhere without a close node."); - } - setMoveSpeed(f_max_speed); - } // distance < ... - - // we can see the bomb, and we act upon it - return true; -} - -int cBot::keyPressed(int key) const { - return pEdict->v.button & key; -} - -// BOT: Act -void cBot::Act() { - // chat - if (fChatTime < gpGlobals->time) { - if (chChatSentence[0] != '\0') { - UTIL_SayTextBot(chChatSentence, this); - std::memset(chChatSentence, 0, sizeof(chChatSentence)); - } - } - - // camp - if (f_camp_time > gpGlobals->time) { - // When camping we duck and we don't move - UTIL_BotPressKey(this, IN_DUCK); - - - setMoveSpeed(0.0f); // do not move - PickBestWeapon(); // pick weapon, do not stare with knife - - // when dropped C4 and CT we look at C4 - if (isCounterTerrorist() && Game.vDroppedC4 != Vector(9999, 9999, 9999)) { - // look at dropped C4 - if (EntityIsVisible(pEdict, Game.vDroppedC4)) - vHead = Game.vDroppedC4; - else { - if (iGoalNode > -1) - { - forgetPath(); - forgetGoal(); - vHead = vBody = NodeMachine.node_vector(iGoalNode); - } - else { - vHead = vBody = Game.vDroppedC4; - } - } - } else { - // Look at iGoalNode - if (iGoalNode > -1) - { - forgetPath(); - forgetGoal(); - vHead = vBody = NodeMachine.node_vector(iGoalNode); - } - else { - vHead = vBody = pEdict->v.origin; - } - } - } - - // C4 timer is set, this means: - // T -> Is planting bomb - // CT-> Is defusing bomb - if (shouldActWithC4()) { - // make sure we override this, or else we learn that we get stuck or something - // which is not the case. - setTimeToMoveToNode(2); - - // terrorist - if (isTerrorist()) { - // When still having the C4 - setMoveSpeed(0.0f); -// f_strafe_speed = 0.0f; - - // When no C4 selected yet, select it - if (!isHoldingWeapon(CS_WEAPON_C4)) { - UTIL_SelectItem(pEdict, "weapon_c4"); - } else { - UTIL_BotPressKey(this, IN_ATTACK); // plant it! - } - - // When we no longer have the C4 , we stop doing this stupid shit - if (!hasBomb() || Game.bBombPlanted) { - rprint_trace("Act()", "I was planting the C4, and it got planted (I no longer have the C4), so find a nearby node to camp/guard the C4"); - f_c4_time = gpGlobals->time; - setGoalNode(NodeMachine.getClosestNode(pEdict->v.origin, 200, pEdict)); - iPathFlags = PATH_CAMP; - forgetPath(); - } - } else { - // counter-terrorist - Defuse(); // old routine from RB AI V1.0 defusing, should get here and more cleaned up - } - } - - if (f_strafe_time < gpGlobals->time) { - f_strafe_speed = 0.0f; - } - - // walk only when NOT holding duck (is same as walking, combination makes bot super slow) - if (f_walk_time > gpGlobals->time && !(pEdict->v.button & IN_DUCK)) { - // From "KickBot": return (float) (((int)flMaxSpeed)/2 + ((int)flMaxSpeed)/50); - //OLD: f_move_speed = f_max_speed / 2.0; // this is not correct - - pEdict->v.button &= (~IN_RUN); // release IN_RUN - rprint("Act", "Walk time > gpGlobals->time"); - setMoveSpeed((f_max_speed) / 2.0f + (f_max_speed) / 50.0f); - } - - // When we are at max speed, press IN_RUN to get a running animation - if (f_move_speed == f_max_speed) { - UTIL_BotPressKey(this, IN_RUN); - } - - if (!keyPressed(IN_MOVELEFT) || keyPressed(IN_MOVERIGHT)) { - if (f_strafe_speed > 0.0f) { - UTIL_BotPressKey(this, IN_MOVERIGHT); - } - else if (f_strafe_speed < 0.0f) { - UTIL_BotPressKey(this, IN_MOVELEFT); - } - } - - // When we should go back, we go back - if (f_goback_time > gpGlobals->time) { - setMoveSpeed(-f_max_speed); - } - - // When holding duck, we hold duck - if (f_hold_duck > gpGlobals->time) - UTIL_BotPressKey(this, IN_DUCK); - - // When we wait, we have no move speed - // notice: 'wait' is not 'stuck' nor 'camping'. Wait should only be used to have a bot - // 'do nothing' for a short period of time. - if (f_wait_time > gpGlobals->time) { - rprint("Act", "f_wait_time > gpGlobals->time"); - setMoveSpeed(0.0f); - } - - // Button usage, change vBody to a 'trigger multiple' because we have to touch these - if (pButtonEdict) { - if (std::strcmp(STRING(pButtonEdict->v.classname), "trigger_multiple") == 0) { - if (func_distance(pEdict->v.origin, VecBModelOrigin(pButtonEdict)) < 60) { - vBody = VecBModelOrigin(pButtonEdict); - } - } - } - - // ------------------------------------------- - // MOVE TO : vBody - // calculate the angle we MOVE to. (VecMoveAngles) - // ------------------------------------------- - Vector vTarget = vBody - pEdict->v.origin; - vecMoveAngles = UTIL_VecToAngles(vTarget); - - // Paulo-La-Frite - START bot aiming bug fix - if (vecMoveAngles.x > 180) - vecMoveAngles.x -= 360; - - vecMoveAngles.x = -vecMoveAngles.x; - vecMoveAngles.z = 0; - UTIL_FixAngles(&vecMoveAngles); - - // when filled in, we look to this (overrides) - if (vEar != Vector(9999, 9999, 9999)) - vHead = vEar; - - // button overrides hearing - if (pButtonEdict) - vHead = VecBModelOrigin(pButtonEdict); - - // ------------------------------------------- - // FACE AT: vHead - // calculate the angle we face at. - // - // ------------------------------------------- - vTarget = (vHead - pEdict->v.origin); - pEdict->v.v_angle = UTIL_VecToAngles(vTarget); - if (pEdict->v.v_angle.y > 180.0f) - pEdict->v.v_angle.y -= 360.0f; - - // Paulo-La-Frite - START bot aiming bug fix - if (pEdict->v.v_angle.x > 180.0f) - pEdict->v.v_angle.x -= 360.0f; - - Vector v_shouldbe; - - // Vector how it should be, however, we don't allow such a fast turn! - v_shouldbe.x = pEdict->v.v_angle.x / 3; - v_shouldbe.y = pEdict->v.v_angle.y; - v_shouldbe.z = 0; //unused? [APG]RoboCop[CL] - - // set the body angles to point the gun correctly - pEdict->v.angles.x = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.x, v_shouldbe.x); - pEdict->v.angles.y = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.y, v_shouldbe.y); - pEdict->v.angles.z = 0; - - // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff) - pEdict->v.v_angle.x = -pEdict->v.v_angle.x; - - // Paulo-La-Frite - END - pEdict->v.ideal_yaw = pEdict->v.v_angle.y; - pEdict->v.idealpitch = pEdict->v.v_angle.x; - - botFixIdealYaw(pEdict); - botFixIdealPitch(pEdict); -} - -bool cBot::shouldActWithC4() const { - return f_c4_time > gpGlobals->time; -} - -// BOT: On ladder? -bool cBot::isOnLadder() const -{ - return FUNC_IsOnLadder(pEdict); -} - -// BOT: Check around body and avoid obstacles -void cBot::CheckAround() { - rprint_trace("CheckAround", "Start"); - // Do not act when on ladder - if (isOnLadder()) - return; - - // The principle is to fire 2 tracelines, both forward; one left - // and one right. When one of the 2 gets hit, we know we are 'about' - // to get hit. Therefor we use strafing to keep distance to the coming wall - // when left and right is both hit we have a problem as this should not happen. - - // Note: we use TRACEHULL instead of TRACELINE, because TRACEHULL detects - // the famous 'undetectable' func_walls. - TraceResult tr; - - // v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); - const Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); - - // Go forward first - const float distance = 90.0f; - const Vector v_forward = v_source + gpGlobals->v_forward * distance; - - // now really go left/right - const Vector v_right = v_source + gpGlobals->v_right * distance; - const Vector v_left = v_source + gpGlobals->v_right * -distance; - - // now really go left/right - const Vector v_forwardright = v_right + gpGlobals->v_forward * distance; - const Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; - - // TRACELINE: forward - UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForward = tr.flFraction < 1.0f; - - // TRACELINE: Left - UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitLeft = tr.flFraction < 1.0f; - - // TRACELINE: Right - UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitRight = tr.flFraction < 1.0f; - - // TRACELINE: Forward left - UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForwardLeft = tr.flFraction < 1.0f; - - // TRACELINE: Forward right - UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); - const bool bHitForwardRight = tr.flFraction < 1.0f; - - - char msg[255]; - std::sprintf(msg, "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); - rprint_trace("CheckAround", msg); - - // Set 'act' properties - - // we are surrounded, so move backwards - if (bHitForward) { - rprint_trace("CheckAround", "Something in front of me blocks, so move back."); -// f_move_speed = -(f_max_speed); - } else { - rprint_trace("CheckAround", "Nothing in front of me"); - } - - if (!bHitForwardLeft && bHitForwardRight) { - strafeLeft(0.5f); - rprint_trace("CheckAround", "Can strafe left (forward left)"); - } else if (bHitForwardLeft && !bHitForwardRight) { - strafeRight(0.5f); - rprint_trace("CheckAround", "Can strafe right (forward right)"); - } - - if (bHitLeft && bHitRight) { - rprint_trace("CheckAround", "Can't strafe left or right"); - } else if (!bHitLeft && bHitRight) { - strafeLeft(0.5f); - rprint_trace("CheckAround", "Can strafe left"); - } else if (bHitLeft && !bHitRight) { - strafeRight(0.5f); - rprint_trace("CheckAround", "Can strafe right"); - } - - // ------------------------------------------------------------- - // When checking around a bot also handles breakable stuff. - // ------------------------------------------------------------- - - edict_t *pent = nullptr; - while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { - char item_name[40]; - std::strcpy(item_name, STRING(pent->v.classname)); - - // See if it matches our object name - if (std::strcmp("func_breakable", item_name) == 0) { - - // Found a func_breakable - const Vector vBreakableOrigin = VecBModelOrigin(pent); - - // Shoot - if ((pent->v.flags & FL_WORLDBRUSH) == 0) // can it be broken? - { - - // Thx for CF by fixing breakable coding - if (pent->v.solid == SOLID_BSP && pent->v.takedamage == DAMAGE_YES && pent->v.impulse == 0 && - pent->v.health < 150) // has it NOT been broken yet? - { - - // trace to vector to be sure we dont get blocked by anything else - if (VectorIsVisibleWithEdict(pEdict, vBreakableOrigin, "func_breakable")) { - setHeadAiming(vBreakableOrigin); - FireWeapon(); - } - return; - } - } - } // CAN BE BROKEN - } // FUNC_BREAKABLE -} - -// BOT: Should be taking cover? -bool cBot::TakeCover() const -{ - - // Its time based. - if (f_cover_time < gpGlobals->time) - return false; - - // And if all went fine, we can return true. - return true; -} - -/** - * Set the node to follow next as the next one (ie, increase index) - */ -void cBot::nextPathIndex() { - this->pathIndex++; -} - -/** - * Set the node to follow next as the previous one (ie, decrease index). Calls forgetPath when index is getting < 0 - */ -void cBot::prevPathIndex() { - rprint("prevPathNodeIndex"); - this->pathIndex--; - if (this->pathIndex < 0) { - forgetPath(); - } -} - -// Returns true if bot has a path to follow -bool cBot::isWalkingPath() const -{ - return this->pathIndex > -1; -} - -// Returns true if bot has goal node -bool cBot::hasGoal() const -{ - return this->iGoalNode > -1; -} - -// Returns true if bot has goal node index (ie referring to Goals[]) -bool cBot::hasGoalIndex() const -{ - return this->goalIndex > -1; -} - -/** - * Returns goal data , if goal data exists - * @return - */ -tGoal *cBot::getGoalData() const -{ - if (!hasGoalIndex()) return nullptr; - tGoal *ptr = NodeMachine.getGoal(this->goalIndex); - if (ptr == nullptr) return nullptr; - - // only goals with a node are valid - if (ptr->iNode > -1) return ptr; - // else not - - return nullptr; -} - -// Returns true if bot has an enemy edict -bool cBot::hasEnemy() const -{ - return this->pEnemyEdict != nullptr; -} - -/** - * Returns true when given edict == our enemy edict - * @param pEdict - * @return - */ -bool cBot::hasEnemy(edict_t * pEdict) const -{ - return this->pEnemyEdict == pEdict; -} - -// Returns true if bot has a path to follow -bool cBot::shouldBeWandering() { - if (this->fWanderTime > gpGlobals->time) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); - rprint(msg); - return true; - } - return false; -} - -void cBot::setMoveSpeed(float value) { -// char msg[255]; -// sprintf(msg, "setting to value %f / maxSpeed %f - sv_maxspeed = %f", value, this->f_max_speed, CVAR_GET_FLOAT("sv_maxspeed")); -// rprint_trace("setMoveSpeed", msg); - this->f_move_speed = value; -} - -void cBot::setStrafeSpeed(float value, float time) { - char msg[255]; - std::sprintf(msg, "%f for %f seconds.", value, time); - rprint_trace("setStrafeSpeed", msg); -// if (f_strafe_time > gpGlobals->time) { -// -// } else { - f_strafe_speed = value; - f_strafe_time = gpGlobals->time + time; -// } -} - -void cBot::strafeLeft(float time) { - setStrafeSpeed(-f_max_speed, time); -} - -void cBot::strafeRight(float time) { - setStrafeSpeed(f_max_speed, time); -} - -void cBot::startWandering(float time) { - this->fWanderTime = gpGlobals->time + time; - setMoveSpeed(f_max_speed); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Start wandering for %f seconds", time); - rprint("startWandering", msg); -} - -void cBot::stopMoving() { - this->setMoveSpeed(0.0f); -} - -void cBot::forgetGoal() { - rprint_trace("forgetGoal"); - this->iGoalNode = -1; - this->goalIndex = -1; -} - -int cBot::getPathIndex() const -{ - return this->pathIndex; -} - -int cBot::getPreviousPathIndex() const -{ - return this->pathIndex - 1; -} - -void cBot::forgetPath() { - rprint("forgetPath"); - this->pathIndex = -1; - NodeMachine.path_clear(this->iBotIndex); -} - -void cBot::forgetEnemy() { - this->pEnemyEdict = nullptr; -} - -edict_t * cBot::getEnemyEdict() const -{ - return this->pEnemyEdict; -} - -int cBot::getGoalNode() const -{ - return this->iGoalNode; -} - -void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { - if (nodeIndex < 0) { - rprint("setGoalNode()", "WARN: Setting a goal lower than 0, assuming this is not intentional. If you need to forget a goal, use forgetGoal()"); - } - this->iGoalNode = nodeIndex; - this->goalIndex = iGoalIndex; - - tGoal *goalPtr = getGoalData(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - - if (goalPtr != nullptr) { - std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", - nodeIndex, - goalIndex, - goalPtr->name, - goalPtr->iChecked - ); - } else { - std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); - } - rprint("setGoalNode()", msg); -} - -void cBot::setGoalNode(int nodeIndex) { - this->setGoalNode(nodeIndex, -1); -} - -void cBot::setGoalNode(tGoal *goal) { - if (goal != nullptr && goal->iNode > -1) { - rprint("setGoalNode with goal pointer\n"); - this->setGoalNode(goal->iNode, goal->index); - } -} - -/** - * Always printed when debug mode is on - * @param Function - * @param msg - */ -void cBot::rprint(const char *Function, const char *msg) { - REALBOT_PRINT(this, Function, msg); -} - -/** - * Only printed when debug mode is on and verbosity is trace - * @param Function - * @param msg - */ -void cBot::rprint_trace(const char *Function, const char *msg) { - if (Game.messageVerbosity > 1) { - REALBOT_PRINT(this, Function, msg); - } -} - -/** - * Only printed when debug mode is on and verbosity is normal - * @param Function - * @param msg - */ -void cBot::rprint_normal(const char *Function, const char *msg) { - if (Game.messageVerbosity > 1) { - REALBOT_PRINT(this, Function, msg); - } -} - -void cBot::rprint(const char *msg) { - rprint("rprint()", msg); -} - -void cBot::rprint_normal(const char *msg) { - rprint_normal("rprint()", msg); -} - -void cBot::rprint_trace(const char *msg) { - rprint_trace("rprint()", msg); -} - -bool cBot::hasBomb() const -{ - return isOwningWeapon(CS_WEAPON_C4); -} - -bool cBot::isCounterTerrorist() const -{ - return iTeam == 2; -} - -bool cBot::isTerrorist() const -{ - return iTeam == 1; -} - -bool cBot::hasPrimaryWeaponEquiped() const -{ - return iPrimaryWeapon > -1; -} - -bool cBot::hasSecondaryWeaponEquiped() const -{ - return iSecondaryWeapon > -1; -} - -bool cBot::hasPrimaryWeapon(int weaponId) const -{ - return isOwningWeapon(weaponId); -} - -bool cBot::hasSecondaryWeapon(int weaponId) const -{ - return isOwningWeapon(weaponId); -} - -void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { - // To be sure the console will only change when we MAY change. - // The values will only be changed when console_nr is 0 - if (Game.getRoundStartedTime() + 4 < gpGlobals->time) - return; // Not valid to buy - - if (this->console_nr == 0) { - // set up first command and argument - std::strcpy(this->arg1, "buy"); - std::strcpy(this->arg2, menuItem); - - if (subMenuItem != nullptr) std::strcpy(this->arg3, subMenuItem); - - this->console_nr = 1; // start console command sequence - } -} - -void cBot::performBuyActions(int weaponIdToBuy) { - if (weaponIdToBuy < 0) { - return; - } - // Buy... - - // TODO - // FRASHMAN 30.08.04 haven't changed the cs 1.5 buycode, maybe there are also errors - - // CS 1.5 only - if (counterstrike == 0) { - switch (weaponIdToBuy) { - case CS_WEAPON_AK47: - performBuyWeapon("4", "1"); - break; - case CS_WEAPON_DEAGLE: - performBuyWeapon("1", "3"); - break; - case CS_WEAPON_P228: - performBuyWeapon("1", "4"); - break; - case CS_WEAPON_SG552: - performBuyWeapon("4", "2"); - break; - case CS_WEAPON_SG550: - performBuyWeapon("4", "8"); - break; - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "5"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "6"); - break; - case CS_WEAPON_MP5NAVY: - performBuyWeapon("3", "1"); - break; - case CS_WEAPON_UMP45: - performBuyWeapon("3", "5"); - break; - case CS_WEAPON_ELITE: - performBuyWeapon("1", "5"); - break; // T only - case CS_WEAPON_MAC10: - performBuyWeapon("3", "4"); - break; // T only - case CS_WEAPON_AUG: - performBuyWeapon("4", "4"); - break; // CT Only - case CS_WEAPON_FIVESEVEN: - performBuyWeapon("1", "6"); - break; // CT only - case CS_WEAPON_M4A1: - performBuyWeapon("4", "3"); - break; // CT Only - case CS_WEAPON_TMP: - performBuyWeapon("3", "2"); - break; // CT only - case CS_WEAPON_HEGRENADE: - performBuyWeapon("8", "4"); - break; - case CS_WEAPON_XM1014: - performBuyWeapon("2", "2"); - break; - case CS_WEAPON_SMOKEGRENADE: - performBuyWeapon("8", "5"); - break; - case CS_WEAPON_USP: - performBuyWeapon("1", "1"); - break; - case CS_WEAPON_GLOCK18: - performBuyWeapon("1", "2"); - break; - case CS_WEAPON_M249: - performBuyWeapon("5", "1"); - break; - case CS_WEAPON_M3: - performBuyWeapon("2", "1"); - break; - - case CS_WEAPON_G3SG1: - performBuyWeapon("4", "7"); - break; - case CS_WEAPON_FLASHBANG: - performBuyWeapon("8", "3"); - break; - case CS_WEAPON_P90: - performBuyWeapon("3", "3"); - break; - - // Armor - case CS_WEAPON_ARMOR_LIGHT: - performBuyWeapon("8", "1"); - break; - case CS_WEAPON_ARMOR_HEAVY: - performBuyWeapon("8", "2"); - break; - - case CS_DEFUSEKIT: - performBuyWeapon("8", "6"); - break; - } - } - - // CS 1.6 only - else if (counterstrike == 1) { // FRASHMAN 30/08/04: redone switch block, it was full of errors - switch (weaponIdToBuy) { - //Pistols - case CS_WEAPON_GLOCK18: - performBuyWeapon("1", "1"); - break; - case CS_WEAPON_USP: - performBuyWeapon("1", "2"); - break; - case CS_WEAPON_P228: - performBuyWeapon("1", "3"); - break; - case CS_WEAPON_DEAGLE: - performBuyWeapon("1", "4"); - break; - case CS_WEAPON_FIVESEVEN: - performBuyWeapon("1", "5"); - break; // CT Only - case CS_WEAPON_ELITE: - performBuyWeapon("1", "5"); - break; // T Only - //ShotGUNS - case CS_WEAPON_M3: - performBuyWeapon("2", "1"); - break; - case CS_WEAPON_XM1014: - performBuyWeapon("2", "2"); - break; - //SMG - case CS_WEAPON_MAC10: - performBuyWeapon("3", "1"); - break; // T Only - case CS_WEAPON_TMP: - performBuyWeapon("3", "1"); - break; // CT Only - case CS_WEAPON_MP5NAVY: - performBuyWeapon("3", "2"); - break; - case CS_WEAPON_UMP45: - performBuyWeapon("3", "3"); - break; - case CS_WEAPON_P90: - performBuyWeapon("3", "4"); - break; - //rifles - case CS_WEAPON_GALIL: - performBuyWeapon("4", "1"); - break; // T Only - case CS_WEAPON_FAMAS: - performBuyWeapon("4", "1"); - break; // CT Only - case CS_WEAPON_AK47: - performBuyWeapon("4", "2"); - break; // T Only - case CS_WEAPON_M4A1: - performBuyWeapon("4", "3"); - break; // CT Only - case CS_WEAPON_SG552: - performBuyWeapon("4", "4"); - break; // T Only - case CS_WEAPON_AUG: - performBuyWeapon("4", "4"); - break; // CT Only - case CS_WEAPON_SG550: - performBuyWeapon("4", "5"); - break; // CT Only - case CS_WEAPON_G3SG1: - performBuyWeapon("4", "6"); - break; // T Only - //machinegun - case CS_WEAPON_M249: - performBuyWeapon("5", "1"); - break; - // equipment - case CS_WEAPON_ARMOR_LIGHT: - performBuyWeapon("8", "1"); - break; - case CS_WEAPON_ARMOR_HEAVY: - performBuyWeapon("8", "2"); - break; - case CS_WEAPON_FLASHBANG: - performBuyWeapon("8", "3"); - break; - case CS_WEAPON_HEGRENADE: - performBuyWeapon("8", "4"); - break; - case CS_WEAPON_SMOKEGRENADE: - performBuyWeapon("8", "5"); - break; - case CS_WEAPON_SHIELD: - performBuyWeapon("8", "8"); - break; - - case CS_DEFUSEKIT: - performBuyWeapon("8", "6"); - break; - //default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] - // performBuyWeapon("3", "2"); - // break; - } - - // This differs per team - // FRASHMAN 30/08/04: all into one ifthen block - if (iTeam == 2) // counter - { - switch (weaponIdToBuy) { - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "2"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "6"); - break; - //whats about nightvision? BuyWeapon (pBot, "8", "7") - } - } else // terror - { - switch (weaponIdToBuy) { - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "3"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "5"); - break; - //whats about nightvision? BuyWeapon (pBot, "8", "6") - } - } - } // end of cs 1.6 part -} // We actually gonna buy this weapon - -// BOT: Memory() -// In this function the bot will receive data; this can be any kind of data. -// For hearing, the bot will check for sounds it should pay attention to and -// store this into its 'hearing vector'. The hearing vector will be used only -// when walking and not when fighting an enemy. Do note that this hearing vector -// is only filled when it is important enough, so all the decisions are made here. -void cBot::Memory() { - - // Skip method when it is too soon. - if (fMemoryTime > gpGlobals->time) { - return; - } - - // Hear players: (loop through all players, determine if they are running and if - // we can hear them (estimated distance)). - if (pEnemyEdict == nullptr) { - Vector vHear = Vector(9999, 9999, 9999); - edict_t *pHearPlayer = nullptr; - - //f_walk_time = gpGlobals->time + 1; - - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - - // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { - // skip this player if not alive (i.e. dead or dying) - if (!IsAlive(pPlayer)) - continue; - - // check if we can 'see it on radar' (skip teammates) - if (UTIL_GetTeam(pPlayer) == UTIL_GetTeam(pEdict)) - continue; - - // check if its running - if (FUNC_PlayerRuns(FUNC_PlayerSpeed(pPlayer))) { - // check distance - const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); - - // estimated distance we can hear somebody - if (fDistance < BOT_HEARDISTANCE) { - // check if this 'hearing' vector is closer then our previous one - if (vHear != Vector(9999, 9999, 9999)) { - if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < - func_distance(pEdict->v.origin, vHear)) { - // this one is closer, thus more important - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } else { - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } - } - - - if ((pPlayer->v.button & IN_ATTACK) - && (FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_HEGRENADE - && FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_FLASHBANG - && FUNC_EdictHoldsWeapon(pEdict) != - CS_WEAPON_SMOKEGRENADE)) { - // check distance - const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); - - // estimated distance we can hear somebody - if (fDistance < BOT_HEARFIREDISTANCE) { - // check if this 'hearing' vector is closer then our previous one - if (vHear != Vector(9999, 9999, 9999)) { - if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < - func_distance(pEdict->v.origin, vHear)) { - // this one is closer, thus more important - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } else { - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } - } - // zooming of a sniper rifle - if (pPlayer->v.button & IN_ATTACK2) { - // check distance - const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); - - // estimated distance we can hear somebody - if (fDistance < BOT_HEARDISTANCE) { - // check if this 'hearing' vector is closer then our previous one - if (vHear != Vector(9999, 9999, 9999)) { - if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < - func_distance(pEdict->v.origin, vHear)) { - // this one is closer, thus more important - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } else { - vHear = pPlayer->v.origin; - pHearPlayer = pPlayer; - } - } - } - - } - } - - // Fill in hearing vectory if any: - if (pHearPlayer != nullptr) { - if (RANDOM_LONG(0, 100) < (ipFearRate + 10)) { - - // determine fuzzyness by distance: - int iFuzz = - static_cast(func_distance(pEdict->v.origin, vHear) / - BOT_HEARDISTANCE) * 250; - - // skill depended - iFuzz /= (bot_skill + 1); - - // create 'estimated hear vector' - vHear = - vHear + Vector(RANDOM_LONG(-iFuzz, iFuzz), - RANDOM_LONG(-iFuzz, iFuzz), - RANDOM_LONG(-iFuzz, iFuzz)); - - TraceResult tr; - - UTIL_TraceHull(pEdict->v.origin, vHear, dont_ignore_monsters, - point_hull, pEdict, &tr); - - int iNodeHearPlayer = - NodeMachine.getClosestNode(vHear, NODE_ZONE * 2, pHearPlayer); - - // if nothing hit: - if (tr.flFraction >= 1.0f) { - // we can look at this spot - vEar = vHear; - } - // we go to the destination - - const float fTime = 5 + static_cast(ipFearRate) / static_cast(7); - - if (RANDOM_LONG(0, 100) < ipFearRate - && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk - f_walk_time = gpGlobals->time + fTime; - - if (RANDOM_LONG(0, 100) < ipCampRate - && f_camp_time + 30 < gpGlobals->time // last 30 seconds did not camp - ) { - f_camp_time = gpGlobals->time + fTime; - } - - } else { - fMemoryTime = gpGlobals->time + 5.0f; - } - - /* - - - int iNodeHearPlayer = NodeMachine.getCloseNode (vHear, NODE_ZONE*2, pHearPlayer); - int iNodeFrom = NodeMachine.getCloseNode (pEdict->v.origin, NODE_ZONE*2, pEdict); - int iHearToNode = NodeMachine.node_look_at_hear(iNodeHearPlayer, iNodeFrom, pEdict); - - // look at hearto node - if (iHearToNode > -1) - { - vHead = NodeMachine.node_vector(iHearToNode); - SERVER_PRINT("found smart look at node\n"); - } - - // only check for new goal when the current goal is way of distance and such - if (ipCampRate > 30 && f_camp_time + 5 < gpGlobals->time) - f_camp_time = gpGlobals->time + 2.5; - */ - - if (f_update_weapon_time + 2 < gpGlobals->time) { - PickBestWeapon(); - } - } else { - vEar = Vector(9999, 9999, 9999); -// -// // check for any 'beeps' of the bomb! -// if (isCounterTerrorist() && Game.bBombPlanted) { -// // find the bomb vector -// edict_t *pent = NULL; -// Vector vC4 = Vector(9999, 9999, 9999); -// while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != NULL) { -// if (UTIL_GetGrenadeType(pent) == 4) // It is a C4 -// { -// vC4 = pent->v.origin; // store origin -// break; // done our part now -// } -// } // --- find the c4 -// -// if (vC4 != Vector(9999, 9999, 9999)) { -// -// if (func_distance(vC4, NodeMachine.node_vector(iGoalNode)) > 100 && -// func_distance(pEdict->v.origin, vC4) < 1024) { -// // set new goal node -// setGoalNode(NodeMachine.getCloseNode(vC4, NODE_ZONE, NULL)); -// forgetPath(); -// } -// } -// } - } - - } else { - vEar = Vector(9999, 9999, 9999); - } -} - -void cBot::Walk() //Experimental implementation [APG]RoboCop[CL] -{ - if (f_walk_time + 0.1f < gpGlobals->time) { - f_walk_time = gpGlobals->time + 0.1f; - if (f_walk_time + 0.1f < gpGlobals->time) { - f_walk_time = gpGlobals->time + 0.1f; - } - } -} - - -// BOT: Do i carry weapon # now? -bool cBot::CarryWeapon(int iType) const -{ - if (current_weapon.iId == iType) - return true; - return false; -} - -// BOT: Do i carry weapon TYPE # now? -int cBot::CarryWeaponType() const -{ - int kind = PRIMARY; - const int weapon_id = current_weapon.iId; - - // Check 1. Is it a knife? - if (weapon_id == CS_WEAPON_KNIFE) - kind = KNIFE; - - // Check 2, is it a 'tool'? - if (weapon_id == CS_WEAPON_FLASHBANG || weapon_id == CS_WEAPON_HEGRENADE - || weapon_id == CS_WEAPON_SMOKEGRENADE) - kind = GRENADE; - - // Check 3, is it a secondary gun? - if (weapon_id == CS_WEAPON_P228 || weapon_id == CS_WEAPON_ELITE - || weapon_id == CS_WEAPON_USP || weapon_id == CS_WEAPON_GLOCK18 - || weapon_id == CS_WEAPON_DEAGLE || weapon_id == CS_WEAPON_FIVESEVEN) - kind = SECONDARY; - - // Check 4, is it a sniper gun? - if (weapon_id == CS_WEAPON_SCOUT || weapon_id == CS_WEAPON_SG550 - || weapon_id == CS_WEAPON_AWP || weapon_id == CS_WEAPON_G3SG1) - kind = SNIPER; - - if (hasShield()) { - kind = SHIELD; - } - //if (weapon_id < 1) - // kind = NONE; - return kind; -} - -// BOT: Think about objectives -// -// This function only takes action when the bot is close a goal. The function -// NodeMachine.path_think() handles WHERE the bot goes. Not WHAT to do at a goal. -void cBot::ThinkAboutGoals() { - //REALBOT_PRINT(this, "thinkAboutGoals()", "start"); - // Depending on bot team we handle goals differently: - // TERRORISTS - if (isTerrorist()) { - // Plant the bomb when the HUD says we can -- BERKED - if (bHUD_C4_plantable) - f_c4_time = gpGlobals->time + 1; // plant bomb - - // A dropped C4 is not a 'goal' (ie. it won't let you win the game - // when you pick up the bomb. Therefor the 'pickup the dropped bomb - // code is in cNodeMachine::path_walk(). - } else if (isCounterTerrorist()) { - // COUNTER-TERRORISTS - if (vip) { - // VIP - } else { - if (Game.bBombPlanted) { - if (isCounterTerrorist()) { - // defuse (or set timers for it) - Defuse(); - } - } else { - if (Game.bHostageRescueMap) { - TryToGetHostageTargetToFollowMe(this); - checkIfHostagesAreRescued(); - checkOfHostagesStillFollowMe(); - } - } - } - } - // in Act() we find the 'acting' code when timers above are set. -} - -void cBot::rememberWhichHostageToRescue(edict_t *pHostage) { - this->pBotHostage = pHostage; -} - -edict_t * cBot::getHostageToRescue() const -{ - return pBotHostage; -} - -edict_t * cBot::findHostageToRescue() { - edict_t *pent = nullptr; - - // Search for all hostages in the game - while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { - if (!isHostageRescueable(this, pent)) continue; - if (!canSeeEntity(pent)) continue; - // skip too far hostages, leave it up to the goal picking to get closer - if (getDistanceTo(pent->v.origin) > (NODE_ZONE * 2.5f)) continue; - - char msg[255]; - std::sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); - this->rprint_trace("findHostageToRescue()", msg); - return pent; - } - - return nullptr; -} - -bool cBot::isDefusing() const -{ - return f_defuse > gpGlobals->time; -} - -bool cBot::hasTimeToMoveToNode() const -{ - return fMoveToNodeTime > -1 && getMoveToNodeTimeRemaining() > 0; -} -/** -This function will set the iCloseNode variable, which is the node most closest to -the bot. Returns the closest node it found. -**/ -int cBot::determineCurrentNode() { - iCloseNode = determineCurrentNode(NODE_ZONE); - return iCloseNode; -} - -/** -This function will set the iCloseNode variable, which is the node most closest to -the bot. Returns the closest node it found. -**/ -int cBot::determineCurrentNodeWithTwoAttempts() { - iCloseNode = determineCurrentNode(); - if (iCloseNode < 0) { - iCloseNode = determineCurrentNode(NODE_ZONE * 2); - } - return iCloseNode; -} - -/** -Find node close to bot, given range. Does not cache result. -**/ -int cBot::determineCurrentNode(float range) const -{ - return NodeMachine.getClosestNode(pEdict->v.origin, range, pEdict); -} - -/** - * This returns the current node (iCloseNode) set. Instead of using determineCurrentNode, which is expensive, - * call this to return the cached value. It will however call determineCurrentNode when node is < 0, usually it means - * the state has been set. - * @return - */ -int cBot::getCurrentNode() { - if (iCloseNode < 0) { - determineCurrentNode(); - } - return iCloseNode; -} - -/** - * Aka, the node we are heading for. - */ -int cBot::getCurrentPathNodeToHeadFor() const -{ - return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex); -} - -/** - * Aka, the node we were coming from. In case the index is < 0 (ie, there is no previous node yet), this will - * return -1; - */ -int cBot::getPreviousPathNodeToHeadFor() const -{ - return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, getPreviousPathIndex()); -} - -bool cBot::isHeadingForGoalNode() const -{ - return getCurrentPathNodeToHeadFor() == getGoalNode(); -} - -/** - * Aka, the next node after we have arrived at the current path node. - */ -int cBot::getNextPathNode() const -{ - return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex + 1); -} - -// Is this bot dead? -bool cBot::isDead() const -{ - return (pEdict->v.health < 1) || (pEdict->v.deadflag != DEAD_NO); -} - -// BOT: Think -void cBot::Think() { - if (mod_id != CSTRIKE_DLL) return; // do not support non-counter-strike mods - - // BOT: If a bot did not join a team yet, then do it - if (!hasJoinedTeam) { - rprint("Need to join team, doing that now"); - JoinTeam(); - return; - } - - // Set closest node - determineCurrentNode(); - - // BOT: If a bot is dead, re-initialize - if (isDead()) { - if (!bInitialize) return; // do nothing when no need to initialize - rprint("Dead, need to re-initialize"); - - // AUTOSKILL - const cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); - - // not killed by a fellow bot, presumably a human player - if (botPointerOfKiller == nullptr) { - if (autoskill) { - bot_skill--; - if (bot_skill < 0) - bot_skill = 0; - } - - if (Game.iKillsBroadcasting != BROADCAST_KILLS_NONE - && killer_edict != nullptr) { - // This is a human, we will tell this human he has been killed - // by a bot. - const int r = RANDOM_LONG(150, 255); - const int g = RANDOM_LONG(30, 155); - const int b = RANDOM_LONG(30, 155); - char msg[128]; - if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - std::sprintf(msg, - "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", - name, bot_skill); - else - std::sprintf(msg, "You have killed a RealBot named %s!", - name); - - HUD_DrawString(r, g, b, msg, killer_edict); - } - } - - if (iCloseNode > -1 && !end_round) { - iDiedNode = iCloseNode; - NodeMachine.danger(iCloseNode, UTIL_GetTeam(pEdict)); - } - - if (console_nr == 0) { - rprint("NewRound - because console_nr ?!"); - NewRound(); - bInitialize = false; - } - - BotConsole(this); - - // dead messages - if (console_nr == 0) { - rprint("console_nr == 0"); //whatever this means - // do some chatting - if (RANDOM_LONG(0, 200) < ipChatRate) { - if (fChatTime + 0.5f < gpGlobals->time) - if (chChatSentence[0] == '\0') // we did not want to say anything - { - // we should say something now? - int iMax = -1; - - for (int tc = 0; tc < 50; tc++) { - if (ChatEngine.ReplyBlock[99].sentence[tc][0] != '\0') iMax++; - } - - const int the_c = RANDOM_LONG(0, iMax); - - if (the_c > -1 && iMax > -1) { - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); - std::sprintf(chSentence, "%s ", - ChatEngine.ReplyBlock[99].sentence[the_c]); - //strcpy(chSentence, ChatEngine.ReplyBlock[99].sentence[the_c]); - PrepareChat(chSentence); - } - } - } else { - // we missed the chatrate chance - if (fChatTime < gpGlobals->time) // time - if (chChatSentence[0] == '\0') // we did not want to say anything - if (RANDOM_LONG(0, 100) < ipChatRate) // rate - fChatTime = gpGlobals->time + - RANDOM_FLOAT(0.0f, ((Game.iProducedSentences + 1.0f) / 2.0f)); // wait - - } - - return; - } - } // isDead(); - - // set this for the next time the bot dies so it will initialize stuff - if (!bInitialize) { - bInitialize = true; - } - - if (end_round) { - rprint("End round"); - MDLL_ClientKill(pEdict); - pEdict->v.frags += 1; - return; - } - - // BOT: Played enough rounds - if (played_rounds > play_rounds && internet_play) { - rprint("Played enough rounds"); - bIsUsed = FALSE; // no longer used - char cmd[80]; - std::sprintf(cmd, "kick \"%s\"\n", name); - SERVER_COMMAND(cmd); // kick the bot using (kick "name") - return; - } - - // Move speed... moved_distance. - if (distanceMovedTimer <= gpGlobals->time) { - // see how far bot has moved since the previous position... - const Vector v_diff = prevOrigin - pEdict->v.origin; - // make distanceMoved an average of this moment and the previous one. - const float movedTwoTimes = distanceMoved + v_diff.Length(); - - // prevent division by zero - if (movedTwoTimes > 0.0f) { - distanceMoved = movedTwoTimes / 2.0f; - } else { - distanceMoved = 0.0f; - } - - // save current position as previous - prevOrigin = pEdict->v.origin; - distanceMovedTimer = gpGlobals->time + 0.1f; - } - - // NEW ROUND - if (Game.NewRound()) { - rprint_trace("Think", "Game.NewRound"); - } - - // -------------------------------- - // MEMORY STEP - // -------------------------------- - Memory(); - - // -------------------------------- - // IMPORTANT THINKING GOING ON HERE - // -------------------------------- - const int healthChange = prev_health - bot_health; - - // handle damage taken - if (prev_health > bot_health - && healthChange > RANDOM_LONG(CSTRIKE_MIN_DAMAGE, CSTRIKE_MAX_DAMAGE) - && hasEnemy()) { - - // need backup! - if (FUNC_DoRadio(this)) { - UTIL_BotRadioMessage(this, 3, "3", ""); - } - - BOT_DecideTakeCover(this); - } - - prev_health = bot_health; - - // Do your console stuff - BotConsole(this); - - // BOT: Blinded - if (isBlindedByFlashbang()) { - // Dude we are messed up. - - // 01/07/04 - Stefan - Pointed out on the forums by Josh Borke... (do not shoot when dontshoot is on) - // shoot randomly - if (!Game.bDoNotShoot) { - if ((RANDOM_LONG(0, 100) < ipFearRate) && RANDOM_LONG(0, 100)) { - UTIL_BotPressKey(this, IN_ATTACK); - } - } - - rprint_trace("Think()", "Blinded"); - return; - } - - - // NEW: When round time is over and still busy playing, kill bots - const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60.0f; - const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); - if (Game.getRoundStartedTime() + 10.0f + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { - end_round = true; - // round is ended - } - - // FREEZETIME: - if (Game.getRoundStartedTime() > gpGlobals->time && freezeTime < gpGlobals->time) { - freezeTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); - } - - // 1 SECOND START OF ROUND - if (Game.getRoundStartedTime() + 1 > gpGlobals->time && - Game.getRoundStartedTime() < gpGlobals->time) { - // TODO: Issue radio command? - this->rprint_trace("cBot::Think()", "First second of round"); - } - - // SITUATION: In freezetime - if (isFreezeTime()) { - stopMoving(); - lastSeenEnemyVector = Vector(0, 0, 0); - setTimeToMoveToNode(2); - vHead = vBody = pEdict->v.origin; - - // find any spawnpoint to look at: - edict_t *pent = nullptr; - - if (isCounterTerrorist()) { - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != nullptr) { - if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && - func_distance(pent->v.origin, pEdict->v.origin) > 50) { - break; - } - } - } else { - while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { - if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && - func_distance(pent->v.origin, pEdict->v.origin) > 50) { - break; - } - } - } - - // when pent is filled, look at it - if (pent != nullptr) { - vBody = vHead = pent->v.origin; - } - - rprint_trace("Think()", "isFreezeTime"); - return; - } - - // **---**---**---**---**---**---** - // MAIN STATE: We have no enemy... - // **---**---**---**---**---**---** - if (!hasEnemy()) { - - if (!Game.bDoNotShoot) { - InteractWithPlayers(); - } - - bool bMayFromGame = true; - - if (Game.fWalkWithKnife > 0.0f) - if (Game.getRoundStartedTime() + Game.fWalkWithKnife < gpGlobals->time) - bMayFromGame = false; - - if (Game.fWalkWithKnife == 0.0f) - bMayFromGame = false; - - if (hasShield()) { - if (!hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { - UTIL_BotPressKey(this, IN_ATTACK2); // draw shield - f_allow_keypress = gpGlobals->time + 0.7f; - } - } - - if (CarryWeapon(CS_WEAPON_KNIFE) == false - && f_camp_time < gpGlobals->time - && freezeTime < gpGlobals->time - && f_c4_time < gpGlobals->time - && f_update_weapon_time < gpGlobals->time && bWalkKnife - && bMayFromGame) { - UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(-1)); // -1 is knife - f_update_weapon_time = gpGlobals->time + 0.7f; - } - - // When holding a grenade (and not switching to another weapon) - if (CarryWeaponType() == GRENADE - && f_update_weapon_time < gpGlobals->time) { - if (iPrimaryWeapon > -1) - UTIL_SelectItem(pEdict, - UTIL_GiveWeaponName(iPrimaryWeapon)); - - else // pick secondary - UTIL_SelectItem(pEdict, - UTIL_GiveWeaponName(iSecondaryWeapon)); - f_update_weapon_time = gpGlobals->time + 0.7f; - } - - // Think about objectives - ThinkAboutGoals(); - } else { - // **---**---**---**---**---**---** - // MAIN STATE: We have an enemy! - // **---**---**---**---**---**---** - - // Keep interacting with players: - InteractWithPlayers(); - - // And combat enemies - Combat(); - } - - // WALK() - NodeMachine.path_think(this, distanceMoved); - - // SITUATION: Passed Freezetime - -} // THINK() - -bool cBot::isFreezeTime() const { - return freezeTime > gpGlobals->time; -} - -/** -Return true if one of the pointers is not NULL -**/ -bool cBot::isEscortingHostages() { - const bool result = getAmountOfHostagesBeingRescued() > 0; - if (result) { - rprint("I am escorting hostages!"); - } - return result; -} - -void cBot::checkOfHostagesStillFollowMe() { - if (fCheckHostageStatusTimer > gpGlobals->time) return; - fCheckHostageStatusTimer = gpGlobals->time + 5; - -//// this->rprint("checkOfHostagesStillFollowMe - START"); -// if (hostage1) { -// if (!isHostageRescued(this, hostage1) && FUNC_EdictIsAlive(hostage1) && !canSeeEntity(hostage1) && getDistanceTo(hostage1->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage1"); -// forgetHostage(hostage1); -// } -// } -// if (hostage2) { -// if (!isHostageRescued(this, hostage2) && FUNC_EdictIsAlive(hostage2) && !canSeeEntity(hostage2) && getDistanceTo(hostage2->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage2"); -// forgetHostage(hostage2); -// } -// } -// if (hostage3) { -// if (!isHostageRescued(this, hostage3) && FUNC_EdictIsAlive(hostage3) && !canSeeEntity(hostage3) && getDistanceTo(hostage3->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage3"); -// forgetHostage(hostage3); -// } -// } -// -// if (hostage4) { -// if (!isHostageRescued(this, hostage4) && FUNC_EdictIsAlive(hostage4) && !canSeeEntity(hostage4) && getDistanceTo(hostage4->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage4"); -// forgetHostage(hostage4); -// } -// } -// rprint("checkOfHostagesStillFollowMe - END"); -} - -void cBot::clearHostages() { - rprint_trace("clearHostages"); - hostage1 = nullptr; - hostage2 = nullptr; - hostage3 = nullptr; - hostage4 = nullptr; - pBotHostage = nullptr; -} - -// BOT: CheckGear, part of UpdateStatus() -void cBot::CheckGear() { - - // PRIMARY - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_mp5navy"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_mp5navy"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ak47"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_ak47"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m3"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m3"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_aug"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_aug"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_sg552"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_sg552"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m249"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m249"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_xm1014"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_xm1014"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_p90"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_p90"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_tmp"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_tmp"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m4a1"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m4a1"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_awp"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_awp"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_sg550"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_sg550"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_scout"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_scout"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_mac10"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_mac10"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_g3sg1"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_g3sg1"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ump45"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_ump45"); - - // Counter-Strike 1.6 weapon FAMAS/GALIL - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_famas"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_famas"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_galil"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_galil"); - - // SECONDARY - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_elite"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_elite"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_fiveseven"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_fiveseven"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_p228"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_p228"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_deagle"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_deagle"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_usp"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_usp"); - if (isOwningWeapon(UTIL_GiveWeaponId("weapon_glock18"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_glock18"); - - // Handle shields as primary weapon - if (hasShield()) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_shield"); -} - -// BOT: Update personal status -void cBot::UpdateStatus() { - // name filled in yet? - if (name[0] == 0) - std::strcpy(name, STRING(pEdict->v.netname)); - - // Set thirdpartybot flag - pEdict->v.flags |= FL_THIRDPARTYBOT; - - // Reset stuff - pEdict->v.button = 0; - setMoveSpeed(f_max_speed); // by default run - - // When its not time to strafe, don't. - if (f_strafe_time < gpGlobals->time) { - if (f_strafe_speed != 0.0f) { - rprint_trace("UpdateStatus", "Strafe speed set to 0!"); - f_strafe_speed = 0.0f; - } - } - - // Update team state when started - if (hasJoinedTeam) { - iTeam = UTIL_GetTeam(pEdict) + 1; // 1 - TERRORIST, 2 - COUNTER-TERRORIST - } - - // Check if we became VIP - vip = UTIL_IsVip(pEdict); - - // Check gear - CheckGear(); - - // Set max speed and such when CS 1.6 - if (counterstrike == 1) { - f_max_speed = pEdict->v.maxspeed; -// char msg[255]; -// sprintf(msg, "f_max_speed set to %f", f_max_speed); -// rprint_trace("UpdateStatus", msg); - bot_health = static_cast(pEdict->v.health); - bot_armor = static_cast(pEdict->v.armorvalue); - } -} - -// ---------------------------------- BOT CLASS FUNCTIONS -// ---------------------------------- BOT CLASS FUNCTIONS -// ---------------------------------- BOT CLASS FUNCTIONS - -//////////////////////////////////////////////////////////////////////////////// -/// Radio Action - Response -//////////////////////////////////////////////////////////////////////////////// -bool BotRadioAction() { - char name[64]; - bool unstood = false; - edict_t *plr = nullptr; - int team = -1; - int i; - int radios = 0; // Hold amount of replies here, so we don't flood :) - std::strcpy(name, radio_messenger); - - // First find the team messager name - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); // Get pEdict - if (pPlayer) // If player exists - { - char netname[64]; - std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname - if (std::strcmp(netname, name) == 0) // If - { - plr = pPlayer; - team = UTIL_GetTeam(pPlayer); - } - } - } - - // Check players and check if radio message applies to them - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - if (pPlayer) { - char netname[64]; - - std::strcpy(netname, STRING(pPlayer->v.netname)); - - if ((std::strcmp(netname, name) != 0) && // When not the same name - (team == UTIL_GetTeam(pPlayer)) && // .. the same team... - (pPlayer->v.deadflag == DEAD_NO) && // .. not dead .. - ((UTIL_GetBotPointer(pPlayer) != nullptr))) // and a RealBot - { - // here are all bots - cBot *BotPointer = UTIL_GetBotPointer(pPlayer); - - if (BotPointer == nullptr) - continue; // somehow this fucked up, bail out - - const float distance = func_distance(plr->v.origin, - BotPointer->pEdict->v.origin); // distance between the 2 - - // Same team, randomly, do we even listen to the radio? - // the more further away, the more chance it will not listen - bool bWantToListen = false; - - // Reply on distance check - if (RANDOM_LONG(0, 8192) > distance) - bWantToListen = true; - - // Hearrate (personality setting) - if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && - bWantToListen) - bool want_to_answer = true; - - // If we want to listen to the radio... then handle it! - if (bWantToListen) { - bool can_do_negative = false; - - // Report in team! - if (std::strstr(message, "#Report_in_team") != nullptr) { - // gives human knowledge who is on his team - } - - // Regroup team! - if (std::strstr(message, "#Regroup_team") != nullptr) { - // regroup now! - unstood = true; - - // get to the leader position - BotPointer->rprint("Setting goal from regroup team"); - BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); - BotPointer->forgetPath(); - } - - // Hold this position - if (std::strstr(message, "#Hold_this_position") != nullptr || - std::strstr(message, "#Get_in_position_and_wait") != nullptr) { - // do nothing - } - // Follow me!! - if (std::strstr(message, "#Follow_me") != nullptr) {} - - // You take the point! - // 23/06/04 - Stefan - Here the leader should break up his position? - // ie, the leader will be assigned to the bot this human/bot is facing? - if (std::strstr(message, "#You_take_the_point") != nullptr) { - can_do_negative = false; - } - // Enemy Sotted! - if (std::strstr(message, "#Enemy_spotted") != nullptr) { - can_do_negative = false; - - // Find player who issues this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - // Help this player - if (iBackupNode > -1) { - - unstood = true; - - BotPointer->rprint("Setting goal for backup"); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - // Enemy Down! - if (std::strstr(message, "#Enemy_down") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); - - unstood = true; - can_do_negative = false; - } - // Stick together team! - if (std::strstr(message, "#Stick_together_team") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); - unstood = true; - can_do_negative = false; - } - // cover me|| strstr (message, "#Cover_me") != NULL - - // Need backup / taking fire... - if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); - - unstood = true; - - // get source of backup - const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - - // Taking fire! - if (std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); - unstood = true; - - // Find player who issued this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - - } - // Team fall back! - if (std::strstr(message, "#Team_fall_back") != nullptr) { - - } - // Go Go Go, stop camping, stop following, get the heck out of there! - if (std::strstr(message, "#Go_go_go") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); - unstood = true; - BotPointer->f_camp_time = gpGlobals->time - 30; - BotPointer->f_walk_time = gpGlobals->time; - BotPointer->f_cover_time = gpGlobals->time - 10; - BotPointer->f_hold_duck = gpGlobals->time - 10; - BotPointer->f_jump_time = gpGlobals->time - 10; - BotPointer->forgetPath(); - BotPointer->forgetGoal(); - } - - if ((FUNC_DoRadio(BotPointer)) && (unstood)) { - const int maxAllowedRadios = gpGlobals->maxClients / 4; - if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { - const bool report_back = false; - - if (!report_back) { - UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! - } else { - UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! - } - - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); - radios++; - } - } - } // they even listen to the radio command? - else { - /* - // filter out the commands where we cannot reply with negative - // You take the point! - if (strstr (message, "#You_take_the_point") != NULL) - can_do_negative = false; - - // Enemy Sotted! - if (strstr (message, "#Enemy_spotted") != NULL) - can_do_negative = false; - - // Enemy Down! - if (strstr (message, "#Enemy_down") != NULL) - can_do_negative = false; - - if ((FUNC_DoRadio(BotPointer)) - && (unstood) && (can_do_negative)) - - { - if (BotPointer->console_nr == 0 - && radios < (gpGlobals->maxClients / 4)) - - { - if (report_back == false) - - { - UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); - radios++; - } - } - } - */ - } - } // End check! - } // If (Player) - } // FOR Clients - return true; -} - -// Is entity visible? (from Entity view) -bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { - - //DebugOut("bot: EntityIsVisible()\n"); - TraceResult tr; - - // trace a line from bot's eyes to destination... - UTIL_TraceLine(pEntity->v.origin + pEntity->v.view_ofs, dest, - dont_ignore_monsters, pEntity->v.pContainingEntity, &tr); - - // check if line of sight to object is not blocked (i.e. visible) - if (tr.flFraction >= 1.0f) - return true; - - else - return false; -} - -// Can see Edict? -bool cBot::canSeeEntity(edict_t *pEntity) const -{ - if (pEntity == nullptr) return false; - - TraceResult tr; - const Vector start = pEdict->v.origin + pEdict->v.view_ofs; - const Vector vDest = pEntity->v.origin; - - // trace a line from bot's eyes to destination... - UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); - - // it hit anything - if (tr.flFraction < 1.0f) { - // if it hit the entity we wanted to see, then its ok! - if (tr.pHit == pEntity) return true; - return false; - } - - return true; -} - -/** - * Returns distance from this bot to a given nodeIndex. If the given NodeIndex is invalid, the distance returned is 0. - * @param nodeIndex - * @return - */ -float cBot::getDistanceTo(int nodeIndex) { - const tNode *nodePtr = NodeMachine.getNode(nodeIndex); - if (nodePtr != nullptr) { - return getDistanceTo(nodePtr->origin); - } - rprint("getDistanceTo(int nodeIndex)", "The given nodeIndex was invalid, returning 9999 distance"); - return 9999; -} - -/** - * Returns distance from this bot position (pEdict->v.origin) to given Vector. - * @param vDest - * @return - */ -float cBot::getDistanceTo(const Vector& vDest) const -{ - return func_distance(pEdict->v.origin, vDest); -} - -bool cBot::isUsingHostage(edict_t *pHostage) { - if (pHostage == nullptr) return false; - - // checks if the current pEdict is already 'in use' - // note: time check only when we have an hostage pointer assigned - if (hostage1 == pHostage) { - rprint("isUsingHostage", "hostage1"); - return true; - } - - if (hostage2 == pHostage) { - rprint("isUsingHostage", "hostage2"); - return true; - } - - if (hostage3 == pHostage) { - rprint("isUsingHostage", "hostage3"); - return true; - } - - if (hostage4 == pHostage) { - rprint("isUsingHostage", "hostage4"); - return true; - } - - return false; -} - -void cBot::forgetHostage(edict_t *pHostage) { - // these are the hostages we are rescueing (ie, they are following this bot) - if (hostage1 == pHostage) { - rprint("forgetHostage", "hostage1"); - hostage1 = nullptr; - } - if (hostage2 == pHostage) { - rprint("forgetHostage", "hostage2"); - hostage2 = nullptr; - } - if (hostage3 == pHostage) { - rprint("forgetHostage", "hostage3"); - hostage3 = nullptr; - } - if (hostage4 == pHostage) { - rprint("forgetHostage", "hostage4"); - hostage4 = nullptr; - } - - // this is the hostage we have taken interest in - if (pBotHostage == pHostage) { - rprint("forgetHostage", "pBotHostage"); - pBotHostage = nullptr; - } -} - -int cBot::getAmountOfHostagesBeingRescued() const -{ - int count = 0; - - if (hostage1 != nullptr) count++; - if (hostage2 != nullptr) count++; - if (hostage3 != nullptr) count++; - if (hostage4 != nullptr) count++; - - return count; -} - -// Will return true when the vector is visible. -// TODO: Make this function more flexible, ie able to hit an entity that it searches -// and return true on that as well. (mix it with the above function) -bool cBot::canSeeVector(const Vector& vDest) const -{ - TraceResult tr; - const Vector start = pEdict->v.origin + pEdict->v.view_ofs; - - // trace a line from bot's eyes to destination... - UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction < 1.0f) - return false; - - return true; -} - -// The coming 2 shield functions where originaly created by Whistler; -// i got them from the JoeBot source though. But... in the end, thank you -// Whistler! -bool cBot::hasShield() const -{ - // Adapted from Wei Mingzhi's YAPB - return (strncmp(STRING(pEdict->v.viewmodel), "models/shield/v_shield_", 23) == 0); -} - -bool cBot::hasShieldDrawn() const -{ - // Adapted from Wei Mingzhi's YAPB - if (!hasShield()) - return false; - - return (pEdict->v.weaponanim == 6 || pEdict->v.weaponanim == 7); -} - -/* - BotThink() - This function is the very general/main/simplified thinking function of the bot. - Do NOT add/remove/change code here! If you want to give the bot information to - work with. Put it in UpdateStatus(). When the bot has to think about it, do it - int Think() and everything else (when all is set, how to 'do' it) in Act(). - */ -void BotThink(cBot *pBot) { - // STEP 1: Update status - pBot->UpdateStatus(); - - // STEP 2: Think - pBot->Think(); - - // STEP 3: Act - pBot->Act(); - - // PASS THROUGH ENGINE - -// float frameInterval = m_lastCommandTime - gpGlobals->time; - const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; - pBot->fLastRunPlayerMoveTime = gpGlobals->time; - - const double upMove = 0.0; - char msg[255]; - std::sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); - pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); - g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, - upMove, pBot->pEdict->v.button, 0, msecval); - - const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps - pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; -} - -// 17/07/04 -// log important variables of the bot (it will be called from dll.cpp once per active bot) -// they are logged into reallog.txt file - -void cBot::Dump() { - char buffer[181]; - const int iCurrentNode = - NodeMachine.getClosestNode(pEdict->v.origin, (NODE_ZONE * 2), pEdict); - - _snprintf(buffer, 180, - "%s (#%d %s): timers, now= %.0f, c4_time=%.0f, camp_time=%.0f, wait_time=%.0f, cover_time=%.0f, wander=%.0f, MoveToNodeTime=%.0f\n", - name, iBotIndex, (iTeam == 1) ? "T" : "CT", gpGlobals->time, - f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, fMoveToNodeTime); - rblog(buffer); - _snprintf(buffer, 180, " GoalNode=%d, CurrentNode=%d, iPathFlags=", - iGoalNode, iCurrentNode); - switch (iPathFlags) { - case PATH_NONE: - std::strncat(buffer, "PATH_NONE ", 180); - break; - case PATH_DANGER: - std::strncat(buffer, "PATH_DANGER ", 180); - break; - case PATH_CONTACT: - std::strncat(buffer, "PATH_CONTACT ", 180); - break; - case PATH_CAMP: - std::strncat(buffer, "PATH_CAMP ", 180); - break; - default: - std::strncat(buffer, "???", 180); - } - std::strncat(buffer, "\n", 180); - rblog(buffer); - if (iGoalNode >= 0) - NodeMachine.dump_path(iBotIndex, pathIndex); -} - -/** - * Will begin walk the path by setting pathNodeIndex to 0, which is a valid nr so that - * isWalkingPath returns true. - */ -void cBot::beginWalkingPath() { - this->pathIndex = 0; -} - -bool cBot::hasHostageToRescue() const -{ - return pBotHostage != nullptr; -} - -bool cBot::canSeeHostageToRescue() const -{ - return canSeeEntity(pBotHostage); -} - -void cBot::clearHostageToRescueTarget() { - rprint_trace("clearHostageToRescueTarget", "clearing pBotHostage pointer"); - this->pBotHostage = nullptr; -} - -// Finds a free hostage pointer and assigns it. -void cBot::rememberHostageIsFollowingMe(edict_t *pHostage) { - if (pHostage == nullptr) { - rprint_trace("rememberHostageIsFollowingMe", "ERROR assigning NULL pHostage pointer!?"); - } - if (hostage1 == nullptr) { - rprint_trace("rememberHostageIsFollowingMe", "hostage1 slot is free."); - hostage1 = pHostage; - } else if (hostage2 == nullptr) { - rprint_trace("rememberHostageIsFollowingMe", "hostage2 slot is free."); - hostage2 = pHostage; - } else if (hostage3 == nullptr) { - rprint_trace("rememberHostageIsFollowingMe", "hostage3 slot is free."); - hostage3 = pHostage; - } else if (hostage4 == nullptr) { - rprint_trace("rememberHostageIsFollowingMe", "hostage4 slot is free."); - hostage4 = pHostage; - } -} - -void cBot::checkIfHostagesAreRescued() { - if (isHostageRescued(this, hostage1)) forgetHostage(hostage1); - if (isHostageRescued(this, hostage2)) forgetHostage(hostage2); - if (isHostageRescued(this, hostage3)) forgetHostage(hostage3); - if (isHostageRescued(this, hostage4)) forgetHostage(hostage4); -} - -bool cBot::isOnSameTeamAs(const cBot *pBot) const -{ - if (pBot == nullptr) return false; - return pBot->iTeam == this->iTeam; -} - -bool cBot::wantsToBuyStuff() const -{ - return buy_secondary == true || - buy_primary == true || - buy_ammo_primary == true || - buy_ammo_secondary == true || - buy_armor == true || - buy_defusekit == true || - buy_grenade == true || - buy_flashbang > 0; -} - -bool cBot::isUsingConsole() const -{ - return console_nr > 0; -} - -bool cBot::shouldBeAbleToMove() const -{ - return !isDead() && - !isFreezeTime() && - !shouldCamp() && - !shouldWait() && - !shouldActWithC4(); -// !isDucking() && -// !isJumping(); -} - -edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const -{ - TraceResult tr; - const Vector vOrigin = pEdict->v.origin; - - const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); - - //Using TraceHull to detect de_aztec bridge and other entities. - //DONT_IGNORE_MONSTERS, we reached it only when there are no other bots standing in our way! - //UTIL_TraceHull(vOrigin, vNode, dont_ignore_monsters, point_hull, pBot->pEdict, &tr); - //UTIL_TraceHull(vOrigin, vNode, dont_ignore_monsters, human_hull, pBot->pEdict, &tr); - UTIL_TraceHull(vOrigin, node->origin, dont_ignore_monsters, head_hull, pEdict, &tr); - - // if nothing hit (else a wall is in between and we don't care about that): - if (tr.flFraction < 1.0f) { - if (tr.pHit) { - return tr.pHit; - } - } - - return nullptr; -} - -/** - * Get distance to the next node we're heading for - * @return - */ -float cBot::getDistanceToNextNode() const -{ - const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); - if (node) { - return getDistanceTo(node->origin); - } - return MAP_MAX_SIZE; -} - -void cBot::setBodyToNode(int nodeIndex) { - const tNode *node = NodeMachine.getNode(nodeIndex); - if (node) { - vBody = node->origin; - } -} - -void cBot::lookAtNode(int nodeIndex) { - const tNode *node = NodeMachine.getNode(nodeIndex); - if (node) { - vHead = node->origin; - } -} - -/** - * Sets timer to allow movement to node, when timer expires we will think about severing the connection - * we used. - * @param timeInSeconds - */ -void cBot::setTimeToMoveToNode(float timeInSeconds) { - char msg[255]; - const float endTime = gpGlobals->time + timeInSeconds; - std::sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); - rprint_trace("setTimeToMoveToNode", msg); - - this->nodeTimeIncreasedAmount = 0; - this->fMoveToNodeTime = endTime; -} - -/** - * Whatever was set, increase the time given in function param. This expands the time a bit. - * @param timeInSeconds - */ -void cBot::increaseTimeToMoveToNode(float timeInSeconds) { - if (nodeTimeIncreasedAmount < 2) { - nodeTimeIncreasedAmount++; - this->fMoveToNodeTime += timeInSeconds; - const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", - timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); - rprint_trace("increaseTimeToMoveToNode", msg); - } else { - rprint_trace("increaseTimeToMoveToNode", "Refused to increase time"); - } -} - -float cBot::getMoveToNodeTimeRemaining() const -{ - return fMoveToNodeTime - gpGlobals->time; -} - -bool cBot::shouldCamp() const -{ - return f_camp_time > gpGlobals->time; -} - -bool cBot::shouldWait() const -{ - return f_wait_time > gpGlobals->time; -} - -void cBot::setTimeToWait(float timeInSeconds) { - this->f_wait_time = gpGlobals->time + timeInSeconds; -} - -bool cBot::shouldBeAbleToInteractWithButton() const -{ - return fButtonTime < gpGlobals->time; -} - -bool cBot::hasButtonToInteractWith() const -{ - return pButtonEdict != nullptr; -} - -bool cBot::hasCurrentNode() const -{ - return iCloseNode > -1; -} - -/** - * Shorthand method for creating path with flags PATH_NONE. - * @param destinationNode - * @return - */ -bool cBot::createPath(int destinationNode) { - return createPath(destinationNode, PATH_NONE); -} - -/** - * Attempts to create a path from current node to destination. Returns true on success, false on failure. - * @param destinationNode - * @param flags - * @return - */ -bool cBot::createPath(int destinationNode, int flags) { - if (destinationNode < 0 || destinationNode >= MAX_NODES) { - rprint("createPath()", "Unable to create path because destination node provided is < 0 or > MAX_NODES"); - return false; - } - - const int currentNode = getCurrentNode(); - if (currentNode < 0) { - rprint("createPath()", "Unable to create path to destination because I am not close to a start node"); - return false; - } - - forgetPath(); - - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); - rprint("createPath()", msg); - - return NodeMachine.createPath(currentNode, destinationNode, iBotIndex, this, flags); -} - -void cBot::doDuck() { - UTIL_BotPressKey(this, IN_DUCK); - this->f_hold_duck = gpGlobals->time + 0.5f; - - this->increaseTimeToMoveToNode(0.5f); -} - -bool cBot::isDucking() { - const bool b = keyPressed(IN_DUCK) || this->f_hold_duck > gpGlobals->time; - if (b) { - rprint_trace("isDucking", "Yes I am ducking"); - } - return b; -} - -bool cBot::isWalking() { - const bool b = !keyPressed(IN_RUN) || this->f_walk_time > gpGlobals->time; - if (b) { - rprint_trace("isWalking", "Yes I am walking"); - } - return b; -} - -void cBot::doJump(const Vector &vector) { - rprint_trace("doJump", "With vector"); - // stay focussed with body and head to this vector - this->vHead = vector; - this->vBody = vector; - - doJump(); -} - -void cBot::doJump() { - rprint_trace("doJump", "no vector"); - UTIL_BotPressKey(this, IN_JUMP); - this->f_jump_time = gpGlobals->time + 0.5f; - - // duck like this, because doDuck increases node time *again*, so no - UTIL_BotPressKey(this, IN_DUCK); // DUCK jump by default - this->f_hold_duck = gpGlobals->time + 0.5f; - - this->increaseTimeToMoveToNode(0.75f); -} - -bool cBot::isJumping() { - const bool b = keyPressed(IN_JUMP) || this->f_jump_time > gpGlobals->time; - if (b) { - rprint_trace("isJumping", "Yes I am jumping"); - } - return b; -} - -// Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] -// -void cBot::doDuckJump(){ - rprint_trace("doDuckJump", "no vector"); - UTIL_BotPressKey(this, IN_DUCK); - this->f_hold_duck = gpGlobals->time + 0.75f; - - UTIL_BotPressKey(this, IN_JUMP); - this->f_jump_time = gpGlobals->time + 0.75f; - - this->increaseTimeToMoveToNode(0.75f); -} - -// Bots require both the combination of the (IN_DUCK) and (IN_JUMP) key to be pressed -// in order to properly duck jump. -bool cBot::isDuckJumping() { - const bool b = keyPressed(IN_JUMP) && keyPressed(IN_DUCK) || - this->f_hold_duck > gpGlobals->time && this->f_jump_time > gpGlobals->time ; - if (b) { - rprint_trace("isDuckJumping", "Yes I am DuckJumping"); - } - return b; -} - -// $Log: bot.cpp,v $ -// Revision 1.21 2004/09/07 18:23:02 eric -// - bumped version to 3061 -// - adding Frashman code to buy the weapon as selected by Josh's code -// - Realbot is really the result of multiple people :-) -// -// Revision 1.20 2004/09/07 15:44:34 eric -// - bumped build nr to 3060 -// - minor changes in add2 (to add nodes for Bsp2Rbn utilities) -// - if compiled with USE_EVY_ADD, then the add2() function is used when adding -// nodes based on human players instead of add() -// - else, it now compiles mostly without warnings :-) -// -// Revision 1.19 2004/08/07 18:42:56 eric -// - bumped version to 3058 -// - added a cNodeMachine::add2 which should do the same job as ::add -// but it seems to work better. ::add2 is used by Bsp2Rbn only for now. -// - added the display of node flags (water, ladder, jump) next to the -// node position in 'debug nodes draw' -// - suppress the debugging information which displayed the hit entity -// while establishing neighbourhood -// -// Revision 1.18 2004/07/30 15:02:29 eric -// - jumped to version 3057 -// - improved readibility (wapen_tabel -> weapons_table) :-P -// - all Josh Borke modifications to the buying stuff: -// * using a switch() instead of several if -// * better buying code for shield and primary weapons -// * new command 'debug pistols 0/1' -// -// Revision 1.16 2004/07/17 21:32:01 eric -// - bumped version to 3055 -// - handling of es_ and as_ maps with new goals -// - added two debug commands: -// realbot debug goals -// realbot debug bots -// - added two nodes commands (for dedicated servers mainly) -// realbot nodes connect n1 n2 -// realbot nodes disconnect n1 n2 -// - slight modification in goal scoring (only reduced score when two bots of -// the SAME team select the same goal) -// -// Revision 1.15 2004/07/03 15:58:54 eric -// nova test comment for erics account -// -// Revision 1.14 2004/07/02 16:43:35 stefan -// - upped to build 3051 -// - changed log() into rblog() -// - removed BOT.CFG code that interpets old RB V1.0 commands -// - neater respons of the RealBot console -// - more help from RealBot console (ie, type realbot server broadcast ... with no arguments it will tell you what you can do with this, etc) -// - removed message "bot personality loaded from file" -// - in overal; some cleaning done, no extra features added -// -// Revision 1.13 2004/07/01 18:09:46 stefan -// - fixed skill 10 bots not causing memory bugger on re-adding (respawning) -// - added extra check for respawning bots so auto-add function cannot crash -// - fixed 2 nitpicks pointed out on the forums -// -// Revision 1.12 2004/06/25 07:39:00 stefan -// - upped to build 3050 -// - fixed reaction time (instant reaction time) bug -// - added evy's goals, but they are not used yet -// - fixed some radio responses here and there for swat behaviour. -// - swat leader automaticly assigned again when one dies -// - HINT: you can see any changes made by me, by looking at DD/MM/YY - Stefan (ie, 22/06/04 - Stefan, will let you find all changes i made that day) -// -// Revision 1.11 2004/06/23 08:24:14 stefan -// - upped to build 3049 -// - added swat behaviour (team leader assignment, radio response change and leaders command team-mates) - THIS IS EXPERIMENTAL AND DOES NOT ALWAYS WORK AS I WANT IT TO. -// - changed some conditions in nodemachine -// - sorry evy, still not added your new goals ;) will do next time, i promise -// -// Revision 1.10 2004/06/20 10:24:13 stefan -// - fixed another steep/stair thingy -// - changed a bit of the aiming code -// -// Revision 1.9 2004/06/19 21:06:14 stefan -// - changed distance check in nodemachine -// - fixed some 'steep' bug in nodemachine -// -// Revision 1.8 2004/06/17 21:23:23 stefan -// - fixes several connection problems with nodes. Going down from steep + crates (de_dust) PLUS going up/down from very steep slopes on as_oilrig.. 0wnage and thx to PMB and Evy -// - fixed chat bug in CS 1.6, its still CS 1.5 & CS 1.6 compatible though -// -// Revision 1.7 2004/06/13 20:08:21 stefan -// - 'bad score for goals' added -// - bmp dump info (Thanks Evy) -// - added 'realbot server players', so you can keep a server full at NR players at all times -// - slightly adjusted goal selection code -// - wander code disabled -// - lots of debug info introduced, do not use this source for REAL USAGE! -// -// Revision 1.6 2004/06/01 15:30:57 stefan -// *** empty log message *** -// -// Revision 1.5 2004/05/29 19:05:47 stefan -// - upped to BUILD 3044 -// - removed several debug messages on screen -// - changed default 'chatrate (max sentences)' to 3 -// - removed copyright notice, which is not valid due GPL license -// -// i know, nothing special :) -// -// Revision 1.4 2004/05/07 13:33:49 stefan -// added more comments, more neat code now -// -// Revision 1.3 2004/04/18 18:32:36 stefan -// - Restructured code a bit -// -// Revision 1.2 2004/04/18 17:39:19 stefan -// - Upped to build 2043 -// - REALBOT_PRINT() works properly now -// - Log() works properly now -// - Clearing in dll.cpp of reallog.txt at dll init -// - Logging works now, add REALBOT_PRINT() at every point you want to log something. -// + fNearestDistance = fDistance; + pNewEnemy = pPlayer; + } + } + } // valid player + } // FOR + + // We found a new enemy & the new enemy is different then previous pointer + if (pNewEnemy && pNewEnemy != pEnemyEdict) { + const int iCurrentNode = determineCurrentNode(); + + // Add 'contact' data + if (iCurrentNode > -1) { + NodeMachine.contact(iCurrentNode, UTIL_GetTeam(pEdict)); + } + + // We have a reaction time to this new enemy + rememberEnemyFound(); + f_shoot_time = gpGlobals->time + ReactionTime(bot_skill); + pEnemyEdict = pNewEnemy; // Update pointer + + // We did not have an enemy before + if (pEnemyEdict == nullptr) { + rprint_trace("FindEnemy()", "Found new enemy"); + + // RADIO: When we found a NEW enemy but NOT via a friend + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "2", ""); + } + + // We found a new enemy + return 0; + } + + // we found an enemy that is newer/more dangerous then previous + rprint_trace("FindEnemy()", "Found 'newer' enemy"); + return 3; + } + + // nothing found + return -1; // return result +} + +void cBot::rememberEnemyFound() { + f_bot_find_enemy_time = gpGlobals->time + REMEMBER_ENEMY_TIME; +} + +/****************************************************************************** + Function purpose: Sets vHead to aim at vector + ******************************************************************************/ +void cBot::setHeadAiming(const Vector& vTarget) { + vHead = vTarget; +} + +/** + * Returns true / false whether enemy is alive. + * @return + */ +bool cBot::isEnemyAlive() const +{ + return IsAlive(pEnemyEdict); +} + +bool cBot::isSeeingEnemy() { + if (!hasEnemy()) { + this->rprint("canSeeEnemy called without having enemy?"); + return false; + } + + if (isBlindedByFlashbang()) { + return false; + } + + Vector vBody = pEnemyEdict->v.origin; + Vector vHead = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs; + + const bool bodyInFOV = FInViewCone(&vBody, pEdict) && FVisible(vBody, pEdict); + const bool headInFOV = FInViewCone(&vHead, pEdict) && FVisible(vHead, pEdict); + if (bodyInFOV || headInFOV) { + return true; + } + return false; +} + +/****************************************************************************** + Function purpose: Aims at enemy, only when valid. Based upon skill how it 'aims' + ******************************************************************************/ +void cBot::AimAtEnemy() { + if (!hasEnemy()) + return; + + // We cannot see our enemy? -> bail out + if (isSeeingEnemy()) { + setHeadAiming(lastSeenEnemyVector); // look at last known vector of enemy + return; + } + + // Distance to enemy + const float fDistance = (pEnemyEdict->v.origin - pEdict->v.origin).Length() + 1; // +1 to make sure we never divide by zero + + // factor in distance, the further away the more deviation - which is based on skill + const int skillReversed = 10 - bot_skill + 1; + float fScale = 0.5f + fDistance / static_cast(64 * + skillReversed); // a good skilled bot is less impacted by distance than a bad skilled bot + + if (CarryWeaponType() == SNIPER) fScale *= 0.80f; // sniping improves aiming + + // Set target here + Vector vTarget; + if (bot_skill <= 1) + vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-0.5f, 1.1f); // aim for the head + else if (bot_skill > 1 && bot_skill < 4) + vTarget = pEnemyEdict->v.origin + + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy + else + vTarget = pEnemyEdict->v.origin; // aim for body + + // Based upon how far, we make this fuzzy + float fDy, fDz; + float fDx = fDy = fDz = static_cast(bot_skill + 1) * fScale; + + // Example 1: + // Super skilled bot (bot_skill 1), with enemy of 2048 units away. Results into: + // skillReversed = (10 - 0 + 1) == 11 + // fScale = 2048 / (128 * 11) -> 2048 / 1408 => 1.454545 + // fd* = 0.5 + 1 * 1,95 + + // Example 2, less skilled bot (skill = 3) same enemy + // skillReversed = (10 - 3 + 1) == 8 + // fScale = 2048 / (128 * 8) -> 2048 / 1024 => 2 + // fd* = 3 * 2 + + vTarget = vTarget + Vector( + RANDOM_FLOAT(-fDx, fDx), + RANDOM_FLOAT(-fDy, fDy), + RANDOM_FLOAT(-fDz, fDz) + ); + + // Add Offset + fDx = fpXOffset; + fDy = fpYOffset; + fDz = fpZOffset; + + // increase offset with personality x,y,z offsets randomly + vTarget = vTarget + Vector( + RANDOM_FLOAT(-fDx, fDx), + RANDOM_FLOAT(-fDy, fDy), + RANDOM_FLOAT(-fDz, fDz) + ); + + if (isHoldingGrenadeOrFlashbang()) { + // aim a bit higher + vTarget = vTarget + Vector(0, 0, 50); + } + + setHeadAiming(vTarget); +} + +bool cBot::isBlindedByFlashbang() const { + return fBlindedTime > gpGlobals->time; +} + +bool cBot::isHoldingGrenadeOrFlashbang() const { + return current_weapon.iId == CS_WEAPON_HEGRENADE || current_weapon.iId == CS_WEAPON_FLASHBANG; +} + +/****************************************************************************** + Function purpose: Perform fighting actions + ******************************************************************************/ +void cBot::FightEnemy() { + // We can see our enemy + if (!isBlindedByFlashbang() && isSeeingEnemy()) { + + // GET OUT OF CAMP MODE + if (f_camp_time > gpGlobals->time) { + f_camp_time = gpGlobals->time; + } + + // Next time our enemy gets out of sight, it will be the 'first' time + // of all 'frame times'. + bFirstOutOfSight = false; + + // Remember last seen enemy position + lastSeenEnemyVector = pEnemyEdict->v.origin; // last seen enemy position + + // FIXME: Fix the darn zoom bug + // zoom in with sniper gun + if (CarryWeaponType() == SNIPER) { + if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + zoomed++; + + if (zoomed > ZOOM_TWICE) + zoomed = ZOOM_NONE; + } + } else if (FUNC_BotHoldsZoomWeapon(this)) { + if (zoomed < ZOOM_ONCE && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + zoomed++; + } + } + + // NOT blinded by flashbang, try to find cover? + if (f_cover_time < gpGlobals->time) { + // COVER: Not taking cover now, fight using fightstyles. + + // when vip, we always take cover. + if (vip) { + // Camp, take cover, etc. + BOT_DecideTakeCover(this); + + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "3", ""); // need backup + } + } else { + // DECIDE: Should we take cover or not. + if (FUNC_ShouldTakeCover(this)) { + FindCover(); + } + } + } else { + + } + + // Keep timer updated for enemy + f_bot_find_enemy_time = gpGlobals->time + REMEMBER_ENEMY_TIME; + } + else // ---- CANNOT SEE ENEMY + { + if (f_bot_find_enemy_time < gpGlobals->time) { + pEnemyEdict = nullptr; + lastSeenEnemyVector = Vector(0, 0, 0); + rprint_trace("FightEnemy()", "Lost enemy out of sight, forgetting path and goal"); + forgetPath(); + forgetGoal(); + } else { + + // When we have the enemy for the first time out of sight + // we calculate a path to the last seen position + if (!bFirstOutOfSight) { + rprint_trace("FightEnemy()", "Enemy out of sight, calculating path towards it."); + // Only change path when we update our information here + const int iGoal = NodeMachine.getClosestNode(lastSeenEnemyVector, NODE_ZONE, pEdict); + if (iGoal > -1) { + setGoalNode(iGoal); + forgetPath(); + } + + bFirstOutOfSight = true; + } else { + if (!hasGoal()) { + rprint("Enemy out of sight and no goal, forgetting enemy"); + forgetEnemy(); + } + } + } + } // visible +} + +void cBot::pickWeapon(int weaponId) { + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(weaponId)); + f_c4_time = gpGlobals->time - 1; // reset C4 timer data + // give Counter-Strike time to switch weapon (animation, update state, etc) + f_update_weapon_time = gpGlobals->time + 0.7f; +} + +bool cBot::ownsFavoritePrimaryWeapon() const +{ + return hasFavoritePrimaryWeaponPreference() && isOwningWeapon(ipFavoPriWeapon); +} + +bool cBot::ownsFavoriteSecondaryWeapon() const +{ + return hasFavoriteSecondaryWeaponPreference() && isOwningWeapon(ipFavoSecWeapon); +} + +/** + * Returns true if bot has weapon (id) in possession + * @param weaponId + * @return + */ +bool cBot::isOwningWeapon(int weaponId) const +{ + return bot_weapons & 1 << weaponId; +} + +/** + * Returns true if bot carries weapon right now + * @param weaponId + * @return + */ +bool cBot::isHoldingWeapon(int weaponId) const +{ + return current_weapon.iId == weaponId; +} + +bool cBot::hasFavoritePrimaryWeaponPreference() const +{ + return ipFavoPriWeapon > -1; +} + +bool cBot::hasFavoriteSecondaryWeaponPreference() const +{ + return ipFavoSecWeapon > -1; +} + +bool cBot::canAfford(int price) const //price muddled with weaponId? [APG]RoboCop[CL] +{ + return this->bot_money > price; +} + +/****************************************************************************** + Function purpose: Based upon several events pick the best weapon + ******************************************************************************/ +void cBot::PickBestWeapon() { + // does Timer allow to change weapon? (only when f_update_weapon_time < gpGlobals->time + if (f_update_weapon_time > gpGlobals->time) + return; + + // Distance to enemy + const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); + + const float knifeDistance = 300.0f; + + // ---------------------------- + // In this function all we do is decide what weapon to pick + // if we don't pick another weapon the current weapon is okay + // ---------------------------- + + // First we handle situations which are bad, no matter the distance + // or any other circumstance. + + // BAD: Carrying C4 or knife + if (CarryWeapon(CS_WEAPON_C4) || // carrying C4 + (CarryWeapon(CS_WEAPON_KNIFE) && fDistance > knifeDistance)) + { + // carrying knife and too far + if (hasPrimaryWeaponEquiped()) { + pickWeapon(iPrimaryWeapon); + return; + } + if (hasSecondaryWeaponEquiped()) { + pickWeapon(iSecondaryWeapon); + return; + } + } + + // At this point we do not update weapon information. And we did not 'switch back' to primary / secondary + if (hasEnemy() && !isSeeingEnemy()) { + // decision to pull HE grenade + if (isOwningWeapon(CS_WEAPON_HEGRENADE) && // we have a grenade + func_distance(pEdict->v.origin, lastSeenEnemyVector) < 900 && // we are close + func_distance(pEdict->v.origin, lastSeenEnemyVector) > 200 && // but not to close + RANDOM_LONG(0, 100) < 10 && // only randomly we pick a grenade in the heat of the battle + current_weapon.iId != CS_WEAPON_HEGRENADE && current_weapon.iId != CS_WEAPON_FLASHBANG && + f_gren_time + 15.0f < gpGlobals->time) // and dont hold it yet + { + UTIL_SelectItem(pEdict, "weapon_hegrenade"); // select grenade + f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) + f_gren_time = + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it + zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon + return; + } + // OR we pull a flashbang? + if (isOwningWeapon(CS_WEAPON_FLASHBANG) && // we have a grenade + func_distance(pEdict->v.origin, lastSeenEnemyVector) < 200 && // we are close + func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300 && // but not to close + RANDOM_LONG(0, 100) < 15 && // only randomly we pick a grenade in the heat of the battle + current_weapon.iId != CS_WEAPON_FLASHBANG && current_weapon.iId != CS_WEAPON_HEGRENADE && + f_gren_time + 15 < gpGlobals->time) // and dont hold it yet + { + UTIL_SelectItem(pEdict, "weapon_flashbang"); // select grenade + f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) + f_gren_time = + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it + zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon + return; + } + } + + // When we are here, we did not decide to switch to grenade/flashbang. Now we look + // if the bot has to reload or switch weapon based upon ammo. + + // ---------------------------------------- + // More complex bad things that can happen: + // ---------------------------------------- + const int iTotalAmmo = current_weapon.iAmmo1; + const int iCurrentAmmo = current_weapon.iClip; + + //char msg[80]; + //sprintf(msg, "BOT: ICLIP %d, TOTALAMMO %d\n", iCurrentAmmo, iTotalAmmo); + + // Clip is out of ammo + if (iCurrentAmmo < 1 + && (CarryWeaponType() == PRIMARY || CarryWeaponType() == SECONDARY)) { + // Camp, take cover, etc. + BOT_DecideTakeCover(this); + + // We still have ammo! + if (iTotalAmmo > 0) { + UTIL_BotPressKey(this, IN_RELOAD); + f_update_weapon_time = gpGlobals->time + 0.7f; // update timer + // return; + } else { + // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code + // a bit though. Btw, distance 600 is too far for slashing :) + + // at here the bot does not have ammo of the current weapon, so + // switch to another weapon. + if (iPrimaryWeapon > -1 && // we have a primary + current_weapon.iId != iPrimaryWeapon && // that's not the current, empty gun + func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300) // and we are not close enough to knife + { + // select primary weapon + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); // select the primary + //return; + } else { + + if (iSecondaryWeapon > -1 && current_weapon.iId != iSecondaryWeapon && + // that's not the current, empty gun + func_distance(pEdict->v.origin, lastSeenEnemyVector) > 300) // and we are not close enough to knife + { + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); // select the secondary + //return; + } else { + if (isOwningWeapon(CS_WEAPON_KNIFE) && // we have a knife (for non-knife maps) + !isHoldingWeapon(CS_WEAPON_KNIFE)) // but we do not carry it + { + UTIL_SelectItem(pEdict, "weapon_knife"); + //return; + } + } + } // end if + } // no ammo + } +} + +/****************************************************************************** + Function purpose: Fire weapon (burst; or do not fire when not allowed) + ******************************************************************************/ +void cBot::FireWeapon() { + // We may not shoot! + if (f_shoot_time > gpGlobals->time || + f_update_weapon_time > gpGlobals->time) + return; + + if (!isSeeingEnemy()) { + return; + } + + // ------------------------------------------------------------ + float fDistance = 50.0f; + + if (hasEnemy()) { + fDistance = func_distance(pEdict->v.origin, pEnemyEdict->v.origin); + } + + // Depending on weapon type + if (CarryWeaponType() == SECONDARY) { + // We may shoot, use shooting rate. + // TODO TODO TODO; Add shooting rates in BUYTABLE.INI + + if (f_sec_weapon < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK); + f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05f, 0.2f); + } + + } else if (CarryWeaponType() == PRIMARY) { + // We may shoot, use shooting rate. + // TODO TODO TODO: Add shooting rates in BUYTABLE.INI + if (f_prim_weapon < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK); // Hold fire + // All other weapons, the more distance, the more time we add to holding weapon + if (f_shoot_wait_time < gpGlobals->time) { + // AK, COLT, STEYR AUG, SIG SG552 only when enough skill! + if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) + || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) + && bot_skill < 3) { + float f_burst = (2048 / fDistance) + 0.1f; + if (f_burst < 0.1f) + f_burst = 0.1f; + if (f_burst > 0.4f) + f_burst = 0.4f; + + // CS 1.6 less burst + if (counterstrike == 1) + if (f_burst > 0.3f) + f_burst = 0.3f; + + f_prim_weapon = gpGlobals->time + f_burst; + + f_shoot_wait_time = gpGlobals->time + (f_burst * 3); + } else // other weapons + { + float f_burst = 0.1f; + if (fDistance > 300 && bot_skill < 6) { + f_burst = (fDistance - 300) / 550; + if (f_burst < 0.1f) + f_burst = 0.0f; + if (f_burst > 0.7f) + f_burst = 0.7f; + + // CS 1.6 less burst + if (counterstrike == 1) + if (f_burst > 0.2f) + f_burst = 0.2f; + if (f_prim_weapon < gpGlobals->time) + f_prim_weapon = gpGlobals->time + f_burst; + } + f_shoot_wait_time = + gpGlobals->time + f_burst + RANDOM_FLOAT(0.2f, 0.7f); + } + } + } // give the bot alteast 0.3 seconds to fire its weapon + } // PRIMARY + else if (CarryWeaponType() == GRENADE) { + if (f_gren_time > gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK); // Hold fire + setMoveSpeed(f_max_speed / 2); + + // Set new goal when holding flashbang! + if (current_weapon.iId == CS_WEAPON_FLASHBANG) { + + //tonode ? + // COVER: Take cover, using tracelines all the time! + FindCover(); + } + } else if (f_gren_time + 0.5f < gpGlobals->time) { + // NOTE: Should not happen, a bot cannot 'forget' this... + f_gren_time = gpGlobals->time + 1; + } + } // GRENADE + else if (CarryWeaponType() == KNIFE) { + setMoveSpeed(f_max_speed); + UTIL_BotPressKey(this, IN_ATTACK); // Hold fire + } // KNIFE + else if (CarryWeaponType() == SNIPER) { + setMoveSpeed(f_max_speed / 2); + UTIL_BotPressKey(this, IN_ATTACK); // Hold fire + f_shoot_time = gpGlobals->time + 1.0f; + } // SNIPER + else if (CarryWeaponType() == SHIELD) { + if (fDistance > 550) { + if (hasShieldDrawn()) { + // when the enemy is far away, we keep it + } else { + // draw shield! + UTIL_BotPressKey(this, IN_ATTACK2); // secondary attack makes shield draw + f_allow_keypress = gpGlobals->time + 0.7f; + } + } else { + // get weapon here. + if (hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { + rblog + ("BOT: Enemy is close enough, i should withdraw shield to attack this enemy\n"); + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + } + } + } else { + // debug print + REALBOT_PRINT(this, "FireWeapon()", "Unknown weapon"); + } +} + +/****************************************************************************** + Function purpose: The combat brain of the bot ( called by Think() ) + ******************************************************************************/ +void cBot::Combat() { + if (!hasEnemy()) { + rprint("Unexpected call to Combat because bot has no enemy!"); + return; + } + + // Bot is on ladder + if (isOnLadder()) { + // TODO: Bot fights when on ladder + + return; + } + + // We have an enemy and it is now dead + if (!isEnemyAlive()) { + + // radio (Enemy down) + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "9", ""); + } + + // get bot pointer + const cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); + + // This bot killed a human; adjust skill when 'autoskill' is on. + if (checkpointer == nullptr) { + + // increase bot_skill value when autoskill enabled (making bot weaker) + if (autoskill && bot_skill < 10) { + bot_skill++; + } + + if (Game.iDeathsBroadcasting != BROADCAST_DEATHS_NONE) { + // This is a human, we will tell this human he has been killed + // by a bot. + const int r = RANDOM_LONG(150, 255); + const int g = RANDOM_LONG(30, 155); + const int b = RANDOM_LONG(30, 155); + char msg[128]; + if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { + std::sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); + } else { + std::sprintf(msg, "A RealBot named %s has killed you!", name); + } + + HUD_DrawString(r, g, b, msg, pEnemyEdict); + } + } + + // clear the pointer for this and other bots that might have the same pEnemyEdict + FUNC_ClearEnemyPointer(pEnemyEdict); + + // from here react after kill... + forgetGoal(); + forgetPath(); + + if (lastSeenEnemyVector != Vector(0, 0, 0)) { + vHead = lastSeenEnemyVector; + } + + lastSeenEnemyVector = Vector(0, 0, 0); + + // random waiting + f_wait_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 0.4f)); + + // keep on walking when afraid (perhaps there are more enemies) + if (RANDOM_LONG(0, 100) < ipFearRate) + f_walk_time = gpGlobals->time + (1 + RANDOM_FLOAT(0.0f, 2.0f)); + + InteractWithPlayers(); // check any new enemy here immediately + + return; + } + + // ----------- combat + + // STEP 1: Pick best weapon to fight with + PickBestWeapon(); + + // STEP 2: Decide how to move to make us a harder target + FightEnemy(); + + // STEP 3: Aim at enemy (skill-based) + AimAtEnemy(); + + // STEP 4: Fire! + FireWeapon(); +} + +/****************************************************************************** + Function purpose: Find cover + Note: Using tracelines to get a cover node. + ******************************************************************************/ +void cBot::FindCover() { + TraceResult tr; + const Vector dest = lastSeenEnemyVector; + // Vector start = pEdict->v.origin; + // Vector end; + Vector cover_vect = Vector(9999, 9999, 9999); + + // TraceLines in 2 directions to find which way to go... + UTIL_MakeVectors(pEdict->v.v_angle); + const Vector v_src = pEdict->v.origin + pEdict->v.view_ofs; + Vector v_right = v_src + gpGlobals->v_right * 90; + Vector v_left = v_src + gpGlobals->v_right * -90; + + // We have now our first 'left' and 'right' + + // First check the right.. + UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); + + if (tr.flFraction >= 1.0f) { + // We can see it + // Now trace from that vector to our threat + UTIL_TraceLine(v_right, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); + + // If this is blocking.. then its a good wpt + if (tr.flFraction < 1.0f) + cover_vect = v_right; + } + + // Now check at the left + UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); + + if (tr.flFraction >= 1.0f) { + // We can see it + // Now trace from that vector to our threat + UTIL_TraceLine(v_left, dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); + + // If this is blocking.. then its a good wpt + if (tr.flFraction < 1.0f) { + // If we already found a wpt, then randomly pick this one + if (cover_vect != Vector(9999, 9999, 9999)) { + if (RANDOM_LONG(0, 100) < 50) + cover_vect = v_left; + } else + cover_vect = v_left; + } + } + // Now update the V_left and V_right and do the checks again. + // Vector old_right = v_right; + // Vector old_left = v_left; + v_right = v_src + gpGlobals->v_right * 180; + v_left = v_src + gpGlobals->v_right * -180; + + // Now check at the right again + UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); + + if (tr.flFraction >= 1.0f) { + // We can see it + // Now trace from that vector to our threat + UTIL_TraceLine(v_right, dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); + + // If this is blocking.. then its a good wpt + if (tr.flFraction < 1.0f) { + // If we already found a wpt, then randomly pick this one + if (cover_vect != Vector(9999, 9999, 9999)) { + if (RANDOM_LONG(0, 100) < 50) + cover_vect = v_right; + } else + cover_vect = v_right; + } + } + + // Now check at the left + UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); + if (tr.flFraction >= 1.0f) { + // We can see it + // Now trace from that vector to our threat + UTIL_TraceLine(v_left, dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); + + // If this is blocking.. then its a good wpt + if (tr.flFraction < 1.0f) { + // If we already found a wpt, then randomly pick this one + if (cover_vect != Vector(9999, 9999, 9999)) { + if (RANDOM_LONG(0, 100) < 50) + cover_vect = v_left; + } else + cover_vect = v_left; + } + } + + const int iNodeEnemy = NodeMachine.getClosestNode(pEnemyEdict->v.origin, 60, pEnemyEdict); + const int iNodeFrom = NodeMachine.getClosestNode(pEdict->v.origin, NODE_ZONE, pEdict); + + // -------------- + // TEST TEST TEST + // -------------- + const int iCoverNode = NodeMachine.node_cover(iNodeFrom, iNodeEnemy, pEdict); + bool bTakenCover = false; + + if (iCoverNode > -1) { + rprint("FindCover()", "cover node found (node based)"); + setGoalNode(iCoverNode); + forgetPath(); + + // Calculate a path to this position and get the heck there. + createPath(iCoverNode); + f_cover_time = gpGlobals->time + 8.0f; + bTakenCover = true; + } else { + + // -------------------------------------------------- + // If cover_vect is found, we find a node close to it + // -------------------------------------------------- + if (cover_vect != Vector(9999, 9999, 9999)) { + rprint("FindCover()", "cover node found (cover_vect based)"); + const int iNodeCover = NodeMachine.getClosestNode(cover_vect, 60, pEdict); + if (iNodeCover > -1) { + setGoalNode(iNodeCover); + forgetPath(); + + // Calculate a path to this position and get the heck there. + rprint("createPath -> find cover node"); + NodeMachine.createPath(iNodeFrom, iNodeCover, iBotIndex, this, PATH_NONE); + f_cover_time = gpGlobals->time + 8; + bTakenCover = true; + } + } + } + + // when we have taken cover, and we are leader, command our team to get + // into our position to cover area + if (bTakenCover) { + // do something... + } + +} // FindCover() + +void cBot::InteractWithFriends() { + + + // TODO TODO TODO; make this thing really work + //return; + + // We interact with our players in some way + // + // When a bot is camping, another bot can choose to say 'go go go' for example. + // + // + + for (int i = 1; i <= gpGlobals->maxClients; i++) { + + edict_t *pPlayer = INDEXENT(i); + + // skip invalid players and skip self (i.e. this bot) + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { + // skip this player if not alive (i.e. dead or dying) + if (!IsAlive(pPlayer)) + continue; + + // skip enemies + if (UTIL_GetTeam(pPlayer) != UTIL_GetTeam(pEdict)) + continue; + + bool bCanSeePlayer = false; + bool bClose = false; + + Vector vVecEnd = pPlayer->v.origin + pPlayer->v.view_ofs; + + if (func_distance(pPlayer->v.origin, pEdict->v.origin) < 450) + bClose = true; + + if (FInViewCone(&vVecEnd, pEdict) && FVisible(vVecEnd, pEdict)) + bCanSeePlayer = true; + + // there are tons of cases + const cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + + // It is a fellow bot + if (pBotPointer != nullptr) { + if (bClose) { + if (pBotPointer->f_camp_time > gpGlobals->time + && pBotPointer->f_camp_time - 10 < gpGlobals->time + && pBotPointer->pEnemyEdict == nullptr + && (RANDOM_LONG(0, 100) < ipCampRate + && FUNC_DoRadio(this))) { + // issue go go go + UTIL_BotRadioMessage(this, 2, "1", ""); // go go go! + } + } + + if (bCanSeePlayer) {} + } else // it is a teammate, but it is human (or a different bot) + { + // when firing + + } + + // any player: + if (bClose) { + // some one is close, need backup? + if (RANDOM_LONG(0, 100) < ipFearRate && pEnemyEdict != nullptr) + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "3", ""); // need backup + } + } + } + } + +} + +// BOT: Interact with Players ('find enemy, and how to react upon them') +void cBot::InteractWithPlayers() { + + // friends are important, we are a team dudes! + InteractWithFriends(); + + const int result = FindEnemy(); + + // ------------------------------- + // RESULT < 0; NO ENEMY FOUND + // ------------------------------- + + // No enemy found, unzoom + if (result < 0) { + // Keep f_prim_weapon updated, else we do burst immidiatly + if (CarryWeaponType() == SNIPER) { + + // Unzoom (for sniper guns) + if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + zoomed++; + } + if (zoomed > ZOOM_TWICE) + zoomed = ZOOM_NONE; + } else if (FUNC_BotHoldsZoomWeapon(this)) { + + // Unzoom (for other guns with only 1 zoom) + if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + zoomed = ZOOM_NONE; + } + } else { + + // For any weapon that has a silencer (the colt for example), use it if we want that. + if (isHoldingWeapon(CS_WEAPON_M4A1)) + if (bot_use_special == 0 && zoomed == ZOOM_NONE + && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + zoomed = ZOOM_ONCE; + } + } + } + // ------------------------------------------------ + // RESULT > -1 ; ENEMY FOUND / NO SPECIFIC REACTION + // ------------------------------------------------ + if (result > -1 && result < 4) { + + // VIP: When we found an enemy, we have a problem. + if (vip) { + + // We do not forget our enemy, but we will try to get the heck out of here. + // TODO TODO TODO: code something here? + + } + // Whenever we hold a knife, get our primary weapon + if (CarryWeapon(CS_WEAPON_KNIFE)) { + + // switch back to primary + if (iPrimaryWeapon > -1) + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); + + else // pick secondary + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); + + f_update_weapon_time = gpGlobals->time + 0.7f; + } + } + // ------------------------------------------------ + // RESULT = 1 ; ENEMY FOUND, VIA FRIEND! + // ------------------------------------------------ + + // When we have found an enemy via a friend, we simply build a path to it. + if (result == 1) { + + /* + f_prim_weapon = gpGlobals->time; + + // DECIDE: + // Do we go into battle, or do we wait first a few seconds? + + // HEALTH: The less we have, the more we want to wait + int vHealth = 100-bot_health; + + // CAMP: The more we want to camp, the more we want to wait. + int vCamp = ipCampRate; + + if (RANDOM_LONG(0,200) < (vHealth+vCamp)) + { + // depending on how much we want, the longer we wait + float fWaitTime = ((200/(vHealth+vCamp))*5); + f_wait_time = gpGlobals->time + fWaitTime; + + // TODO TODO TODO; we might not even want to wait, but also take 'cover'? + } + + // INITIALIZATION: + int iGoal = NodeMachine.getCloseNode(pBotEnemy->v.origin, NODE_ZONE, pBotEnemy); + if (iGoal > -1) + { + iGoalNode = iGoal; + pathNodeIndex = -1; + } + */ + } + // ------------------------------------------------ + // RESULT = 0 ; NEW ENEMY FOUND + // ------------------------------------------------ + if (result == 0) { + // First Encounter + //f_prim_weapon = gpGlobals->time; + if (CarryWeaponType() == SNIPER) { + if (zoomed < ZOOM_TWICE && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); + f_allow_keypress = gpGlobals->time + 0.7f; + zoomed++; + } + } + + // INITIALIZATION: + const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); + if (iGoal > -1) { + rprint_trace("InteractWithPlayers()", "Found a new enemy, setting goal and forgetting path"); + setGoalNode(iGoal); + forgetPath(); + } + + // Speed our enemy runs + // int run_speed = FUNC_PlayerSpeed(pBot->pBotEnemy); + // Distance between Us and Enemy. + // float f_distance = func_distance(pBot->pEdict->v.origin, + // pBot->pBotEnemy->v.origin); + + // Does our enemy (when a bot) has focus on us? + bool focused; + const cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); + if (playerbot) { + if (playerbot->pEnemyEdict == pEdict) + focused = true; + } else // Its a human + { + + // When we are in his 'sight' of 25 degrees , we are pretty + // much focussed for a first encounter. + if (FUNC_InFieldOfView + (pEdict, (pEnemyEdict->v.origin - pEdict->v.origin)) < 25) + focused = true; + } + + /****************************** + At this moment we know: + - The distance between us and enemy + - The focus (are we targetted too?) + - The speed of the enemy (running, standing still? etc) + *******************************/ + } // We have a first encounter + + // ------------------------------------------------ + // RESULT = 3 ; NEWER ENEMY FOUND + // ------------------------------------------------ + if (result == 3) { + // + // Newer enemy found, update goals and such, but thats all! + // + + // INITIALIZATION: + const int iGoal = NodeMachine.getClosestNode(pEnemyEdict->v.origin, NODE_ZONE, pEnemyEdict); + + if (iGoal > -1) { + rprint_trace("InteractWithPlayers()", "Found a *newer* enemy, so picking goal node to that"); + setGoalNode(iGoal); + forgetPath(); + } + } +} + +// BOT: INTERACT WITH PLAYERS +void cBot::JoinTeam() { + if (mod_id != CSTRIKE_DLL) return; + // When bot plays Counter-Strike (only Counter-Strike is supported) + + char c_class[32]; + + // Choose team first + if (start_action == MSG_CS_TEAM_SELECT) { + char c_team[32]; + start_action = MSG_CS_IDLE; // switch back to idle + + // in case of bad state/input fall-back to 'pick one for me' + if (iTeam != 1 && iTeam != 2 && iTeam != 5) { + iTeam = 5; + } + + // select the team the bot wishes to join... + if (iTeam == 1) { + std::strcpy(c_team, "1"); + } else if (iTeam == 2) { + std::strcpy(c_team, "2"); + } else { + std::strcpy(c_team, "5"); + } + + // choose + FakeClientCommand(this->pEdict, "menuselect", c_team, nullptr); + + return; + } + + // counter terrorist menu, which class/outfit? + if (start_action == MSG_CS_CT_SELECT) { + start_action = MSG_CS_IDLE; // switch back to idle + + if (bot_class < 1 || bot_class > 4) + bot_class = 5; // use random if invalid + + // Since cs 1.6 does not give us pretty random models + // we do it ourselves + if (bot_class == 5) { + bot_class = RANDOM_LONG(1, 4); + } + + // select the class the bot wishes to use... + if (bot_class == 1) + std::strcpy(c_class, "1"); + else if (bot_class == 2) + std::strcpy(c_class, "2"); + else if (bot_class == 3) + std::strcpy(c_class, "3"); + else if (bot_class == 4) + std::strcpy(c_class, "4"); + else + std::strcpy(c_class, "5"); // random + + FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); + + // bot has now joined a team + hasJoinedTeam = true; + + return; + } + + // terrorist select + if (start_action == MSG_CS_T_SELECT) { + start_action = MSG_CS_IDLE; // switch back to idle + + if (bot_class < 1 || bot_class > 4) + bot_class = 5; // use random if invalid + + // Since cs 1.6 does not give us pretty random models + // we do it ourselves + if (bot_class == 5) + bot_class = RANDOM_LONG(1, 4); + + // select the class the bot wishes to use... + if (bot_class == 1) + std::strcpy(c_class, "1"); + else if (bot_class == 2) + std::strcpy(c_class, "2"); + else if (bot_class == 3) + std::strcpy(c_class, "3"); + else if (bot_class == 4) + std::strcpy(c_class, "4"); + else + std::strcpy(c_class, "5"); // random + + FakeClientCommand(this->pEdict, "menuselect", c_class, nullptr); + + // bot has now joined the game (doesn't need to be started) + hasJoinedTeam = true; + + //return; + } +} + +int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { + + // hope this fix the unnescesary turning of bots. + // how? we save the values here, andc alculate the new value. + // this part is copied from botchangeyaw/pitch so it SHOULD work :) + float current_180; // current +/- 180 degrees + + // turn from the current v_angle pitch to the idealpitch by selecting + // the quickest way to turn to face that direction + + // find the difference in the current and ideal angle + const float diff = std::fabs(current - ideal); + + // check if the bot is already facing the idealpitch direction... + if (diff <= 1.0f) + return static_cast(current); // return number of degrees turned + + // check if difference is less than the max degrees per turn + if (diff < speed) + speed = diff; // just need to turn a little bit (less than max) + + // here we have four cases, both angle positive, one positive and + // the other negative, one negative and the other positive, or + // both negative. handle each case separately... + if (current >= 0.0f && ideal >= 0.0f) // both positive + { + if (current > ideal) + current -= speed; + + else + current += speed; + } else if (current >= 0.0f && ideal < 0.0f) { + current_180 = current - 180.0f; + if (current_180 > ideal) + current += speed; + + else + current -= speed; + } else if (current < 0 && ideal >= 0) { + current_180 = current + 180; + if (current_180 > ideal) + current += speed; + + else + current -= speed; + } else // (current < 0) && (ideal < 0) both negative + { + if (current > ideal) + current -= speed; + + else + current += speed; + } + + // check for wrap around of angle... + if (current > 180) + current -= 360; + if (current < -180) + current += 360; + return static_cast(current); // return what it should be +} + +// BOT: sub-function (DEFUSE) for ACT() +bool cBot::Defuse() { + if (!isCounterTerrorist()) // non-Counter-Terrorists have no business here + return false; + + // this bot is defusing + if (shouldActWithC4() && keyPressed(IN_USE)) { + setTimeToMoveToNode(3); + return true; + } + + // What i do, i search for the c4 timer, store its origin and check + // if this bot is close. If so, the bot should be defusing the bomb + // if the timers are set. The above check makes sure that no other + // bot will be defusing the bomb. + edict_t *pent = nullptr; + bool c4Found = false; + while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != nullptr) { + if (UTIL_GetGrenadeType(pent) == 4) { // It is a C4 + c4Found = true; + break; + } + } + + if (!c4Found) { + rprint_normal("Defuse()", "No C4 planted yet"); + return false; + } + + rprint_normal("Defuse()", "C4 is planted!"); + + // A c4 has been found, oh dear. + // Remember, pent=c4 now! + + // Calculate the distance between our position to the c4 + const Vector vC4 = pent->v.origin; + const float distance = func_distance(pEdict->v.origin, vC4); + + // can see C4 + const bool canSeeC4 = canSeeVector(vC4); + + if (!canSeeC4) { + rprint_trace("Defuse()", "Cannot see planted C4 - bailing"); + return false; + } + + // it can be seen, so it has been discovered + if (!Game.isPlantedC4Discovered()) { + this->rprint_trace("Defuse()", "C4 is discovered, remembering its coordinates"); + Game.vPlantedC4 = vC4; + } + + // We can do 2 things now + // - If we are not close, we check if we can walk to it, and if so we face to the c4 + // - If we are close, we face it and (begin) defuse the bomb. + const int distanceForC4ToBeInReach = 70; + if (distance < distanceForC4ToBeInReach) { + vHead = vC4; + vBody = vC4; + + setTimeToMoveToNode(3); // we are going to do non-path-follow stuff, so keep timer updated + const int angle_to_c4 = FUNC_InFieldOfView(pEdict, (vC4 - pEdict->v.origin)); + + // if defusion timer has not been set (ie, the bot is not yet going to defuse the bomb) + if (f_defuse < gpGlobals->time && angle_to_c4 < 35) { + this->rprint("Defuse()", "I'll start defusing the bomb"); + // when we are 'about to' defuse, we simply set the timers + f_defuse = gpGlobals->time + 90; // hold as long as you can + f_allow_keypress = gpGlobals->time + 1.5f; // And stop any key pressing the first second + // ABOUT TO DEFUSE BOMB + } + + // Defusion timer is set and c4 is within vision + if (f_defuse > gpGlobals->time && angle_to_c4 < 35) { + this->rprint("Defuse()", "I'm defusing the bomb"); + setMoveSpeed(0.0); + f_c4_time = gpGlobals->time + 6; + UTIL_BotPressKey(this, IN_DUCK); + + if (func_distance(pEdict->v.origin, vC4) > 50 + && f_allow_keypress + 0.5f > gpGlobals->time) { + setMoveSpeed(f_max_speed / 2); + } + } + + if (f_allow_keypress < gpGlobals->time && f_defuse > gpGlobals->time) { + UTIL_BotPressKey(this, IN_USE); + } + + } else { + rprint_trace("Defuse()", "I can see C4, but it is out of reach."); + const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); + if (iGoalNode < 0) { + rprint_normal("Defuse()", "No node close, so just look at it/body face at it and move towards it."); + vHead = vC4; + vBody = vC4; + } + + if (iGoalNode > -1) { + // we are not heading for this goal yet + if (getGoalNode() != iGoalNode) { + rprint_normal("Defuse()", "I don't have a goal towards the C4, overriding it now to C4 destination!"); + forgetPath(); + forgetGoal(); + setGoalNode(iGoalNode); + } else { + rprint_normal("Defuse()", "I already have a goal towards the C4!"); + } + } else { + rprint_normal("Defuse()", "C4 is somewhere without a close node."); + } + setMoveSpeed(f_max_speed); + } // distance < ... + + // we can see the bomb, and we act upon it + return true; +} + +int cBot::keyPressed(int key) const { + return pEdict->v.button & key; +} + +// BOT: Act +void cBot::Act() { + // chat + if (fChatTime < gpGlobals->time) { + if (chChatSentence[0] != '\0') { + UTIL_SayTextBot(chChatSentence, this); + std::memset(chChatSentence, 0, sizeof(chChatSentence)); + } + } + + // camp + if (f_camp_time > gpGlobals->time) { + // When camping we duck and we don't move + UTIL_BotPressKey(this, IN_DUCK); + + + setMoveSpeed(0.0f); // do not move + PickBestWeapon(); // pick weapon, do not stare with knife + + // when dropped C4 and CT we look at C4 + if (isCounterTerrorist() && Game.vDroppedC4 != Vector(9999, 9999, 9999)) { + // look at dropped C4 + if (EntityIsVisible(pEdict, Game.vDroppedC4)) + vHead = Game.vDroppedC4; + else { + if (iGoalNode > -1) + { + forgetPath(); + forgetGoal(); + vHead = vBody = NodeMachine.node_vector(iGoalNode); + } + else { + vHead = vBody = Game.vDroppedC4; + } + } + } else { + // Look at iGoalNode + if (iGoalNode > -1) + { + forgetPath(); + forgetGoal(); + vHead = vBody = NodeMachine.node_vector(iGoalNode); + } + else { + vHead = vBody = pEdict->v.origin; + } + } + } + + // C4 timer is set, this means: + // T -> Is planting bomb + // CT-> Is defusing bomb + if (shouldActWithC4()) { + // make sure we override this, or else we learn that we get stuck or something + // which is not the case. + setTimeToMoveToNode(2); + + // terrorist + if (isTerrorist()) { + // When still having the C4 + setMoveSpeed(0.0f); + // f_strafe_speed = 0.0f; + + // When no C4 selected yet, select it + if (!isHoldingWeapon(CS_WEAPON_C4)) { + UTIL_SelectItem(pEdict, "weapon_c4"); + } else { + UTIL_BotPressKey(this, IN_ATTACK); // plant it! + } + + // When we no longer have the C4 , we stop doing this stupid shit + if (!hasBomb() || Game.bBombPlanted) { + rprint_trace("Act()", "I was planting the C4, and it got planted (I no longer have the C4), so find a nearby node to camp/guard the C4"); + f_c4_time = gpGlobals->time; + setGoalNode(NodeMachine.getClosestNode(pEdict->v.origin, 200, pEdict)); + iPathFlags = PATH_CAMP; + forgetPath(); + } + } else { + // counter-terrorist + Defuse(); // old routine from RB AI V1.0 defusing, should get here and more cleaned up + } + } + + if (f_strafe_time < gpGlobals->time) { + f_strafe_speed = 0.0f; + } + + // walk only when NOT holding duck (is same as walking, combination makes bot super slow) + if (f_walk_time > gpGlobals->time && !(pEdict->v.button & IN_DUCK)) { + // From "KickBot": return (float) (((int)flMaxSpeed)/2 + ((int)flMaxSpeed)/50); + //OLD: f_move_speed = f_max_speed / 2.0; // this is not correct + + pEdict->v.button &= ~IN_RUN; // release IN_RUN + rprint("Act", "Walk time > gpGlobals->time"); + setMoveSpeed(f_max_speed / 2.0f + f_max_speed / 50.0f); + } + + // When we are at max speed, press IN_RUN to get a running animation + if (f_move_speed == f_max_speed) { + UTIL_BotPressKey(this, IN_RUN); + } + + if (!keyPressed(IN_MOVELEFT) || keyPressed(IN_MOVERIGHT)) { + if (f_strafe_speed > 0.0f) { + UTIL_BotPressKey(this, IN_MOVERIGHT); + } + else if (f_strafe_speed < 0.0f) { + UTIL_BotPressKey(this, IN_MOVELEFT); + } + } + + // When we should go back, we go back + if (f_goback_time > gpGlobals->time) { + setMoveSpeed(-f_max_speed); + } + + // When holding duck, we hold duck + if (f_hold_duck > gpGlobals->time) + UTIL_BotPressKey(this, IN_DUCK); + + // When we wait, we have no move speed + // notice: 'wait' is not 'stuck' nor 'camping'. Wait should only be used to have a bot + // 'do nothing' for a short period of time. + if (f_wait_time > gpGlobals->time) { + rprint("Act", "f_wait_time > gpGlobals->time"); + setMoveSpeed(0.0f); + } + + // Button usage, change vBody to a 'trigger multiple' because we have to touch these + if (pButtonEdict) { + if (std::strcmp(STRING(pButtonEdict->v.classname), "trigger_multiple") == 0) { + if (func_distance(pEdict->v.origin, VecBModelOrigin(pButtonEdict)) < 60) { + vBody = VecBModelOrigin(pButtonEdict); + } + } + } + + // ------------------------------------------- + // MOVE TO : vBody + // calculate the angle we MOVE to. (VecMoveAngles) + // ------------------------------------------- + Vector vTarget = vBody - pEdict->v.origin; + vecMoveAngles = UTIL_VecToAngles(vTarget); + + // Paulo-La-Frite - START bot aiming bug fix + if (vecMoveAngles.x > 180) + vecMoveAngles.x -= 360; + + vecMoveAngles.x = -vecMoveAngles.x; + vecMoveAngles.z = 0; + UTIL_FixAngles(&vecMoveAngles); + + // when filled in, we look to this (overrides) + if (vEar != Vector(9999, 9999, 9999)) + vHead = vEar; + + // button overrides hearing + if (pButtonEdict) + vHead = VecBModelOrigin(pButtonEdict); + + // ------------------------------------------- + // FACE AT: vHead + // calculate the angle we face at. + // + // ------------------------------------------- + vTarget = vHead - pEdict->v.origin; + pEdict->v.v_angle = UTIL_VecToAngles(vTarget); + if (pEdict->v.v_angle.y > 180.0f) + pEdict->v.v_angle.y -= 360.0f; + + // Paulo-La-Frite - START bot aiming bug fix + if (pEdict->v.v_angle.x > 180.0f) + pEdict->v.v_angle.x -= 360.0f; + + Vector v_shouldbe; + + // Vector how it should be, however, we don't allow such a fast turn! + v_shouldbe.x = pEdict->v.v_angle.x / 3; + v_shouldbe.y = pEdict->v.v_angle.y; + v_shouldbe.z = 0; //unused? [APG]RoboCop[CL] + + // set the body angles to point the gun correctly + pEdict->v.angles.x = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.x, v_shouldbe.x); + pEdict->v.angles.y = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.y, v_shouldbe.y); + pEdict->v.angles.z = 0; + + // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff) + pEdict->v.v_angle.x = -pEdict->v.v_angle.x; + + // Paulo-La-Frite - END + pEdict->v.ideal_yaw = pEdict->v.v_angle.y; + pEdict->v.idealpitch = pEdict->v.v_angle.x; + + botFixIdealYaw(pEdict); + botFixIdealPitch(pEdict); +} + +bool cBot::shouldActWithC4() const +{ + return f_c4_time > gpGlobals->time; +} + +// BOT: On ladder? +bool cBot::isOnLadder() const +{ + return FUNC_IsOnLadder(pEdict); +} + +// BOT: Check around body and avoid obstacles +void cBot::CheckAround() { + rprint_trace("CheckAround", "Start"); + // Do not act when on ladder + if (isOnLadder()) + return; + + // The principle is to fire 2 tracelines, both forward; one left + // and one right. When one of the 2 gets hit, we know we are 'about' + // to get hit. Therefor we use strafing to keep distance to the coming wall + // when left and right is both hit we have a problem as this should not happen. + + // Note: we use TRACEHULL instead of TRACELINE, because TRACEHULL detects + // the famous 'undetectable' func_walls. + TraceResult tr; + + // v_source = pEdict->v.origin + Vector(0, 0, -CROUCHED_HEIGHT + (MAX_JUMPHEIGHT + 1)); + const Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); + + // Go forward first + const float distance = 90.0f; + const Vector v_forward = v_source + gpGlobals->v_forward * distance; + + // now really go left/right + const Vector v_right = v_source + gpGlobals->v_right * distance; + const Vector v_left = v_source + gpGlobals->v_right * -distance; + + // now really go left/right + const Vector v_forwardright = v_right + gpGlobals->v_forward * distance; + const Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; + + // TRACELINE: forward + UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + const bool bHitForward = tr.flFraction < 1.0f; + + // TRACELINE: Left + UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + const bool bHitLeft = tr.flFraction < 1.0f; + + // TRACELINE: Right + UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + const bool bHitRight = tr.flFraction < 1.0f; + + // TRACELINE: Forward left + UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + const bool bHitForwardLeft = tr.flFraction < 1.0f; + + // TRACELINE: Forward right + UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + const bool bHitForwardRight = tr.flFraction < 1.0f; + + char msg[255]; + std::sprintf(msg, "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); + rprint_trace("CheckAround", msg); + + // Set 'act' properties + + // we are surrounded, so move backwards + if (bHitForward) { + rprint_trace("CheckAround", "Something in front of me blocks, so move back."); + // f_move_speed = -(f_max_speed); + } else { + rprint_trace("CheckAround", "Nothing in front of me"); + } + + if (!bHitForwardLeft && bHitForwardRight) { + strafeLeft(0.5f); + rprint_trace("CheckAround", "Can strafe left (forward left)"); + } else if (bHitForwardLeft && !bHitForwardRight) { + strafeRight(0.5f); + rprint_trace("CheckAround", "Can strafe right (forward right)"); + } + + if (bHitLeft && bHitRight) { + rprint_trace("CheckAround", "Can't strafe left or right"); + } else if (!bHitLeft && bHitRight) { + strafeLeft(0.5f); + rprint_trace("CheckAround", "Can strafe left"); + } else if (bHitLeft && !bHitRight) { + strafeRight(0.5f); + rprint_trace("CheckAround", "Can strafe right"); + } + + // ------------------------------------------------------------- + // When checking around a bot also handles breakable stuff. + // ------------------------------------------------------------- + + edict_t *pent = nullptr; + while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { + char item_name[40]; + std::strcpy(item_name, STRING(pent->v.classname)); + + // See if it matches our object name + if (std::strcmp("func_breakable", item_name) == 0) { + + // Found a func_breakable + const Vector vBreakableOrigin = VecBModelOrigin(pent); + + // Shoot + if ((pent->v.flags & FL_WORLDBRUSH) == 0) // can it be broken? + { + // Thx for CF by fixing breakable coding + if (pent->v.solid == SOLID_BSP && pent->v.takedamage == DAMAGE_YES && pent->v.impulse == 0 && + pent->v.health < 150) // has it NOT been broken yet? + { + // trace to vector to be sure we dont get blocked by anything else + if (VectorIsVisibleWithEdict(pEdict, vBreakableOrigin, "func_breakable")) { + setHeadAiming(vBreakableOrigin); + FireWeapon(); + } + return; + } + } + } // CAN BE BROKEN + } // FUNC_BREAKABLE +} + +// BOT: Should be taking cover? +bool cBot::TakeCover() const +{ + // Its time based. + if (f_cover_time < gpGlobals->time) + return false; + + // And if all went fine, we can return true. + return true; +} + +/** + * Set the node to follow next as the next one (ie, increase index) + */ +void cBot::nextPathIndex() +{ + this->pathIndex++; +} + +/** + * Set the node to follow next as the previous one (ie, decrease index). Calls forgetPath when index is getting < 0 + */ +void cBot::prevPathIndex() +{ + rprint("prevPathNodeIndex"); + this->pathIndex--; + if (this->pathIndex < 0) { + forgetPath(); + } +} + +// Returns true if bot has a path to follow +bool cBot::isWalkingPath() const +{ + return this->pathIndex > -1; +} + +// Returns true if bot has goal node +bool cBot::hasGoal() const +{ + return this->iGoalNode > -1; +} + +// Returns true if bot has goal node index (ie referring to Goals[]) +bool cBot::hasGoalIndex() const +{ + return this->goalIndex > -1; +} + +/** + * Returns goal data , if goal data exists + * @return + */ +tGoal *cBot::getGoalData() const +{ + if (!hasGoalIndex()) return nullptr; + tGoal *ptr = NodeMachine.getGoal(this->goalIndex); + if (ptr == nullptr) return nullptr; + + // only goals with a node are valid + if (ptr->iNode > -1) return ptr; + // else not + + return nullptr; +} + +// Returns true if bot has an enemy edict +bool cBot::hasEnemy() const +{ + return this->pEnemyEdict != nullptr; +} + +/** + * Returns true when given edict == our enemy edict + * @param pEdict + * @return + */ +bool cBot::hasEnemy(edict_t * pEdict) const +{ + return this->pEnemyEdict == pEdict; +} + +// Returns true if bot has a path to follow +bool cBot::shouldBeWandering() { + if (this->fWanderTime > gpGlobals->time) { + char msg[255]; + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); + rprint(msg); + return true; + } + return false; +} + +void cBot::setMoveSpeed(float value) { +// char msg[255]; +// sprintf(msg, "setting to value %f / maxSpeed %f - sv_maxspeed = %f", value, this->f_max_speed, CVAR_GET_FLOAT("sv_maxspeed")); +// rprint_trace("setMoveSpeed", msg); + this->f_move_speed = value; +} + +void cBot::setStrafeSpeed(float value, float time) { + char msg[255]; + std::sprintf(msg, "%f for %f seconds.", value, time); + rprint_trace("setStrafeSpeed", msg); + // if (f_strafe_time > gpGlobals->time) { + // + // } else { + f_strafe_speed = value; + f_strafe_time = gpGlobals->time + time; + // } +} + +void cBot::strafeLeft(float time) +{ + setStrafeSpeed(-f_max_speed, time); +} + +void cBot::strafeRight(float time) +{ + setStrafeSpeed(f_max_speed, time); +} + +void cBot::startWandering(float time) +{ + this->fWanderTime = gpGlobals->time + time; + setMoveSpeed(f_max_speed); + char msg[255]; + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Start wandering for %f seconds", time); + rprint("startWandering", msg); +} + +void cBot::stopMoving() +{ + this->setMoveSpeed(0.0f); +} + +void cBot::forgetGoal() +{ + rprint_trace("forgetGoal"); + this->iGoalNode = -1; + this->goalIndex = -1; +} + +int cBot::getPathIndex() const +{ + return this->pathIndex; +} + +int cBot::getPreviousPathIndex() const +{ + return this->pathIndex - 1; +} + +void cBot::forgetPath() +{ + rprint("forgetPath"); + this->pathIndex = -1; + NodeMachine.path_clear(this->iBotIndex); +} + +void cBot::forgetEnemy() { + this->pEnemyEdict = nullptr; +} + +edict_t * cBot::getEnemyEdict() const +{ + return this->pEnemyEdict; +} + +int cBot::getGoalNode() const +{ + return this->iGoalNode; +} + +void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { + if (nodeIndex < 0) { + rprint("setGoalNode()", "WARN: Setting a goal lower than 0, assuming this is not intentional. If you need to forget a goal, use forgetGoal()"); + } + this->iGoalNode = nodeIndex; + this->goalIndex = iGoalIndex; + + tGoal *goalPtr = getGoalData(); + char msg[255]; + std::memset(msg, 0, sizeof(msg)); + + if (goalPtr != nullptr) { + std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", + nodeIndex, + goalIndex, + goalPtr->name, + goalPtr->iChecked + ); + } else { + std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); + } + rprint("setGoalNode()", msg); +} + +void cBot::setGoalNode(int nodeIndex) +{ + this->setGoalNode(nodeIndex, -1); +} + +void cBot::setGoalNode(tGoal *goal) +{ + if (goal != nullptr && goal->iNode > -1) { + rprint("setGoalNode with goal pointer\n"); + this->setGoalNode(goal->iNode, goal->index); + } +} + +/** + * Always printed when debug mode is on + * @param Function + * @param msg + */ +void cBot::rprint(const char *Function, const char *msg) +{ + REALBOT_PRINT(this, Function, msg); +} + +/** + * Only printed when debug mode is on and verbosity is trace + * @param Function + * @param msg + */ +void cBot::rprint_trace(const char *Function, const char *msg) +{ + if (Game.messageVerbosity > 1) { + REALBOT_PRINT(this, Function, msg); + } +} + +/** + * Only printed when debug mode is on and verbosity is normal + * @param Function + * @param msg + */ +void cBot::rprint_normal(const char *Function, const char *msg) { + if (Game.messageVerbosity > 1) { + REALBOT_PRINT(this, Function, msg); + } +} + +void cBot::rprint(const char *msg) { + rprint("rprint()", msg); +} + +void cBot::rprint_normal(const char *msg) { + rprint_normal("rprint()", msg); +} + +void cBot::rprint_trace(const char *msg) { + rprint_trace("rprint()", msg); +} + +bool cBot::hasBomb() const +{ + return isOwningWeapon(CS_WEAPON_C4); +} + +bool cBot::isCounterTerrorist() const +{ + return iTeam == 2; +} + +bool cBot::isTerrorist() const +{ + return iTeam == 1; +} + +bool cBot::hasPrimaryWeaponEquiped() const +{ + return iPrimaryWeapon > -1; +} + +bool cBot::hasSecondaryWeaponEquiped() const +{ + return iSecondaryWeapon > -1; +} + +bool cBot::hasPrimaryWeapon(int weaponId) const +{ + return isOwningWeapon(weaponId); +} + +bool cBot::hasSecondaryWeapon(int weaponId) const +{ + return isOwningWeapon(weaponId); +} + +void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { + // To be sure the console will only change when we MAY change. + // The values will only be changed when console_nr is 0 + if (Game.getRoundStartedTime() + 4 < gpGlobals->time) + return; // Not valid to buy + + if (this->console_nr == 0) { + // set up first command and argument + std::strcpy(this->arg1, "buy"); + std::strcpy(this->arg2, menuItem); + + if (subMenuItem != nullptr) std::strcpy(this->arg3, subMenuItem); + + this->console_nr = 1; // start console command sequence + } +} + +void cBot::performBuyActions(int weaponIdToBuy) { + if (weaponIdToBuy < 0) { + return; + } + // Buy... + + // TODO + // FRASHMAN 30.08.04 haven't changed the cs 1.5 buycode, maybe there are also errors + + // CS 1.5 only + if (counterstrike == 0) { + switch (weaponIdToBuy) { + case CS_WEAPON_AK47: + performBuyWeapon("4", "1"); + break; + case CS_WEAPON_DEAGLE: + performBuyWeapon("1", "3"); + break; + case CS_WEAPON_P228: + performBuyWeapon("1", "4"); + break; + case CS_WEAPON_SG552: + performBuyWeapon("4", "2"); + break; + case CS_WEAPON_SG550: + performBuyWeapon("4", "8"); + break; + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "5"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "6"); + break; + case CS_WEAPON_MP5NAVY: + performBuyWeapon("3", "1"); + break; + case CS_WEAPON_UMP45: + performBuyWeapon("3", "5"); + break; + case CS_WEAPON_ELITE: + performBuyWeapon("1", "5"); + break; // T only + case CS_WEAPON_MAC10: + performBuyWeapon("3", "4"); + break; // T only + case CS_WEAPON_AUG: + performBuyWeapon("4", "4"); + break; // CT Only + case CS_WEAPON_FIVESEVEN: + performBuyWeapon("1", "6"); + break; // CT only + case CS_WEAPON_M4A1: + performBuyWeapon("4", "3"); + break; // CT Only + case CS_WEAPON_TMP: + performBuyWeapon("3", "2"); + break; // CT only + case CS_WEAPON_HEGRENADE: + performBuyWeapon("8", "4"); + break; + case CS_WEAPON_XM1014: + performBuyWeapon("2", "2"); + break; + case CS_WEAPON_SMOKEGRENADE: + performBuyWeapon("8", "5"); + break; + case CS_WEAPON_USP: + performBuyWeapon("1", "1"); + break; + case CS_WEAPON_GLOCK18: + performBuyWeapon("1", "2"); + break; + case CS_WEAPON_M249: + performBuyWeapon("5", "1"); + break; + case CS_WEAPON_M3: + performBuyWeapon("2", "1"); + break; + case CS_WEAPON_G3SG1: + performBuyWeapon("4", "7"); + break; + case CS_WEAPON_FLASHBANG: + performBuyWeapon("8", "3"); + break; + case CS_WEAPON_P90: + performBuyWeapon("3", "3"); + break; + + // Armor + case CS_WEAPON_ARMOR_LIGHT: + performBuyWeapon("8", "1"); + break; + case CS_WEAPON_ARMOR_HEAVY: + performBuyWeapon("8", "2"); + break; + + case CS_DEFUSEKIT: + performBuyWeapon("8", "6"); + break; + } + } + + // CS 1.6 only + else if (counterstrike == 1) { // FRASHMAN 30/08/04: redone switch block, it was full of errors + switch (weaponIdToBuy) { + //Pistols + case CS_WEAPON_GLOCK18: + performBuyWeapon("1", "1"); + break; + case CS_WEAPON_USP: + performBuyWeapon("1", "2"); + break; + case CS_WEAPON_P228: + performBuyWeapon("1", "3"); + break; + case CS_WEAPON_DEAGLE: + performBuyWeapon("1", "4"); + break; + case CS_WEAPON_FIVESEVEN: + performBuyWeapon("1", "5"); + break; // CT Only + case CS_WEAPON_ELITE: + performBuyWeapon("1", "5"); + break; // T Only + //ShotGUNS + case CS_WEAPON_M3: + performBuyWeapon("2", "1"); + break; + case CS_WEAPON_XM1014: + performBuyWeapon("2", "2"); + break; + //SMG + case CS_WEAPON_MAC10: + performBuyWeapon("3", "1"); + break; // T Only + case CS_WEAPON_TMP: + performBuyWeapon("3", "1"); + break; // CT Only + case CS_WEAPON_MP5NAVY: + performBuyWeapon("3", "2"); + break; + case CS_WEAPON_UMP45: + performBuyWeapon("3", "3"); + break; + case CS_WEAPON_P90: + performBuyWeapon("3", "4"); + break; + //rifles + case CS_WEAPON_GALIL: + performBuyWeapon("4", "1"); + break; // T Only + case CS_WEAPON_FAMAS: + performBuyWeapon("4", "1"); + break; // CT Only + case CS_WEAPON_AK47: + performBuyWeapon("4", "2"); + break; // T Only + case CS_WEAPON_M4A1: + performBuyWeapon("4", "3"); + break; // CT Only + case CS_WEAPON_SG552: + performBuyWeapon("4", "4"); + break; // T Only + case CS_WEAPON_AUG: + performBuyWeapon("4", "4"); + break; // CT Only + case CS_WEAPON_SG550: + performBuyWeapon("4", "5"); + break; // CT Only + case CS_WEAPON_G3SG1: + performBuyWeapon("4", "6"); + break; // T Only + //machinegun + case CS_WEAPON_M249: + performBuyWeapon("5", "1"); + break; + // equipment + case CS_WEAPON_ARMOR_LIGHT: + performBuyWeapon("8", "1"); + break; + case CS_WEAPON_ARMOR_HEAVY: + performBuyWeapon("8", "2"); + break; + case CS_WEAPON_FLASHBANG: + performBuyWeapon("8", "3"); + break; + case CS_WEAPON_HEGRENADE: + performBuyWeapon("8", "4"); + break; + case CS_WEAPON_SMOKEGRENADE: + performBuyWeapon("8", "5"); + break; + case CS_WEAPON_SHIELD: + performBuyWeapon("8", "8"); + break; + + case CS_DEFUSEKIT: + performBuyWeapon("8", "6"); + break; + //default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] + // performBuyWeapon("3", "2"); + // break; + } + + // This differs per team + // FRASHMAN 30/08/04: all into one ifthen block + if (iTeam == 2) // counter + { + switch (weaponIdToBuy) { + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "2"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "6"); + break; + //whats about nightvision? BuyWeapon (pBot, "8", "7") + } + } else // terror + { + switch (weaponIdToBuy) { + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "3"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "5"); + break; + //whats about nightvision? BuyWeapon (pBot, "8", "6") + } + } + } // end of cs 1.6 part +} // We actually gonna buy this weapon + +// BOT: Memory() +// In this function the bot will receive data; this can be any kind of data. +// For hearing, the bot will check for sounds it should pay attention to and +// store this into its 'hearing vector'. The hearing vector will be used only +// when walking and not when fighting an enemy. Do note that this hearing vector +// is only filled when it is important enough, so all the decisions are made here. +void cBot::Memory() { + + // Skip method when it is too soon. + if (fMemoryTime > gpGlobals->time) { + return; + } + + // Hear players: (loop through all players, determine if they are running and if + // we can hear them (estimated distance)). + if (pEnemyEdict == nullptr) { + Vector vHear = Vector(9999, 9999, 9999); + edict_t *pHearPlayer = nullptr; + + //f_walk_time = gpGlobals->time + 1; + + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t *pPlayer = INDEXENT(i); + + // skip invalid players and skip self (i.e. this bot) + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { + // skip this player if not alive (i.e. dead or dying) + if (!IsAlive(pPlayer)) + continue; + + // check if we can 'see it on radar' (skip teammates) + if (UTIL_GetTeam(pPlayer) == UTIL_GetTeam(pEdict)) + continue; + + // check if its running + if (FUNC_PlayerRuns(FUNC_PlayerSpeed(pPlayer))) { + // check distance + const float fDistance = + (pPlayer->v.origin - pEdict->v.origin).Length(); + + // estimated distance we can hear somebody + if (fDistance < BOT_HEARDISTANCE) { + // check if this 'hearing' vector is closer then our previous one + if (vHear != Vector(9999, 9999, 9999)) { + if (func_distance + (pEdict->v.origin, + pPlayer->v.origin) < + func_distance(pEdict->v.origin, vHear)) { + // this one is closer, thus more important + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } else { + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } + } + + if (pPlayer->v.button & IN_ATTACK + && (FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_HEGRENADE + && FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_FLASHBANG + && FUNC_EdictHoldsWeapon(pEdict) != + CS_WEAPON_SMOKEGRENADE)) { + // check distance + const float fDistance = + (pPlayer->v.origin - pEdict->v.origin).Length(); + + // estimated distance we can hear somebody + if (fDistance < BOT_HEARFIREDISTANCE) { + // check if this 'hearing' vector is closer then our previous one + if (vHear != Vector(9999, 9999, 9999)) { + if (func_distance + (pEdict->v.origin, + pPlayer->v.origin) < + func_distance(pEdict->v.origin, vHear)) { + // this one is closer, thus more important + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } else { + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } + } + // zooming of a sniper rifle + if (pPlayer->v.button & IN_ATTACK2) { + // check distance + const float fDistance = + (pPlayer->v.origin - pEdict->v.origin).Length(); + + // estimated distance we can hear somebody + if (fDistance < BOT_HEARDISTANCE) { + // check if this 'hearing' vector is closer then our previous one + if (vHear != Vector(9999, 9999, 9999)) { + if (func_distance + (pEdict->v.origin, + pPlayer->v.origin) < + func_distance(pEdict->v.origin, vHear)) { + // this one is closer, thus more important + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } else { + vHear = pPlayer->v.origin; + pHearPlayer = pPlayer; + } + } + } + + } + } + + // Fill in hearing vectory if any: + if (pHearPlayer != nullptr) { + if (RANDOM_LONG(0, 100) < ipFearRate + 10) { + + // determine fuzzyness by distance: + int iFuzz = + static_cast(func_distance(pEdict->v.origin, vHear) / + BOT_HEARDISTANCE) * 250; + + // skill depended + iFuzz /= bot_skill + 1; + + // create 'estimated hear vector' + const float randX = RANDOM_LONG(-iFuzz, iFuzz); + const float randY = RANDOM_LONG(-iFuzz, iFuzz); + const float randZ = RANDOM_LONG(-iFuzz, iFuzz); + + vHear = vHear + Vector(randX, randY, randZ); + + TraceResult tr; + + UTIL_TraceHull(pEdict->v.origin, vHear, dont_ignore_monsters, + point_hull, pEdict, &tr); + + int iNodeHearPlayer = + NodeMachine.getClosestNode(vHear, NODE_ZONE * 2, pHearPlayer); + + // if nothing hit: + if (tr.flFraction >= 1.0f) { + // we can look at this spot + vEar = vHear; + } + // we go to the destination + + const float fTime = 5 + static_cast(ipFearRate) / static_cast(7); + + if (RANDOM_LONG(0, 100) < ipFearRate + && f_walk_time + 5 < gpGlobals->time) // last 5 seconds did not walk + f_walk_time = gpGlobals->time + fTime; + + if (RANDOM_LONG(0, 100) < ipCampRate + && f_camp_time + 30 < gpGlobals->time // last 30 seconds did not camp + ) { + f_camp_time = gpGlobals->time + fTime; + } + + } else { + fMemoryTime = gpGlobals->time + 5.0f; + } + + /* + + + int iNodeHearPlayer = NodeMachine.getCloseNode (vHear, NODE_ZONE*2, pHearPlayer); + int iNodeFrom = NodeMachine.getCloseNode (pEdict->v.origin, NODE_ZONE*2, pEdict); + int iHearToNode = NodeMachine.node_look_at_hear(iNodeHearPlayer, iNodeFrom, pEdict); + + // look at hearto node + if (iHearToNode > -1) + { + vHead = NodeMachine.node_vector(iHearToNode); + SERVER_PRINT("found smart look at node\n"); + } + + // only check for new goal when the current goal is way of distance and such + if (ipCampRate > 30 && f_camp_time + 5 < gpGlobals->time) + f_camp_time = gpGlobals->time + 2.5; + */ + + if (f_update_weapon_time + 2 < gpGlobals->time) { + PickBestWeapon(); + } + } else { + vEar = Vector(9999, 9999, 9999); +// +// // check for any 'beeps' of the bomb! +// if (isCounterTerrorist() && Game.bBombPlanted) { +// // find the bomb vector +// edict_t *pent = NULL; +// Vector vC4 = Vector(9999, 9999, 9999); +// while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != NULL) { +// if (UTIL_GetGrenadeType(pent) == 4) // It is a C4 +// { +// vC4 = pent->v.origin; // store origin +// break; // done our part now +// } +// } // --- find the c4 +// +// if (vC4 != Vector(9999, 9999, 9999)) { +// +// if (func_distance(vC4, NodeMachine.node_vector(iGoalNode)) > 100 && +// func_distance(pEdict->v.origin, vC4) < 1024) { +// // set new goal node +// setGoalNode(NodeMachine.getCloseNode(vC4, NODE_ZONE, NULL)); +// forgetPath(); +// } +// } +// } + } + + } else { + vEar = Vector(9999, 9999, 9999); + } +} + +void cBot::Walk() //Experimental implementation [APG]RoboCop[CL] +{ + if (f_walk_time + 0.1f < gpGlobals->time) { + f_walk_time = gpGlobals->time + 0.1f; + if (f_walk_time + 0.1f < gpGlobals->time) { + f_walk_time = gpGlobals->time + 0.1f; + } + } +} + + +// BOT: Do i carry weapon # now? +bool cBot::CarryWeapon(int iType) const +{ + if (current_weapon.iId == iType) + return true; + return false; +} + +// BOT: Do i carry weapon TYPE # now? +int cBot::CarryWeaponType() const +{ + int kind = PRIMARY; + const int weapon_id = current_weapon.iId; + + // Check 1. Is it a knife? + if (weapon_id == CS_WEAPON_KNIFE) + kind = KNIFE; + + // Check 2, is it a 'tool'? + if (weapon_id == CS_WEAPON_FLASHBANG || weapon_id == CS_WEAPON_HEGRENADE + || weapon_id == CS_WEAPON_SMOKEGRENADE) + kind = GRENADE; + + // Check 3, is it a secondary gun? + if (weapon_id == CS_WEAPON_P228 || weapon_id == CS_WEAPON_ELITE + || weapon_id == CS_WEAPON_USP || weapon_id == CS_WEAPON_GLOCK18 + || weapon_id == CS_WEAPON_DEAGLE || weapon_id == CS_WEAPON_FIVESEVEN) + kind = SECONDARY; + + // Check 4, is it a sniper gun? + if (weapon_id == CS_WEAPON_SCOUT || weapon_id == CS_WEAPON_SG550 + || weapon_id == CS_WEAPON_AWP || weapon_id == CS_WEAPON_G3SG1) + kind = SNIPER; + + if (hasShield()) { + kind = SHIELD; + } + //if (weapon_id < 1) + // kind = NONE; + return kind; +} + +// BOT: Think about objectives +// +// This function only takes action when the bot is close a goal. The function +// NodeMachine.path_think() handles WHERE the bot goes. Not WHAT to do at a goal. +void cBot::ThinkAboutGoals() { + //REALBOT_PRINT(this, "thinkAboutGoals()", "start"); + // Depending on bot team we handle goals differently: + // TERRORISTS + if (isTerrorist()) { + // Plant the bomb when the HUD says we can -- BERKED + if (bHUD_C4_plantable) + f_c4_time = gpGlobals->time + 1; // plant bomb + + // A dropped C4 is not a 'goal' (ie. it won't let you win the game + // when you pick up the bomb. Therefor the 'pickup the dropped bomb + // code is in cNodeMachine::path_walk(). + } else if (isCounterTerrorist()) { + // COUNTER-TERRORISTS + if (vip) { + // VIP + } else { + if (Game.bBombPlanted) { + if (isCounterTerrorist()) { + // defuse (or set timers for it) + Defuse(); + } + } else { + if (Game.bHostageRescueMap) { + TryToGetHostageTargetToFollowMe(this); + checkIfHostagesAreRescued(); + checkOfHostagesStillFollowMe(); + } + } + } + } + // in Act() we find the 'acting' code when timers above are set. +} + +void cBot::rememberWhichHostageToRescue(edict_t *pHostage) { + this->pBotHostage = pHostage; +} + +edict_t * cBot::getHostageToRescue() const +{ + return pBotHostage; +} + +edict_t * cBot::findHostageToRescue() { + edict_t *pent = nullptr; + + // Search for all hostages in the game + while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { + if (!isHostageRescueable(this, pent)) continue; + if (!canSeeEntity(pent)) continue; + // skip too far hostages, leave it up to the goal picking to get closer + if (getDistanceTo(pent->v.origin) > NODE_ZONE * 2.5f) continue; + + char msg[255]; + std::sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); + this->rprint_trace("findHostageToRescue()", msg); + return pent; + } + + return nullptr; +} + +bool cBot::isDefusing() const +{ + return f_defuse > gpGlobals->time; +} + +bool cBot::hasTimeToMoveToNode() const +{ + return fMoveToNodeTime > -1 && getMoveToNodeTimeRemaining() > 0; +} +/** +This function will set the iCloseNode variable, which is the node most closest to +the bot. Returns the closest node it found. +**/ +int cBot::determineCurrentNode() { + iCloseNode = determineCurrentNode(NODE_ZONE); + return iCloseNode; +} + +/** +This function will set the iCloseNode variable, which is the node most closest to +the bot. Returns the closest node it found. +**/ +int cBot::determineCurrentNodeWithTwoAttempts() { + iCloseNode = determineCurrentNode(); + if (iCloseNode < 0) { + iCloseNode = determineCurrentNode(NODE_ZONE * 2); + } + return iCloseNode; +} + +/** +Find node close to bot, given range. Does not cache result. +**/ +int cBot::determineCurrentNode(float range) const +{ + return NodeMachine.getClosestNode(pEdict->v.origin, range, pEdict); +} + +/** + * This returns the current node (iCloseNode) set. Instead of using determineCurrentNode, which is expensive, + * call this to return the cached value. It will however call determineCurrentNode when node is < 0, usually it means + * the state has been set. + * @return + */ +int cBot::getCurrentNode() { + if (iCloseNode < 0) { + determineCurrentNode(); + } + return iCloseNode; +} + +/** + * Aka, the node we are heading for. + */ +int cBot::getCurrentPathNodeToHeadFor() const +{ + return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex); +} + +/** + * Aka, the node we were coming from. In case the index is < 0 (ie, there is no previous node yet), this will + * return -1; + */ +int cBot::getPreviousPathNodeToHeadFor() const +{ + return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, getPreviousPathIndex()); +} + +bool cBot::isHeadingForGoalNode() const +{ + return getCurrentPathNodeToHeadFor() == getGoalNode(); +} + +/** + * Aka, the next node after we have arrived at the current path node. + */ +int cBot::getNextPathNode() const +{ + return NodeMachine.getNodeIndexFromBotForPath(iBotIndex, pathIndex + 1); +} + +// Is this bot dead? +bool cBot::isDead() const +{ + return pEdict->v.health < 1 || pEdict->v.deadflag != DEAD_NO; +} + +// BOT: Think +void cBot::Think() { + if (mod_id != CSTRIKE_DLL) return; // do not support non-counter-strike mods + + // BOT: If a bot did not join a team yet, then do it + if (!hasJoinedTeam) { + rprint("Need to join team, doing that now"); + JoinTeam(); + return; + } + + // Set closest node + determineCurrentNode(); + + // BOT: If a bot is dead, re-initialize + if (isDead()) { + if (!bInitialize) return; // do nothing when no need to initialize + rprint("Dead, need to re-initialize"); + + // AUTOSKILL + const cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); + + // not killed by a fellow bot, presumably a human player + if (botPointerOfKiller == nullptr) { + if (autoskill) { + bot_skill--; + if (bot_skill < 0) + bot_skill = 0; + } + + if (Game.iKillsBroadcasting != BROADCAST_KILLS_NONE + && killer_edict != nullptr) { + // This is a human, we will tell this human he has been killed + // by a bot. + const int r = RANDOM_LONG(150, 255); + const int g = RANDOM_LONG(30, 155); + const int b = RANDOM_LONG(30, 155); + char msg[128]; + if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) + std::sprintf(msg, + "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", + name, bot_skill); + else + std::sprintf(msg, "You have killed a RealBot named %s!", + name); + + HUD_DrawString(r, g, b, msg, killer_edict); + } + } + + if (iCloseNode > -1 && !end_round) { + iDiedNode = iCloseNode; + NodeMachine.danger(iCloseNode, UTIL_GetTeam(pEdict)); + } + + if (console_nr == 0) { + rprint("NewRound - because console_nr ?!"); + NewRound(); + bInitialize = false; + } + + BotConsole(this); + + // dead messages + if (console_nr == 0) { + rprint("console_nr == 0"); //whatever this means + // do some chatting + if (RANDOM_LONG(0, 200) < ipChatRate) { + if (fChatTime + 0.5f < gpGlobals->time) + if (chChatSentence[0] == '\0') // we did not want to say anything + { + // we should say something now? + int iMax = -1; + + for (int tc = 0; tc < 50; tc++) { + if (ChatEngine.ReplyBlock[99].sentence[tc][0] != '\0') iMax++; + } + + const int the_c = RANDOM_LONG(0, iMax); + + if (the_c > -1 && iMax > -1) { + char chSentence[80]; + std::memset(chSentence, 0, sizeof(chSentence)); + std::sprintf(chSentence, "%s ", + ChatEngine.ReplyBlock[99].sentence[the_c]); + //strcpy(chSentence, ChatEngine.ReplyBlock[99].sentence[the_c]); + PrepareChat(chSentence); + } + } + } else { + // we missed the chatrate chance + if (fChatTime < gpGlobals->time) // time + if (chChatSentence[0] == '\0') // we did not want to say anything + if (RANDOM_LONG(0, 100) < ipChatRate) // rate + fChatTime = gpGlobals->time + + RANDOM_FLOAT(0.0f, (Game.iProducedSentences + 1.0f) / 2.0f); // wait + + } + + return; + } + } // isDead(); + + // set this for the next time the bot dies so it will initialize stuff + if (!bInitialize) { + bInitialize = true; + } + + if (end_round) { + rprint("End round"); + MDLL_ClientKill(pEdict); + pEdict->v.frags += 1; + return; + } + + // BOT: Played enough rounds + if (played_rounds > play_rounds && internet_play) { + rprint("Played enough rounds"); + bIsUsed = false; // no longer used + char cmd[80]; + std::sprintf(cmd, "kick \"%s\"\n", name); + SERVER_COMMAND(cmd); // kick the bot using (kick "name") + return; + } + + // Move speed... moved_distance. + if (distanceMovedTimer <= gpGlobals->time) { + // see how far bot has moved since the previous position... + const Vector v_diff = prevOrigin - pEdict->v.origin; + // make distanceMoved an average of this moment and the previous one. + const float movedTwoTimes = distanceMoved + v_diff.Length(); + + // prevent division by zero + if (movedTwoTimes > 0.0f) { + distanceMoved = movedTwoTimes / 2.0f; + } else { + distanceMoved = 0.0f; + } + + // save current position as previous + prevOrigin = pEdict->v.origin; + distanceMovedTimer = gpGlobals->time + 0.1f; + } + + // NEW ROUND + if (Game.NewRound()) { + rprint_trace("Think", "Game.NewRound"); + } + + // -------------------------------- + // MEMORY STEP + // -------------------------------- + Memory(); + + // -------------------------------- + // IMPORTANT THINKING GOING ON HERE + // -------------------------------- + const int healthChange = prev_health - bot_health; + + // handle damage taken + if (prev_health > bot_health + && healthChange > RANDOM_LONG(CSTRIKE_MIN_DAMAGE, CSTRIKE_MAX_DAMAGE) + && hasEnemy()) { + + // need backup! + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "3", ""); + } + + BOT_DecideTakeCover(this); + } + + prev_health = bot_health; + + // Do your console stuff + BotConsole(this); + + // BOT: Blinded + if (isBlindedByFlashbang()) { + // Dude we are messed up. + + // 01/07/04 - Stefan - Pointed out on the forums by Josh Borke... (do not shoot when dontshoot is on) + // shoot randomly + if (!Game.bDoNotShoot) { + if (RANDOM_LONG(0, 100) < ipFearRate && RANDOM_LONG(0, 100)) { + UTIL_BotPressKey(this, IN_ATTACK); + } + } + + rprint_trace("Think()", "Blinded"); + return; + } + + // NEW: When round time is over and still busy playing, kill bots + const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60.0f; + const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); + if (Game.getRoundStartedTime() + 10.0f + roundTimeInSeconds + freezeTimeCVAR < gpGlobals->time) { + end_round = true; + // round is ended + } + + // FREEZETIME: + if (Game.getRoundStartedTime() > gpGlobals->time && freezeTime < gpGlobals->time) { + freezeTime = gpGlobals->time + RANDOM_FLOAT(0.1f, 2.0f); + } + + // 1 SECOND START OF ROUND + if (Game.getRoundStartedTime() + 1 > gpGlobals->time && + Game.getRoundStartedTime() < gpGlobals->time) { + // TODO: Issue radio command? + this->rprint_trace("cBot::Think()", "First second of round"); + } + + // SITUATION: In freezetime + if (isFreezeTime()) { + stopMoving(); + lastSeenEnemyVector = Vector(0, 0, 0); + setTimeToMoveToNode(2); + vHead = vBody = pEdict->v.origin; + + // find any spawnpoint to look at: + edict_t *pent = nullptr; + + if (isCounterTerrorist()) { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != nullptr) { + if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && + func_distance(pent->v.origin, pEdict->v.origin) > 50) { + break; + } + } + } else { + while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { + if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && + func_distance(pent->v.origin, pEdict->v.origin) > 50) { + break; + } + } + } + + // when pent is filled, look at it + if (pent != nullptr) { + vBody = vHead = pent->v.origin; + } + + rprint_trace("Think()", "isFreezeTime"); + return; + } + + // **---**---**---**---**---**---** + // MAIN STATE: We have no enemy... + // **---**---**---**---**---**---** + if (!hasEnemy()) { + + if (!Game.bDoNotShoot) { + InteractWithPlayers(); + } + + bool bMayFromGame = true; + + if (Game.fWalkWithKnife > 0.0f) + if (Game.getRoundStartedTime() + Game.fWalkWithKnife < gpGlobals->time) + bMayFromGame = false; + + if (Game.fWalkWithKnife == 0.0f) + bMayFromGame = false; + + if (hasShield()) { + if (!hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { + UTIL_BotPressKey(this, IN_ATTACK2); // draw shield + f_allow_keypress = gpGlobals->time + 0.7f; + } + } + + if (CarryWeapon(CS_WEAPON_KNIFE) == false + && f_camp_time < gpGlobals->time + && freezeTime < gpGlobals->time + && f_c4_time < gpGlobals->time + && f_update_weapon_time < gpGlobals->time && bWalkKnife + && bMayFromGame) { + UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(-1)); // -1 is knife + f_update_weapon_time = gpGlobals->time + 0.7f; + } + + // When holding a grenade (and not switching to another weapon) + if (CarryWeaponType() == GRENADE + && f_update_weapon_time < gpGlobals->time) { + if (iPrimaryWeapon > -1) + UTIL_SelectItem(pEdict, + UTIL_GiveWeaponName(iPrimaryWeapon)); + + else // pick secondary + UTIL_SelectItem(pEdict, + UTIL_GiveWeaponName(iSecondaryWeapon)); + f_update_weapon_time = gpGlobals->time + 0.7f; + } + + // Think about objectives + ThinkAboutGoals(); + } else { + // **---**---**---**---**---**---** + // MAIN STATE: We have an enemy! + // **---**---**---**---**---**---** + + // Keep interacting with players: + InteractWithPlayers(); + + // And combat enemies + Combat(); + } + + // WALK() + NodeMachine.path_think(this, distanceMoved); + + // SITUATION: Passed Freezetime + +} // THINK() + +bool cBot::isFreezeTime() const { + return freezeTime > gpGlobals->time; +} + +/** +Return true if one of the pointers is not NULL +**/ +bool cBot::isEscortingHostages() { + const bool result = getAmountOfHostagesBeingRescued() > 0; + if (result) { + rprint("I am escorting hostages!"); + } + return result; +} + +void cBot::checkOfHostagesStillFollowMe() { + if (fCheckHostageStatusTimer > gpGlobals->time) return; + fCheckHostageStatusTimer = gpGlobals->time + 5; + +//// this->rprint("checkOfHostagesStillFollowMe - START"); +// if (hostage1) { +// if (!isHostageRescued(this, hostage1) && FUNC_EdictIsAlive(hostage1) && !canSeeEntity(hostage1) && getDistanceTo(hostage1->v.origin) > NODE_ZONE*2.5) { +// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage1"); +// forgetHostage(hostage1); +// } +// } +// if (hostage2) { +// if (!isHostageRescued(this, hostage2) && FUNC_EdictIsAlive(hostage2) && !canSeeEntity(hostage2) && getDistanceTo(hostage2->v.origin) > NODE_ZONE*2.5) { +// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage2"); +// forgetHostage(hostage2); +// } +// } +// if (hostage3) { +// if (!isHostageRescued(this, hostage3) && FUNC_EdictIsAlive(hostage3) && !canSeeEntity(hostage3) && getDistanceTo(hostage3->v.origin) > NODE_ZONE*2.5) { +// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage3"); +// forgetHostage(hostage3); +// } +// } +// +// if (hostage4) { +// if (!isHostageRescued(this, hostage4) && FUNC_EdictIsAlive(hostage4) && !canSeeEntity(hostage4) && getDistanceTo(hostage4->v.origin) > NODE_ZONE*2.5) { +// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage4"); +// forgetHostage(hostage4); +// } +// } +// rprint("checkOfHostagesStillFollowMe - END"); +} + +void cBot::clearHostages() { + rprint_trace("clearHostages"); + hostage1 = nullptr; + hostage2 = nullptr; + hostage3 = nullptr; + hostage4 = nullptr; + pBotHostage = nullptr; +} + +// BOT: CheckGear, part of UpdateStatus() +void cBot::CheckGear() { + + // PRIMARY + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_mp5navy"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_mp5navy"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ak47"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_ak47"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m3"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m3"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_aug"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_aug"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_sg552"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_sg552"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m249"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m249"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_xm1014"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_xm1014"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_p90"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_p90"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_tmp"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_tmp"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_m4a1"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_m4a1"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_awp"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_awp"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_sg550"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_sg550"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_scout"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_scout"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_mac10"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_mac10"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_g3sg1"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_g3sg1"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_ump45"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_ump45"); + + // Counter-Strike 1.6 weapon FAMAS/GALIL + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_famas"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_famas"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_galil"))) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_galil"); + + // SECONDARY + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_elite"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_elite"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_fiveseven"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_fiveseven"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_p228"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_p228"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_deagle"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_deagle"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_usp"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_usp"); + if (isOwningWeapon(UTIL_GiveWeaponId("weapon_glock18"))) iSecondaryWeapon = UTIL_GiveWeaponId("weapon_glock18"); + + // Handle shields as primary weapon + if (hasShield()) iPrimaryWeapon = UTIL_GiveWeaponId("weapon_shield"); +} + +// BOT: Update personal status +void cBot::UpdateStatus() { + // name filled in yet? + if (name[0] == 0) + std::strcpy(name, STRING(pEdict->v.netname)); + + // Set thirdpartybot flag + pEdict->v.flags |= FL_THIRDPARTYBOT; + + // Reset stuff + pEdict->v.button = 0; + setMoveSpeed(f_max_speed); // by default run + + // When its not time to strafe, don't. + if (f_strafe_time < gpGlobals->time) { + if (f_strafe_speed != 0.0f) { + rprint_trace("UpdateStatus", "Strafe speed set to 0!"); + f_strafe_speed = 0.0f; + } + } + + // Update team state when started + if (hasJoinedTeam) { + iTeam = UTIL_GetTeam(pEdict) + 1; // 1 - TERRORIST, 2 - COUNTER-TERRORIST + } + + // Check if we became VIP + vip = UTIL_IsVip(pEdict); + + // Check gear + CheckGear(); + + // Set max speed and such when CS 1.6 + if (counterstrike == 1) { + f_max_speed = pEdict->v.maxspeed; +// char msg[255]; +// sprintf(msg, "f_max_speed set to %f", f_max_speed); +// rprint_trace("UpdateStatus", msg); + bot_health = static_cast(pEdict->v.health); + bot_armor = static_cast(pEdict->v.armorvalue); + } +} + +// ---------------------------------- BOT CLASS FUNCTIONS +// ---------------------------------- BOT CLASS FUNCTIONS +// ---------------------------------- BOT CLASS FUNCTIONS + +//////////////////////////////////////////////////////////////////////////////// +/// Radio Action - Response +//////////////////////////////////////////////////////////////////////////////// +bool BotRadioAction() { + char name[64]; + bool unstood = false; + edict_t *plr = nullptr; + int team = -1; + int i; + int radios = 0; // Hold amount of replies here, so we don't flood :) + std::strcpy(name, radio_messenger); + + // First find the team messager name + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t *pPlayer = INDEXENT(i); // Get pEdict + if (pPlayer) // If player exists + { + char netname[64]; + std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname + if (std::strcmp(netname, name) == 0) // If + { + plr = pPlayer; + team = UTIL_GetTeam(pPlayer); + } + } + } + + // Check players and check if radio message applies to them + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t *pPlayer = INDEXENT(i); + if (pPlayer) { + char netname[64]; + + std::strcpy(netname, STRING(pPlayer->v.netname)); + + if (std::strcmp(netname, name) != 0 && // When not the same name + team == UTIL_GetTeam(pPlayer) && // .. the same team... + pPlayer->v.deadflag == DEAD_NO && // .. not dead .. + UTIL_GetBotPointer(pPlayer) != nullptr) // and a RealBot + { + // here are all bots + cBot *BotPointer = UTIL_GetBotPointer(pPlayer); + + if (BotPointer == nullptr) + continue; // somehow this fucked up, bail out + + const float distance = func_distance(plr->v.origin, + BotPointer->pEdict->v.origin); // distance between the 2 + + // Same team, randomly, do we even listen to the radio? + // the more further away, the more chance it will not listen + bool bWantToListen = false; + + // Reply on distance check + if (RANDOM_LONG(0, 8192) > distance) + bWantToListen = true; + + // Hearrate (personality setting) + if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && + bWantToListen) + bool want_to_answer = true; + + // If we want to listen to the radio... then handle it! + if (bWantToListen) { + bool can_do_negative = false; + + // Report in team! + if (std::strstr(message, "#Report_in_team") != nullptr) { + // gives human knowledge who is on his team + } + + // Regroup team! + if (std::strstr(message, "#Regroup_team") != nullptr) { + // regroup now! + unstood = true; + + // get to the leader position + BotPointer->rprint("Setting goal from regroup team"); + BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); + BotPointer->forgetPath(); + } + + // Hold this position + if (std::strstr(message, "#Hold_this_position") != nullptr || + std::strstr(message, "#Get_in_position_and_wait") != nullptr) { + // do nothing + } + // Follow me!! + if (std::strstr(message, "#Follow_me") != nullptr) {} + + // You take the point! + // 23/06/04 - Stefan - Here the leader should break up his position? + // ie, the leader will be assigned to the bot this human/bot is facing? + if (std::strstr(message, "#You_take_the_point") != nullptr) { + can_do_negative = false; + } + // Enemy Sotted! + if (std::strstr(message, "#Enemy_spotted") != nullptr) { + can_do_negative = false; + + // Find player who issues this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + // Help this player + if (iBackupNode > -1) { + + unstood = true; + + BotPointer->rprint("Setting goal for backup"); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + // Enemy Down! + if (std::strstr(message, "#Enemy_down") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); + + unstood = true; + can_do_negative = false; + } + // Stick together team! + if (std::strstr(message, "#Stick_together_team") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); + unstood = true; + can_do_negative = false; + } + // cover me|| strstr (message, "#Cover_me") != NULL + + // Need backup / taking fire... + if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); + + unstood = true; + + // get source of backup + const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + + // Taking fire! + if (std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); + unstood = true; + + // Find player who issued this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + + } + // Team fall back! + if (std::strstr(message, "#Team_fall_back") != nullptr) { + + } + // Go Go Go, stop camping, stop following, get the heck out of there! + if (std::strstr(message, "#Go_go_go") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); + unstood = true; + BotPointer->f_camp_time = gpGlobals->time - 30; + BotPointer->f_walk_time = gpGlobals->time; + BotPointer->f_cover_time = gpGlobals->time - 10; + BotPointer->f_hold_duck = gpGlobals->time - 10; + BotPointer->f_jump_time = gpGlobals->time - 10; + BotPointer->forgetPath(); + BotPointer->forgetGoal(); + } + + if (FUNC_DoRadio(BotPointer) && unstood) { + const int maxAllowedRadios = gpGlobals->maxClients / 4; + if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { + constexpr bool report_back = false; + + if constexpr (!report_back) { + UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! + } else { + UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! + } + + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); + radios++; + } + } + } // they even listen to the radio command? + else { + /* + // filter out the commands where we cannot reply with negative + // You take the point! + if (strstr (message, "#You_take_the_point") != NULL) + can_do_negative = false; + + // Enemy Sotted! + if (strstr (message, "#Enemy_spotted") != NULL) + can_do_negative = false; + + // Enemy Down! + if (strstr (message, "#Enemy_down") != NULL) + can_do_negative = false; + + if ((FUNC_DoRadio(BotPointer)) + && (unstood) && (can_do_negative)) + + { + if (BotPointer->console_nr == 0 + && radios < (gpGlobals->maxClients / 4)) + + { + if (report_back == false) + + { + UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); + radios++; + } + } + } + */ + } + } // End check! + } // If (Player) + } // FOR Clients + return true; +} + +// Is entity visible? (from Entity view) +bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { + + //DebugOut("bot: EntityIsVisible()\n"); + TraceResult tr; + + // trace a line from bot's eyes to destination... + UTIL_TraceLine(pEntity->v.origin + pEntity->v.view_ofs, dest, + dont_ignore_monsters, pEntity->v.pContainingEntity, &tr); + + // check if line of sight to object is not blocked (i.e. visible) + if (tr.flFraction >= 1.0f) + return true; + + else + return false; +} + +// Can see Edict? +bool cBot::canSeeEntity(edict_t *pEntity) const +{ + if (pEntity == nullptr) return false; + + TraceResult tr; + const Vector start = pEdict->v.origin + pEdict->v.view_ofs; + const Vector vDest = pEntity->v.origin; + + // trace a line from bot's eyes to destination... + UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); + + // it hit anything + if (tr.flFraction < 1.0f) { + // if it hit the entity we wanted to see, then its ok! + if (tr.pHit == pEntity) return true; + return false; + } + + return true; +} + +/** + * Returns distance from this bot to a given nodeIndex. If the given NodeIndex is invalid, the distance returned is 0. + * @param nodeIndex + * @return + */ +float cBot::getDistanceTo(int nodeIndex) { + const tNode *nodePtr = NodeMachine.getNode(nodeIndex); + if (nodePtr != nullptr) { + return getDistanceTo(nodePtr->origin); + } + rprint("getDistanceTo(int nodeIndex)", "The given nodeIndex was invalid, returning 9999 distance"); + return 9999; +} + +/** + * Returns distance from this bot position (pEdict->v.origin) to given Vector. + * @param vDest + * @return + */ +float cBot::getDistanceTo(const Vector& vDest) const +{ + return func_distance(pEdict->v.origin, vDest); +} + +bool cBot::isUsingHostage(edict_t *pHostage) { + if (pHostage == nullptr) return false; + + // checks if the current pEdict is already 'in use' + // note: time check only when we have an hostage pointer assigned + if (hostage1 == pHostage) { + rprint("isUsingHostage", "hostage1"); + return true; + } + + if (hostage2 == pHostage) { + rprint("isUsingHostage", "hostage2"); + return true; + } + + if (hostage3 == pHostage) { + rprint("isUsingHostage", "hostage3"); + return true; + } + + if (hostage4 == pHostage) { + rprint("isUsingHostage", "hostage4"); + return true; + } + + return false; +} + +void cBot::forgetHostage(edict_t *pHostage) { + // these are the hostages we are rescueing (ie, they are following this bot) + if (hostage1 == pHostage) { + rprint("forgetHostage", "hostage1"); + hostage1 = nullptr; + } + if (hostage2 == pHostage) { + rprint("forgetHostage", "hostage2"); + hostage2 = nullptr; + } + if (hostage3 == pHostage) { + rprint("forgetHostage", "hostage3"); + hostage3 = nullptr; + } + if (hostage4 == pHostage) { + rprint("forgetHostage", "hostage4"); + hostage4 = nullptr; + } + + // this is the hostage we have taken interest in + if (pBotHostage == pHostage) { + rprint("forgetHostage", "pBotHostage"); + pBotHostage = nullptr; + } +} + +int cBot::getAmountOfHostagesBeingRescued() const +{ + int count = 0; + + if (hostage1 != nullptr) count++; + if (hostage2 != nullptr) count++; + if (hostage3 != nullptr) count++; + if (hostage4 != nullptr) count++; + + return count; +} + +// Will return true when the vector is visible. +// TODO: Make this function more flexible, ie able to hit an entity that it searches +// and return true on that as well. (mix it with the above function) +bool cBot::canSeeVector(const Vector& vDest) const +{ + TraceResult tr; + const Vector start = pEdict->v.origin + pEdict->v.view_ofs; + + // trace a line from bot's eyes to destination... + UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); + + if (tr.flFraction < 1.0f) + return false; + + return true; +} + +// The coming 2 shield functions where originaly created by Whistler; +// i got them from the JoeBot source though. But... in the end, thank you +// Whistler! +bool cBot::hasShield() const +{ + // Adapted from Wei Mingzhi's YAPB + return strncmp(STRING(pEdict->v.viewmodel), "models/shield/v_shield_", 23) == 0; +} + +bool cBot::hasShieldDrawn() const +{ + // Adapted from Wei Mingzhi's YAPB + if (!hasShield()) + return false; + + return pEdict->v.weaponanim == 6 || pEdict->v.weaponanim == 7; +} + +/* + BotThink() + This function is the very general/main/simplified thinking function of the bot. + Do NOT add/remove/change code here! If you want to give the bot information to + work with. Put it in UpdateStatus(). When the bot has to think about it, do it + int Think() and everything else (when all is set, how to 'do' it) in Act(). + */ +void BotThink(cBot *pBot) { + // STEP 1: Update status + pBot->UpdateStatus(); + + // STEP 2: Think + pBot->Think(); + + // STEP 3: Act + pBot->Act(); + + // PASS THROUGH ENGINE + + // float frameInterval = m_lastCommandTime - gpGlobals->time; + const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; + pBot->fLastRunPlayerMoveTime = gpGlobals->time; + + const double upMove = 0.0; + char msg[255]; + std::sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); + pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); + g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, + upMove, pBot->pEdict->v.button, 0, msecval); + + const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps + pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; +} + +// 17/07/04 +// log important variables of the bot (it will be called from dll.cpp once per active bot) +// they are logged into reallog.txt file + +void cBot::Dump() { + char buffer[181]; + const int iCurrentNode = + NodeMachine.getClosestNode(pEdict->v.origin, (NODE_ZONE * 2), pEdict); + + snprintf(buffer, 180, + "%s (#%d %s): timers, now= %.0f, c4_time=%.0f, camp_time=%.0f, wait_time=%.0f, cover_time=%.0f, wander=%.0f, MoveToNodeTime=%.0f\n", + name, iBotIndex, (iTeam == 1) ? "T" : "CT", gpGlobals->time, + f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, fMoveToNodeTime); + rblog(buffer); + snprintf(buffer, 180, " GoalNode=%d, CurrentNode=%d, iPathFlags=", + iGoalNode, iCurrentNode); + switch (iPathFlags) { + case PATH_NONE: + std::strncat(buffer, "PATH_NONE ", 180); + break; + case PATH_DANGER: + std::strncat(buffer, "PATH_DANGER ", 180); + break; + case PATH_CONTACT: + std::strncat(buffer, "PATH_CONTACT ", 180); + break; + case PATH_CAMP: + std::strncat(buffer, "PATH_CAMP ", 180); + break; + default: + std::strncat(buffer, "???", 180); + } + std::strncat(buffer, "\n", 180); + rblog(buffer); + if (iGoalNode >= 0) + NodeMachine.dump_path(iBotIndex, pathIndex); +} + +/** + * Will begin walk the path by setting pathNodeIndex to 0, which is a valid nr so that + * isWalkingPath returns true. + */ +void cBot::beginWalkingPath() { + this->pathIndex = 0; +} + +bool cBot::hasHostageToRescue() const +{ + return pBotHostage != nullptr; +} + +bool cBot::canSeeHostageToRescue() const +{ + return canSeeEntity(pBotHostage); +} + +void cBot::clearHostageToRescueTarget() { + rprint_trace("clearHostageToRescueTarget", "clearing pBotHostage pointer"); + this->pBotHostage = nullptr; +} + +// Finds a free hostage pointer and assigns it. +void cBot::rememberHostageIsFollowingMe(edict_t *pHostage) { + if (pHostage == nullptr) { + rprint_trace("rememberHostageIsFollowingMe", "ERROR assigning NULL pHostage pointer!?"); + } + if (hostage1 == nullptr) { + rprint_trace("rememberHostageIsFollowingMe", "hostage1 slot is free."); + hostage1 = pHostage; + } else if (hostage2 == nullptr) { + rprint_trace("rememberHostageIsFollowingMe", "hostage2 slot is free."); + hostage2 = pHostage; + } else if (hostage3 == nullptr) { + rprint_trace("rememberHostageIsFollowingMe", "hostage3 slot is free."); + hostage3 = pHostage; + } else if (hostage4 == nullptr) { + rprint_trace("rememberHostageIsFollowingMe", "hostage4 slot is free."); + hostage4 = pHostage; + } +} + +void cBot::checkIfHostagesAreRescued() { + if (isHostageRescued(this, hostage1)) forgetHostage(hostage1); + if (isHostageRescued(this, hostage2)) forgetHostage(hostage2); + if (isHostageRescued(this, hostage3)) forgetHostage(hostage3); + if (isHostageRescued(this, hostage4)) forgetHostage(hostage4); +} + +bool cBot::isOnSameTeamAs(const cBot *pBot) const +{ + if (pBot == nullptr) return false; + return pBot->iTeam == this->iTeam; +} + +bool cBot::wantsToBuyStuff() const +{ + return buy_secondary == true || + buy_primary == true || + buy_ammo_primary == true || + buy_ammo_secondary == true || + buy_armor == true || + buy_defusekit == true || + buy_grenade == true || + buy_flashbang > 0; +} + +bool cBot::isUsingConsole() const +{ + return console_nr > 0; +} + +bool cBot::shouldBeAbleToMove() const +{ + return !isDead() && + !isFreezeTime() && + !shouldCamp() && + !shouldWait() && + !shouldActWithC4(); + // !isDucking() && + // !isJumping(); +} + +edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const +{ + TraceResult tr; + const Vector vOrigin = pEdict->v.origin; + + const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + + //Using TraceHull to detect de_aztec bridge and other entities. + //DONT_IGNORE_MONSTERS, we reached it only when there are no other bots standing in our way! + //UTIL_TraceHull(vOrigin, vNode, dont_ignore_monsters, point_hull, pBot->pEdict, &tr); + //UTIL_TraceHull(vOrigin, vNode, dont_ignore_monsters, human_hull, pBot->pEdict, &tr); + UTIL_TraceHull(vOrigin, node->origin, dont_ignore_monsters, head_hull, pEdict, &tr); + + // if nothing hit (else a wall is in between and we don't care about that): + if (tr.flFraction < 1.0f) { + if (tr.pHit) { + return tr.pHit; + } + } + + return nullptr; +} + +/** + * Get distance to the next node we're heading for + * @return + */ +float cBot::getDistanceToNextNode() const +{ + const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + if (node) { + return getDistanceTo(node->origin); + } + return MAP_MAX_SIZE; +} + +void cBot::setBodyToNode(int nodeIndex) { + const tNode *node = NodeMachine.getNode(nodeIndex); + if (node) { + vBody = node->origin; + } +} + +void cBot::lookAtNode(int nodeIndex) { + const tNode *node = NodeMachine.getNode(nodeIndex); + if (node) { + vHead = node->origin; + } +} + +/** + * Sets timer to allow movement to node, when timer expires we will think about severing the connection + * we used. + * @param timeInSeconds + */ +void cBot::setTimeToMoveToNode(float timeInSeconds) { + char msg[255]; + const float endTime = gpGlobals->time + timeInSeconds; + std::sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); + rprint_trace("setTimeToMoveToNode", msg); + + this->nodeTimeIncreasedAmount = 0; + this->fMoveToNodeTime = endTime; +} + +/** + * Whatever was set, increase the time given in function param. This expands the time a bit. + * @param timeInSeconds + */ +void cBot::increaseTimeToMoveToNode(float timeInSeconds) { + if (nodeTimeIncreasedAmount < 2) { + nodeTimeIncreasedAmount++; + this->fMoveToNodeTime += timeInSeconds; + const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); + char msg[255]; + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", + timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); + rprint_trace("increaseTimeToMoveToNode", msg); + } else { + rprint_trace("increaseTimeToMoveToNode", "Refused to increase time"); + } +} + +float cBot::getMoveToNodeTimeRemaining() const +{ + return fMoveToNodeTime - gpGlobals->time; +} + +bool cBot::shouldCamp() const +{ + return f_camp_time > gpGlobals->time; +} + +bool cBot::shouldWait() const +{ + return f_wait_time > gpGlobals->time; +} + +void cBot::setTimeToWait(float timeInSeconds) +{ + this->f_wait_time = gpGlobals->time + timeInSeconds; +} + +bool cBot::shouldBeAbleToInteractWithButton() const +{ + return fButtonTime < gpGlobals->time; +} + +bool cBot::hasButtonToInteractWith() const +{ + return pButtonEdict != nullptr; +} + +bool cBot::hasCurrentNode() const +{ + return iCloseNode > -1; +} + +/** + * Shorthand method for creating path with flags PATH_NONE. + * @param destinationNode + * @return + */ +bool cBot::createPath(int destinationNode) { + return createPath(destinationNode, PATH_NONE); +} + +/** + * Attempts to create a path from current node to destination. Returns true on success, false on failure. + * @param destinationNode + * @param flags + * @return + */ +bool cBot::createPath(int destinationNode, int flags) { + if (destinationNode < 0 || destinationNode >= MAX_NODES) { + rprint("createPath()", "Unable to create path because destination node provided is < 0 or > MAX_NODES"); + return false; + } + + const int currentNode = getCurrentNode(); + if (currentNode < 0) { + rprint("createPath()", "Unable to create path to destination because I am not close to a start node"); + return false; + } + + forgetPath(); + + char msg[255]; + std::memset(msg, 0, sizeof(msg)); + std::sprintf(msg, "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); + rprint("createPath()", msg); + + return NodeMachine.createPath(currentNode, destinationNode, iBotIndex, this, flags); +} + +void cBot::doDuck() { + UTIL_BotPressKey(this, IN_DUCK); + this->f_hold_duck = gpGlobals->time + 0.5f; + + this->increaseTimeToMoveToNode(0.5f); +} + +bool cBot::isDucking() { + const bool b = keyPressed(IN_DUCK) || this->f_hold_duck > gpGlobals->time; + if (b) { + rprint_trace("isDucking", "Yes I am ducking"); + } + return b; +} + +bool cBot::isWalking() { + const bool b = !keyPressed(IN_RUN) || this->f_walk_time > gpGlobals->time; + if (b) { + rprint_trace("isWalking", "Yes I am walking"); + } + return b; +} + +void cBot::doJump(const Vector &vector) { + rprint_trace("doJump", "With vector"); + // stay focussed with body and head to this vector + this->vHead = vector; + this->vBody = vector; + + doJump(); +} + +void cBot::doJump() { + rprint_trace("doJump", "no vector"); + UTIL_BotPressKey(this, IN_JUMP); + this->f_jump_time = gpGlobals->time + 0.5f; + + // duck like this, because doDuck increases node time *again*, so no + UTIL_BotPressKey(this, IN_DUCK); // DUCK jump by default + this->f_hold_duck = gpGlobals->time + 0.5f; + + this->increaseTimeToMoveToNode(0.75f); +} + +bool cBot::isJumping() { + const bool b = keyPressed(IN_JUMP) || this->f_jump_time > gpGlobals->time; + if (b) { + rprint_trace("isJumping", "Yes I am jumping"); + } + return b; +} + +// Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] +// +void cBot::doDuckJump(){ + rprint_trace("doDuckJump", "no vector"); + UTIL_BotPressKey(this, IN_DUCK); + this->f_hold_duck = gpGlobals->time + 0.75f; + + UTIL_BotPressKey(this, IN_JUMP); + this->f_jump_time = gpGlobals->time + 0.75f; + + this->increaseTimeToMoveToNode(0.75f); +} + +// Bots require both the combination of the (IN_DUCK) and (IN_JUMP) key to be pressed +// in order to properly duck jump. +bool cBot::isDuckJumping() { + const bool b = keyPressed(IN_JUMP) && keyPressed(IN_DUCK) || + this->f_hold_duck > gpGlobals->time && this->f_jump_time > gpGlobals->time ; + if (b) { + rprint_trace("isDuckJumping", "Yes I am DuckJumping"); + } + return b; +} + +// $Log: bot.cpp,v $ +// Revision 1.21 2004/09/07 18:23:02 eric +// - bumped version to 3061 +// - adding Frashman code to buy the weapon as selected by Josh's code +// - Realbot is really the result of multiple people :-) +// +// Revision 1.20 2004/09/07 15:44:34 eric +// - bumped build nr to 3060 +// - minor changes in add2 (to add nodes for Bsp2Rbn utilities) +// - if compiled with USE_EVY_ADD, then the add2() function is used when adding +// nodes based on human players instead of add() +// - else, it now compiles mostly without warnings :-) +// +// Revision 1.19 2004/08/07 18:42:56 eric +// - bumped version to 3058 +// - added a cNodeMachine::add2 which should do the same job as ::add +// but it seems to work better. ::add2 is used by Bsp2Rbn only for now. +// - added the display of node flags (water, ladder, jump) next to the +// node position in 'debug nodes draw' +// - suppress the debugging information which displayed the hit entity +// while establishing neighbourhood +// +// Revision 1.18 2004/07/30 15:02:29 eric +// - jumped to version 3057 +// - improved readibility (wapen_tabel -> weapons_table) :-P +// - all Josh Borke modifications to the buying stuff: +// * using a switch() instead of several if +// * better buying code for shield and primary weapons +// * new command 'debug pistols 0/1' +// +// Revision 1.16 2004/07/17 21:32:01 eric +// - bumped version to 3055 +// - handling of es_ and as_ maps with new goals +// - added two debug commands: +// realbot debug goals +// realbot debug bots +// - added two nodes commands (for dedicated servers mainly) +// realbot nodes connect n1 n2 +// realbot nodes disconnect n1 n2 +// - slight modification in goal scoring (only reduced score when two bots of +// the SAME team select the same goal) +// +// Revision 1.15 2004/07/03 15:58:54 eric +// nova test comment for erics account +// +// Revision 1.14 2004/07/02 16:43:35 stefan +// - upped to build 3051 +// - changed log() into rblog() +// - removed BOT.CFG code that interpets old RB V1.0 commands +// - neater respons of the RealBot console +// - more help from RealBot console (ie, type realbot server broadcast ... with no arguments it will tell you what you can do with this, etc) +// - removed message "bot personality loaded from file" +// - in overal; some cleaning done, no extra features added +// +// Revision 1.13 2004/07/01 18:09:46 stefan +// - fixed skill 10 bots not causing memory bugger on re-adding (respawning) +// - added extra check for respawning bots so auto-add function cannot crash +// - fixed 2 nitpicks pointed out on the forums +// +// Revision 1.12 2004/06/25 07:39:00 stefan +// - upped to build 3050 +// - fixed reaction time (instant reaction time) bug +// - added evy's goals, but they are not used yet +// - fixed some radio responses here and there for swat behaviour. +// - swat leader automaticly assigned again when one dies +// - HINT: you can see any changes made by me, by looking at DD/MM/YY - Stefan (ie, 22/06/04 - Stefan, will let you find all changes i made that day) +// +// Revision 1.11 2004/06/23 08:24:14 stefan +// - upped to build 3049 +// - added swat behaviour (team leader assignment, radio response change and leaders command team-mates) - THIS IS EXPERIMENTAL AND DOES NOT ALWAYS WORK AS I WANT IT TO. +// - changed some conditions in nodemachine +// - sorry evy, still not added your new goals ;) will do next time, i promise +// +// Revision 1.10 2004/06/20 10:24:13 stefan +// - fixed another steep/stair thingy +// - changed a bit of the aiming code +// +// Revision 1.9 2004/06/19 21:06:14 stefan +// - changed distance check in nodemachine +// - fixed some 'steep' bug in nodemachine +// +// Revision 1.8 2004/06/17 21:23:23 stefan +// - fixes several connection problems with nodes. Going down from steep + crates (de_dust) PLUS going up/down from very steep slopes on as_oilrig.. 0wnage and thx to PMB and Evy +// - fixed chat bug in CS 1.6, its still CS 1.5 & CS 1.6 compatible though +// +// Revision 1.7 2004/06/13 20:08:21 stefan +// - 'bad score for goals' added +// - bmp dump info (Thanks Evy) +// - added 'realbot server players', so you can keep a server full at NR players at all times +// - slightly adjusted goal selection code +// - wander code disabled +// - lots of debug info introduced, do not use this source for REAL USAGE! +// +// Revision 1.6 2004/06/01 15:30:57 stefan +// *** empty log message *** +// +// Revision 1.5 2004/05/29 19:05:47 stefan +// - upped to BUILD 3044 +// - removed several debug messages on screen +// - changed default 'chatrate (max sentences)' to 3 +// - removed copyright notice, which is not valid due GPL license +// +// i know, nothing special :) +// +// Revision 1.4 2004/05/07 13:33:49 stefan +// added more comments, more neat code now +// +// Revision 1.3 2004/04/18 18:32:36 stefan +// - Restructured code a bit +// +// Revision 1.2 2004/04/18 17:39:19 stefan +// - Upped to build 2043 +// - REALBOT_PRINT() works properly now +// - Log() works properly now +// - Clearing in dll.cpp of reallog.txt at dll init +// - Logging works now, add REALBOT_PRINT() at every point you want to log something. +// diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 31c232c..9c390c8 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -106,54 +106,39 @@ bool GoodWeaponForTeam(int weapon, int team) { switch (weapon) { case CS_WEAPON_SG552: return false; - break; case CS_WEAPON_AK47: return false; - break; case CS_WEAPON_DEAGLE: return false; - break; case CS_WEAPON_MP5NAVY: return false; - break; case CS_WEAPON_GALIL: return false; - break; case CS_WEAPON_P90: return false; - break; - // 30.8.04 added by frashman + // 30.8.04 added by frashman case CS_WEAPON_G3SG1: return false; - break; } } else { switch (weapon) { case CS_WEAPON_AUG: return false; - break; case CS_WEAPON_DEAGLE: return false; - break; case CS_WEAPON_M4A1: return false; - break; case CS_WEAPON_MP5NAVY: return false; - break; case CS_WEAPON_FAMAS: return false; - break; case CS_WEAPON_P90: return false; - break; - //30.8.04 added by Frashman + //30.8.04 added by Frashman case CS_WEAPON_SG550: return false; - break; case CS_DEFUSEKIT: return false; - break; } } } @@ -243,8 +228,8 @@ void BotDecideWhatToBuy(cBot *pBot) { // 31.08.04 Frashman Filter Out all except PRIMARY and SHIELD // SHIELD is used as primary weapon - if ((UTIL_GiveWeaponType(weapons_table[i].iId) != PRIMARY) - && (UTIL_GiveWeaponType(weapons_table[i].iId) != SHIELD)) + if (UTIL_GiveWeaponType(weapons_table[i].iId) != PRIMARY + && UTIL_GiveWeaponType(weapons_table[i].iId) != SHIELD) continue; // must be a weapon that the team can buy (CT/T weapon) @@ -287,8 +272,8 @@ void BotDecideWhatToBuy(cBot *pBot) { // TODO: this should be dependant on something else... not only money // 01.09.04 Frashman if buyed a Shield, try to buy a good Pistol if (iMoneyLeft >= 600) - if ((RANDOM_LONG(0, 100) < 15) - || (pBot->iPrimaryWeapon == CS_WEAPON_SHIELD)) + if (RANDOM_LONG(0, 100) < 15 + || pBot->iPrimaryWeapon == CS_WEAPON_SHIELD) pBot->buy_secondary = true; } } else if (pBot->buy_secondary) { @@ -496,7 +481,7 @@ void BotConsole(cBot *pBot) { if (pBot->console_nr > 0) pBot->console_nr++; // Increase command - return; + //return; } } // BotConsole() diff --git a/bot_client.cpp b/bot_client.cpp index 21e5c46..9888350 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -58,11 +58,11 @@ static FILE *fp; // This message is sent when the Counter-Strike VGUI menu is displayed. void BotClient_CS_VGUI(void *p, int bot_index) { //DebugOut("bot_client: BotClient_CS_VGUI()\n"); - if ((*static_cast(p)) == 2) // is it a team select menu? + if (*static_cast(p) == 2) // is it a team select menu? bots[bot_index].start_action = MSG_CS_TEAM_SELECT; - else if ((*static_cast(p)) == 26) // is is a terrorist model select menu? + else if (*static_cast(p) == 26) // is is a terrorist model select menu? bots[bot_index].start_action = MSG_CS_T_SELECT; - else if ((*static_cast(p)) == 27) // is is a counter-terrorist model select menu? + else if (*static_cast(p) == 27) // is is a counter-terrorist model select menu? bots[bot_index].start_action = MSG_CS_CT_SELECT; } @@ -187,8 +187,8 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { iClip = *static_cast(p); // ammo currently in the clip for this weapon - if (iId <= 32) { - bots[bot_index].bot_weapons |= (1 << iId); // set this weapon bit + if (iId < static_cast(sizeof(weapon_defs) / sizeof(weapon_defs[0]))) { + bots[bot_index].bot_weapons |= 1 << iId; // set this weapon bit if (iState == 1) { bots[bot_index].current_weapon.iId = iId; // weapon id @@ -205,7 +205,6 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { } } } - } void BotClient_CS_CurrentWeapon(void *p, int bot_index) { @@ -447,7 +446,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { state = 0; damage_origin.z = *static_cast(p); - if ((damage_armor > 0) || (damage_taken > 0)) { + if (damage_armor > 0 || damage_taken > 0) { // Damage recieved: // - when the prev node was higher (so we are sure we do FIX the correct nodes!) @@ -479,7 +478,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { return; // depending on bot skill slow this bot down a bit -// pBot->f_move_speed *= (((10 - pBot->bot_skill) + 1) / 10); + // pBot->f_move_speed *= (((10 - pBot->bot_skill) + 1) / 10); // if the bot doesn't have an enemy and someone is shooting at it then // turn in the attacker's direction... @@ -577,15 +576,16 @@ void BotClient_CS_SayText(void *p, int bot_index) { std::strcpy(sentence, static_cast(p)); // the actual sentence - int length = 0; + unsigned int length = 0; // FIXED: In any case that this might return NULL, do not crash the server - if (std::strstr(sentence, " : ")) - length = std::strlen(sentence) - std::strlen(std::strstr(sentence, " : ")); + const char* found = std::strstr(sentence, " : "); + if (found != nullptr) + length = std::strlen(sentence) - std::strlen(found); int tc = 0; - for (int c = length; c < MAX_SENTENCE_LENGTH; c++) { + for (unsigned int c = length; c < MAX_SENTENCE_LENGTH; c++) { chSentence[tc] = sentence[c]; tc++; } @@ -838,9 +838,9 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { const int iCoverNode = NodeMachine.node_cover(iCurrentNode, iCurrentNode, pBot->pEdict); if (iCoverNode > -1) { -// pBot->forgetPath(); -// pBot->rprint("Setting goal from screenfade"); -// pBot->setGoalNode(iCoverNode); + // pBot->forgetPath(); + // pBot->rprint("Setting goal from screenfade"); + // pBot->setGoalNode(iCoverNode); pBot->rprint("TODO: Make bot react upon screenfade/flashbang\n"); } diff --git a/bot_func.cpp b/bot_func.cpp index 0e8172a..0aa33f2 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -110,9 +110,9 @@ bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { // check if line of sight to object is not blocked (i.e. visible) // Als er NONE wordt opgegeven dan checken we gewoon of we worden geblokt if (tr.flFraction >= 1.0f) - return TRUE; + return true; else - return FALSE; + return false; } @@ -241,7 +241,7 @@ cBot *getCloseFellowBot(cBot *pBot) { edict_t *pPlayer = INDEXENT(i); // skip invalid players - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; @@ -272,18 +272,18 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { const int fov = 90;// TODO: use server var "default_fov" ? // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; - if (!((pPlayer->v.flags & FL_THIRDPARTYBOT) - || (pPlayer->v.flags & FL_FAKECLIENT) - || (pPlayer->v.flags & FL_CLIENT))) + if (!(pPlayer->v.flags & FL_THIRDPARTYBOT + || pPlayer->v.flags & FL_FAKECLIENT + || pPlayer->v.flags & FL_CLIENT)) continue; - const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); + const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, pPlayer->v.origin - pBot->pEdict->v.origin); const int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < fov) { @@ -327,14 +327,14 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free) && (pPlayer != pEdict)) { + if (pPlayer && !pPlayer->free && pPlayer != pEdict) { // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; - if (!((pPlayer->v.flags & FL_THIRDPARTYBOT) - || (pPlayer->v.flags & FL_FAKECLIENT) - || (pPlayer->v.flags & FL_CLIENT))) + if (!(pPlayer->v.flags & FL_THIRDPARTYBOT + || pPlayer->v.flags & FL_FAKECLIENT + || pPlayer->v.flags & FL_CLIENT)) continue; //int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); @@ -452,23 +452,23 @@ bool BotShouldJump(cBot *pBot) { v_dest = v_source + gpGlobals->v_forward * 40; // -// int player_index = 0; -// for (player_index = 1; player_index <= gpGlobals->maxClients; -// player_index++) { -// edict_t *pPlayer = INDEXENT(player_index); -// -// if (pPlayer && !pPlayer->free) { -// if (FBitSet(pPlayer->v.flags, FL_CLIENT)) { // do not draw for now -// -// DrawBeam( -// pPlayer, // player sees beam -// v_source, // + Vector(0, 0, 32) (head?) -// v_dest, -// 255, 255, 255 -// ); -// } -// } -// } + // int player_index = 0; + // for (player_index = 1; player_index <= gpGlobals->maxClients; + // player_index++) { + // edict_t *pPlayer = INDEXENT(player_index); + // + // if (pPlayer && !pPlayer->free) { + // if (FBitSet(pPlayer->v.flags, FL_CLIENT)) { // do not draw for now + // + // DrawBeam( + // pPlayer, // player sees beam + // v_source, // + Vector(0, 0, 32) (head?) + // v_dest, + // 255, 255, 255 + // ); + // } + // } + // } UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -623,7 +623,7 @@ bool FUNC_ShouldTakeCover(cBot *pBot) { // CAMP: The more we want, the more we want to take cover const int vCamp = pBot->ipCampRate; - return RANDOM_LONG(0, TOTAL_SCORE) < (vMoney + vHealth + vCamp); + return RANDOM_LONG(0, TOTAL_SCORE) < vMoney + vHealth + vCamp; } bool FUNC_TakeCover(cBot* pBot) //Experimental [APG]RoboCop[CL] @@ -709,28 +709,26 @@ int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest) //Experim if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (farthest == -1) { - farthest = i; - farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); - } else { - const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); - - if (safest) { - if (distance < farthest_distance) { - farthest = i; - farthest_distance = distance; - } - } else { - if (distance > farthest_distance) { - farthest = i; - farthest_distance = distance; - } - } - } - } - } + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (farthest == -1) { + farthest = i; + farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + } else { + const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + + if (safest) { + if (distance < farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } else { + if (distance > farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } + } + } } return farthest; @@ -755,21 +753,19 @@ int FUNC_FindCover(const cBot* pBot) //Experimental [APG]RoboCop[CL] if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { - if (farthest == -1) { - farthest = i; - farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); - } else { - const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); - - if (distance > farthest_distance) { - farthest = i; - farthest_distance = distance; - } - } - } - } + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { + if (farthest == -1) { + farthest = i; + farthest_distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + } else { + const float distance = (pEdict->v.origin - pBot->pEdict->v.origin).Length(); + + if (distance > farthest_distance) { + farthest = i; + farthest_distance = distance; + } + } + } } return farthest; @@ -831,7 +827,7 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG edict_t *pPlayer = INDEXENT(i); // Skip invalid players. - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) @@ -850,7 +846,6 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG botpointer->forgetEnemy(); // Clear its pointer } } - } } @@ -879,14 +874,12 @@ void FUNC_FindBreakable(edict_t* pEntity) //TODO: not functioning, bots won't sh if (pEdict->v.flags & FL_DORMANT) continue; - if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { - if (std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { - if (pEdict->v.origin == pEntity->v.origin) { - pEntity->v.enemy = pEdict; - return; - } - } - } + if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { + if (pEdict->v.origin == pEntity->v.origin) { + pEntity->v.enemy = pEdict; + return; + } + } } } @@ -932,31 +925,29 @@ void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] * @param pHostage * @return */ -bool isHostageFree(cBot *pBotWhoIsAsking, edict_t *pHostage) { +bool isHostageFree(cBot* pBotWhoIsAsking, edict_t* pHostage) { if (pHostage == nullptr) return false; if (pBotWhoIsAsking == nullptr) return false; - + for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - - if ((!pPlayer) || // NULL - (pPlayer && pPlayer->free)) // free - ie no client + edict_t* pPlayer = INDEXENT(i); + if (!pPlayer || pPlayer->free) // free - ie no client continue; // next - + // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; - + // not a bot if (!(pPlayer->v.flags & FL_THIRDPARTYBOT)) continue; - + // Only check other bots (do not check self) - cBot *botpointer = UTIL_GetBotPointer(pPlayer); + cBot* botpointer = UTIL_GetBotPointer(pPlayer); if (botpointer && // a bot - (botpointer != pBotWhoIsAsking) && // not self + botpointer != pBotWhoIsAsking && // not self !botpointer->isDead()) { // not dead - + // other bot uses hostage, so hostage is not 'free' if (botpointer->isUsingHostage(pHostage)) { pBotWhoIsAsking->rprint("Looks like the hostage is used by another one"); @@ -965,7 +956,7 @@ bool isHostageFree(cBot *pBotWhoIsAsking, edict_t *pHostage) { } } } - + return true; } @@ -1125,7 +1116,7 @@ bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { // Already used by bot? if (pBot != nullptr) { -// rblog("isHostageRescueable - pBot is != NULL\n"); + // rblog("isHostageRescueable - pBot is != NULL\n"); if (pBot->isUsingHostage(pHostage)) return false; // Is the hostage not used by *any other* bot? if (!isHostageFree(pBot, pHostage)) { @@ -1193,7 +1184,7 @@ void rblog(char *txt) { // and to reallog file if (fpRblog) { - fprintf(fpRblog, "%s", txt); // print the text into the file + std::fprintf(fpRblog, "%s", txt); // print the text into the file // this way we make sure we have all latest info - even with crashes fflush(fpRblog); diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 20652ab..65f07bd 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -54,8 +54,8 @@ enum * @return */ float fixAngle(float angle) { - if (angle > 180.0f) return (angle - 360.0f); - if (angle < -180.0f) return (angle + 360.0f); + if (angle > 180.0f) return angle - 360.0f; + if (angle < -180.0f) return angle + 360.0f; return angle; } @@ -102,7 +102,7 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; // now check same height to one side of the bot... v_source = @@ -116,7 +116,7 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; // now check same height on the other side of the bot... v_source = @@ -130,7 +130,7 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; // now trace from head level downward to check for obstructions... @@ -152,7 +152,7 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; // now check same height to one side of the bot... v_source = @@ -167,7 +167,7 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; // now check same height on the other side of the bot... v_source = @@ -182,9 +182,9 @@ bool BotCanJumpUp(const cBot * pBot) { // if trace hit something, return FALSE if (tr.flFraction < 1.0f) - return FALSE; + return false; - return TRUE; + return true; } bool BotCanDuckUnder(const cBot * pBot) { diff --git a/bot_weapons.h b/bot_weapons.h index ce072e3..6f45b3c 100644 --- a/bot_weapons.h +++ b/bot_weapons.h @@ -57,7 +57,7 @@ // weapon ID values for Counter-Strike #define CS_WEAPON_P228 1 -#define CS_WEAPON_UNKNOWN2 2 +#define CS_WEAPON_SHIELD 2 #define CS_WEAPON_SCOUT 3 #define CS_WEAPON_HEGRENADE 4 #define CS_WEAPON_XM1014 5 @@ -91,7 +91,7 @@ #define CS_DEFUSEKIT 98 // old value was 99, same as SHIELD -> Bug?? // NOT CONFIRMED -#define CS_WEAPON_SHIELD 99 // Not used for detecting, only for +//#define CS_WEAPON_SHIELD 99 // Not used for detecting, only for // bot.dll // Woah, i rule! :D, figured out all Earth Special Forces Weapon ID's.. diff --git a/build.cpp b/build.cpp index d0f1555..3309b64 100644 --- a/build.cpp +++ b/build.cpp @@ -8,4 +8,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.5-beta3"; +const char *rb_version_nr = "4.0.5-beta4"; diff --git a/dependencies/hlsdk/dlls/util.h b/dependencies/hlsdk/dlls/util.h index 42e1667..ad3e000 100644 --- a/dependencies/hlsdk/dlls/util.h +++ b/dependencies/hlsdk/dlls/util.h @@ -74,7 +74,7 @@ inline edict_t *FIND_ENTITY_BY_TARGET(edict_t *entStart, const char *pszName) typedef int EOFFSET; // In case it's not alread defined -typedef int BOOL; +typedef int BOOL; //-V677 // In case this ever changes #ifndef M_PI diff --git a/dependencies/metamod-hl1/metamod/osdep.h b/dependencies/metamod-hl1/metamod/osdep.h index f20d773..b60507c 100644 --- a/dependencies/metamod-hl1/metamod/osdep.h +++ b/dependencies/metamod-hl1/metamod/osdep.h @@ -216,7 +216,7 @@ mBOOL os_safe_call(REG_CMD_FN pfn); #elif defined(_WIN32) #define snprintf _snprintf #define vsnprintf _vsnprintf - #define sleep(x) Sleep(x*1000) + #define sleep(x) Sleep((x)*1000) #define strcasecmp stricmp #define strncasecmp _strnicmp #include diff --git a/dll.cpp b/dll.cpp index e14ecb1..b8a3bd7 100644 --- a/dll.cpp +++ b/dll.cpp @@ -71,7 +71,7 @@ float f_load_time = 0.0f; float f_minplayers_think = 0.0f; // timer used to add realbots if internet play enabled int mod_id = CSTRIKE_DLL; // should be changed to 0 when we are going to do multi-mod stuff int m_spriteTexture = 0; -bool isFakeClientCommand = FALSE; +bool isFakeClientCommand = false; int fake_arg_count; float bot_check_time = 30.0f; int min_bots = -1; @@ -79,17 +79,17 @@ int max_bots = -1; int min_players = -1; // minimum amount of players that should be in the server all the time int num_bots = 0; int prev_num_bots = 0; -bool g_GameRules = FALSE; +bool g_GameRules = false; edict_t *clients[32]; edict_t *pHostEdict = nullptr; float welcome_time = 0.0f; bool welcome_sent = false; FILE *bot_cfg_fp = nullptr; -bool need_to_open_cfg = TRUE; +bool need_to_open_cfg = true; float bot_cfg_pause_time = 0.0f; float respawn_time = 0.0f; -bool spawn_time_reset = FALSE; +bool spawn_time_reset = false; // Interval between joining bots. int internet_max_interval = 30; @@ -175,23 +175,23 @@ C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, // if plugin has later interface version, it's incompatible (update metamod) sscanf(ifvers, "%d:%d", &mmajor, &mminor); sscanf(META_INTERFACE_VERSION, "%d:%d", &pmajor, &pminor); - if ((pmajor > mmajor) || ((pmajor == mmajor) && (pminor > mminor))) { + if (pmajor > mmajor || (pmajor == mmajor && pminor > mminor)) { LOG_CONSOLE(PLID, "metamod version is too old for this plugin; update metamod"); LOG_ERROR(PLID, "metamod version is too old for this plugin; update metamod"); - return (FALSE); + return false; } // if plugin has older major interface version, it's incompatible (update plugin) - else if (pmajor < mmajor) { - LOG_CONSOLE(PLID, - "metamod version is incompatible with this plugin; please find a newer version of this plugin"); - LOG_ERROR(PLID, - "metamod version is incompatible with this plugin; please find a newer version of this plugin"); - return (FALSE); + if (pmajor < mmajor) { + LOG_CONSOLE(PLID, + "metamod version is incompatible with this plugin; please find a newer version of this plugin"); + LOG_ERROR(PLID, + "metamod version is incompatible with this plugin; please find a newer version of this plugin"); + return false; } } - return (TRUE); // tell metamod this plugin looks safe + return true; // tell metamod this plugin looks safe } C_DLLEXPORT int @@ -209,7 +209,7 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, LOG_ERROR(PLID, "%s: plugin NOT attaching (can't load plugin right now)", Plugin_info.name); - return (FALSE); // returning FALSE prevents metamod from attaching this plugin + return false; // returning FALSE prevents metamod from attaching this plugin } // keep track of the pointers to engine function tables metamod gives us gpMetaGlobals = pMGlobals; @@ -226,7 +226,7 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, // Notify user that 'realbot' command is regged LOG_CONSOLE(PLID, "realbot - command prefix is now reserved."); LOG_MESSAGE(PLID, "realbot - command prefix is now reserved."); - return (TRUE); // returning TRUE enables metamod to attach this plugin + return true; // returning TRUE enables metamod to attach this plugin } C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { @@ -241,12 +241,12 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { LOG_ERROR(PLID, "%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name); - return (FALSE); // returning FALSE prevents metamod from unloading this plugin + return false; // returning FALSE prevents metamod from unloading this plugin } NodeMachine.FreeVisibilityTable(); free(message); - return (TRUE); // returning TRUE enables metamod to unload this plugin + return true; // returning TRUE enables metamod to unload this plugin } // END of Metamod stuff @@ -254,7 +254,7 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { #ifdef _WIN32 // Required DLL entry point int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - return TRUE; + return true; } #endif /* */ @@ -271,16 +271,16 @@ GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, } void GameDLLInit() { - FILE* fplog = fopen("reallog.txt", "wt"); + FILE* fplog = std::fopen("reallog.txt", "wt"); if (fplog) { - fprintf(fplog, "Realbot Logbook\n"); - fprintf(fplog, "Version %s\n\n", rb_version_nr); - fclose(fplog); + std::fprintf(fplog, "Realbot Logbook\n"); + std::fprintf(fplog, "Version %s\n\n", rb_version_nr); + std::fclose(fplog); } // and now open it for the entire bot-dll-lifetime - fpRblog = fopen("reallog.txt", "at"); + fpRblog = std::fopen("reallog.txt", "at"); rblog("Initializing clients.."); for (int i = 0; i < 32; i++) @@ -289,22 +289,22 @@ void GameDLLInit() { // initialize the bots array of structures... rblog("Initializing memory for bots array.."); - std::memset(bots, 0.0f, sizeof(bots)); + std::memset(bots, 0, sizeof(bots)); rblog("OK\n"); rblog("Verifying realbot is installed correctly.."); bool bInstalledCorrectly = false; - FILE* fp = fopen("realbot/dll/realbot_mm.dll", "rb"); + FILE* fp = std::fopen("realbot/dll/realbot_mm.dll", "rb"); if (fp != nullptr) { bInstalledCorrectly = true; - fclose(fp); + std::fclose(fp); } - fp = fopen("realbot/dll/realbot_mm_i386.so", "rb"); + fp = std::fopen("realbot/dll/realbot_mm.so", "rb"); if (fp != nullptr) { bInstalledCorrectly = true; - fclose(fp); + std::fclose(fp); } if (bInstalledCorrectly) @@ -345,15 +345,15 @@ void GameDLLInit() { // if you know a more orthodox way of doing this, please tell me. // test file, if found = STEAM Linux/Win32 dedicated server - fp = fopen("valve/steam.inf", "rb"); + fp = std::fopen("valve/steam.inf", "rb"); if (fp != nullptr) { - fclose(fp); // test was successful, close it + std::fclose(fp); // test was successful, close it counterstrike = 1; // its cs 1.6 } // test file, if found = STEAM Win32 listenserver - fp = fopen("FileSystem_Steam.dll", "rb"); + fp = std::fopen("FileSystem_Steam.dll", "rb"); if (fp != nullptr) { - fclose(fp); // test was successful, close it + std::fclose(fp); // test was successful, close it counterstrike = 1; // its cs 1.6 } @@ -385,10 +385,10 @@ int Spawn(edict_t *pent) { // sound PRECACHE_SOUND("misc/imgood12.wav"); - g_GameRules = TRUE; + g_GameRules = true; //bot_cfg_pause_time = 0.0; respawn_time = 0.0f; - spawn_time_reset = FALSE; + spawn_time_reset = false; prev_num_bots = num_bots; num_bots = 0; bot_check_time = gpGlobals->time + 30.0f; @@ -440,7 +440,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, } // if there are currently more than the minimum number of bots running // then kick one of the bots off the server... - if ((count > min_bots) && (min_bots != -1)) { + if (count > min_bots && min_bots != -1) { for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) // is this slot used? { @@ -463,7 +463,7 @@ void ClientDisconnect(edict_t *pEntity) { if (gpGlobals->deathmatch) { int i = 0; - while ((i < 32) && (clients[i] != pEntity)) + while (i < 32 && clients[i] != pEntity) i++; if (i < 32) @@ -488,7 +488,7 @@ void ClientDisconnect(edict_t *pEntity) { void ClientPutInServer(edict_t *pEntity) { int i = 0; - while ((i < 32) && (clients[i] != nullptr)) + while (i < 32 && (clients[i] != nullptr)) i++; if (i < 32) @@ -591,7 +591,7 @@ void StartFrame() { // which is determined by comparing the previously recorded time (at the end of this function) // with the current time. If the current time somehow was less (before) the previous time, then we // assume a reset/restart/reload of a map. - if ((gpGlobals->time + 0.1f) < previous_time) { + if (gpGlobals->time + 0.1f < previous_time) { static int index; static float check_server_cmd = 0.0f; rblog("NEW MAP because time is reset #1\n"); @@ -615,7 +615,7 @@ void StartFrame() { } // check for any bots that were very recently kicked... - if ((pBot->fKickTime + 5.0f) > previous_time) { + if (pBot->fKickTime + 5.0f > previous_time) { pBot->respawn_state = RESPAWN_NEED_TO_RESPAWN; count++; } else { @@ -656,7 +656,7 @@ void StartFrame() { for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { edict_t *pPlayer = INDEXENT(iIndex); // skip invalid players - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { // we found a player which is alive. w00t welcome_time = gpGlobals->time + 10.0f; break; @@ -664,7 +664,7 @@ void StartFrame() { } } - if ((welcome_time > 0.0f) && (welcome_time < gpGlobals->time)) { + if (welcome_time > 0.0f && welcome_time < gpGlobals->time) { // let's send a welcome message to this client... char total_welcome[256]; std::sprintf(total_welcome, "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); @@ -682,14 +682,14 @@ void StartFrame() { for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { edict_t *pPlayer = INDEXENT(iIndex); // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { // skip bots! if (UTIL_GetBotPointer(pPlayer)) continue; // skip fake clients - if ((pPlayer->v.flags & FL_THIRDPARTYBOT) - || (pPlayer->v.flags & FL_FAKECLIENT)) + if (pPlayer->v.flags & FL_THIRDPARTYBOT + || pPlayer->v.flags & FL_FAKECLIENT) continue; // random color @@ -760,7 +760,7 @@ void StartFrame() { for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t *pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) - if ((pPlayer) && (!pPlayer->free)) { + if (pPlayer && !pPlayer->free) { // a bot if (UTIL_GetBotPointer(pPlayer) != nullptr) iBots++; @@ -831,7 +831,7 @@ void StartFrame() { if (internet_addbot) { // When timer is set, create a new bot. - if (add_timer > gpGlobals->time && internet_addbot) { + if (add_timer > gpGlobals->time) { internet_addbot = false; Game.createBot(nullptr, nullptr, nullptr, nullptr, nullptr); bot_check_time = gpGlobals->time + 8.0f; @@ -851,8 +851,8 @@ void StartFrame() { for (bot_index = 0; bot_index < gpGlobals->maxClients; bot_index++) { cBot &bot = bots[bot_index]; - if ((bot.bIsUsed) && // is this slot used AND - (bot.respawn_state == RESPAWN_IDLE)) // not respawning + if (bot.bIsUsed && // is this slot used AND + bot.respawn_state == RESPAWN_IDLE) // not respawning { if (bot.fUpdateTime < gpGlobals->time) { BotThink(&bot); @@ -921,11 +921,11 @@ void StartFrame() { } // are we currently respawning bots and is it time to spawn one yet? - if ((respawn_time > 1.0f) && (respawn_time <= gpGlobals->time)) { + if (respawn_time > 1.0f && respawn_time <= gpGlobals->time) { int index = 0; // find bot needing to be respawned... - while ((index < 32) - && (bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN)) + while (index < 32 + && bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN) index++; if (index < 32) { @@ -963,14 +963,14 @@ void StartFrame() { char msg[256]; char filename[256]; - need_to_open_cfg = FALSE; // only do this once!!! + need_to_open_cfg = false; // only do this once!!! UTIL_BuildFileNameRB("bot.cfg", filename); std::sprintf(msg, "Executing %s\n", filename); ALERT(at_console, msg); - bot_cfg_fp = fopen(filename, "r"); + bot_cfg_fp = std::fopen(filename, "r"); if (bot_cfg_fp == nullptr) ALERT(at_console, "bot.cfg file not found\n"); @@ -984,7 +984,7 @@ void StartFrame() { if (!IS_DEDICATED_SERVER() && !spawn_time_reset) { if (pHostEdict != nullptr) { if (IsAlive(pHostEdict)) { - spawn_time_reset = TRUE; + spawn_time_reset = true; if (respawn_time >= 1.0f) respawn_time = std::min(respawn_time, gpGlobals->time + 1.0f); @@ -997,8 +997,8 @@ void StartFrame() { } } // DO BOT.CFG crap here - if ((bot_cfg_fp) && (bot_cfg_pause_time >= 1.0f) - && (bot_cfg_pause_time <= gpGlobals->time)) { + if (bot_cfg_fp && bot_cfg_pause_time >= 1.0f + && bot_cfg_pause_time <= gpGlobals->time) { // process bot.cfg file options... ProcessBotCfgFile(); } @@ -1008,7 +1008,7 @@ void StartFrame() { // remember the time previous_time = gpGlobals->time; -// REALBOT_PRINT("StartFrame", "END"); + // REALBOT_PRINT("StartFrame", "END"); RETURN_META(MRES_IGNORED); } @@ -1017,15 +1017,15 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { std::memset(g_argv, 0, sizeof(g_argv)); - isFakeClientCommand = TRUE; + isFakeClientCommand = true; - if ((arg1 == nullptr) || (*arg1 == 0)) + if (arg1 == nullptr || *arg1 == 0) return; - if ((arg2 == nullptr) || (*arg2 == 0)) { + if (arg2 == nullptr || *arg2 == 0) { length = std::sprintf(&g_argv[0], "%s", arg1); fake_arg_count = 1; - } else if ((arg3 == nullptr) || (*arg3 == 0)) { + } else if (arg3 == nullptr || *arg3 == 0) { length = std::sprintf(&g_argv[0], "%s %s", arg1, arg2); fake_arg_count = 2; } else { @@ -1046,7 +1046,7 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { // allow the MOD DLL to execute the ClientCommand... MDLL_ClientCommand(pBot); - isFakeClientCommand = FALSE; + isFakeClientCommand = false; } /*void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) // KWo 02.03.2010 - thanks to MeRcyLeZZ @@ -1135,7 +1135,7 @@ void ProcessBotCfgFile() { while (ch == ' ') ch = fgetc(bot_cfg_fp); - while ((ch != EOF) && (ch != '\r') && (ch != '\n')) { + while (ch != EOF && ch != '\r' && ch != '\n') { if (ch == '\t') // convert tabs to spaces ch = ' '; @@ -1144,7 +1144,7 @@ void ProcessBotCfgFile() { ch = fgetc(bot_cfg_fp); // skip multiple spaces in input file - while ((cmd_line[cmd_index] == ' ') && (ch == ' ')) + while (cmd_line[cmd_index] == ' ' && ch == ' ') ch = fgetc(bot_cfg_fp); cmd_index++; @@ -1156,7 +1156,7 @@ void ProcessBotCfgFile() { } // if reached end of file, then close it if (ch == EOF) { - fclose(bot_cfg_fp); + std::fclose(bot_cfg_fp); bot_cfg_fp = nullptr; @@ -1174,7 +1174,7 @@ void ProcessBotCfgFile() { const char* arg1 = arg2 = arg3 = arg4 = nullptr; // skip to blank or end of string... - while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0)) + while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) cmd_index++; if (cmd_line[cmd_index] == ' ') { @@ -1182,7 +1182,7 @@ void ProcessBotCfgFile() { arg1 = &cmd_line[cmd_index]; // skip to blank or end of string... - while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0)) + while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) cmd_index++; if (cmd_line[cmd_index] == ' ') { @@ -1191,7 +1191,7 @@ void ProcessBotCfgFile() { // skip to blank or end of string... - while ((cmd_line[cmd_index] != ' ') && (cmd_line[cmd_index] != 0)) + while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) cmd_index++; if (cmd_line[cmd_index] == ' ') { @@ -1199,8 +1199,8 @@ void ProcessBotCfgFile() { arg3 = &cmd_line[cmd_index]; // skip to blank or end of string... - while ((cmd_line[cmd_index] != ' ') - && (cmd_line[cmd_index] != 0)) + while (cmd_line[cmd_index] != ' ' + && cmd_line[cmd_index] != 0) cmd_index++; if (cmd_line[cmd_index] == ' ') { @@ -1211,7 +1211,7 @@ void ProcessBotCfgFile() { } } - if ((cmd_line[0] == '#') || (cmd_line[0] == 0)) + if (cmd_line[0] == '#' || cmd_line[0] == 0) return; // return if comment or blank line if (std::strcmp(cmd, "pause") == 0) { @@ -1262,7 +1262,7 @@ void RealBot_ServerCommand() { SERVER_PRINT("realbot server [subcommand]\n"); SERVER_PRINT("=====================================\n"); } else if (FStrEq(pcmd, "chatrate")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { Game.iMaxSentences = std::atoi(arg1); if (Game.iMaxSentences < -1) Game.iMaxSentences = -1; @@ -1294,7 +1294,7 @@ void RealBot_ServerCommand() { std::sprintf(cMessage, "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { const float fVar = std::atof(arg1); // Only set when valid @@ -1316,9 +1316,9 @@ void RealBot_ServerCommand() { } else std::sprintf(cMessage, "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "max")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { max_bots = std::atoi(arg1); - if ((max_bots < 0) || (max_bots > 31)) + if (max_bots < 0 || max_bots > 31) max_bots = -1; // Show amount set @@ -1356,7 +1356,7 @@ void RealBot_ServerCommand() { std::sprintf(cMessage, "REALBOT: Killing all bots."); end_round = true; } else if (FStrEq(pcmd, "csversion")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); if (temp <= 0) counterstrike = 0; // cs 1.5 @@ -1379,7 +1379,7 @@ void RealBot_ServerCommand() { "REALBOT: bot-rules are set for Counter-Strike 1.6."); } } else if (FStrEq(pcmd, "internet")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { // switch on/off internet mode const int temp = std::atoi(arg1); @@ -1398,7 +1398,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "internet_interval")) { // 1st argument - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { // switch on/off internet mode int temp = std::atoi(arg1); @@ -1409,7 +1409,7 @@ void RealBot_ServerCommand() { } } // 2nd argument - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { // switch on/off internet mode int temp = std::atoi(arg2); @@ -1426,7 +1426,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "remove") && kick_amount_bots == 0) { // ARG1 - Amount - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { // get amount const int temp = std::atoi(arg1); @@ -1437,7 +1437,7 @@ void RealBot_ServerCommand() { kick_amount_bots = 0; } // ARG 2 - Team - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { // get team int team = 0; @@ -1465,16 +1465,16 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "roundlimit")) { // Check if Arguments are valid - if (((arg2 != nullptr) && (*arg2 != 0)) - && ((arg1 != nullptr) && (*arg1 != 0))) { + if (arg2 != nullptr && *arg2 != 0 + && (arg1 != nullptr && *arg1 != 0)) { int s1 = -1, s2 = -1; // argument 1 - if ((arg1 != nullptr) && (*arg1 != 0)) + if (arg1 != nullptr && *arg1 != 0) s1 = std::atoi(arg1); // argument 2 - if ((arg2 != nullptr) && (*arg2 != 0)) + if (arg2 != nullptr && *arg2 != 0) s2 = std::atoi(arg2); Game.SetPlayingRounds(s1, s2); std::sprintf(cMessage, @@ -1487,11 +1487,11 @@ void RealBot_ServerCommand() { int s1 = -2, s2 = -2; // argument 1 - if ((arg1 != nullptr) && (*arg1 != 0)) + if (arg1 != nullptr && *arg1 != 0) s1 = std::atoi(arg1); // argument 2 - if ((arg2 != nullptr) && (*arg2 != 0)) + if (arg2 != nullptr && *arg2 != 0) s2 = std::atoi(arg2); // When first argument is invalid @@ -1519,7 +1519,7 @@ void RealBot_ServerCommand() { Game.iRandomMinSkill, Game.iRandomMaxSkill); } } else if (FStrEq(pcmd, "autoskill")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); if (temp == 1) autoskill = true; @@ -1533,7 +1533,7 @@ void RealBot_ServerCommand() { else std::sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); if (temp == 1) Game.iOverrideBotSkill = GAME_YES; @@ -1549,9 +1549,9 @@ void RealBot_ServerCommand() { std::sprintf(cMessage, "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { - if ((arg1 != nullptr) && (*arg1 != 0)) { + if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); - if ((temp < -1) || (temp > 10)) { + if (temp < -1 || temp > 10) { std::sprintf(cMessage, "REALBOT: Invalid argument given - default skill = %d.", Game.iDefaultBotSkill); @@ -1571,7 +1571,7 @@ void RealBot_ServerCommand() { else if (FStrEq(pcmd, "server")) { // Minimum amount of playing players... bots or not if (FStrEq(arg1, "players")) { - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { int temp = std::atoi(arg2); // argument if (temp > 31) temp = 31; @@ -1590,7 +1590,7 @@ void RealBot_ServerCommand() { // Broadcast what? if (FStrEq(arg2, "version")) { // How do we broadcast version message? - if ((arg3 != nullptr) && (*arg3 != 0)) { + if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1620,7 +1620,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(arg2, "kills")) { // How do we broadcast kills by bots? - if ((arg3 != nullptr) && (*arg3 != 0)) { + if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1655,7 +1655,7 @@ void RealBot_ServerCommand() { } } else if (FStrEq(arg2, "deaths")) { // How do we broadcast deaths by bots. - if ((arg3 != nullptr) && (*arg3 != 0)) { + if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument if (temp <= 0) temp = 0; @@ -1711,7 +1711,7 @@ void RealBot_ServerCommand() { bool bValidArg = false; // check for valid argument - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { const int iTo = std::atoi(arg2); // add connection TO // Add this connection @@ -1739,7 +1739,7 @@ void RealBot_ServerCommand() { bool bValidArg = false; // check for valid argument - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { const int iTo = std::atoi(arg2); // remove connection TO // remove this connection @@ -1849,11 +1849,11 @@ void RealBot_ServerCommand() { // Don't care whether we are close to a node... if (FStrEq(arg1, "connect")) { // check for valid argument - if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) - && (*arg3 != 0)) { + if (arg2 != nullptr && *arg2 != 0 && arg3 != nullptr + && *arg3 != 0) { const int Node1 = std::atoi(arg2); // add connection TO const int Node2 = std::atoi(arg3); // add connection TO - if ((Node1 >= 0) && (Node2 >= 0) + if (Node1 >= 0 && Node2 >= 0 && NodeMachine.add_neighbour_node(Node1, Node2)) std::sprintf(cMessage, "NODES EDITOR: Added connection from node %d to node %d.", @@ -1866,11 +1866,11 @@ void RealBot_ServerCommand() { "NODES EDITOR: this command requires TWO numeric arguments!"); } else if (FStrEq(arg1, "disconnect")) { // check for valid argument - if ((arg2 != nullptr) && (*arg2 != 0) && (arg3 != nullptr) - && (*arg3 != 0)) { + if (arg2 != nullptr && *arg2 != 0 && arg3 != nullptr + && *arg3 != 0) { const int Node1 = std::atoi(arg2); const int Node2 = std::atoi(arg3); - if ((Node1 >= 0) && (Node2 >= 0) + if (Node1 >= 0 && Node2 >= 0 && NodeMachine.removeConnection(Node1, Node2)) std::sprintf(cMessage, "NODES EDITOR: Removed connection from node %d to node %d.", @@ -1891,7 +1891,7 @@ void RealBot_ServerCommand() { // Arg 1 is command: if (FStrEq(arg1, "dontshoot")) { // realbot debug dontshoot [1/0] // check for valid argument - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { const int temp = std::atoi(arg2); if (temp) Game.bDoNotShoot = true; @@ -1906,7 +1906,7 @@ void RealBot_ServerCommand() { } // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { const int temp = std::atoi(arg2); if (temp) Game.bPistols = true; @@ -1926,7 +1926,7 @@ void RealBot_ServerCommand() { // Print information about all current bots { rblog("Dumping information about all bots:\n"); - for (int iBot = 0; (iBot < 32) && (bots[iBot].bIsUsed == true); iBot++) { + for (int iBot = 0; iBot < 32 && bots[iBot].bIsUsed == true; iBot++) { bots[iBot].Dump(); } @@ -1937,7 +1937,7 @@ void RealBot_ServerCommand() { Game.bDebug = -2; std::sprintf(cMessage, "RBDEBUG: Debug messages off."); } else { - if ((arg2 != nullptr) && (*arg2 != 0)) { + if (arg2 != nullptr && *arg2 != 0) { const int temp = std::atoi(arg2); Game.bDebug = temp; std::sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); @@ -1974,9 +1974,9 @@ void RealBot_ServerCommand() { std::sprintf(cMessage, "RBDEBUG: Drawing nodes - disabled."); } else if (FStrEq(arg2, "path")) { int iFrom = -1, iTo = -1; - if ((arg3 != nullptr) && (*arg3 != 0)) + if (arg3 != nullptr && *arg3 != 0) iFrom = std::atoi(arg3); - if ((arg4 != nullptr) && (*arg4 != 0)) + if (arg4 != nullptr && *arg4 != 0) iTo = std::atoi(arg4); if (iFrom > -1) { @@ -1991,7 +1991,7 @@ void RealBot_ServerCommand() { std::sprintf(cMessage, "RBDEBUG: Usage: realbot debug nodes path "); } } else if (FStrEq(arg2, "drawpath")) { - if ((arg3 != nullptr) && (*arg3 != 0)) + if (arg3 != nullptr && *arg3 != 0) draw_nodepath = std::atoi(arg3); if (draw_nodepath > -1) { std::sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); @@ -2065,16 +2065,16 @@ int Spawn_Post(edict_t *pent) { // is this a transparent entity ? if (pent->v.rendermode == kRenderTransTexture //|| -// (pent->v.rendermode == kRenderTransAlpha && strcmp("func_illusionary", STRING(pent->v.classname)) == 0) + // (pent->v.rendermode == kRenderTransAlpha && strcmp("func_illusionary", STRING(pent->v.classname)) == 0) ) { // func_illusionary on cs_italy uses this rendermode pent->v.flags |= FL_WORLDBRUSH; // set WORLD BRUSH -// // this seems to enforce solidness, and hence the tracehull/line will detect it now. -// pent->v.solid = SOLID_BSP; -// pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much -// pent->v.rendermode == kRenderNormal; + // this seems to enforce solidness, and hence the tracehull/line will detect it now. + // pent->v.solid = SOLID_BSP; + // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much + // pent->v.rendermode == kRenderNormal; } else { } @@ -2091,12 +2091,12 @@ int Spawn_Post(edict_t *pent) { // Perhaps this fixes also the as_oilrig problem where a traceline goes through the button without // detecting?? // this seems to enforce solidness, and hence the tracehull/line will detect it now. -// pent->v.solid = SOLID_BSP; -// pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much + // pent->v.solid = SOLID_BSP; + // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much -// pent->v.solid = SOLID_TRIGGER; -// pent->v.solid = SOLID_BSP; -// SERVER_PRINT("Adjusted a trigger_multiple!!\n"); + // pent->v.solid = SOLID_TRIGGER; + // pent->v.solid = SOLID_BSP; + // SERVER_PRINT("Adjusted a trigger_multiple!!\n"); } RETURN_META_VALUE(MRES_IGNORED, 0); @@ -2113,7 +2113,7 @@ GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable.pfnClientCommand = ClientCommand; gFunctionTable.pfnStartFrame = StartFrame; std::memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); - return (TRUE); + return true; } // Whistler: @@ -2121,7 +2121,7 @@ C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable_post.pfnSpawn = Spawn_Post; // need to declare another gFunctionTable_post in the top of the dll.cpp file std::memcpy(pFunctionTable, &gFunctionTable_post, sizeof(DLL_FUNCTIONS)); - return (TRUE); + return true; } // Stefan says: You where right, i did not understand it properly. But now i see the little diff --git a/engine.cpp b/engine.cpp index 2e34767..aa4c2fd 100644 --- a/engine.cpp +++ b/engine.cpp @@ -111,11 +111,11 @@ void pfnRemoveEntity(edict_t *e) { #if DO_DEBUG == 2 { - fp = fopen("!rbdebug.txt", "a"); - fprintf(fp, R"(pfnRemoveEntity: %x)", e); + fp = std::fopen("!rbdebug.txt", "a"); + std::fprintf(fp, R"(pfnRemoveEntity: %x)", e); if (e->v.model != 0) - fprintf(fp, " model=%s\n", STRING(e->v.model)); - fclose(fp); + std::fprintf(fp, " model=%s\n", STRING(e->v.model)); + std::fclose(fp); } #endif @@ -392,37 +392,38 @@ void pfnWriteString(const char *sz) { if (gpGlobals->deathmatch) { // Ditlew's Radio - if ((std::strstr(sz, "(RADIO):") != nullptr) && !radio_message) { + if (sz != nullptr && std::strstr(sz, "(RADIO):") != nullptr && !radio_message) { // We found an old radio message, we should convert the strings... radio_message = true; // we found a radio message // Thank god Ditlew you already coded this... - const unsigned length = std::strlen(sz) - std::strlen(std::strstr(sz, " (RADIO)")); - std::strncpy(radio_messenger, sz, length); + const char* radio_ptr = std::strstr(sz, " (RADIO)"); + if (radio_ptr != nullptr) { + const unsigned length = std::strlen(sz) - std::strlen(radio_ptr); + std::strncpy(radio_messenger, sz, length); + } // Now search for any compatible radio command (old string). // if found then convert the message in the new way so the code // thinks its CS 1.1 and thus every version lower then CS 1.1 should work too... - if ((std::strstr(sz, "Follow Me") != nullptr)) { - // convert string + if (std::strstr(sz, "Follow Me") != nullptr) { std::strcpy(message, "#Follow me"); - } else if ((std::strstr(sz, "You Take the Point") != nullptr)) { - // convert string + } + else if (std::strstr(sz, "You Take the Point") != nullptr) { std::strcpy(message, "#You_take_the_point"); - } else if ((std::strstr(sz, "Need backup") != nullptr)) { - // convert string + } + else if (std::strstr(sz, "Need backup") != nullptr) { std::strcpy(message, "#Need_backup"); - } else if ((std::strstr(sz, "Taking Fire.. Need Assistance!") != nullptr)) { - // convert string + } + else if (std::strstr(sz, "Taking Fire.. Need Assistance!") != nullptr) { std::strcpy(message, "#Taking_fire"); - } else if ((std::strstr(sz, "Team, fall back!") != nullptr)) { - // convert string + } + else if (std::strstr(sz, "Team, fall back!") != nullptr) { std::strcpy(message, "#Team_fall_back"); - } else if ((std::strstr(sz, "Go go go") != nullptr)) { - // convert string + } + else if (std::strstr(sz, "Go go go") != nullptr) { std::strcpy(message, "#Go_go_go"); } - } /* else @@ -551,15 +552,11 @@ const char *pfnCmd_Argv(int argc) { if (isFakeClientCommand) { if (argc == 0) RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[64]); - - else if (argc == 1) - RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[128]); - - else if (argc == 2) - RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[192]); - - else - RETURN_META_VALUE(MRES_SUPERCEDE, NULL); + if (argc == 1) + RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[128]); + if (argc == 2) + RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[192]); + RETURN_META_VALUE(MRES_SUPERCEDE, NULL); } RETURN_META_VALUE(MRES_IGNORED, NULL); } @@ -629,5 +626,5 @@ GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, meta_engfuncs.pfnSetClientMaxspeed = pfnSetClientMaxspeed; meta_engfuncs.pfnGetPlayerUserId = pfnGetPlayerUserId; std::memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t)); - return TRUE; + return true; } diff --git a/game.cpp b/game.cpp index 3801e45..bab507c 100644 --- a/game.cpp +++ b/game.cpp @@ -230,9 +230,8 @@ float cGame::getRoundTimeElapsed() const { if (getRoundStartedTime() > -1) { return gpGlobals->time - getRoundStartedTime(); - } else { - return -1; } + return -1; } // GAME: Set new round flag @@ -290,21 +289,21 @@ void cGame::LoadCFG() { void cGame::LoadNames() { char filename[256]; UTIL_BuildFileNameRB("rb_names.txt", filename); - FILE* bot_name_fp = fopen(filename, "r"); + FILE* bot_name_fp = std::fopen(filename, "r"); if (bot_name_fp != nullptr) { char name_buffer[80]; - while ((iAmountNames < MAX_BOT_NAMES) && - (fgets(name_buffer, 80, bot_name_fp) != nullptr)) { + while (iAmountNames < MAX_BOT_NAMES && + std::fgets(name_buffer, 80, bot_name_fp) != nullptr) { int length = static_cast(std::strlen(name_buffer)); - if (name_buffer[length - 1] == '\n') { + if (length > 0 && name_buffer[length - 1] == '\n') { name_buffer[length - 1] = 0; // remove '\n' length--; } int str_index = 0; while (str_index < length) { - if ((name_buffer[str_index] < ' ') - || (name_buffer[str_index] > '~') - || (name_buffer[str_index] == '"')) + if (name_buffer[str_index] < ' ' + || name_buffer[str_index] > '~' + || name_buffer[str_index] == '"') for (int index = str_index; index < length; index++) name_buffer[index] = name_buffer[index + 1]; str_index++; @@ -315,7 +314,7 @@ void cGame::LoadNames() { iAmountNames++; } } - fclose(bot_name_fp); + std::fclose(bot_name_fp); } } // LoadNames() @@ -455,8 +454,8 @@ void cGame::UpdateGameStatus() { } // planted, and not planted before // Every 3 seconds update the goals - if (gpGlobals->time > (fUpdateGoalTimer + 3)) { -// rblog("cGame::UpdateGameStatus - updateGoals\n"); + if (gpGlobals->time > fUpdateGoalTimer + 3) { + // rblog("cGame::UpdateGameStatus - updateGoals\n"); NodeMachine.updateGoals(); fUpdateGoalTimer = gpGlobals->time; } @@ -480,7 +479,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg char botName[BOT_NAME_LEN + 1]; std::memset(botName, 0, sizeof(botName)); // if name given, use that - if ((nameArg != nullptr) && (*nameArg != 0)) { + if (nameArg != nullptr && *nameArg != 0) { std::strncpy(botName, nameArg, BOT_NAME_LEN - 1); botName[BOT_NAME_LEN] = 0; // make sure botName is null terminated } else { // else pick random one or fallback to default "RealBot" @@ -512,7 +511,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg } // when not valid (-2), it has default skill - if ((botSkill < -1) || (botSkill > 10)) { + if (botSkill < -1 || botSkill > 10) { botSkill = iDefaultBotSkill; } @@ -531,13 +530,13 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg char ptr[128]; // allocate space for message from ClientConnect int freeBotIndex = 0; - while ((bots[freeBotIndex].bIsUsed) && (freeBotIndex < MAX_BOTS)) + while (freeBotIndex < MAX_BOTS && bots[freeBotIndex].bIsUsed) freeBotIndex++; if (freeBotIndex == MAX_BOTS) { // failure return GAME_MSG_FAILURE; } - + // create the player entity by calling MOD's player function // (from LINK_ENTITY_TO_CLASS for player object) diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 444d140..843d64a 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -16,6 +16,7 @@ v143 false MultiByte + Spectre diff --git a/todo.txt b/todo.txt index c577dca..e6bdea2 100644 --- a/todo.txt +++ b/todo.txt @@ -10,4 +10,5 @@ - To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up +- To allow bots to use melee on breakables or "func_breakable" to infiltrate windows and vents - Ensure that the RealBot personality directories are correctly assigned \ No newline at end of file diff --git a/util.cpp b/util.cpp index 61ec5c3..d8149c3 100644 --- a/util.cpp +++ b/util.cpp @@ -57,7 +57,7 @@ #include #ifndef _WIN32 -#define _snprintf snprintf +#define snprintf std::snprintf //-V1059 #endif extern int mod_id; @@ -82,7 +82,7 @@ UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, edict_t* pentIgnore, TraceResult* ptr) { TRACE_LINE(vecStart, vecEnd, (igmon == - ignore_monsters ? TRUE : FALSE) | (ignoreGlass ? 0x100 : 0), + ignore_monsters) | (ignoreGlass ? 0x100 : 0), pentIgnore, ptr); } @@ -90,7 +90,7 @@ void UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, IGNORE_MONSTERS igmon, edict_t* pentIgnore, TraceResult* ptr) { - TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), + TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters), pentIgnore, ptr); } @@ -98,7 +98,7 @@ void UTIL_TraceHull(const Vector& vecStart, const Vector& vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t* pentIgnore, TraceResult* ptr) { - TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters ? TRUE : FALSE), hullNumber, pentIgnore, ptr); + TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters), hullNumber, pentIgnore, ptr); } void UTIL_MakeVectors(const Vector& vecAngles) { @@ -233,14 +233,14 @@ void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { const int sender_team = UTIL_GetTeam(pEntity); edict_t* client = nullptr; - while (((client = UTIL_FindEntityByClassname(client, "player")) != nullptr) - && (!FNullEnt(client))) { + while ((client = UTIL_FindEntityByClassname(client, "player")) != nullptr + && !FNullEnt(client)) { if (client == pEntity) // skip sender of message continue; const int player_team = UTIL_GetTeam(client); - if (teamonly && (sender_team != player_team)) + if (teamonly && sender_team != player_team) continue; MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, client); @@ -282,15 +282,13 @@ edict_t* DBG_EntOfVars(const entvars_t* pev) { bool UTIL_IsVip(edict_t* pEntity) { if (mod_id != CSTRIKE_DLL) return false; - else { - char model_name[32]; + char model_name[32]; - char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); - std::strcpy(model_name, (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); + char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); + std::strcpy(model_name, g_engfuncs.pfnInfoKeyValue(infobuffer, "model")); - if (std::strcmp(model_name, "vip") == 0) // VIP - return true; - } + if (std::strcmp(model_name, "vip") == 0) // VIP + return true; return false; } @@ -302,24 +300,24 @@ int UTIL_GetTeam(edict_t* pEntity) { char* infobuffer = (*g_engfuncs.pfnGetInfoKeyBuffer)(pEntity); std::strcpy(model_name, - (g_engfuncs.pfnInfoKeyValue(infobuffer, "model"))); - - if ((std::strcmp(model_name, "terror") == 0) || // Phoenix Connektion - (std::strcmp(model_name, "arab") == 0) || // old L337 Krew - (std::strcmp(model_name, "leet") == 0) || // L337 Krew - (std::strcmp(model_name, "artic") == 0) || // Artic Avenger - (std::strcmp(model_name, "arctic") == 0) || // Artic Avenger - fix for arctic? - seemed a typo? - (std::strcmp(model_name, "guerilla") == 0)) // Gorilla Warfare + g_engfuncs.pfnInfoKeyValue(infobuffer, "model")); + + if (std::strcmp(model_name, "terror") == 0 || // Phoenix Connektion + std::strcmp(model_name, "arab") == 0 || // old L337 Krew + std::strcmp(model_name, "leet") == 0 || // L337 Krew + std::strcmp(model_name, "artic") == 0 || // Artic Avenger + std::strcmp(model_name, "arctic") == 0 || // Artic Avenger - fix for arctic? - seemed a typo? + std::strcmp(model_name, "guerilla") == 0) // Gorilla Warfare //(strcmp(model_name, "militia") == 0)) // CZ Militia { return 0; // team Terrorists } - else if ((std::strcmp(model_name, "urban") == 0) || // Seal Team 6 - (std::strcmp(model_name, "gsg9") == 0) || // German GSG-9 - (std::strcmp(model_name, "sas") == 0) || // UK SAS - (std::strcmp(model_name, "gign") == 0) || // French GIGN - (std::strcmp(model_name, "vip") == 0) || // VIP - (std::strcmp(model_name, "spetsnatz") == 0)) // CZ Spetsnatz + if (std::strcmp(model_name, "urban") == 0 || // Seal Team 6 + std::strcmp(model_name, "gsg9") == 0 || // German GSG-9 + std::strcmp(model_name, "sas") == 0 || // UK SAS + std::strcmp(model_name, "gign") == 0 || // French GIGN + std::strcmp(model_name, "vip") == 0 || // VIP + std::strcmp(model_name, "spetsnatz") == 0) // CZ Spetsnatz { return 1; // team Counter-Terrorists } @@ -367,11 +365,11 @@ cBot* UTIL_GetBotPointer(edict_t* pEdict) { bool IsAlive(edict_t* pEdict) { // FIX: Make sure the edict is valid and such, else return false: - return ((pEdict != nullptr) && // VALID - (pEdict->v.deadflag == DEAD_NO) && // NOT DEAD - (pEdict->v.health > 0) && // ENOUGHT HEALTH + return pEdict != nullptr && // VALID + pEdict->v.deadflag == DEAD_NO && // NOT DEAD + pEdict->v.health > 0 && // ENOUGHT HEALTH !(pEdict->v.flags & FL_NOTARGET) && // ? - (pEdict->v.takedamage != 0.0f)); // CAN TAKE DAMAGE + pEdict->v.takedamage != 0.0f; // CAN TAKE DAMAGE } bool FInViewCone(Vector* pOrigin, edict_t* pEdict) { @@ -384,11 +382,9 @@ bool FInViewCone(Vector* pOrigin, edict_t* pEdict) { if (flDot > 0.50f) // 60 degree field of view { - return TRUE; - } - else { - return FALSE; + return true; } + return false; } // FVisible() @@ -398,27 +394,25 @@ bool FVisible(const Vector& vecOrigin, edict_t* pEdict) { // look through caller's eyes const Vector vecLookerOrigin = pEdict->v.origin + pEdict->v.view_ofs; - const int bInWater = (UTIL_PointContents(vecOrigin) == CONTENTS_WATER); + const int bInWater = UTIL_PointContents(vecOrigin) == CONTENTS_WATER; const int bLookerInWater = - (UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER); + UTIL_PointContents(vecLookerOrigin) == CONTENTS_WATER; // don't look through water if (bInWater != bLookerInWater) - return FALSE; + return false; UTIL_TraceLine(vecLookerOrigin, vecOrigin, ignore_monsters, ignore_glass, pEdict, &tr); if (tr.flFraction != 1.0f) { - return FALSE; // Line of sight is not established - } - else { - return TRUE; // line of sight is valid. + return false; // Line of sight is not established } + return true; // line of sight is valid. } Vector GetGunPosition(edict_t* pEdict) { - return (pEdict->v.origin + pEdict->v.view_ofs); + return pEdict->v.origin + pEdict->v.view_ofs; } void UTIL_SelectItem(edict_t* pEdict, char* item_name) { @@ -459,12 +453,12 @@ void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { return; } - if ((arg1) && (*arg1) && (arg2) && (*arg2)) { + if (arg1 && *arg1 && arg2 && *arg2) { std::strcat(filename, arg1); std::strcat(filename, "/"); std::strcat(filename, arg2); } - else if ((arg1) && (*arg1)) { + else if (arg1 && *arg1) { std::strcat(filename, arg1); } } @@ -622,69 +616,73 @@ int UTIL_GiveWeaponType(int weapon_id) { // Return weapon ID (depended on mod) int UTIL_GiveWeaponId(const char* name) { if (mod_id == CSTRIKE_DLL) { - if (std::strcmp(name, "weapon_knife") == 0) + if (name != nullptr && std::strcmp(name, "weapon_knife") == 0) return CS_WEAPON_KNIFE; - if (std::strcmp(name, "weapon_c4") == 0) + if (name != nullptr && std::strcmp(name, "weapon_c4") == 0) return CS_WEAPON_C4; - if (std::strcmp(name, "weapon_mp5navy") == 0) + if (name != nullptr && std::strcmp(name, "weapon_mp5navy") == 0) return CS_WEAPON_MP5NAVY; - if (std::strcmp(name, "weapon_ak47") == 0) + if (name != nullptr && std::strcmp(name, "weapon_ak47") == 0) return CS_WEAPON_AK47; - if (std::strcmp(name, "weapon_m3") == 0) + if (name != nullptr && std::strcmp(name, "weapon_m3") == 0) return CS_WEAPON_M3; - if (std::strcmp(name, "weapon_aug") == 0) + if (name != nullptr && std::strcmp(name, "weapon_aug") == 0) return CS_WEAPON_AUG; - if (std::strcmp(name, "weapon_sg552") == 0) + if (name != nullptr && std::strcmp(name, "weapon_sg552") == 0) return CS_WEAPON_SG552; - if (std::strcmp(name, "weapon_m249") == 0) + if (name != nullptr && std::strcmp(name, "weapon_m249") == 0) return CS_WEAPON_M249; - if (std::strcmp(name, "weapon_xm1014") == 0) + if (name != nullptr && std::strcmp(name, "weapon_xm1014") == 0) return CS_WEAPON_XM1014; - if (std::strcmp(name, "weapon_p90") == 0) + if (name != nullptr && std::strcmp(name, "weapon_p90") == 0) return CS_WEAPON_P90; - if (std::strcmp(name, "weapon_tmp") == 0) + if (name != nullptr && std::strcmp(name, "weapon_tmp") == 0) return CS_WEAPON_TMP; - if (std::strcmp(name, "weapon_m4a1") == 0) + if (name != nullptr && std::strcmp(name, "weapon_m4a1") == 0) return CS_WEAPON_M4A1; - if (std::strcmp(name, "weapon_awp") == 0) + if (name != nullptr && std::strcmp(name, "weapon_awp") == 0) return CS_WEAPON_AWP; - if (std::strcmp(name, "weapon_fiveseven") == 0) + if (name != nullptr && std::strcmp(name, "weapon_fiveseven") == 0) return CS_WEAPON_FIVESEVEN; - if (std::strcmp(name, "weapon_ump45") == 0) + if (name != nullptr && std::strcmp(name, "weapon_ump45") == 0) return CS_WEAPON_UMP45; - if (std::strcmp(name, "weapon_sg550") == 0) + if (name != nullptr && std::strcmp(name, "weapon_sg550") == 0) return CS_WEAPON_SG550; - if (std::strcmp(name, "weapon_scout") == 0) + if (name != nullptr && std::strcmp(name, "weapon_scout") == 0) return CS_WEAPON_SCOUT; - if (std::strcmp(name, "weapon_mac10") == 0) + if (name != nullptr && std::strcmp(name, "weapon_mac10") == 0) return CS_WEAPON_MAC10; - if (std::strcmp(name, "weapon_g3sg1") == 0) + if (name != nullptr && std::strcmp(name, "weapon_g3sg1") == 0) return CS_WEAPON_G3SG1; - if (std::strcmp(name, "weapon_elite") == 0) + if (name != nullptr && std::strcmp(name, "weapon_elite") == 0) return CS_WEAPON_ELITE; - if (std::strcmp(name, "weapon_p228") == 0) + if (name != nullptr && std::strcmp(name, "weapon_p228") == 0) return CS_WEAPON_P228; - if (std::strcmp(name, "weapon_deagle") == 0) + if (name != nullptr && std::strcmp(name, "weapon_deagle") == 0) return CS_WEAPON_DEAGLE; - if (std::strcmp(name, "weapon_usp") == 0) + if (name != nullptr && std::strcmp(name, "weapon_usp") == 0) return CS_WEAPON_USP; - if (std::strcmp(name, "weapon_glock18") == 0) + if (name != nullptr && std::strcmp(name, "weapon_glock18") == 0) return CS_WEAPON_GLOCK18; // Counter-Strike 1.6 - if (std::strcmp(name, "weapon_famas") == 0) + if (name != nullptr && std::strcmp(name, "weapon_famas") == 0) return CS_WEAPON_FAMAS; - if (std::strcmp(name, "weapon_galil") == 0) + if (name != nullptr && std::strcmp(name, "weapon_galil") == 0) return CS_WEAPON_GALIL; - - // TODO: Detect shield carrying. + // 06/07/04 // Unconfirmed for handling shield // 31.08.04 Frashman: moved shield string before unknown weapon, not after it if (name != nullptr && std::strcmp(name, "weapon_shield") == 0) return CS_WEAPON_SHIELD; - + char buffer[80]; - _snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); + if (name != nullptr) { + snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); + } + else { + snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name (null)\n"); + } rblog(buffer); } @@ -697,86 +695,60 @@ char* UTIL_GiveWeaponName(int id) { switch (id) { case CS_WEAPON_C4: return "weapon_c4"; - break; case CS_WEAPON_MP5NAVY: return "weapon_mp5navy"; - break; case CS_WEAPON_AK47: return "weapon_ak47"; - break; case CS_WEAPON_M3: return "weapon_m3"; - break; case CS_WEAPON_AUG: return "weapon_aug"; - break; case CS_WEAPON_SG552: return "weapon_sg552"; - break; case CS_WEAPON_M249: return "weapon_m249"; - break; case CS_WEAPON_XM1014: return "weapon_xm1014"; - break; case CS_WEAPON_P90: return "weapon_p90"; - break; case CS_WEAPON_TMP: return "weapon_tmp"; - break; case CS_WEAPON_M4A1: return "weapon_m4a1"; - break; case CS_WEAPON_AWP: return "weapon_awp"; - break; case CS_WEAPON_FIVESEVEN: return "weapon_fiveseven"; - break; case CS_WEAPON_UMP45: return "weapon_ump45"; - break; case CS_WEAPON_SG550: return "weapon_ag550"; - break; case CS_WEAPON_SCOUT: return "weapon_scout"; - break; case CS_WEAPON_MAC10: return "weapon_mac10"; - break; case CS_WEAPON_G3SG1: return "weapon_g3sg1"; - break; case CS_WEAPON_ELITE: return "weapon_elite"; - break; case CS_WEAPON_P228: return "weapon_p228"; - break; case CS_WEAPON_DEAGLE: return "weapon_deagle"; - break; case CS_WEAPON_USP: return "weapon_usp"; - break; case CS_WEAPON_GLOCK18: return "weapon_glock18"; - break; - // Counter-Strike 1.6 + // Counter-Strike 1.6 case CS_WEAPON_FAMAS: return "weapon_famas"; - break; case CS_WEAPON_GALIL: return "weapon_galil"; - break; - // Unconfirmed shield + // Unconfirmed shield case CS_WEAPON_SHIELD: return "weapon_shield"; - break; } } @@ -844,10 +816,10 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { pBot->console_nr = 1; // Begin message // 02/07/04 - pointed out, eliminate any possible 'devide by zero' - int iExtra = (100 / (pBot->ipCreateRadio + 1)); + int iExtra = 100 / (pBot->ipCreateRadio + 1); if (iExtra > 30) iExtra = 30; - pBot->fDoRadio = gpGlobals->time + iExtra; + pBot->fDoRadio = gpGlobals->time + static_cast(iExtra); } } From 30cd4f144f66ebee1adfd703ebf504953ae4bcf1 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 13 Apr 2024 15:26:59 +0100 Subject: [PATCH 084/114] Reducing buffer overflows --- AMBuildScript | 10 ++ ChatEngine.cpp | 40 ++--- ChatEngine.h | 2 +- IniParser.cpp | 14 +- NodeDataTypes.h | 2 +- NodeMachine.cpp | 435 ++++++++++++++++++++++----------------------- NodeMachine.h | 4 +- bot.cpp | 81 ++++----- bot.h | 2 +- bot_buycode.cpp | 38 ++-- bot_client.cpp | 6 +- bot_func.cpp | 14 +- bot_func.h | 8 +- dll.cpp | 263 +++++++++++++-------------- engine.cpp | 27 +-- game.cpp | 33 ++-- game.h | 4 +- realbot_mm.vcxproj | 2 +- util.cpp | 27 ++- 19 files changed, 509 insertions(+), 503 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index 1151fc1..5ff7ea3 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -32,9 +32,19 @@ if builder.cxx.target.platform == 'linux': builder.cxx.defines += ['_LINUX', 'POSIX', 'LINUX', 'linux'] # Linux compiler C flags builder.cxx.cflags += [ + '-mtune=generic', '-pipe', '-fPIC', + '-mmmx', + '-msse', '-msse2', + '-msse3', + '-mssse3', + '-msse4', + '-msse4a', + '-msse4.1', + '-msse4.2', + '-mfpmath=sse', '-fno-strict-aliasing', '-Wall', '-Werror', diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 6e75f23..b0f5558 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -56,14 +56,15 @@ extern cBot bots[32]; void cChatEngine::init() { // clear all blocks - for (int iB = 0; iB < MAX_BLOCKS; iB++) { + for (tReplyBlock& iB : ReplyBlock) + { for (int iBs = 0; iBs < 50; iBs++) - ReplyBlock[iB].sentence[iBs][0] = '\0'; + iB.sentence[iBs][0] = '\0'; for (int iBw = 0; iBw < 10; iBw++) - ReplyBlock[iB].word[iBw][0] = '\0'; + iB.word[iBw][0] = '\0'; - ReplyBlock[iB].bUsed = false; + iB.bUsed = false; } iLastBlock = -1; @@ -101,10 +102,7 @@ void cChatEngine::think() { edict_t *pPlayer = INDEXENT(i); if (pPlayer && !pPlayer->free) { - char name[30], name2[30]; - // clear - std::memset(name, 0, sizeof(name)); - std::memset(name2, 0, sizeof(name2)); + char name[30] = {}, name2[30] = {}; // copy std::strcpy(name, STRING(pPlayer->v.netname)); @@ -119,9 +117,8 @@ void cChatEngine::think() { // Edict pointer established // Scan the message so we know in what block we should be to reply: - char word[20]; - std::memset(word, 0, sizeof(word)); - + char word[20] = {}; + int c = 0; int wc = 0; @@ -144,8 +141,9 @@ void cChatEngine::think() { int WordBlockScore[MAX_BLOCKS]; // Init, none of the block has a score yet (set to -1) - for (int wbs = 0; wbs < MAX_BLOCKS; wbs++) { - WordBlockScore[wbs] = -1; + for (int& wbs : WordBlockScore) + { + wbs = -1; } // loop over the sentence character by character @@ -174,17 +172,18 @@ void cChatEngine::think() { } else { for (int iB = 0; iB < MAX_BLOCKS; iB++) { if (ReplyBlock[iB].bUsed) { - for (int iBw = 0; iBw < 10; iBw++) { + for (char (&iBw)[25] : ReplyBlock[iB].word) + { // skip any word in the reply block that is not valid - if (ReplyBlock[iB].word[iBw][0] == '\0') + if (iBw[0] == '\0') continue; // not filled in - if (std::strlen(ReplyBlock[iB].word[iBw]) <= 0) + if (std::strlen(iBw) <= 0) continue; // not long enough (a space?) // 03/07/04 // add score to matching word (evy: ignoring case) - if (std::strcmp(ReplyBlock[iB].word[iBw], word) == 0) + if (std::strcmp(iBw, word) == 0) WordBlockScore[iB]++; } // all words in this block } // any used block @@ -231,9 +230,10 @@ void cChatEngine::think() { int iMax = -1; // now choose a sentence to reply with - for (int iS = 0; iS < 50; iS++) { + for (char (&iS)[128] : ReplyBlock[iTheBlock].sentence) + { // Find max sentences of this reply block - if (ReplyBlock[iTheBlock].sentence[iS][0] != '\0') + if (iS[0] != '\0') iMax++; } @@ -339,7 +339,7 @@ void cChatEngine::think() { // terminate temp[tc] = '\n'; - std::sprintf(chSentence, "%s \n", temp); + snprintf(chSentence, sizeof(chSentence), "%s \n", temp); } // when no name pos is found, we just copy the string and say that (works ok) else diff --git a/ChatEngine.h b/ChatEngine.h index 973b120..8f5eabf 100644 --- a/ChatEngine.h +++ b/ChatEngine.h @@ -34,7 +34,7 @@ #define MAX_BLOCKS 100 #define BLOCK_DEATHS (MAX_BLOCKS-1) -static const int MAX_SENTENCE_LENGTH = 128; +static constexpr int MAX_SENTENCE_LENGTH = 128; // Reply block typedef struct { // words, hinting that in this block a logical sentence will be to reply with diff --git a/IniParser.cpp b/IniParser.cpp index b3a6f79..73f5e87 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -401,8 +401,8 @@ int INI_WordValueINT(char result[80]) { char number[10]; // clear out entire string - for (int i = 0; i < 10; i++) - number[i] = '\0'; + for (char& i : number) + i = '\0'; // Copy the part to 'number', Make sure we won't get outside the array of the character. int cp = is_pos + 1; @@ -462,8 +462,8 @@ float INI_WordValueFLOAT(char result[80]) { char number[10]; // clear out entire string - for (int i = 0; i < 10; i++) - number[i] = '\0'; + for (char& i : number) + i = '\0'; // Copy the part to 'number', Make sure we won't get outside the array of the character. int cp = is_pos + 1; @@ -613,8 +613,7 @@ void INI_PARSE_CHATFILE() { iBlockWord = 9; // write the word in the block - char chWord[25]; - std::memset(chWord, 0, sizeof(chWord)); + char chWord[25] = {}; INI_WordValueCHAR(linefeed, chWord); // lower case //chWord = _strlwr( _strdup( chWord ) ); @@ -644,8 +643,7 @@ void INI_PARSE_CHATFILE() { iBlockSentence = 49; // write the word in the block - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); + char chSentence[80] = {}; INI_WordValueCHAR(linefeed, chSentence); std::strcpy(ChatEngine.ReplyBlock[iBlockId]. sentence[iBlockSentence], chSentence); diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 93253b1..4613ca0 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -121,7 +121,7 @@ #define CLOSED 2 // closed, do nothing with it #define AVAILABLE 3 // available, may open -const unsigned long g_iMaxVisibilityByte = MAX_NODES * MAX_NODES / 8; +constexpr unsigned long g_iMaxVisibilityByte = MAX_NODES * MAX_NODES / 8; // doors (doors.cpp) HLSDK #define SF_DOOR_ROTATE_Y 0 diff --git a/NodeMachine.cpp b/NodeMachine.cpp index db47a2a..525a0b1 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -51,6 +51,8 @@ #include "NodeMachine.h" +#include + tNodestar astar_list[MAX_NODES]; const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); @@ -145,23 +147,25 @@ void cNodeMachine::init() { for (int i = 0; i < MAX_NODES; i++) { // --- nodes Nodes[i].origin = Vector(9999, 9999, 9999); - for (int n = 0; n < MAX_NEIGHBOURS; n++) - Nodes[i].iNeighbour[n] = -1; + for (int& n : Nodes[i].iNeighbour) + n = -1; // No bits set Nodes[i].iNodeBits = 0; // --- info nodes - for (int d = 0; d < 2; d++) { - InfoNodes[i].fDanger[d] = 0.0f; + for (float& d : InfoNodes[i].fDanger) + { + d = 0.0f; } } // Init trouble - for (int t = 0; t < MAX_TROUBLE; t++) { - Troubles[t].iFrom = -1; - Troubles[t].iTo = -1; - Troubles[t].iTries = -1; + for (tTrouble& Trouble : Troubles) + { + Trouble.iFrom = -1; + Trouble.iTo = -1; + Trouble.iTries = -1; } initGoals(); @@ -171,12 +175,13 @@ void cNodeMachine::init() { path_clear(p); // Init VisTable - for (int iVx = 0; iVx < MAX_NODES; iVx++) { - iVisChecked[iVx] = 0; // not checked yet + for (unsigned char& iVx : iVisChecked) + { + iVx = 0; // not checked yet } // CODE: From cheesemonster - const unsigned long iSize = g_iMaxVisibilityByte; + constexpr unsigned long iSize = g_iMaxVisibilityByte; //create a heap type thing... FreeVisibilityTable(); // 16/07/04 - free it first @@ -192,10 +197,10 @@ void cNodeMachine::init() { // END: // Init Meredians - for (int iMx = 0; iMx < MAX_MEREDIANS; iMx++) - for (int iMy = 0; iMy < MAX_MEREDIANS; iMy++) + for (tMeredian (&Meredian)[64] : Meredians) + for (int iMy = 0; iMy < MAX_MEREDIANS; iMy++) for (int iNode = 0; iNode < MAX_NODES_IN_MEREDIANS; iNode++) - Meredians[iMx][iMy].iNodes[iNode] = -1; + Meredian[iMy].iNodes[iNode] = -1; rblog("cNodeMachine::init() - END\n"); } @@ -234,9 +239,8 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const for (int index = 0; index < MAX_TROUBLE; index++) { if (Troubles[index].iFrom == iFrom && Troubles[index].iTo == iTo) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); rblog(msg); // found troubled connection, return its index return index; @@ -290,7 +294,7 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) const const tTrouble &trouble = Troubles[index]; char msg[255]; - std::sprintf(msg, "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); + snprintf(msg, sizeof(msg), "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); if (trouble.iTries > 2) { @@ -333,29 +337,28 @@ void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) { if (index < 0 || index >= MAX_TROUBLE) return; - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Increasing trouble for connection [%d]\n", index); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "(trouble) IncreaseAttemptsForTroubledConnection | Increasing trouble for connection [%d]\n", index); rblog(msg); Troubles[index].iTries++; const tTrouble &trouble = Troubles[index]; std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "(trouble) IncreaseAttemptsForTroubledConnection | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); + snprintf(msg, sizeof(msg), "(trouble) IncreaseAttemptsForTroubledConnection | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); } bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) { char msg[255]; - std::sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); + snprintf(msg, sizeof(msg), "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); rblog(msg); const int index = GetTroubleIndexForConnection(iFrom, iTo); std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d has index %d\n", iFrom, iTo, index); + snprintf(msg, sizeof(msg), "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d has index %d\n", iFrom, iTo, index); rblog(msg); if (index < 0) { @@ -521,10 +524,11 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE int iCloseNode = -1; // Search in this meredian - for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) { - if (Meredians[iX][iY].iNodes[i] < 0) continue; // skip invalid node indexes + for (const int i : Meredians[iX][iY].iNodes) + { + if (i < 0) continue; // skip invalid node indexes - const int iNode = Meredians[iX][iY].iNodes[i]; + const int iNode = i; //if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us @@ -582,10 +586,11 @@ int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, const edic int iFarNode = -1; // Search in this meredian - for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) { - if (Meredians[iX][iY].iNodes[i] < 0) continue; // skip invalid node indexes + for (const int i : Meredians[iX][iY].iNodes) + { + if (i < 0) continue; // skip invalid node indexes - const int iNode = Meredians[iX][iY].iNodes[i]; + const int iNode = i; // if (Nodes[iNode].origin.z > (vOrigin.z + 32)) continue; // do not pick nodes higher than us @@ -647,12 +652,11 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { return false; } - char msg[255]; - std::memset(msg, 0, sizeof(msg)); + char msg[255] = {}; tNode *node = getNode(iFrom); if (!node) { - std::sprintf(msg, "(trouble) cNodeMachine::removeConnection | From %d, to %d has no node! (error)\n", iFrom, iTo); + snprintf(msg, sizeof(msg), "(trouble) cNodeMachine::removeConnection | From %d, to %d has no node! (error)\n", iFrom, iTo); rblog(msg); return false; } @@ -662,7 +666,7 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { for (int i = 0; i < MAX_NEIGHBOURS; i++) { const int neighbourNode = node->iNeighbour[i]; - std::sprintf(msg, + snprintf(msg, sizeof(msg), "(trouble) removeConnection(from->%d, to->%d), evaluating neighbour [%d] = node %d\n", iFrom, iTo, @@ -690,8 +694,8 @@ bool cNodeMachine::remove_neighbour_nodes(int iNode) { if (iNode < 0) return false; - for (int i = 0; i < MAX_NEIGHBOURS; i++) - Nodes[iNode].iNeighbour[i] = -1; + for (int& i : Nodes[iNode].iNeighbour) + i = -1; return true; } @@ -971,7 +975,7 @@ int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { // When walking the human player can't pass a certain speed and distance // however, when a human is falling, the distance will be bigger. - const int maxDistance = 3 * NODE_ZONE; + constexpr int maxDistance = 3 * NODE_ZONE; if (horizontal_distance(Nodes[newNodeIndex].origin, Nodes[j].origin) > maxDistance) continue; @@ -1212,7 +1216,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { && (bNeighbourWater == false && bIsInWater == false) && Nodes[currentIndex].origin.z >= Nodes[nodeIndex].origin.z) { char msg[80]; - std::sprintf(msg, "J.Z = %f, INDEX.Z = %f\n", Nodes[nodeIndex].origin.z, + snprintf(msg, sizeof(msg), "J.Z = %f, INDEX.Z = %f\n", Nodes[nodeIndex].origin.z, Nodes[currentIndex].origin.z); // UTIL_ClientPrintAll( HUD_PRINTNOTIFY, msg); bCanConnect = false; // cannot connect @@ -1256,9 +1260,10 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // Players initialization void cNodeMachine::init_players() { - for (int i = 0; i < 32; i++) { - Players[i].vPrevPos = Vector(9999, 9999, 9999); - Players[i].iNode = -1; + for (tPlayer& Player : Players) + { + Player.vPrevPos = Vector(9999, 9999, 9999); + Player.iNode = -1; } } @@ -1278,9 +1283,9 @@ void cNodeMachine::init_round() { path_clear(p); // decrease bad score for bad goal nodes - for (int g = 0; g < MAX_GOALS; g++) - if (Goals[g].iBadScore > 0) - Goals[g].iBadScore--; + for (tGoal& Goal : Goals) + if (Goal.iBadScore > 0) + Goal.iBadScore--; } /** @@ -1310,30 +1315,29 @@ void cNodeMachine::addNodesForPlayers() { void cNodeMachine::connections(edict_t *pEntity) const { int closeNode; - char msg[75]; - std::memset(msg, 0, sizeof(msg)); + char msg[75] = {}; if (draw_nodepath > -1 && draw_nodepath < 32) { cBot botPointer = bots[draw_nodepath]; if (botPointer.bIsUsed) { closeNode = botPointer.determineCurrentNodeWithTwoAttempts(); if (closeNode > -1) { const Vector &vector = Nodes[closeNode].origin; - std::sprintf(msg, "Bot [%s|%d] is at node %d (%f,%f,%f)\n", botPointer.name, draw_nodepath, closeNode, vector.x, vector.y, vector.z); + snprintf(msg, sizeof(msg), "Bot [%s|%d] is at node %d (%f,%f,%f)\n", botPointer.name, draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { - std::sprintf(msg, "Bot [%s|%d] is at node %d\n", botPointer.name, draw_nodepath, closeNode); + snprintf(msg, sizeof(msg), "Bot [%s|%d] is at node %d\n", botPointer.name, draw_nodepath, closeNode); } } else { closeNode = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); if (closeNode > -1) { const Vector &vector = Nodes[closeNode].origin; - std::sprintf(msg, "No bot used for slot [%d], YOU are at node %d (%f,%f,%f)\n", draw_nodepath, closeNode, vector.x, vector.y, vector.z); + snprintf(msg, sizeof(msg), "No bot used for slot [%d], YOU are at node %d (%f,%f,%f)\n", draw_nodepath, closeNode, vector.x, vector.y, vector.z); } else { - std::sprintf(msg, "No bot used for slot [%d], YOU are at node %d\n", draw_nodepath, closeNode); + snprintf(msg, sizeof(msg), "No bot used for slot [%d], YOU are at node %d\n", draw_nodepath, closeNode); } } } else { closeNode = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); - std::sprintf(msg, "YOU are at node %d\n", closeNode); + snprintf(msg, sizeof(msg), "YOU are at node %d\n", closeNode); } CenterMessage(msg); @@ -1392,10 +1396,11 @@ void cNodeMachine::draw(edict_t* pEntity) const // Declare 'start' vector outside the loop Vector start; - for (int i = 0; i < MAX_NODES; i++) { - if (Nodes[i].origin != Vector(9999, 9999, 9999)) { - start = Nodes[i].origin - Vector(0, 0, 36); - Vector end = Nodes[i].origin; + for (const tNode& Node : Nodes) + { + if (Node.origin != Vector(9999, 9999, 9999)) { + start = Node.origin - Vector(0, 0, 36); + Vector end = Node.origin; const bool good = VectorIsVisibleWithEdict(pEntity, end, "none"); @@ -1409,22 +1414,22 @@ void cNodeMachine::draw(edict_t* pEntity) const // l = 250; // Normally light is 250 - if (Nodes[i].iNodeBits & BIT_LADDER) + if (Node.iNodeBits & BIT_LADDER) b = g = 0; - if (Nodes[i].iNodeBits & BIT_WATER) + if (Node.iNodeBits & BIT_WATER) r = g = 0; - if (Nodes[i].iNodeBits & BIT_DUCK) + if (Node.iNodeBits & BIT_DUCK) r = b = 50; // Jump and DuckJump were missing for those nodes? [APG]RoboCop[CL] - if (Nodes[i].iNodeBits & BIT_JUMP) + if (Node.iNodeBits & BIT_JUMP) r = b = 100; - if (Nodes[i].iNodeBits & BIT_DUCKJUMP) + if (Node.iNodeBits & BIT_DUCKJUMP) r = b = 150; - if (Nodes[i].iNeighbour[0] < 0) + if (Node.iNeighbour[0] < 0) r = 0; if (max_drawn < 39) { @@ -1436,9 +1441,9 @@ void cNodeMachine::draw(edict_t* pEntity) const } const int iNodeClose = getClosestNode(pEntity->v.origin, NODE_ZONE, pEntity); - if (iNodeClose >= static_cast(sizeof(Nodes) / sizeof(Nodes[0]))) { + if (iNodeClose >= static_cast(std::size(Nodes))) { char msg[50]; - std::sprintf(msg, "Node %d\nMe: (%.0f,%.0f,%.0f)\n", iNodeClose, + snprintf(msg, sizeof(msg), "Node %d\nMe: (%.0f,%.0f,%.0f)\n", iNodeClose, pEntity->v.origin.x, pEntity->v.origin.y, pEntity->v.origin.z); CenterMessage(msg); @@ -1450,23 +1455,21 @@ void cNodeMachine::draw(edict_t* pEntity) const Flags[0] = 0; - if (Nodes[iNodeClose].iNodeBits & BIT_LADDER) - std::strcat(Flags, "L"); - - if (Nodes[iNodeClose].iNodeBits & BIT_WATER) - std::strcat(Flags, "W"); - - if (Nodes[iNodeClose].iNodeBits & BIT_JUMP) - std::strcat(Flags, "J"); - - if (Nodes[iNodeClose].iNodeBits & BIT_DUCK) - std::strcat(Flags, "D"); - - // Experimental DuckJump added for this new node [APG]RoboCop[CL] - if (Nodes[iNodeClose].iNodeBits & BIT_DUCKJUMP) - std::strcat(Flags, "h"); - - std::sprintf(msg, "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", + if (iNodeClose >= 0) + { + if (Nodes[iNodeClose].iNodeBits & BIT_LADDER) + std::strcat(Flags, "L"); + if (Nodes[iNodeClose].iNodeBits & BIT_WATER) + std::strcat(Flags, "W"); + if (Nodes[iNodeClose].iNodeBits & BIT_JUMP) + std::strcat(Flags, "J"); + if (Nodes[iNodeClose].iNodeBits & BIT_DUCK) + std::strcat(Flags, "D"); + // Experimental DuckJump added for this new node [APG]RoboCop[CL] + if (Nodes[iNodeClose].iNodeBits & BIT_DUCKJUMP) + std::strcat(Flags, "h"); + } + snprintf(msg, sizeof(msg), "Node %d(%.0f,%.0f,%.0f)%s\nMe: (%.0f,%.0f,%.0f)\n", iNodeClose, iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.x, iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.y, iNodeClose < 0 ? -1 : Nodes[iNodeClose].origin.z, Flags, @@ -1491,12 +1494,18 @@ void cNodeMachine::experience_save() { FILE* rbl = std::fopen(filename, "wb"); if (rbl != nullptr) { - const int iVersion = FILE_EXP_VER2; + constexpr int iVersion = FILE_EXP_VER2; std::fwrite(&iVersion, sizeof(int), 1, rbl); - //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] + struct Node { + Vector fDanger[2]; + Vector fContact[2]; + }; + + //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (int i = 0; i < MAX_NODES; i++) { - std::fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + Node InfoNodes[MAX_NODES]; + std::fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); std::fwrite(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); std::fwrite(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); @@ -1566,7 +1575,14 @@ void cNodeMachine::experience_load() { int iVersion = FILE_EXP_VER1; std::fread(&iVersion, sizeof(int), 1, rbl); + struct Node { + Vector fDanger[2]; + Vector fContact[2]; + }; + Node InfoNodes[MAX_NODES]; + if (iVersion == FILE_EXP_VER1) { + //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { std::fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); @@ -1657,15 +1673,16 @@ void cNodeMachine::save() const if (rbl != nullptr) { // Write down version number - const int iVersion = FILE_NODE_VER1; + constexpr int iVersion = FILE_NODE_VER1; std::fwrite(&iVersion, sizeof(int), 1, rbl); - for (int i = 0; i < MAX_NODES; i++) { - std::fwrite(&Nodes[i].origin, sizeof(Vector), 1, rbl); + for (const tNode& Node : Nodes) + { + std::fwrite(&Node.origin, sizeof(Vector), 1, rbl); for (int n = 0; n < MAX_NEIGHBOURS; n++) - std::fwrite(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + std::fwrite(&Node.iNeighbour[n], sizeof(int), 1, rbl); // save bit flags - std::fwrite(&Nodes[i].iNodeBits, sizeof(int), 1, rbl); + std::fwrite(&Node.iNodeBits, sizeof(int), 1, rbl); } std::fclose(rbl); } else @@ -1693,11 +1710,12 @@ void cNodeMachine::save_important() const "; RealBot : Important Area Definition file\n; Do not hand-edit, this is _not_ an editable ini file!\n;\n\n"); // save important areas: - for (int iGn = 0; iGn < MAX_GOALS; iGn++) { - if (Goals[iGn].iType == GOAL_IMPORTANT) { + for (const tGoal& Goal : Goals) + { + if (Goal.iType == GOAL_IMPORTANT) { // save this area std::fprintf(rbl, "[AREA]\n"); - const Vector iGoalVector = node_vector(Goals[iGn].iNode); + const Vector iGoalVector = node_vector(Goal.iNode); std::fprintf(rbl, "X=%f\n", iGoalVector.x); std::fprintf(rbl, "Y=%f\n", iGoalVector.y); std::fprintf(rbl, "Z=%f\n\n", iGoalVector.z); @@ -1735,8 +1753,9 @@ void cNodeMachine::load() { if (iVersion == FILE_NODE_VER1) { for (i = 0; i < MAX_NODES; i++) { std::fread(&Nodes[i].origin, sizeof(Vector), 1, rbl); - for (int n = 0; n < MAX_NEIGHBOURS; n++) { - std::fread(&Nodes[i].iNeighbour[n], sizeof(int), 1, rbl); + for (int& n : Nodes[i].iNeighbour) + { + std::fread(&n, sizeof(int), 1, rbl); } // save bit flags @@ -1764,7 +1783,7 @@ void cNodeMachine::load() { rblog("!!! Nodes table is full\n"); char msg[80]; - std::sprintf(msg, "After NodeMachine::load iMaxUsedNodes=%d\n", + snprintf(msg, sizeof(msg), "After NodeMachine::load iMaxUsedNodes=%d\n", iMaxUsedNodes); rblog(msg); SERVER_PRINT("Going to load IAD file : "); @@ -1777,12 +1796,13 @@ void cNodeMachine::load() { } void cNodeMachine::ClearImportantGoals() { - for (int iGn = 0; iGn < MAX_GOALS; iGn++) { - if (Goals[iGn].iType == GOAL_IMPORTANT && Goals[iGn].iNode > -1) { - Goals[iGn].iType = -1; - Goals[iGn].iNode = -1; - Goals[iGn].pGoalEdict = nullptr; - std::memset(Goals[iGn].name, 0, sizeof(Goals[iGn].name)); + for (tGoal& Goal : Goals) + { + if (Goal.iType == GOAL_IMPORTANT && Goal.iNode > -1) { + Goal.iType = -1; + Goal.iNode = -1; + Goal.pGoalEdict = nullptr; + std::memset(Goal.name, 0, sizeof(Goal.name)); } } } @@ -1813,7 +1833,7 @@ void cNodeMachine::path_draw(edict_t* pEntity) const FUNC_InFieldOfView(pEntity, end - pEntity->v.origin); if (max_drawn < 39 && good && angle_to_waypoint < 50) { - const int red = 255; + constexpr int red = 255; int green = 0; int blue = 255; int width = 15; @@ -1969,9 +1989,8 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { goal->iType = goalType; //strcpy(goal->name, getGoalTypeAsText(*goal)); //That appears to trigger crash [APG]RoboCop[CL] - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Adding goal at index %d of type %s, with nearby node %d\n", index, goal->name, nNode); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Adding goal at index %d of type %s, with nearby node %d\n", index, goal->name, nNode); rblog(msg); } @@ -2013,8 +2032,9 @@ bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const { if (pEdict == nullptr) return false; // no edict == by default no - for (int g = 0; g < MAX_GOALS; g++) { - if (Goals[g].pGoalEdict == pEdict) { + for (const tGoal& Goal : Goals) + { + if (Goal.pGoalEdict == pEdict) { return true; } } @@ -2024,18 +2044,19 @@ bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const } void cNodeMachine::resetCheckedValuesForGoals() { - for (int g = 0; g < MAX_GOALS; g++) { - if (Goals[g].iChecked > 0) - Goals[g].iChecked = 0; + for (tGoal& Goal : Goals) + { + if (Goal.iChecked > 0) + Goal.iChecked = 0; } } // returns goal type from node, -1 for unknown int cNodeMachine::getGoalIndexFromNode(int iNode) const { - for (int g = 0; g < MAX_GOALS; g++) - if (Goals[g].iNode == iNode) - return Goals[g].iType; + for (const tGoal& Goal : Goals) + if (Goal.iNode == iNode) + return Goal.iType; return -1; } @@ -2167,8 +2188,9 @@ tGoal* cNodeMachine::getRandomGoalByType(int goalType) { return nullptr; int possibleGoalNodes[MAX_GOALS]; - for (int c = 0; c < MAX_GOALS; c++) { - possibleGoalNodes[c] = -1; + for (int& possibleGoalNode : possibleGoalNodes) + { + possibleGoalNode = -1; } int possibleCandidateIndex = 0; @@ -2188,7 +2210,7 @@ tGoal* cNodeMachine::getRandomGoalByType(int goalType) { const int randomGoalIndex = RANDOM_LONG(0, possibleCandidateIndex - 1); char msg[255]; - std::sprintf(msg, "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", + snprintf(msg, sizeof(msg), "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", possibleCandidateIndex, goalType, randomGoalIndex); rblog(msg); @@ -2260,9 +2282,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // Will create a path from nodeStartIndex to nodeTargetIndex, and store it into index number iPathId if (pBot) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "createPath(from->%d, to->%d, botIndex->%d)", nodeStartIndex, nodeTargetIndex, botIndex); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "createPath(from->%d, to->%d, botIndex->%d)", nodeStartIndex, nodeTargetIndex, botIndex); pBot->rprint("cNodeMachine::createPath", msg); } @@ -2293,7 +2314,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn makeAllWaypointsAvailable(); // Our start waypoint is open - const float gCost = 0.0f; // distance from starting node + constexpr float gCost = 0.0f; // distance from starting node const float hCost = func_distance(Nodes[nodeStartIndex].origin, Nodes[nodeTargetIndex].origin); // distance from end node to node const float cost = gCost + hCost; @@ -2424,9 +2445,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // print out full path so we know what the order is if (pBot != nullptr) { - char pathMsg[255]; - std::memset(pathMsg, 0, sizeof(pathMsg)); - std::sprintf(pathMsg, "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); + char pathMsg[255] = {}; + snprintf(pathMsg, sizeof(pathMsg), "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); pBot->rprint("cNodeMachine::createPath", pathMsg); } @@ -2481,9 +2501,9 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou const tNode &node = Nodes[nodeToOpenNeighboursFrom]; // node evaluating neighbours - for (int i = 0; i < MAX_NEIGHBOURS; i++) { - const int neighbourNode = node.iNeighbour[i]; - if (neighbourNode < 0) continue; // skip invalid nodes + for (int neighbourNode : node.iNeighbour) + { + if (neighbourNode < 0) continue; // skip invalid nodes if (Nodes[neighbourNode].origin == INVALID_VECTOR) continue; // skip nodes with invalid vector const float gCost = func_distance(startNode.origin, destNode.origin); // distance from starting node @@ -2526,10 +2546,11 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou */ void cNodeMachine::makeAllWaypointsAvailable() { - for (int nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { - astar_list[nodeIndex].cost = 0; - astar_list[nodeIndex].parent = -1; - astar_list[nodeIndex].state = AVAILABLE; + for (tNodestar& nodeIndex : astar_list) + { + nodeIndex.cost = 0; + nodeIndex.parent = -1; + nodeIndex.state = AVAILABLE; } // rblog("All nodes set to AVAILABLE\n"); } @@ -2552,9 +2573,9 @@ int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const float fDistance = 9999.0f; float fDanger = 2.0f; // Search in this meredian - for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) - if (Meredians[iX][iY].iNodes[i] > -1) { - const int iNode = Meredians[iX][iY].iNodes[i]; + for (const int i : Meredians[iX][iY].iNodes) + if (i > -1) { + const int iNode = i; if (Nodes[iNode].iNodeBits & BIT_WATER) continue; // next node, do not camp under water! @@ -2592,7 +2613,7 @@ void cNodeMachine::vis_calculate(int iFrom) { for (int i = 0; i < MAX_NODES; i++) if (i != iFrom && Nodes[i].origin != Vector(9999, 9999, 9999)) { - const float fClosest = 1024.0f; + constexpr float fClosest = 1024.0f; const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); if (fDistance < fClosest) { TraceResult tr; @@ -2667,7 +2688,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, } } char msg[255]; - std::sprintf(msg, "Found best node to camp at %d\n", iBestNode); + snprintf(msg, sizeof(msg), "Found best node to camp at %d\n", iBestNode); rblog(msg); return iBestNode; } @@ -2836,7 +2857,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { tGoal *goalData = pBot->getGoalData(); if (goalData) { char msg[255]; - std::sprintf(msg, "Heading for goal node of type [%s]", goalData->name); + snprintf(msg, sizeof(msg), "Heading for goal node of type [%s]", goalData->name); pBot->rprint_trace("cNodeMachine::path_walk (bNear)", msg); if (goalData->iType == GOAL_HOSTAGE) { pBot->rprint_normal("cNodeMachine::path_walk (bNear)", "next node is destination and GOAL_HOSTAGE, so need to get really close"); @@ -2852,7 +2873,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } char msg[255]; - std::sprintf(msg, "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", + snprintf(msg, sizeof(msg), "Heading for node %d, required distance is %f, actual distance is %f, time remaining %f", pBot->getCurrentPathNodeToHeadFor(), requiredDistance, pBot->getDistanceToNextNode(), pBot->getMoveToNodeTimeRemaining()); pBot->rprint_trace("cNodeMachine::path_walk (bNear)", msg); @@ -2938,7 +2959,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { !isEntityWorldspawn(pEntityHit)) // and it is not worldspawn (ie, the map itself) { char msg[255]; - std::sprintf(msg, "Entity [%s] between me and next node.", STRING(pEntityHit->v.classname)); + snprintf(msg, sizeof(msg), "Entity [%s] between me and next node.", STRING(pEntityHit->v.classname)); pBot->rprint_trace("cNodeMachine::path_walk", msg); // hit by a door? @@ -2973,10 +2994,10 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { // - unstuck // - go back in path... - const float timeEvaluatingMoveSpeed = 0.1f; + constexpr float timeEvaluatingMoveSpeed = 0.1f; const bool notStuckForAWhile = pBot->fNotStuckTime + timeEvaluatingMoveSpeed < gpGlobals->time; - const double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. + constexpr double fraction = 0.7; // 0.7 is an arbitrary number based on several tests to consider stuck at a more sane moment. // Else it would trigger stuck logic too soon, too often. const double speedInOneTenthOfASecond = static_cast(pBot->f_move_speed * timeEvaluatingMoveSpeed) * fraction; @@ -2987,10 +3008,9 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { if (pBot->isJumping()) expectedMoveDistance = speedInOneTenthOfASecond / 3.0; // no need for 'is walking' because walking time influence `f_move_speed` hence it is already taken care of - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, - expectedMoveDistance, notStuckForAWhile); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Distance moved %f, expected %f, should be able to move yes, notStuck for a while %d", distanceMoved, + expectedMoveDistance, notStuckForAWhile); pBot->rprint_trace("cNodeMachine::path_walk", msg); const bool isStuck = distanceMoved < expectedMoveDistance && pBot->shouldBeAbleToMove() && notStuckForAWhile; // also did not evaluate this logic for 0.5 second @@ -3063,10 +3083,9 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "No need to duck or to jump"); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); + char msg[255] = {}; const float timeRemaining = pBot->getMoveToNodeTimeRemaining(); - std::sprintf(msg, "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); + snprintf(msg, sizeof(msg), "I still have %f seconds to go to node before considered 'stuck' for connection", timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); const cBot *pBotStuck = getCloseFellowBot(pBot); @@ -3089,7 +3108,7 @@ void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, con } std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", + snprintf(msg, sizeof(msg), "Player in FOV? %d, hostage in FOV? %d bot close ? %d, time remaining? %f", playerNearbyInFOV != nullptr, hostageNearbyInFOV != nullptr, pBotStuck != nullptr, timeRemaining); pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", msg); @@ -3206,8 +3225,7 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { if (!isHeadingForGoalNode) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); + char msg[255] = {}; const int currentPathNode = pBot->getCurrentPathNodeToHeadFor(); @@ -3215,12 +3233,12 @@ void cNodeMachine::ExecuteNearNodeLogic(cBot *pBot) { const int troubleIndex = GetTroubleIndexForConnection(pBot->getPreviousPathNodeToHeadFor(), currentNodeToHeadFor); if (troubleIndex > -1) { const tTrouble &trouble = Troubles[troubleIndex]; - std::sprintf(msg, "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); + snprintf(msg, sizeof(msg), "Heading to next node: %d, trouble (tries) %d", currentPathNode, trouble.iTries); } else { - std::sprintf(msg, "Heading to next node: %d - with no trouble", currentPathNode); + snprintf(msg, sizeof(msg), "Heading to next node: %d - with no trouble", currentPathNode); } } else { - std::sprintf(msg, "Heading to next node: %d", currentPathNode); + snprintf(msg, sizeof(msg), "Heading to next node: %d", currentPathNode); } pBot->rprint("cNodeMachine::path_walk()", msg); } @@ -3435,8 +3453,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { int iFinalGoalNode = -1; int iFinalGoalIndex = -1; - const float MAX_DISTANCE = 16384.0f; // theoretical max distance - const float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0f; + constexpr float MAX_DISTANCE = 16384.0f; // theoretical max distance + constexpr float MAX_GOAL_DISTANCE = MAX_DISTANCE / 2.0f; // 01-07-2008; Instead of using 'scores', use a normalized score. // We do: @@ -3446,7 +3464,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->rprint_normal("cNodeMachine::path_think", "going to choose goal"); for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { - const int maxCheckedScore = 5; + constexpr int maxCheckedScore = 5; // Make sure this goal is valid if (Goals[goalIndex].iNode < 0) { @@ -3482,9 +3500,10 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { float goalAlreadyUsedScore = 0.0f; float teamMembers = 1.0f; // count self by default - for (int botIndex = 0; botIndex < MAX_BOTS; botIndex++) { + for (cBot& bot : bots) + { // not a bot - const cBot* botPointer = &bots[botIndex]; + const cBot* botPointer = ⊥ if (!botPointer->bIsUsed || botPointer == pBot) { // skip self continue; @@ -3574,9 +3593,8 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { if (Game.bBombPlanted) { if (Game.isPlantedC4Discovered()) { pBot->rprint_trace("path_think/determine goal", "I know where the C4 is planted, evaluating if this is the closest bombspot."); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "C4 is located at %f, %f, %f", Game.vPlantedC4.x, Game.vPlantedC4.y, Game.vPlantedC4.z); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "C4 is located at %f, %f, %f", Game.vPlantedC4.x, Game.vPlantedC4.y, Game.vPlantedC4.z); pBot->rprint_trace("path_think/determine goal", msg); // find a node close to the C4 @@ -3597,7 +3615,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { const float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; goalscore = 1.5f + score; std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", + snprintf(msg, sizeof(msg), "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", distanceToC4FromCloseNode, distanceToC4FromThisGoalNode, goalscore); @@ -3646,7 +3664,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } else { score = 0; // don't care about VIP // if distance is too big, go to it. (guard the VIP) - const int maxDistanceWeKeepToVIP = 500; + constexpr int maxDistanceWeKeepToVIP = 500; const float goalScore = maxDistanceWeKeepToVIP / fDistanceToGoal; score = (score + goalScore) / 2.0f; } @@ -3686,12 +3704,9 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { // even though its float comparison, it can h appen since we hard-set it to 2.0 at some places, making // some scores the same - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Evaluating goal %s gives a score of %f, highest score so far is %f", - Goals[goalIndex].name, - score, - highestScore); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Evaluating goal %s gives a score of %f, highest score so far is %f", + Goals[goalIndex].name, score, highestScore); pBot->rprint_trace("path_think/determine goal", msg); if (score == highestScore && RANDOM_LONG(0,100) < 50) { pBot->rprint_trace("path_think/determine goal", "SCORE == HIGHEST SCORE and chosen to override randomly."); @@ -3757,11 +3772,10 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->setGoalNode(iFinalGoalNode, iFinalGoalIndex); tGoal *goalData = pBot->getGoalData(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); + char msg[255] = {}; if (goalData != nullptr) { - std::sprintf(msg, "I have chosen a goal: Node [%d], Goal type [%s], checked [%d], score [%f], distance [%f]", + snprintf(msg, sizeof(msg), "I have chosen a goal: Node [%d], Goal type [%s], checked [%d], score [%f], distance [%f]", iFinalGoalNode, goalData->name, goalData->iChecked, @@ -3769,7 +3783,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { pBot->getDistanceTo(iFinalGoalNode) ); } else { - std::sprintf(msg, "I have chosen a goal: Node [%d], - NO GOAL DATA - score [%f], distance [%f]", + snprintf(msg, sizeof(msg), "I have chosen a goal: Node [%d], - NO GOAL DATA - score [%f], distance [%f]", iFinalGoalNode, highestScore, pBot->getDistanceTo(iFinalGoalNode) @@ -3819,55 +3833,38 @@ tNode *cNodeMachine::getNode(int index) { return &Nodes[index]; } -char *cNodeMachine::getGoalTypeAsText(const tGoal &goal) +std::string cNodeMachine::getGoalTypeAsText(const tGoal& goal) { - char typeAsText[32]; - std::memset(typeAsText, 0, sizeof(typeAsText)); - switch (goal.iType) { - case GOAL_SPAWNT: - std::sprintf(typeAsText, "GOAL_SPAWNT"); - break; - case GOAL_SPAWNCT: - std::sprintf(typeAsText, "GOAL_SPAWNCT"); - break; + case GOAL_SPAWNT: + return "GOAL_SPAWNT"; + case GOAL_SPAWNCT: + return "GOAL_SPAWNCT"; case GOAL_BOMBSPOT: - std::sprintf(typeAsText, "GOAL_BOMBSPOT"); - break; + return "GOAL_BOMBSPOT"; case GOAL_BOMB: - std::sprintf(typeAsText, "GOAL_BOMB"); - break; + return "GOAL_BOMB"; case GOAL_HOSTAGE: - std::sprintf(typeAsText, "GOAL_HOSTAGE"); - break; + return "GOAL_HOSTAGE"; case GOAL_RESCUEZONE: - std::sprintf(typeAsText, "GOAL_RESCUEZONE"); - break; + return "GOAL_RESCUEZONE"; case GOAL_CONTACT: - std::sprintf(typeAsText, "GOAL_CONTACT"); - break; + return "GOAL_CONTACT"; case GOAL_IMPORTANT: - std::sprintf(typeAsText, "GOAL_IMPORTANT"); - break; + return "GOAL_IMPORTANT"; case GOAL_VIP: - std::sprintf(typeAsText, "GOAL_VIP"); - break; + return "GOAL_VIP"; case GOAL_VIPSAFETY: - std::sprintf(typeAsText, "GOAL_VIPSAFETY"); - break; + return "GOAL_VIPSAFETY"; case GOAL_ESCAPEZONE: - std::sprintf(typeAsText, "GOAL_ESCAPEZONE"); - break; + return "GOAL_ESCAPEZONE"; case GOAL_WEAPON: - std::sprintf(typeAsText, "GOAL_WEAPON"); - break; + return "GOAL_WEAPON"; case GOAL_NONE: - std::sprintf(typeAsText, "GOAL_NONE"); - break; + return "GOAL_NONE"; default: - std::sprintf(typeAsText, "GOAL UNKNOWN"); + return "GOAL UNKNOWN"; } - return typeAsText; //TODO: local variable invalid [APG]RoboCop[CL] } // Find cover @@ -4022,9 +4019,9 @@ void cNodeMachine::dump_goals() const for (int i = 0; i < MAX_GOALS && Goals[i].iNode >= 0; i++) { char buffer[100]; const Vector v = Nodes[Goals[i].iNode].origin; - std::sprintf(buffer, - "Goal#%d is at node %d (%.0f, %.0f, %.0f), iChecked= %d, ", - i + 1, Goals[i].iNode, v.x, v.y, v.z, Goals[i].iChecked); + snprintf(buffer, sizeof(buffer), + "Goal#%d is at node %d (%.0f, %.0f, %.0f), iChecked= %d, ", + i + 1, Goals[i].iNode, v.x, v.y, v.z, Goals[i].iChecked); switch (Goals[i].iType) { case GOAL_SPAWNCT: std::strcat(buffer, "GOAL_SPAWNCT"); @@ -4087,9 +4084,9 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) const rblog(" Path is: "); for (i = 0; i < MAX_NODES && iPath[iBot][i] >= 0; i++) { if (i == CurrentPath) - std::sprintf(buffer, "<%d> ", iPath[iBot][i]); + snprintf(buffer, sizeof(buffer), "<%d> ", iPath[iBot][i]); else - std::sprintf(buffer, "%d ", iPath[iBot][i]); + snprintf(buffer, sizeof(buffer), "%d ", iPath[iBot][i]); rblog(buffer); } rblog("\n"); @@ -4100,8 +4097,7 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) const if (Nodes[CurrentNode].iNeighbour[i] >= 0) { const int j = Nodes[CurrentNode].iNeighbour[i]; const Vector v = Nodes[j].origin; - std::sprintf(buffer, " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, - v.z); + snprintf(buffer, sizeof(buffer), " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, v.z); rblog(buffer); } rblog("\n"); @@ -4591,7 +4587,7 @@ void cNodeMachine::Draw() const PlotNodes(0, 5); // 0 = black, 5 = blue PlotPaths(11, 7); // 11 = Red 7 = light blue ? PlotGoals(9); // 9 = green - std::sprintf(Filename, "%s%4.4d.bmp", STRING(gpGlobals->mapname), Count++); + snprintf(Filename, sizeof(Filename), "%s%4.4d.bmp", STRING(gpGlobals->mapname), Count++); WriteDebugBitmap(Filename); } @@ -4622,9 +4618,8 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) const char *doorButtonToLookFor = STRING(pEntityHit->v.targetname); if (doorButtonToLookFor) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "There is a target button , named %s, to open this door [%s] - going to search for it.", doorButtonToLookFor, STRING(pEntityHit->v.classname)); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "There is a target button , named %s, to open this door [%s] - going to search for it.", doorButtonToLookFor, STRING(pEntityHit->v.classname)); pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", msg); // find this entity @@ -4739,13 +4734,13 @@ void cNodeMachine::ExecuteDoorInteractionLogic(cBot *pBot, edict_t *pEntityHit) // When node found, create path to it if (pBot->createPath(iButtonNode, PATH_NONE)) { - std::sprintf(msg, "Found a button at node %d and created a path to it.", iButtonNode); + snprintf(msg, sizeof(msg), "Found a button at node %d and created a path to it.", iButtonNode); pBot->pButtonEdict = pButtonEdict; } else { if (iButtonNode > -1) { - std::sprintf(msg, "Found a button at node %d but failed to create a path to it.", iButtonNode); + snprintf(msg, sizeof(msg), "Found a button at node %d but failed to create a path to it.", iButtonNode); } else { - std::sprintf(msg, "Found a button, but there is no nearby node :/"); + snprintf(msg, sizeof(msg), "Found a button, but there is no nearby node :/"); } } pBot->rprint_trace("cNodeMachine::ExecuteDoorInteractionLogic", msg); diff --git a/NodeMachine.h b/NodeMachine.h index 2cafc25..22cf353 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -35,6 +35,8 @@ #ifndef NODEMACHINE_H #define NODEMACHINE_H +#include + #include "bot.h" #include "NodeDataTypes.h" @@ -207,7 +209,7 @@ class cNodeMachine { static void closeNode(int nodeIndex, int parent, float cost); void openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) const; - static char *getGoalTypeAsText(const tGoal &goal); + static std::string getGoalTypeAsText(const tGoal& goal); int getFreeGoalIndex() const; diff --git a/bot.cpp b/bot.cpp index ed3b1af..ca9ac21 100644 --- a/bot.cpp +++ b/bot.cpp @@ -458,16 +458,16 @@ void cBot::NewRound() { // we should say something now? int iMax = -1; - for (int tc = 0; tc < 50; tc++) { - if (ChatEngine.ReplyBlock[98].sentence[tc][0] != '\0') + for (const char (&tc)[128] : ChatEngine.ReplyBlock[98].sentence) + { + if (tc[0] != '\0') iMax++; } const int the_c = RANDOM_LONG(0, iMax); if (the_c > -1 && iMax > -1) { - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); + char chSentence[80] = {}; snprintf(chSentence, sizeof(chSentence), "%s ", ChatEngine.ReplyBlock[98].sentence[the_c]); PrepareChat(chSentence); } @@ -499,7 +499,7 @@ float cBot::ReactionTime(int iSkill) { const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); if (Game.messageVerbosity > 1) { char msg[255]; - std::sprintf(msg, "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); + snprintf(msg, sizeof(msg), "minReactTime %f, maxReactTime %f, skill %d, results into %f", fpMinReactTime, fpMaxReactTime, iSkill, time); rprint_trace("ReactionTime()", msg); } return time; @@ -882,7 +882,7 @@ void cBot::PickBestWeapon() { // Distance to enemy const float fDistance = func_distance(pEdict->v.origin, lastSeenEnemyVector); - const float knifeDistance = 300.0f; + constexpr float knifeDistance = 300.0f; // ---------------------------- // In this function all we do is decide what weapon to pick @@ -1169,9 +1169,9 @@ void cBot::Combat() { const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { - std::sprintf(msg, "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); + snprintf(msg, sizeof(msg), "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); } else { - std::sprintf(msg, "A RealBot named %s has killed you!", name); + snprintf(msg, sizeof(msg), "A RealBot named %s has killed you!", name); } HUD_DrawString(r, g, b, msg, pEnemyEdict); @@ -1827,7 +1827,7 @@ bool cBot::Defuse() { // We can do 2 things now // - If we are not close, we check if we can walk to it, and if so we face to the c4 // - If we are close, we face it and (begin) defuse the bomb. - const int distanceForC4ToBeInReach = 70; + constexpr int distanceForC4ToBeInReach = 70; if (distance < distanceForC4ToBeInReach) { vHead = vC4; vBody = vC4; @@ -2123,7 +2123,7 @@ void cBot::CheckAround() { const Vector v_source = pEdict->v.origin + Vector(0, 0, ORIGIN_HEIGHT); // Go forward first - const float distance = 90.0f; + constexpr float distance = 90.0f; const Vector v_forward = v_source + gpGlobals->v_forward * distance; // now really go left/right @@ -2155,7 +2155,7 @@ void cBot::CheckAround() { const bool bHitForwardRight = tr.flFraction < 1.0f; char msg[255]; - std::sprintf(msg, "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); + snprintf(msg, sizeof(msg), "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); rprint_trace("CheckAround", msg); // Set 'act' properties @@ -2305,9 +2305,8 @@ bool cBot::hasEnemy(edict_t * pEdict) const // Returns true if bot has a path to follow bool cBot::shouldBeWandering() { if (this->fWanderTime > gpGlobals->time) { - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Wander time is %f , globals time is %f, so should still wander", this->fWanderTime, gpGlobals->time); rprint(msg); return true; } @@ -2323,7 +2322,7 @@ void cBot::setMoveSpeed(float value) { void cBot::setStrafeSpeed(float value, float time) { char msg[255]; - std::sprintf(msg, "%f for %f seconds.", value, time); + snprintf(msg, sizeof(msg), "%f for %f seconds.", value, time); rprint_trace("setStrafeSpeed", msg); // if (f_strafe_time > gpGlobals->time) { // @@ -2347,9 +2346,8 @@ void cBot::startWandering(float time) { this->fWanderTime = gpGlobals->time + time; setMoveSpeed(f_max_speed); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Start wandering for %f seconds", time); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Start wandering for %f seconds", time); rprint("startWandering", msg); } @@ -2404,18 +2402,17 @@ void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { this->goalIndex = iGoalIndex; tGoal *goalPtr = getGoalData(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); + char msg[255] = {}; if (goalPtr != nullptr) { - std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", + snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", nodeIndex, goalIndex, goalPtr->name, goalPtr->iChecked ); } else { - std::sprintf(msg, "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); + snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); } rprint("setGoalNode()", msg); } @@ -3092,7 +3089,7 @@ edict_t * cBot::findHostageToRescue() { if (getDistanceTo(pent->v.origin) > NODE_ZONE * 2.5f) continue; char msg[255]; - std::sprintf(msg, "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); + snprintf(msg, sizeof(msg), "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); this->rprint_trace("findHostageToRescue()", msg); return pent; } @@ -3226,11 +3223,11 @@ void cBot::Think() { const int b = RANDOM_LONG(30, 155); char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - std::sprintf(msg, + snprintf(msg, sizeof(msg), "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", name, bot_skill); else - std::sprintf(msg, "You have killed a RealBot named %s!", + snprintf(msg, sizeof(msg), "You have killed a RealBot named %s!", name); HUD_DrawString(r, g, b, msg, killer_edict); @@ -3261,17 +3258,17 @@ void cBot::Think() { // we should say something now? int iMax = -1; - for (int tc = 0; tc < 50; tc++) { - if (ChatEngine.ReplyBlock[99].sentence[tc][0] != '\0') iMax++; + for (char (&tc)[128] : ChatEngine.ReplyBlock[99].sentence) + { + if (tc[0] != '\0') iMax++; } const int the_c = RANDOM_LONG(0, iMax); if (the_c > -1 && iMax > -1) { - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); - std::sprintf(chSentence, "%s ", - ChatEngine.ReplyBlock[99].sentence[the_c]); + char chSentence[80] = {}; + snprintf(chSentence, sizeof(chSentence), + "%s ", ChatEngine.ReplyBlock[99].sentence[the_c]); //strcpy(chSentence, ChatEngine.ReplyBlock[99].sentence[the_c]); PrepareChat(chSentence); } @@ -3307,7 +3304,7 @@ void cBot::Think() { rprint("Played enough rounds"); bIsUsed = false; // no longer used char cmd[80]; - std::sprintf(cmd, "kick \"%s\"\n", name); + snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") return; } @@ -4073,14 +4070,14 @@ void BotThink(cBot *pBot) { const float msecval = (gpGlobals->time - pBot->fLastRunPlayerMoveTime) * 1000.0f; pBot->fLastRunPlayerMoveTime = gpGlobals->time; - const double upMove = 0.0; + constexpr double upMove = 0.0; char msg[255]; - std::sprintf(msg, "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); + snprintf(msg, sizeof(msg), "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, upMove, pBot->pEdict->v.button, 0, msecval); - const float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps + constexpr float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; } @@ -4264,7 +4261,7 @@ void cBot::lookAtNode(int nodeIndex) { void cBot::setTimeToMoveToNode(float timeInSeconds) { char msg[255]; const float endTime = gpGlobals->time + timeInSeconds; - std::sprintf(msg, "Set to %f so results into end time of %f", timeInSeconds, endTime); + snprintf(msg, sizeof(msg), "Set to %f so results into end time of %f", timeInSeconds, endTime); rprint_trace("setTimeToMoveToNode", msg); this->nodeTimeIncreasedAmount = 0; @@ -4280,10 +4277,9 @@ void cBot::increaseTimeToMoveToNode(float timeInSeconds) { nodeTimeIncreasedAmount++; this->fMoveToNodeTime += timeInSeconds; const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", - timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", + timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); rprint_trace("increaseTimeToMoveToNode", msg); } else { rprint_trace("increaseTimeToMoveToNode", "Refused to increase time"); @@ -4354,9 +4350,8 @@ bool cBot::createPath(int destinationNode, int flags) { forgetPath(); - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "Creating path from currentNode [%d] to destination node [%d]", currentNode, destinationNode); rprint("createPath()", msg); return NodeMachine.createPath(currentNode, destinationNode, iBotIndex, this, flags); diff --git a/bot.h b/bot.h index 54c87a6..06905fe 100644 --- a/bot.h +++ b/bot.h @@ -626,7 +626,7 @@ void UTIL_SelectItem(edict_t *pEdict, char *item_name); void UTIL_BuildFileName(char *filename, char *arg1, char *arg2); -void UTIL_BuildFileNameRB(char *subdir, char *filename); +void UTIL_BuildFileNameRB(const char *subdir, char *filename); unsigned short fixed_unsigned16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 9c390c8..789e10c 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -223,37 +223,38 @@ void BotDecideWhatToBuy(cBot *pBot) { pBot->rprint("BotDecideWhatToBuy()", "I have no primary weapon preference, deciding what to buy."); // Find weapon we can buy in the list of weapons - for (int i = 0; i < MAX_WEAPONS; i++) { + for (const weapon_price_table& i : weapons_table) + { // 31.08.04 Frashman Filter Out all except PRIMARY and SHIELD // SHIELD is used as primary weapon - if (UTIL_GiveWeaponType(weapons_table[i].iId) != PRIMARY - && UTIL_GiveWeaponType(weapons_table[i].iId) != SHIELD) + if (UTIL_GiveWeaponType(i.iId) != PRIMARY + && UTIL_GiveWeaponType(i.iId) != SHIELD) continue; // must be a weapon that the team can buy (CT/T weapon) - if (!GoodWeaponForTeam(weapons_table[i].iId, team)) + if (!GoodWeaponForTeam(i.iId, team)) continue; // can afford it - if (weapons_table[i].price <= money) { + if (i.price <= money) { // owns a primary weapon if (pBot->iPrimaryWeapon > -1) { // and the primary weapon has a higher priority than the other primary weapon - if (weapons_table[ListIdWeapon(pBot->iPrimaryWeapon)].priority >= weapons_table[i].priority) + if (weapons_table[ListIdWeapon(pBot->iPrimaryWeapon)].priority >= i.priority) continue; } // nothing to buy yet, so chose this one if (buy_weapon == -1) { - buy_weapon = weapons_table[i].iId; + buy_weapon = i.iId; } else { // randomly overrule it based on priority. The higher priority the more chance // it will be bought. - if (RANDOM_LONG(0, 100) < weapons_table[i].priority) { - buy_weapon = weapons_table[i].iId; // randomly buy a different weapon + if (RANDOM_LONG(0, 100) < i.priority) { + buy_weapon = i.iId; // randomly buy a different weapon } } } @@ -317,34 +318,35 @@ void BotDecideWhatToBuy(cBot *pBot) { pBot->rprint("BotDecideWhatToBuy()", "Deciding which secondary weapon to buy"); // Buy secondary // Find weapon we can buy in the list of weapons - for (int i = 0; i < MAX_WEAPONS; i++) { + for (const weapon_price_table& i : weapons_table) + { // When enough money and the priority is high enough.. // Filter out Secondary and Grenades - if (UTIL_GiveWeaponType(weapons_table[i].iId) != SECONDARY) + if (UTIL_GiveWeaponType(i.iId) != SECONDARY) continue; - if (GoodWeaponForTeam(weapons_table[i].iId, team) == false) + if (GoodWeaponForTeam(i.iId, team) == false) continue; - if (weapons_table[i].price <= money) { + if (i.price <= money) { if (pBot->iSecondaryWeapon > -1) { const int index = weapons_table[pBot->iSecondaryWeapon].iIdIndex; // 31.08.04 Frashman > corrected to >= , // else the bot will buy another weapon with the same priority if (weapons_table[index].priority >= - weapons_table[i].priority) + i.priority) continue; } if (buy_weapon == -1) - buy_weapon = weapons_table[i].iId; + buy_weapon = i.iId; else { - if (RANDOM_LONG(0, 100) < weapons_table[i].priority) - buy_weapon = weapons_table[i].iId; + if (RANDOM_LONG(0, 100) < i.priority) + buy_weapon = i.iId; } - if (RANDOM_LONG(0, 100) < weapons_table[i].priority) + if (RANDOM_LONG(0, 100) < i.priority) break; } } diff --git a/bot_client.cpp b/bot_client.cpp index 9888350..b7d139c 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -187,7 +187,7 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { iClip = *static_cast(p); // ammo currently in the clip for this weapon - if (iId < static_cast(sizeof(weapon_defs) / sizeof(weapon_defs[0]))) { + if (iId < static_cast(std::size(weapon_defs))) { bots[bot_index].bot_weapons |= 1 << iId; // set this weapon bit if (iState == 1) { @@ -496,7 +496,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { pBot->rprint("BotClient_Valve_Damage", "Damage taken, by player, change goal to damage origin."); char msg[255]; - std::sprintf(msg, "damage_origin (x,y,z) => (%f,%f,%f) | damageInflictor->v.origin (x,y,z) => (%f,%f,%f)", + snprintf(msg, sizeof(msg), "damage_origin (x,y,z) => (%f,%f,%f) | damageInflictor->v.origin (x,y,z) => (%f,%f,%f)", damage_origin.x, damage_origin.y, damage_origin.z, @@ -512,7 +512,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { pBot->forgetPath(); } else { char msg[255]; - std::sprintf(msg, "I have a damage inflictor! -> %s", STRING(damageInflictor->v.classname)); + snprintf(msg, sizeof(msg), "I have a damage inflictor! -> %s", STRING(damageInflictor->v.classname)); pBot->rprint("BotClient_Valve_Damage", msg); } } else { diff --git a/bot_func.cpp b/bot_func.cpp index 0aa33f2..993d2ed 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -54,7 +54,7 @@ extern cNodeMachine NodeMachine; // For taking cover decision #define TOTAL_SCORE 16300 // 16000 money + 100 health + 100 fear + 100 camp desire -bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, char *checkname) { +bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *checkname) { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -273,7 +273,7 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { - const int fov = 90;// TODO: use server var "default_fov" ? + constexpr int fov = 90;// TODO: use server var "default_fov" ? // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; @@ -285,11 +285,10 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, pPlayer->v.origin - pBot->pEdict->v.origin); - const int distance = NODE_ZONE; + constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < fov) { return pPlayer; } - } } return nullptr; @@ -339,11 +338,10 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { //int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - const int distance = NODE_ZONE; + constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { return true; } - } } return false; @@ -364,7 +362,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { if (pBot->iJumpTries > 5) { char msg[255]; - std::sprintf(msg, "Returning false because jumped too many times (%d)", pBot->iJumpTries); + snprintf(msg, sizeof(msg), "Returning false because jumped too many times (%d)", pBot->iJumpTries); pBot->rprint_trace("BotShouldJumpIfStuck", msg); return false; } @@ -1178,7 +1176,7 @@ bool BOT_DecideTakeCover(cBot *pBot) { } // logs into a file -void rblog(char *txt) { +void rblog(const char* txt) { // output to stdout printf("%s", txt); diff --git a/bot_func.h b/bot_func.h index d5528b3..87eba12 100644 --- a/bot_func.h +++ b/bot_func.h @@ -96,14 +96,14 @@ bool FUNC_BotHoldsZoomWeapon(cBot * pBot); int FUNC_InFieldOfView(edict_t * pEntity, const Vector& dest); bool VectorIsVisibleWithEdict(edict_t * pEdict, const Vector& dest, - char *checkname); + const char *checkname); bool BOT_DecideTakeCover(cBot * pBot); // bot_buycode.cpp void BotConsole(cBot * pBot); -void rblog(char *txt); +void rblog(const char* txt); // bot.cpp @@ -114,10 +114,10 @@ int UTIL_GetGrenadeType(edict_t * pEntity); bool UTIL_IsVip(edict_t * pEntity); -char *UTIL_GiveWeaponName(int id); +char* UTIL_GiveWeaponName(int id); void UTIL_SpeechSynth(edict_t * pEdict, char *szMessage); -void UTIL_BotRadioMessage(cBot * pBot, int radio, char *arg1, char *arg2); +void UTIL_BotRadioMessage(cBot * pBot, int radio, const char *arg1, const char *arg2); void UTIL_BotPressKey(cBot * pBot, int type); // bot_navigate.cpp diff --git a/dll.cpp b/dll.cpp index b8a3bd7..d2f6f18 100644 --- a/dll.cpp +++ b/dll.cpp @@ -283,8 +283,8 @@ void GameDLLInit() { fpRblog = std::fopen("reallog.txt", "at"); rblog("Initializing clients.."); - for (int i = 0; i < 32; i++) - clients[i] = nullptr; + for (edict_t*& client : clients) + client = nullptr; rblog("OK\n"); // initialize the bots array of structures... @@ -446,7 +446,7 @@ ClientConnect(edict_t *pEntity, const char *pszName, { char cmd[80]; - std::sprintf(cmd, "kick \"%s\"\n", bots[i].name); + snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; @@ -574,7 +574,7 @@ void StartFrame() { { if (bots[i].iTeam == kicking_team) { char cmd[80]; - std::sprintf(cmd, "kick \"%s\"\n", bots[i].name); + snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; } @@ -667,7 +667,7 @@ void StartFrame() { if (welcome_time > 0.0f && welcome_time < gpGlobals->time) { // let's send a welcome message to this client... char total_welcome[256]; - std::sprintf(total_welcome, "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); + snprintf(total_welcome, sizeof(total_welcome), "RealBot - Version %s\nBy Stefan Hendriks\n", rb_version_nr); int r, g, b; /* r = RANDOM_LONG(30, 255); @@ -939,9 +939,9 @@ void StartFrame() { char c_team[2]; char c_class[3]; - std::sprintf(c_skill, "%d", bots[index].bot_skill); - std::sprintf(c_team, "%d", bots[index].iTeam); - std::sprintf(c_class, "%d", bots[index].bot_class); + snprintf(c_skill, sizeof(c_skill), "%d", bots[index].bot_skill); + snprintf(c_team, sizeof(c_team), "%d", bots[index].iTeam); + snprintf(c_class, sizeof(c_class), "%d", bots[index].bot_class); Game.createBot(nullptr, c_team, c_skill, c_class, bots[index].name); @@ -967,7 +967,7 @@ void StartFrame() { UTIL_BuildFileNameRB("bot.cfg", filename); - std::sprintf(msg, "Executing %s\n", filename); + snprintf(msg, sizeof(msg), "Executing %s\n", filename); ALERT(at_console, msg); bot_cfg_fp = std::fopen(filename, "r"); @@ -1023,13 +1023,15 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { return; if (arg2 == nullptr || *arg2 == 0) { - length = std::sprintf(&g_argv[0], "%s", arg1); + length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s", arg1); fake_arg_count = 1; - } else if (arg3 == nullptr || *arg3 == 0) { - length = std::sprintf(&g_argv[0], "%s %s", arg1, arg2); + } + else if (arg3 == nullptr || *arg3 == 0) { + length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s %s", arg1, arg2); fake_arg_count = 2; - } else { - length = std::sprintf(&g_argv[0], "%s %s %s", arg1, arg2, arg3); + } + else { + length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s %s %s", arg1, arg2, arg3); fake_arg_count = 3; } @@ -1166,7 +1168,10 @@ void ProcessBotCfgFile() { cmd_line[cmd_index] = 0; // terminate the command line // copy the command line to a server command buffer... - std::strcpy(server_cmd, cmd_line); + //TODO: To use std:string for this [APG]RoboCop[CL] + std::strncpy(server_cmd, cmd_line, sizeof(server_cmd)); + server_cmd[sizeof(server_cmd) - 1] = '\0'; + std::strcat(server_cmd, "\n"); cmd_index = 0; @@ -1222,7 +1227,7 @@ void ProcessBotCfgFile() { // use 'realbot addbot' to add a bot, etc. I dont think we need more // it would double the work. - std::sprintf(msg, "BOT.CFG >> Executing command: %s", server_cmd); // removed \n + snprintf(msg, sizeof(msg), "BOT.CFG >> Executing command: %s", server_cmd); // removed \n ALERT(at_console, msg); if (IS_DEDICATED_SERVER()) @@ -1270,10 +1275,10 @@ void RealBot_ServerCommand() { if (Game.iMaxSentences > 10) Game.iMaxSentences = 10; - std::sprintf(cMessage, "REALBOT: Chat-rate set to %d", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Chat-rate set to %d", Game.iMaxSentences); } else { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: No argument given, current chat-rate is %d", Game.iMaxSentences); @@ -1285,13 +1290,13 @@ void RealBot_ServerCommand() { const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); bot_check_time = gpGlobals->time + 8.0f; if (iStatus == GAME_MSG_SUCCESS) - std::sprintf(cMessage, "REALBOT: Successfully created bot."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Successfully created bot."); else if (iStatus == GAME_MSG_FAILURE) - std::sprintf(cMessage, "REALBOT: Failed creating bot."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Failed creating bot."); else if (iStatus == GAME_MSG_FAIL_SERVERFULL) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { if (arg1 != nullptr && *arg1 != 0) { @@ -1306,15 +1311,15 @@ void RealBot_ServerCommand() { // Show amount set if (Game.fWalkWithKnife > 0) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Bots may walk with knife for %f seconds.", Game.fWalkWithKnife); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Bots may not walk with knife (value=0)"); } else - std::sprintf(cMessage, "REALBOT: No valid argument given."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "max")) { if (arg1 != nullptr && *arg1 != 0) { max_bots = std::atoi(arg1); @@ -1322,11 +1327,11 @@ void RealBot_ServerCommand() { max_bots = -1; // Show amount set - std::sprintf(cMessage, "REALBOT: Max amount of bots is set to %d.", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Max amount of bots is set to %d.", max_bots); } else { // sprintf (cMessage, "REALBOT: No valid argument given."); - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Max amount of bots is %d -- no valid argument given.", max_bots); } @@ -1335,25 +1340,25 @@ void RealBot_ServerCommand() { if (FStrEq(arg1, "add")) { if (pHostEdict != nullptr) { NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, pHostEdict->v.origin); - std::sprintf(cMessage, "REALBOT: Added important area/goal."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Added important area/goal."); } else - std::sprintf(cMessage, "REALBOT: Only a listen server can execute this command!"); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Only a listen server can execute this command!"); } else if (FStrEq(arg1, "save")) { NodeMachine.save_important(); - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Important Area Definitions written to INI file"); } else if (FStrEq(arg1, "init")) { // clear all goals that are 'goal_important' NodeMachine.ClearImportantGoals(); - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: All important goals have been removed."); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: 'important' sub-commands are: add, save, init"); } else if (FStrEq(pcmd, "killall")) { - std::sprintf(cMessage, "REALBOT: Killing all bots."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Killing all bots."); end_round = true; } else if (FStrEq(pcmd, "csversion")) { if (arg1 != nullptr && *arg1 != 0) { @@ -1363,19 +1368,19 @@ void RealBot_ServerCommand() { else counterstrike = 1; // cs 1.6 if (counterstrike == 0) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Set bot-rules for Counter-Strike 1.5."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Set bot-rules for Counter-Strike 1.6."); } else { if (counterstrike == 0) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: bot-rules are set for Counter-Strike 1.5."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: bot-rules are set for Counter-Strike 1.6."); } } else if (FStrEq(pcmd, "internet")) { @@ -1389,12 +1394,12 @@ void RealBot_ServerCommand() { else internet_play = true; if (internet_play) - std::sprintf(cMessage, "REALBOT: Internet simulation - enabled."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Internet simulation - enabled."); else - std::sprintf(cMessage, "REALBOT: Internet simulation - disabled."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Internet simulation - disabled."); } else - std::sprintf(cMessage, "REALBOT: No valid argument given."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "internet_interval")) { // 1st argument @@ -1420,7 +1425,7 @@ void RealBot_ServerCommand() { } } // Create message - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Internet simulation - Interval set to, MIN %d - MAX %d", internet_min_interval, internet_max_interval); } else if (FStrEq(pcmd, "remove") && kick_amount_bots == 0) { @@ -1449,16 +1454,16 @@ void RealBot_ServerCommand() { kick_bots_team = team; } if (kick_bots_team < 1) - std::sprintf(cMessage, "REALBOT: Removing randomly %d bots.", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Removing randomly %d bots.", kick_amount_bots); else { if (kick_bots_team == 1) - std::sprintf(cMessage, "REALBOT: Removing %d terrorist bots.", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Removing %d terrorist bots.", kick_amount_bots); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Removing %d counter-terrorist bots.", kick_amount_bots); } @@ -1477,11 +1482,11 @@ void RealBot_ServerCommand() { if (arg2 != nullptr && *arg2 != 0) s2 = std::atoi(arg2); Game.SetPlayingRounds(s1, s2); - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Bots play at minimum %d and at maximum %d rounds.\n", Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: No(t) (enough) valid arguments given."); } else if (FStrEq(pcmd, "setrandom")) { int s1 = -2, s2 = -2; @@ -1496,7 +1501,7 @@ void RealBot_ServerCommand() { // When first argument is invalid if (s1 < -1) { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: No valid argument(s) given. (minimum random skill=%d, maximum random skill=%d).", Game.iRandomMinSkill, Game.iRandomMaxSkill); } else { @@ -1514,7 +1519,7 @@ void RealBot_ServerCommand() { s2 = s1; Game.iRandomMinSkill = s1; Game.iRandomMaxSkill = s2; - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: minimum random skill=%d, maximum random skill=%d.", Game.iRandomMinSkill, Game.iRandomMaxSkill); } @@ -1528,10 +1533,10 @@ void RealBot_ServerCommand() { autoskill = false; } if (autoskill) - std::sprintf(cMessage, "REALBOT: Auto adjust skill - enabled."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Auto adjust skill - enabled."); else - std::sprintf(cMessage, "REALBOT: Auto adjust skill - disabled."); + snprintf(cMessage, sizeof(cMessage), "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); @@ -1542,26 +1547,26 @@ void RealBot_ServerCommand() { Game.iOverrideBotSkill = GAME_NO; } if (Game.iOverrideBotSkill == GAME_YES) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Using personality skill (if present) instead of default bot skill."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { if (arg1 != nullptr && *arg1 != 0) { const int temp = std::atoi(arg1); if (temp < -1 || temp > 10) { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Invalid argument given - default skill = %d.", Game.iDefaultBotSkill); } else { Game.iDefaultBotSkill = temp; - std::sprintf(cMessage, "REALBOT: Default skill = %d", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Default skill = %d", Game.iDefaultBotSkill); } } else { - std::sprintf(cMessage, "REALBOT: Default skill = %d", + snprintf(cMessage, sizeof(cMessage), "REALBOT: Default skill = %d", Game.iDefaultBotSkill); } } @@ -1582,7 +1587,7 @@ void RealBot_ServerCommand() { f_minplayers_think = gpGlobals->time; } - std::sprintf(cMessage, "RBSERVER: Minimum playing forced to %d.", + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Minimum playing forced to %d.", min_players); } // Broadcast @@ -1598,11 +1603,11 @@ void RealBot_ServerCommand() { temp = 1; Game.iVersionBroadcasting = temp; if (Game.iVersionBroadcasting == BROADCAST_ROUND) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting RealBot version every round and map change.\n"); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting RealBot version every map change only.\n"); } } else if (FStrEq(arg2, "speech")) { @@ -1614,9 +1619,9 @@ void RealBot_ServerCommand() { } if (Game.bSpeechBroadcasting) - std::sprintf(cMessage, "RBSERVER: Broadcasting speech is ON"); + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting speech is ON"); else - std::sprintf(cMessage, "RBSERVER: Broadcasting speech is OFF"); + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting speech is OFF"); } else if (FStrEq(arg2, "kills")) { // How do we broadcast kills by bots? @@ -1633,24 +1638,24 @@ void RealBot_ServerCommand() { if (temp == 2) Game.iKillsBroadcasting = BROADCAST_KILLS_NONE; if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Nothing will be sent to player.\n"); } } else if (FStrEq(arg2, "deaths")) { @@ -1668,31 +1673,31 @@ void RealBot_ServerCommand() { if (temp == 2) Game.iDeathsBroadcasting = BROADCAST_DEATHS_NONE; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcasting name of bot who killed human player.\n"); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Nothing will be sent to player.\n"); } } else { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Broadcast what?\nversion\nspeech\nkills\ndeaths"); } } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBSERVER: Invalid sub-command.\nValid commands are:\nbroadcast (version/kill)\nplayers (keep ## player slots full)"); } // ----------------------------------------- @@ -1720,11 +1725,11 @@ void RealBot_ServerCommand() { NodeMachine.add_neighbour_node(iOnNode, iTo); if (bSuccess) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Added connection from node %d to node %d.", iOnNode, iTo); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); bValidArg = true; @@ -1732,7 +1737,7 @@ void RealBot_ServerCommand() { } if (bValidArg == false) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeto")) { // removes connection TO @@ -1748,11 +1753,11 @@ void RealBot_ServerCommand() { NodeMachine.removeConnection(iOnNode, iTo); if (bSuccess) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Removed connection from node %d to node %d.", iOnNode, iTo); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Could not remove connection, connection does not exist."); bValidArg = true; @@ -1760,14 +1765,14 @@ void RealBot_ServerCommand() { } if (bValidArg == false) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeall")) { const bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); if (bSuccess) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Removed all connections from node %d.", iOnNode); } else if (FStrEq(arg1, "draw")) { @@ -1776,9 +1781,9 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - enabled."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) @@ -1787,22 +1792,22 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes connections - enabled."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); - std::sprintf(cMessage, "NODES EDITOR: Nodes initialized."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes initialized."); } else if (FStrEq(arg1, "save")) { NodeMachine.save(); - std::sprintf(cMessage, "NODES EDITOR: Nodes saved."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes saved."); } else if (FStrEq(arg1, "load")) { NodeMachine.load(); - std::sprintf(cMessage, "NODES EDITOR: Nodes loaded."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes loaded."); } else { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Unknown command\n Valid commands are:\naddto,removeto,removeall,draw,connections,init,save,load."); } } else { @@ -1814,9 +1819,9 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - std::sprintf(cMessage, "NODES EDITOR: Drawing nodes - enabled."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - enabled."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) @@ -1825,22 +1830,22 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes connections - enabled."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); - std::sprintf(cMessage, "NODES EDITOR: Nodes initialized."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes initialized."); } else if (FStrEq(arg1, "save")) { NodeMachine.save(); - std::sprintf(cMessage, "NODES EDITOR: Nodes saved."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes saved."); } else if (FStrEq(arg1, "load")) { NodeMachine.load(); - std::sprintf(cMessage, "NODES EDITOR: Nodes loaded."); + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes loaded."); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Not close enough to a node to edit."); } // commands not needed for a node to be close @@ -1855,14 +1860,14 @@ void RealBot_ServerCommand() { const int Node2 = std::atoi(arg3); // add connection TO if (Node1 >= 0 && Node2 >= 0 && NodeMachine.add_neighbour_node(Node1, Node2)) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Added connection from node %d to node %d.", Node1, Node2); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: this command requires TWO numeric arguments!"); } else if (FStrEq(arg1, "disconnect")) { // check for valid argument @@ -1872,14 +1877,14 @@ void RealBot_ServerCommand() { const int Node2 = std::atoi(arg3); if (Node1 >= 0 && Node2 >= 0 && NodeMachine.removeConnection(Node1, Node2)) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Removed connection from node %d to node %d.", Node1, Node2); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Connection could not be removed..."); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: this command requires TWO numeric arguments!"); } } @@ -1900,9 +1905,9 @@ void RealBot_ServerCommand() { } if (Game.bDoNotShoot) - std::sprintf(cMessage, "RBDEBUG: Bots will not shoot."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Bots will not shoot."); else - std::sprintf(cMessage, "RBDEBUG: Bots will shoot."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Bots will shoot."); } // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] @@ -1915,9 +1920,9 @@ void RealBot_ServerCommand() { } if (Game.bPistols) - std::sprintf(cMessage, "RBDEBUG: Bots will only use pistols."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Bots will only use pistols."); else - std::sprintf(cMessage, "RBDEBUG: Bots will use all weapons."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Bots will use all weapons."); } else if (FStrEq(arg1, "goals")) // Print all current goals { NodeMachine.dump_goals(); @@ -1935,33 +1940,33 @@ void RealBot_ServerCommand() { } else if (FStrEq(arg1, "print")) { // realbot debug print (toggles, and last argument is bot index) if (Game.bDebug > -2) { Game.bDebug = -2; - std::sprintf(cMessage, "RBDEBUG: Debug messages off."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Debug messages off."); } else { if (arg2 != nullptr && *arg2 != 0) { const int temp = std::atoi(arg2); Game.bDebug = temp; - std::sprintf(cMessage, "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); } else { Game.bDebug = -1; - std::sprintf(cMessage, "RBDEBUG: Debug messages on for all bots"/*, Game.bDebug*/); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Debug messages on for all bots"/*, Game.bDebug*/); } } } else if (FStrEq(arg1, "verbosity")) { // realbot verbosity if (FStrEq(arg2, "low")) { - std::sprintf(cMessage, "RBDEBUG: Message verbosity low."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Message verbosity low."); Game.messageVerbosity = 0; } else if (FStrEq(arg2, "normal")) { - std::sprintf(cMessage, "RBDEBUG: Message verbosity normal."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Message verbosity normal."); Game.messageVerbosity = 1; } else if (FStrEq(arg2, "trace")) { - std::sprintf(cMessage, "RBDEBUG: Message verbosity trace."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Message verbosity trace."); Game.messageVerbosity = 2; // extreme verbose } else { - std::sprintf(cMessage, "RBDEBUG: Usage: realbot debug verbosity [low][normal][trace]"); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Usage: realbot debug verbosity [low][normal][trace]"); } } else if (FStrEq(arg1, "nodes")) { // realbot debug nodes if (FStrEq(arg2, "dumpbmp")) { // realbot debug nodes dumpbmp - std::sprintf(cMessage, "RBDEBUG: Dumping Nodes information into bitmap file"); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Dumping Nodes information into bitmap file"); NodeMachine.Draw(); } else if (FStrEq(arg2, "draw")) { if (draw_nodes == false) @@ -1969,9 +1974,9 @@ void RealBot_ServerCommand() { else draw_nodes = false; if (draw_nodes) - std::sprintf(cMessage, "RBDEBUG: Drawing nodes - enabled."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing nodes - enabled."); else - std::sprintf(cMessage, "RBDEBUG: Drawing nodes - disabled."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing nodes - disabled."); } else if (FStrEq(arg2, "path")) { int iFrom = -1, iTo = -1; if (arg3 != nullptr && *arg3 != 0) @@ -1985,18 +1990,18 @@ void RealBot_ServerCommand() { if (ptr) iTo = ptr->iNode; } - std::sprintf(cMessage, "RBDEBUG: Creating path from [%d] to [%d].", iFrom, iTo); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Creating path from [%d] to [%d].", iFrom, iTo); NodeMachine.createPath(iFrom, iTo, 0, nullptr, PATH_DANGER); } else { - std::sprintf(cMessage, "RBDEBUG: Usage: realbot debug nodes path "); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Usage: realbot debug nodes path "); } } else if (FStrEq(arg2, "drawpath")) { if (arg3 != nullptr && *arg3 != 0) draw_nodepath = std::atoi(arg3); if (draw_nodepath > -1) { - std::sprintf(cMessage, "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); } else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing path of bot id [%d] - no better or valid argument given.", draw_nodepath); } else if (FStrEq(arg2, "connections")) { @@ -2006,30 +2011,30 @@ void RealBot_ServerCommand() { draw_connodes = false; if (draw_connodes) - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing nodes connections - enabled."); else - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing nodes connections - disabled."); } else if (FStrEq(arg2, "init")) { NodeMachine.init(); - std::sprintf(cMessage, "RBDEBUG: Nodes initialized."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Nodes initialized."); } else if (FStrEq(arg2, "save")) { NodeMachine.save(); - std::sprintf(cMessage, "RBDEBUG: Nodes saved."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Nodes saved."); } else if (FStrEq(arg2, "load")) { NodeMachine.load(); - std::sprintf(cMessage, "RBDEBUG: Nodes loaded."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Nodes loaded."); } else - std::sprintf(cMessage, "RBDEBUG: No argument given."); + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: No argument given."); } else { - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Unknown debug command.\n\nKnown commands are:\ndontshoot, pistols, nodes, print"); } } else { // Not a valid command - std::sprintf(cMessage, + snprintf(cMessage, sizeof(cMessage), "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); bool bValidCommand = false; //Unused variable boolean [APG]RoboCop[CL] } @@ -2079,7 +2084,7 @@ int Spawn_Post(edict_t *pent) { } char msg[255]; - std::sprintf(msg, "Found an entity %s - %s - %s with rendermode %d!\n", STRING(pent->v.classname), STRING(pent->v.netname), STRING(pent->v.model), pent->v.rendermode); + snprintf(msg, sizeof(msg), "Found an entity %s - %s - %s with rendermode %d!\n", STRING(pent->v.classname), STRING(pent->v.netname), STRING(pent->v.model), pent->v.rendermode); rblog(msg); // is this a trigger_multiple ? diff --git a/engine.cpp b/engine.cpp index aa4c2fd..32630a9 100644 --- a/engine.cpp +++ b/engine.cpp @@ -68,14 +68,15 @@ int botMsgIndex; void pfnChangeLevel(const char *s1, const char *s2) { // kick any bot off of the server after time/frag limit... - for (int index = 0; index < 32; index++) { - if (bots[index].bIsUsed) // is this slot used? + for (cBot& bot : bots) + { + if (bot.bIsUsed) // is this slot used? { char cmd[40]; - std::sprintf(cmd, "kick \"%s\"\n", bots[index].name); + snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", bot.name); - bots[index].respawn_state = RESPAWN_NEED_TO_RESPAWN; + bot.respawn_state = RESPAWN_NEED_TO_RESPAWN; SERVER_COMMAND(cmd); // kick the bot using (kick "name") } @@ -121,7 +122,7 @@ void pfnRemoveEntity(edict_t *e) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnRemoveEntity() - model -> '%s'\n", + snprintf(msg, sizeof(msg), "ENGINE: pfnRemoveEntity() - model -> '%s'\n", STRING(e->v.model)); rblog(msg); } @@ -145,7 +146,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict if (Game.bEngineDebug) { char dmsg[256]; - std::sprintf(dmsg, "ENGINE: pfnMessageBegin(), dest=%d, msg_type=%d\n", msg_dest, msg_type); + snprintf(dmsg, sizeof(dmsg), "ENGINE: pfnMessageBegin(), dest=%d, msg_type=%d\n", msg_dest, msg_type); rblog(dmsg); } @@ -294,7 +295,7 @@ void pfnWriteByte(int iValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteByte() - '%d'\n", iValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteByte() - '%d'\n", iValue); rblog(msg); } @@ -310,7 +311,7 @@ void pfnWriteChar(int iValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteChar() - '%d'\n", iValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteChar() - '%d'\n", iValue); rblog(msg); } RETURN_META(MRES_IGNORED); @@ -325,7 +326,7 @@ void pfnWriteShort(int iValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteShort() - '%d'\n", iValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteShort() - '%d'\n", iValue); rblog(msg); } @@ -341,7 +342,7 @@ void pfnWriteLong(int iValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteLong() - '%d'\n", iValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteLong() - '%d'\n", iValue); rblog(msg); } @@ -358,7 +359,7 @@ void pfnWriteAngle(float flValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteAngle() - '%f'\n", flValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteAngle() - '%f'\n", flValue); rblog(msg); } @@ -375,7 +376,7 @@ void pfnWriteCoord(float flValue) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteCoord() - '%f'\n", flValue); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteCoord() - '%f'\n", flValue); rblog(msg); } @@ -386,7 +387,7 @@ void pfnWriteCoord(float flValue) { void pfnWriteString(const char *sz) { if (Game.bEngineDebug) { char msg[256]; - std::sprintf(msg, "ENGINE: pfnWriteByte() - '%s'\n", sz); + snprintf(msg, sizeof(msg), "ENGINE: pfnWriteByte() - '%s'\n", sz); rblog(msg); } diff --git a/game.cpp b/game.cpp index bab507c..9acbff4 100644 --- a/game.cpp +++ b/game.cpp @@ -126,9 +126,9 @@ void cGame::InitNewRound() { DetermineMapGoal(); // initialize bots for new round - for (int i = 0; i < MAX_BOTS; i++) { - cBot &bot = bots[i]; - if (bot.bIsUsed) { + for (auto& bot : bots) + { + if (bot.bIsUsed) { bot.NewRound(); } } @@ -170,9 +170,8 @@ void cGame::DetermineMapGoal() const hostagesFound++; } - char msg[255]; - std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "DetermineMapGoal: There are %d hostages found to rescue\n", hostagesFound); + char msg[255] = {}; + snprintf(msg, sizeof(msg), "DetermineMapGoal: There are %d hostages found to rescue\n", hostagesFound); rblog(msg); Game.bHostageRescueMap = hostagesFound > 0; @@ -188,7 +187,7 @@ void cGame::DetermineMapGoal() const } std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "DetermineMapGoal: There are %d rescue zones found\n", rescueZonesFound); + snprintf(msg, sizeof(msg), "DetermineMapGoal: There are %d rescue zones found\n", rescueZonesFound); rblog(msg); Game.bHostageRescueZoneFound = rescueZonesFound > 0; @@ -204,7 +203,7 @@ void cGame::DetermineMapGoal() const bombSpots++; } std::memset(msg, 0, sizeof(msg)); - std::sprintf(msg, "DetermineMapGoal: There are %d bomb spots in this level\n", bombSpots); + snprintf(msg, sizeof(msg), "DetermineMapGoal: There are %d bomb spots in this level\n", bombSpots); Game.bBombPlantMap = bombSpots > 0; rblog(msg); } @@ -334,8 +333,9 @@ void cGame::SelectName(char *name) const int iNameIndex = 0; // zero based (RANDOM_LONG (0, iAmountNames-1)) bool iNameUsed[MAX_BOT_NAMES]; - for (int i = 0; i < MAX_BOT_NAMES; i++) { - iNameUsed[i] = false; + for (bool& i : iNameUsed) + { + i = false; } // check make sure this name isn't used @@ -476,8 +476,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg { // NAME - char botName[BOT_NAME_LEN + 1]; - std::memset(botName, 0, sizeof(botName)); + char botName[BOT_NAME_LEN + 1] = {}; // if name given, use that if (nameArg != nullptr && *nameArg != 0) { std::strncpy(botName, nameArg, BOT_NAME_LEN - 1); @@ -591,8 +590,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg pBot->bot_money = 0; // clear - char c_skin[BOT_SKIN_LEN + 1]; - std::memset(c_skin, 0, sizeof(c_skin)); + constexpr char c_skin[BOT_SKIN_LEN + 1] = {}; std::strcpy(pBot->skin, c_skin); pBot->pEdict = pBotEdict; @@ -684,7 +682,10 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { if (pBot) { botIndex = pBot->iBotIndex; std::memset(name, 0, sizeof(name)); // clear - std::strcpy(name, pBot->name); // copy name + + //TODO: To use std:string for this [APG]RoboCop[CL] + std::strncpy(name, pBot->name, sizeof(name)); + name[sizeof(name) - 1] = '\0'; if (pBot->isCounterTerrorist()) { std::strcpy(team, "COUNTER"); @@ -704,7 +705,7 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { const int minutesLeft = static_cast(roundTimeRemaining) / 60; const int secondsLeft = static_cast(roundTimeRemaining) % 60; - std::sprintf(cMessage, "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); + snprintf(cMessage, sizeof(cMessage), "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); // print in console only when on debug print if (Game.bDebug > -2) { diff --git a/game.h b/game.h index 9042aed..a0ac0f7 100644 --- a/game.h +++ b/game.h @@ -57,8 +57,8 @@ #define BROADCAST_DEATHS_MIN 7 // died, show min info (name) #define BROADCAST_DEATHS_NONE 8 // died, show no information -static const int MAX_BOTS = 32; -static const int MAX_NAME_LENGTH = 32; +static constexpr int MAX_BOTS = 32; +static constexpr int MAX_NAME_LENGTH = 32; // Debug messages for realbot void REALBOT_PRINT(cBot * pBot, const char *Function, const char *msg); diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 843d64a..657e90e 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -62,7 +62,7 @@ .\Release/ true .\Release/ - EnableAllWarnings + Level4 false true ProgramDatabase diff --git a/util.cpp b/util.cpp index d8149c3..42905ec 100644 --- a/util.cpp +++ b/util.cpp @@ -354,9 +354,10 @@ int UTIL_GetBotIndex(edict_t* pEdict) { * @return */ cBot* UTIL_GetBotPointer(edict_t* pEdict) { - for (int index = 0; index < 32; index++) { - if (bots[index].pEdict == pEdict) { - return (&bots[index]); + for (cBot& bot : bots) + { + if (bot.pEdict == pEdict) { + return (&bot); } } @@ -465,7 +466,7 @@ void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { // added by Tub // copies subdir/file to filename -void UTIL_BuildFileNameRB(char* subdir, char* filename) { +void UTIL_BuildFileNameRB(const char* subdir, char* filename) { #if DO_DEBUG != 0 char* filenamedebug = filename; #endif @@ -563,7 +564,7 @@ void UTIL_BotPressKey(cBot* pBot, int type) { break; default: char msg[255]; - std::sprintf(msg, "unknown key to print [%d]", type); + snprintf(msg, sizeof(msg), "unknown key to print [%d]", type); pBot->rprint_trace("UTIL_BotPressKey", msg); break; } @@ -795,7 +796,7 @@ void UTIL_BotSprayLogo(edict_t* pEntity, char* logo_name) { } // Give a radio message botty boy! -void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { +void UTIL_BotRadioMessage(cBot* pBot, int radio, const char* arg1, const char* arg2) { // To be sure the console will only change when we MAY change. // The values will only be changed when console_nr is 0 if (pBot->console_nr == 0) { @@ -827,10 +828,9 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, char* arg1, char* arg2) { // UTIL_getGrenadeType function // - Stefan ////////////////////////////////// int UTIL_GetGrenadeType(edict_t* pEntity) { - const int length = 32; + constexpr int length = 32; - char model_name[length]; - std::memset(model_name, 0, sizeof(model_name)); + char model_name[length] = {}; std::strncpy(model_name, STRING(pEntity->v.model), length - 1); model_name[length - 1] = 0; // Make sure it is NULL terminated @@ -840,11 +840,11 @@ int UTIL_GetGrenadeType(edict_t* pEntity) { if (std::strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade if (std::strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive - char msg[512]; - std::memset(msg, 0, sizeof(msg)); - // when an empty string, let us know we missed something if (model_name[0] == '\0') { + + char msg[512] = {}; + snprintf(msg, sizeof(msg), "UTIL_GetGrenadeType unknown grenade model: %s\n", model_name); } @@ -966,8 +966,7 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { // pass through on ChatEngine (not always) if (RANDOM_LONG(0, 100) < 90) { - char chSentence[80]; - std::memset(chSentence, 0, sizeof(chSentence)); + char chSentence[80] = {}; // copy pText to chSentence std::strcpy(chSentence, pText); From 471f7549ac2633dd214fb5f283545467ab07320f Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Thu, 5 Sep 2024 14:45:37 +0100 Subject: [PATCH 085/114] Repaired rouge snprintf --- dll.cpp | 8 ++++---- util.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dll.cpp b/dll.cpp index d2f6f18..b8f46ba 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1012,7 +1012,7 @@ void StartFrame() { RETURN_META(MRES_IGNORED); } -void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { +void FakeClientCommand(edict_t* pBot, char* arg1, char* arg2, char* arg3) { int length; std::memset(g_argv, 0, sizeof(g_argv)); @@ -1023,15 +1023,15 @@ void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3) { return; if (arg2 == nullptr || *arg2 == 0) { - length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s", arg1); + length = snprintf(&g_argv[0], sizeof(g_argv), "%s", arg1); fake_arg_count = 1; } else if (arg3 == nullptr || *arg3 == 0) { - length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s %s", arg1, arg2); + length = snprintf(&g_argv[0], sizeof(g_argv), "%s %s", arg1, arg2); fake_arg_count = 2; } else { - length = snprintf(&g_argv[0], sizeof(g_argv[0]), "%s %s %s", arg1, arg2, arg3); + length = snprintf(&g_argv[0], sizeof(g_argv), "%s %s %s", arg1, arg2, arg3); fake_arg_count = 3; } diff --git a/util.cpp b/util.cpp index 42905ec..fa6b52d 100644 --- a/util.cpp +++ b/util.cpp @@ -498,7 +498,7 @@ void UTIL_LogPrintf(char* fmt, ...) { static char string[1024]; va_start(argptr, fmt); - vsprintf(string, fmt, argptr); + vsnprintf(string, sizeof(string), fmt, argptr); va_end(argptr); // Print to server console From 6a868e83a9287c1392da1ffda94672362bb2e42b Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Sat, 7 Dec 2024 12:51:49 +0000 Subject: [PATCH 086/114] Using C++ Algorithms and Modern Enums --- ChatEngine.cpp | 12 ++++---- IniParser.cpp | 21 ++++++------- NodeMachine.cpp | 79 +++++++++++++++++++++--------------------------- bot.cpp | 30 +++++++----------- bot.h | 2 +- bot_buycode.cpp | 4 +-- bot_client.cpp | 4 +-- bot_navigate.cpp | 2 +- dll.cpp | 67 +++++++++++++++------------------------- game.cpp | 9 +++--- game.h | 2 +- util.cpp | 18 +++++------ 12 files changed, 104 insertions(+), 146 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index b0f5558..989c4e4 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -58,11 +58,11 @@ cChatEngine::init() { // clear all blocks for (tReplyBlock& iB : ReplyBlock) { - for (int iBs = 0; iBs < 50; iBs++) - iB.sentence[iBs][0] = '\0'; + for (char (&iBs)[128] : iB.sentence) + iBs[0] = '\0'; - for (int iBw = 0; iBw < 10; iBw++) - iB.word[iBw][0] = '\0'; + for (char (&iBw)[25] : iB.word) + iBw[0] = '\0'; iB.bUsed = false; } @@ -172,7 +172,7 @@ void cChatEngine::think() { } else { for (int iB = 0; iB < MAX_BLOCKS; iB++) { if (ReplyBlock[iB].bUsed) { - for (char (&iBw)[25] : ReplyBlock[iB].word) + for (const char (&iBw)[25] : ReplyBlock[iB].word) { // skip any word in the reply block that is not valid if (iBw[0] == '\0') @@ -230,7 +230,7 @@ void cChatEngine::think() { int iMax = -1; // now choose a sentence to reply with - for (char (&iS)[128] : ReplyBlock[iTheBlock].sentence) + for (const char (&iS)[128] : ReplyBlock[iTheBlock].sentence) { // Find max sentences of this reply block if (iS[0] != '\0') diff --git a/IniParser.cpp b/IniParser.cpp index 73f5e87..ff17b17 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -32,6 +32,7 @@ * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 **/ +#include #include #include #include @@ -577,8 +578,7 @@ void INI_PARSE_CHATFILE() { if (section == INI_BLOCK) { iBlockId++; - if (iBlockId > 97) - iBlockId = 97; + iBlockId = std::min(iBlockId, 97); section = INI_NONE; iBlockWord = -1; iBlockSentence = -1; @@ -609,8 +609,7 @@ void INI_PARSE_CHATFILE() { // We load in words if (wordtype == WORD_WORD) { iBlockWord++; - if (iBlockWord > 9) - iBlockWord = 9; + iBlockWord = std::min(iBlockWord, 9); // write the word in the block char chWord[25] = {}; @@ -639,8 +638,7 @@ void INI_PARSE_CHATFILE() { if (wordtype == WORD_SENTENCE) { iBlockSentence++; - if (iBlockSentence > 49) - iBlockSentence = 49; + iBlockSentence = std::min(iBlockSentence, 49); // write the word in the block char chSentence[80] = {}; @@ -1059,11 +1057,12 @@ void INI_PARSE_BUYTABLE() { UTIL_BuildFileNameRB(dirname, filename); // clear out weapon table completely - for (int cl = 0; cl < 32; cl++) { - weapons_table[cl].iId = -1; - weapons_table[cl].price = -1; - weapons_table[cl].priority = -1; - weapons_table[cl].iIdIndex = -1; + for (weapon_price_table& cl : weapons_table) + { + cl.iId = -1; + cl.price = -1; + cl.priority = -1; + cl.iIdIndex = -1; } if ((stream = std::fopen(filename, "r+t")) != nullptr) { diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 525a0b1..36cd6ea 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -32,6 +32,7 @@ * COPYRIGHTED BY STEFAN HENDRIKS (C) 2003-2004 **/ +#include #include #include #include @@ -198,9 +199,9 @@ void cNodeMachine::init() { // Init Meredians for (tMeredian (&Meredian)[64] : Meredians) - for (int iMy = 0; iMy < MAX_MEREDIANS; iMy++) - for (int iNode = 0; iNode < MAX_NODES_IN_MEREDIANS; iNode++) - Meredian[iMy].iNodes[iNode] = -1; + for (tMeredian& iMy : Meredian) + for (int& iNode : iMy.iNodes) + iNode = -1; rblog("cNodeMachine::init() - END\n"); } @@ -924,8 +925,7 @@ int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { } Nodes[newNodeIndex].origin = vOrigin; - if (newNodeIndex > iMaxUsedNodes) - iMaxUsedNodes = newNodeIndex; + iMaxUsedNodes = std::max(newNodeIndex, iMaxUsedNodes); // Set different flags about the node Nodes[newNodeIndex].iNodeBits = iType; // EVY's extension @@ -1251,8 +1251,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { } - if (currentIndex > iMaxUsedNodes) - iMaxUsedNodes = currentIndex; + iMaxUsedNodes = std::max(currentIndex, iMaxUsedNodes); //UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "NodeMachine: Succesfully added node\n"); return currentIndex; @@ -1504,12 +1503,13 @@ void cNodeMachine::experience_save() { //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (int i = 0; i < MAX_NODES; i++) { - Node InfoNodes[MAX_NODES]; - std::fwrite(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fwrite(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + Node localInfoNodes[MAX_NODES]; + + std::fwrite(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fwrite(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - std::fwrite(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fwrite(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fwrite(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fwrite(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } if (iMaxUsedNodes > MAX_NODES) @@ -1579,19 +1579,18 @@ void cNodeMachine::experience_load() { Vector fDanger[2]; Vector fContact[2]; }; - Node InfoNodes[MAX_NODES]; + Node localInfoNodes[MAX_NODES]; if (iVersion == FILE_EXP_VER1) { //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - std::fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - std::fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } - + std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); // make sure we never exceed the limit @@ -1603,18 +1602,17 @@ void cNodeMachine::experience_load() { // Read table from what we know std::fread(cVisTable, iSize, 1, rbl); std::fread(iVisChecked, sizeof(iVisChecked), 1, rbl); - } else if (iVersion == FILE_EXP_VER2) { + } + else if (iVersion == FILE_EXP_VER2) { //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - std::fread(&InfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fread(&InfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - std::fread(&InfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fread(&InfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); + std::fread(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); } std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); - // make sure we never exceed the limit if (iMaxUsedNodes > MAX_NODES) iMaxUsedNodes = MAX_NODES; @@ -1678,8 +1676,8 @@ void cNodeMachine::save() const for (const tNode& Node : Nodes) { std::fwrite(&Node.origin, sizeof(Vector), 1, rbl); - for (int n = 0; n < MAX_NEIGHBOURS; n++) - std::fwrite(&Node.iNeighbour[n], sizeof(int), 1, rbl); + for (const int& n : Node.iNeighbour) + std::fwrite(&n, sizeof(int), 1, rbl); // save bit flags std::fwrite(&Node.iNodeBits, sizeof(int), 1, rbl); @@ -2046,8 +2044,7 @@ bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const void cNodeMachine::resetCheckedValuesForGoals() { for (tGoal& Goal : Goals) { - if (Goal.iChecked > 0) - Goal.iChecked = 0; + Goal.iChecked = std::min(Goal.iChecked, 0); } } @@ -2226,8 +2223,7 @@ void cNodeMachine::scale_contact() { float fHighest = 0.0f; int i; // <-- ADDED BY PMB ELSE LINUX COMPILER ISNT HAPPY for (i = 0; i < MAX_NODES; i++) - if (InfoNodes[i].fContact[iTeam] > fHighest) - fHighest = InfoNodes[i].fContact[iTeam]; + fHighest = std::max(InfoNodes[i].fContact[iTeam], fHighest); if (fHighest < 1.0f) { iTeam++; @@ -2256,8 +2252,7 @@ void cNodeMachine::scale_danger() { float fHighest = 0.0f; int i; // ADDED BY PMB FOR COMPILING UNDER LINUX for (i = 0; i < MAX_NODES; i++) - if (InfoNodes[i].fDanger[iTeam] > fHighest) - fHighest = InfoNodes[i].fDanger[iTeam]; + fHighest = std::max(InfoNodes[i].fDanger[iTeam], fHighest); if (fHighest < 0.8f) { iTeam++; @@ -2501,7 +2496,7 @@ void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighbou const tNode &node = Nodes[nodeToOpenNeighboursFrom]; // node evaluating neighbours - for (int neighbourNode : node.iNeighbour) + for (const int neighbourNode : node.iNeighbour) { if (neighbourNode < 0) continue; // skip invalid nodes if (Nodes[neighbourNode].origin == INVALID_VECTOR) continue; // skip nodes with invalid vector @@ -4107,7 +4102,7 @@ void cNodeMachine::dump_path(int iBot, int CurrentPath) const // Graphs from PMB & Botman // width and height of the debug bitmap image -enum +enum : std::uint16_t { DEBUG_BMP_WIDTH = 2048, DEBUG_BMP_HEIGHT = 2048 @@ -4442,14 +4437,10 @@ void cNodeMachine::FindMinMax() const for (int i = 0; i < MAX_NODES && Nodes[i].origin != Vector(9999, 9999, 9999); i++) { - if (Nodes[i].origin.x > maxx) - maxx = Nodes[i].origin.x; - if (Nodes[i].origin.y > maxy) - maxy = Nodes[i].origin.y; - if (Nodes[i].origin.x < minx) - minx = Nodes[i].origin.x; - if (Nodes[i].origin.y < miny) - miny = Nodes[i].origin.y; + maxx = std::max(Nodes[i].origin.x, maxx); + maxy = std::max(Nodes[i].origin.y, maxy); + minx = std::min(Nodes[i].origin.x, minx); + miny = std::min(Nodes[i].origin.y, miny); } // Avoid having lines/points just on the bitmap border, add some more spaces diff --git a/bot.cpp b/bot.cpp index ca9ac21..7b38231 100644 --- a/bot.cpp +++ b/bot.cpp @@ -72,6 +72,7 @@ bool CBaseBot::IsShootableThruObstacle(Vector vecDest) */ +#include #include #include #include @@ -732,9 +733,7 @@ void cBot::FightEnemy() { if (!isBlindedByFlashbang() && isSeeingEnemy()) { // GET OUT OF CAMP MODE - if (f_camp_time > gpGlobals->time) { - f_camp_time = gpGlobals->time; - } + f_camp_time = std::min(f_camp_time, gpGlobals->time); // Next time our enemy gets out of sight, it will be the 'first' time // of all 'frame times'. @@ -1040,15 +1039,12 @@ void cBot::FireWeapon() { || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) && bot_skill < 3) { float f_burst = (2048 / fDistance) + 0.1f; - if (f_burst < 0.1f) - f_burst = 0.1f; - if (f_burst > 0.4f) - f_burst = 0.4f; + f_burst = std::max(f_burst, 0.1f); + f_burst = std::min(f_burst, 0.4f); // CS 1.6 less burst if (counterstrike == 1) - if (f_burst > 0.3f) - f_burst = 0.3f; + f_burst = std::min(f_burst, 0.3f); f_prim_weapon = gpGlobals->time + f_burst; @@ -1060,13 +1056,11 @@ void cBot::FireWeapon() { f_burst = (fDistance - 300) / 550; if (f_burst < 0.1f) f_burst = 0.0f; - if (f_burst > 0.7f) - f_burst = 0.7f; + f_burst = std::min(f_burst, 0.7f); // CS 1.6 less burst if (counterstrike == 1) - if (f_burst > 0.2f) - f_burst = 0.2f; + f_burst = std::min(f_burst, 0.2f); if (f_prim_weapon < gpGlobals->time) f_prim_weapon = gpGlobals->time + f_burst; } @@ -1728,8 +1722,7 @@ int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { return static_cast(current); // return number of degrees turned // check if difference is less than the max degrees per turn - if (diff < speed) - speed = diff; // just need to turn a little bit (less than max) + speed = std::min(diff, speed); // just need to turn a little bit (less than max) // here we have four cases, both angle positive, one positive and // the other negative, one negative and the other positive, or @@ -2297,7 +2290,7 @@ bool cBot::hasEnemy() const * @param pEdict * @return */ -bool cBot::hasEnemy(edict_t * pEdict) const +bool cBot::hasEnemy(const edict_t * pEdict) const { return this->pEnemyEdict == pEdict; } @@ -3210,8 +3203,7 @@ void cBot::Think() { if (botPointerOfKiller == nullptr) { if (autoskill) { bot_skill--; - if (bot_skill < 0) - bot_skill = 0; + bot_skill = std::max(bot_skill, 0); } if (Game.iKillsBroadcasting != BROADCAST_KILLS_NONE @@ -3258,7 +3250,7 @@ void cBot::Think() { // we should say something now? int iMax = -1; - for (char (&tc)[128] : ChatEngine.ReplyBlock[99].sentence) + for (const char (&tc)[128] : ChatEngine.ReplyBlock[99].sentence) { if (tc[0] != '\0') iMax++; } diff --git a/bot.h b/bot.h index 06905fe..1f4ba1a 100644 --- a/bot.h +++ b/bot.h @@ -476,7 +476,7 @@ class cBot { // ------------------- bool hasEnemy() const; - bool hasEnemy(edict_t * pEdict) const; + bool hasEnemy(const edict_t * pEdict) const; edict_t * getEnemyEdict() const; bool hasGoal() const; diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 789e10c..0f20482 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -27,6 +27,7 @@ * **/ +#include #include #include #include @@ -457,8 +458,7 @@ void BotConsole(cBot *pBot) { // Here the bot will excecute the console commands if the console counter has been set/changed if (pBot->console_nr != 0 && pBot->f_console_timer < gpGlobals->time) { // safety net - if (pBot->console_nr < 0) - pBot->console_nr = 0; // Set it to 0 + pBot->console_nr = std::max(pBot->console_nr, 0); // Set it to 0 // issue command (buy/radio) if (pBot->console_nr == 1) diff --git a/bot_client.cpp b/bot_client.cpp index b7d139c..9aca41b 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -27,6 +27,7 @@ * **/ +#include #include #include #include @@ -825,8 +826,7 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { float length = (static_cast(duration + hold_time)) / 4096.0f; int iDevide = bots[bot_index].bot_skill; - if (iDevide < 1) - iDevide = 1; + iDevide = std::max(iDevide, 1); length -= (static_cast(10) / static_cast(iDevide) * 0.5f); diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 65f07bd..1a1a222 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -43,7 +43,7 @@ extern int mod_id; extern edict_t *pHostEdict; -enum +enum : std::uint8_t { SCAN_RADIUS = 60 // Radius to scan to prevent blocking with players }; diff --git a/dll.cpp b/dll.cpp index b8f46ba..e6c9ca9 100644 --- a/dll.cpp +++ b/dll.cpp @@ -27,6 +27,7 @@ * **/ +#include #include #include #include @@ -868,8 +869,7 @@ void StartFrame() { ChatEngine.think(); // Keep number of bots up-to-date. - if (count > num_bots) - num_bots = count; + num_bots = std::max(count, num_bots); // handle radio commands if (radio_message) { @@ -1269,14 +1269,12 @@ void RealBot_ServerCommand() { } else if (FStrEq(pcmd, "chatrate")) { if (arg1 != nullptr && *arg1 != 0) { Game.iMaxSentences = std::atoi(arg1); - if (Game.iMaxSentences < -1) - Game.iMaxSentences = -1; + Game.iMaxSentences = std::max(Game.iMaxSentences, -1); - if (Game.iMaxSentences > 10) - Game.iMaxSentences = 10; + Game.iMaxSentences = std::min(Game.iMaxSentences, 10); snprintf(cMessage, sizeof(cMessage), "REALBOT: Chat-rate set to %d", - Game.iMaxSentences); + Game.iMaxSentences); } else { snprintf(cMessage, sizeof(cMessage), "REALBOT: No argument given, current chat-rate is %d", @@ -1408,9 +1406,8 @@ void RealBot_ServerCommand() { // switch on/off internet mode int temp = std::atoi(arg1); if (temp > -1) { - if (temp < 1) - temp = 1; - internet_min_interval = temp; + temp = std::max(temp, 1); + internet_min_interval = temp; } } // 2nd argument @@ -1419,9 +1416,8 @@ void RealBot_ServerCommand() { // switch on/off internet mode int temp = std::atoi(arg2); if (temp > -1) { - if (temp < internet_min_interval) - temp = internet_min_interval; - internet_max_interval = temp; + temp = std::max(temp, internet_min_interval); + internet_max_interval = temp; } } // Create message @@ -1436,10 +1432,8 @@ void RealBot_ServerCommand() { // get amount const int temp = std::atoi(arg1); kick_amount_bots = temp; - if (kick_amount_bots > 31) - kick_amount_bots = 31; - if (kick_amount_bots < 0) - kick_amount_bots = 0; + kick_amount_bots = std::min(kick_amount_bots, 31); + kick_amount_bots = std::max(kick_amount_bots, 0); } // ARG 2 - Team if (arg2 != nullptr && *arg2 != 0) { @@ -1507,16 +1501,11 @@ void RealBot_ServerCommand() { } else { if (s2 < -1) s2 = Game.iRandomMaxSkill; - if (s1 > 10) - s1 = 10; - if (s1 < 0) - s1 = 0; - if (s2 > 10) - s2 = 10; - if (s2 < 0) - s2 = 0; - if (s2 < s1) // be sure s1 is lower then s2 or atleast the same - s2 = s1; + s1 = std::min(s1, 10); + s1 = std::max(s1, 0); + s2 = std::min(s2, 10); + s2 = std::max(s2, 0); + s2 = std::max(s2, s1); Game.iRandomMinSkill = s1; Game.iRandomMaxSkill = s2; snprintf(cMessage, sizeof(cMessage), @@ -1578,10 +1567,8 @@ void RealBot_ServerCommand() { if (FStrEq(arg1, "players")) { if (arg2 != nullptr && *arg2 != 0) { int temp = std::atoi(arg2); // argument - if (temp > 31) - temp = 31; - if (temp < -1) - temp = -1; + temp = std::min(temp, 31); + temp = std::max(temp, -1); min_players = temp; f_minplayers_think = gpGlobals->time; @@ -1597,10 +1584,8 @@ void RealBot_ServerCommand() { // How do we broadcast version message? if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument - if (temp <= 0) - temp = 0; - if (temp >= 1) - temp = 1; + temp = std::max(temp, 0); + temp = std::min(temp, 1); Game.iVersionBroadcasting = temp; if (Game.iVersionBroadcasting == BROADCAST_ROUND) snprintf(cMessage, sizeof(cMessage), @@ -1627,10 +1612,8 @@ void RealBot_ServerCommand() { // How do we broadcast kills by bots? if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument - if (temp <= 0) - temp = 0; - if (temp >= 2) - temp = 2; + temp = std::max(temp, 0); + temp = std::min(temp, 2); if (temp == 0) Game.iKillsBroadcasting = BROADCAST_KILLS_FULL; if (temp == 1) @@ -1662,10 +1645,8 @@ void RealBot_ServerCommand() { // How do we broadcast deaths by bots. if (arg3 != nullptr && *arg3 != 0) { int temp = std::atoi(arg3); // argument - if (temp <= 0) - temp = 0; - if (temp >= 2) - temp = 2; + temp = std::max(temp, 0); + temp = std::min(temp, 2); if (temp == 0) Game.iDeathsBroadcasting = BROADCAST_DEATHS_FULL; if (temp == 1) diff --git a/game.cpp b/game.cpp index 9acbff4..1b8e03d 100644 --- a/game.cpp +++ b/game.cpp @@ -27,6 +27,7 @@ * **/ +#include #include #include #include @@ -160,7 +161,7 @@ char *cGame::RandomSentence() { return cSpeechSentences[RANDOM_LONG(0, 15)]; } -void cGame::DetermineMapGoal() const +void cGame::DetermineMapGoal() { rblog("DetermineMapGoal called\n"); edict_t *pEnt = nullptr; @@ -253,10 +254,8 @@ void cGame::SetPlayingRounds(int iMin, int iMax) { iMaxPlayRounds = iMax; // Boundries - if (iMinPlayRounds < 1) - iMinPlayRounds = 1; - if (iMaxPlayRounds < 2) - iMaxPlayRounds = 2; + iMinPlayRounds = std::max(iMinPlayRounds, 1); + iMaxPlayRounds = std::max(iMaxPlayRounds, 2); // Make sure MAX never is lower then MIN if (iMinPlayRounds > iMaxPlayRounds) diff --git a/game.h b/game.h index a0ac0f7..495ecdf 100644 --- a/game.h +++ b/game.h @@ -81,7 +81,7 @@ class cGame { void SetNewRound(bool bState); void resetRoundTime(); void SetRoundTime(float fTime); - void DetermineMapGoal() const; + static void DetermineMapGoal(); // --------------------- char *RandomSentence(); diff --git a/util.cpp b/util.cpp index fa6b52d..78420d3 100644 --- a/util.cpp +++ b/util.cpp @@ -42,6 +42,7 @@ * **/ +#include #include #include #include @@ -818,8 +819,7 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, const char* arg1, const char* a // 02/07/04 - pointed out, eliminate any possible 'devide by zero' int iExtra = 100 / (pBot->ipCreateRadio + 1); - if (iExtra > 30) - iExtra = 30; + iExtra = std::min(iExtra, 30); pBot->fDoRadio = gpGlobals->time + static_cast(iExtra); } } @@ -854,10 +854,9 @@ int UTIL_GetGrenadeType(edict_t* pEntity) { // 2 functions from podbot source unsigned short fixed_unsigned16(float value, float scale) { int output = static_cast(value * scale); - if (output < 0) - output = 0; - if (output > 0xFFFF) - output = 0xFFFF; + + output = std::max(output, 0); + output = std::min(output, 0xFFFF); return static_cast(output); } @@ -865,11 +864,8 @@ unsigned short fixed_unsigned16(float value, float scale) { short fixed_signed16(float value, float scale) { int output = static_cast(value * scale); - if (output > 32767) - output = 32767; - - if (output < -32768) - output = -32768; + output = std::min(output, 32767); + output = std::max(output, -32768); return static_cast(output); } From 4a804cd87e785f289f26aacdf4b07a597327b78a Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Mon, 9 Dec 2024 21:59:43 +0000 Subject: [PATCH 087/114] Splitting the NodeMachine implementations --- ChatEngine.cpp | 144 +++++++-------- ChatEngine.h | 5 +- NodeDataTypes.h | 1 + NodeMachine.cpp | 100 +++++----- NodeMachine.h | 15 ++ bot.cpp | 471 ++++++++++++++++++++++++----------------------- bot_func.cpp | 47 +++-- bot_func.h | 1 + bot_navigate.cpp | 360 ++++++++++++++++++------------------ engine.cpp | 3 + game.cpp | 2 +- 11 files changed, 590 insertions(+), 559 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 989c4e4..16f1f87 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -33,7 +33,6 @@ // Some tests by EVYNCKE #include #include -#include #include #include @@ -48,21 +47,20 @@ #include "ChatEngine.h" -extern edict_t *pHostEdict; +extern edict_t* pHostEdict; extern cGame Game; extern cBot bots[32]; // initialize all -void -cChatEngine::init() { +void cChatEngine::init() { // clear all blocks for (tReplyBlock& iB : ReplyBlock) { - for (char (&iBs)[128] : iB.sentence) - iBs[0] = '\0'; + for (char(&iBs)[128] : iB.sentence) + iBs[0] = '\0'; - for (char (&iBw)[25] : iB.word) - iBw[0] = '\0'; + for (char(&iBw)[25] : iB.word) + iBw[0] = '\0'; iB.bUsed = false; } @@ -97,9 +95,9 @@ void cChatEngine::think() { // 29/08/2019 Stefan: by using string compare on the name of the sender (ie sender[] is the name) we retrieve // the edict pointer - edict_t *pSender = nullptr; + edict_t* pSender = nullptr; for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if (pPlayer && !pPlayer->free) { char name[30] = {}, name2[30] = {}; @@ -127,7 +125,7 @@ void cChatEngine::think() { // When length is not valid, get out. // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? // how did we allow for this to happen? - if (sentenceLength == 0 || sentenceLength >= MAX_SENTENCE_LENGTH-1) { + if (sentenceLength == 0 || sentenceLength >= MAX_SENTENCE_LENGTH - 1) { // clear out sentence and sender std::memset(sentence, 0, sizeof(sentence)); std::memset(sender, 0, sizeof(sender)); @@ -143,7 +141,7 @@ void cChatEngine::think() { // Init, none of the block has a score yet (set to -1) for (int& wbs : WordBlockScore) { - wbs = -1; + wbs = -1; } // loop over the sentence character by character @@ -169,10 +167,11 @@ void cChatEngine::think() { // not a good word (too small) if (std::strlen(word) <= 0) { //SERVER_PRINT("This is not a good word!\n"); - } else { + } + else { for (int iB = 0; iB < MAX_BLOCKS; iB++) { if (ReplyBlock[iB].bUsed) { - for (const char (&iBw)[25] : ReplyBlock[iB].word) + for (const char(&iBw)[25] : ReplyBlock[iB].word) { // skip any word in the reply block that is not valid if (iBw[0] == '\0') @@ -230,7 +229,7 @@ void cChatEngine::think() { int iMax = -1; // now choose a sentence to reply with - for (const char (&iS)[128] : ReplyBlock[iTheBlock].sentence) + for (const char(&iS)[128] : ReplyBlock[iTheBlock].sentence) { // Find max sentences of this reply block if (iS[0] != '\0') @@ -239,17 +238,17 @@ void cChatEngine::think() { // loop through all bots: for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pSender != pPlayer) { - const bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here - const bool bPlayerAlive = IsAlive(pPlayer); + const bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here + const bool bPlayerAlive = IsAlive(pPlayer); if (bSenderAlive != bPlayerAlive) continue; - cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + cBot* pBotPointer = UTIL_GetBotPointer(pPlayer); if (pBotPointer != nullptr) if (RANDOM_LONG(0, 100) < @@ -273,7 +272,7 @@ void cChatEngine::think() { // the_c is choosen, it is the sentence we reply with. // do a check if its valid: if (ReplyBlock[iTheBlock]. - sentence[the_c][0] != '\0') { + sentence[the_c][0] != '\0') { // chSentence is eventually what the bot will say. char chSentence[128]; @@ -283,16 +282,16 @@ void cChatEngine::think() { std::memset(temp, 0, sizeof(temp)); // get character position - const char *name_pos = - std::strstr(ReplyBlock[iTheBlock]. - sentence[the_c], "%n"); + const char* name_pos = + std::strstr(ReplyBlock[iTheBlock]. + sentence[the_c], "%n"); // when name_pos var is found, fill it in. if (name_pos != nullptr) { // when name is in this one: int name_offset = - name_pos - - ReplyBlock[iTheBlock].sentence[the_c]; + name_pos - + ReplyBlock[iTheBlock].sentence[the_c]; name_offset--; // copy every character till name_offset @@ -300,8 +299,8 @@ void cChatEngine::think() { for (nC = 0; nC < name_offset; nC++) { //chSentence[nC] = ReplyBlock[iTheBlock].sentence[the_c][nC]; temp[nC] = - ReplyBlock[iTheBlock]. - sentence[the_c][nC]; + ReplyBlock[iTheBlock]. + sentence[the_c][nC]; } temp[nC] = ' '; @@ -320,15 +319,15 @@ void cChatEngine::think() { // get entire length of ReplyBlock and go until we reach the end const int length = static_cast(std::strlen(ReplyBlock[iTheBlock]. - sentence[the_c])); + sentence[the_c])); // for every nC , read character from ReplyBlock for (; nC <= length; nC++) { // ... and copy it into chSentence temp[tc] = - ReplyBlock[iTheBlock]. - sentence[the_c][nC]; + ReplyBlock[iTheBlock]. + sentence[the_c][nC]; //char tmsg[80]; //sprintf(tmsg,"Copying char %c , tc = %d, nC = %d\n", temp[tc], tc, nC); //SERVER_PRINT(tmsg); @@ -341,10 +340,10 @@ void cChatEngine::think() { snprintf(chSentence, sizeof(chSentence), "%s \n", temp); } - // when no name pos is found, we just copy the string and say that (works ok) + // when no name pos is found, we just copy the string and say that (works ok) else - snprintf(chSentence, sizeof(chSentence), "%s \n", - ReplyBlock[iTheBlock].sentence[the_c]); + snprintf(chSentence, sizeof(chSentence), "%s \n", + ReplyBlock[iTheBlock].sentence[the_c]); // reply: pBotPointer->PrepareChat(chSentence); @@ -370,61 +369,46 @@ void cChatEngine::think() { fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); } -void cChatEngine::handle_sentence() //Experimental implementation [APG]RoboCop[CL] -{ - // if we have a sentence to say - if (sentence[0] != '\0') { - // loop through all bots: - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - - // skip invalid players and skip self (i.e. this bot) - if (pPlayer && !pPlayer->free) { - cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); - - if (pBotPointer != nullptr) - if (RANDOM_LONG(0, 100) < - pBotPointer->ipChatRate + 25) { - // reply: - pBotPointer->PrepareChat(sentence); - //UTIL_SayTextBot(sentence, pBotPointer); - } - } - } - } - - // clear sentence and such - std::memset(sentence, 0, sizeof(sentence)); - std::memset(sender, 0, sizeof(sender)); - - fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); +void cChatEngine::handle_sentence() { + // Define a constant for the chat rate threshold + constexpr int CHAT_RATE_THRESHOLD = 25; + + // Check if there is a sentence to process + if (sentence[0] == '\0') { + return; + } + + // Loop through all clients + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + + // Skip invalid players + if (pPlayer && !pPlayer->free) { + cBot* pBotPointer = UTIL_GetBotPointer(pPlayer); + + // Check if bot pointer is valid and decide to prepare chat + if (pBotPointer != nullptr && RANDOM_LONG(0, 100) < pBotPointer->ipChatRate + CHAT_RATE_THRESHOLD) { + pBotPointer->PrepareChat(sentence); + } + } + } + + // Clear sentence and sender buffers + std::memset(sentence, 0, sizeof(sentence)); + std::memset(sender, 0, sizeof(sender)); + + // Set the think timer + fThinkTimer = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f); } -// -void cChatEngine::set_sentence(char csender[30], char csentence[MAX_SENTENCE_LENGTH]) { +void cChatEngine::set_sentence(char csender[MAX_NAME_LENGTH], char csentence[MAX_SENTENCE_LENGTH]) { if (sender[0] == ' ' || sender[0] == '\0') { - // SERVER_PRINT("Sender & sentence set.\nSender="); - // SERVER_PRINT(csender); - // SERVER_PRINT("\nSentence="); - // SERVER_PRINT(csentence); - // SERVER_PRINT("--\n"); - std::strcpy(sender, csender); #ifdef _WIN32 - _strupr(csentence); - // #elseif did not compile in MSVC - stefan (26/04/04) #else - //for linux by ok: - //further changed back by evyncke as these are normal string not CString - //Hence, hardcoding the strupr inline... - char *pString; - pString = csentence; - while (*pString) { - *pString = toupper(*pString); - pString++; - } + std::transform(csentence, csentence + std::strlen(csentence), csentence, ::toupper); #endif std::strcpy(sentence, csentence); } diff --git a/ChatEngine.h b/ChatEngine.h index 8f5eabf..8f5884d 100644 --- a/ChatEngine.h +++ b/ChatEngine.h @@ -31,7 +31,8 @@ #ifndef CHATENGINE_H #define CHATENGINE_H -#define MAX_BLOCKS 100 +constexpr int MAX_BLOCKS = 100; + #define BLOCK_DEATHS (MAX_BLOCKS-1) static constexpr int MAX_SENTENCE_LENGTH = 128; @@ -62,7 +63,7 @@ class cChatEngine { void think(); // make the chat engine think // add sentence from any player/bot into memory to handle - void set_sentence(char csender[30], char csentence[MAX_SENTENCE_LENGTH]); + void set_sentence(char csender[32], char csentence[MAX_SENTENCE_LENGTH]); // handles a sentence, decides to reply on it or not. void handle_sentence(); diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 4613ca0..cb38c1f 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -177,6 +177,7 @@ typedef struct { Vector origin; // Node origin int iNeighbour[MAX_NEIGHBOURS]; // Reachable nodes for this node int iNodeBits; + int index; } tNode; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 36cd6ea..328db28 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -145,41 +145,44 @@ void cNodeMachine::init() { rblog("cNodeMachine::init() - START\n"); iMaxUsedNodes = 0; - for (int i = 0; i < MAX_NODES; i++) { - // --- nodes - Nodes[i].origin = Vector(9999, 9999, 9999); - for (int& n : Nodes[i].iNeighbour) - n = -1; + initNodes(); + initTroubles(); + initGoals(); + initPaths(); + initVisTable(); + initMeredians(); - // No bits set - Nodes[i].iNodeBits = 0; + rblog("cNodeMachine::init() - END\n"); +} - // --- info nodes - for (float& d : InfoNodes[i].fDanger) - { - d = 0.0f; - } +void cNodeMachine::initNodes() { + for (tNode& node : Nodes) { + initializeNode(node); } +} +void cNodeMachine::initializeNode(tNode& node) { + node.origin = INVALID_VECTOR; + std::fill(std::begin(node.iNeighbour), std::end(node.iNeighbour), -1); + node.iNodeBits = 0; + std::fill(std::begin(InfoNodes[node.index].fDanger), std::end(InfoNodes[node.index].fDanger), 0.0f); +} - // Init trouble - for (tTrouble& Trouble : Troubles) - { - Trouble.iFrom = -1; - Trouble.iTo = -1; - Trouble.iTries = -1; +void cNodeMachine::initTroubles() { + for (tTrouble& Trouble : Troubles) { + Trouble.iFrom = -1; + Trouble.iTo = -1; + Trouble.iTries = -1; } +} - initGoals(); - - // Init paths - for (int p = 0; p < MAX_BOTS; p++) +void cNodeMachine::initPaths() { + for (int p = 0; p < MAX_BOTS; p++) { path_clear(p); - - // Init VisTable - for (unsigned char& iVx : iVisChecked) - { - iVx = 0; // not checked yet } +} + +void cNodeMachine::initVisTable() { + std::fill(std::begin(iVisChecked), std::end(iVisChecked), 0); // CODE: From cheesemonster constexpr unsigned long iSize = g_iMaxVisibilityByte; @@ -191,19 +194,17 @@ void cNodeMachine::init() { std::memset(cVisTable, 0, iSize); } else { - rblog("cNodeMachine::init() - ERROR: Could not allocate memory for visibility table\n"); + rblog("cNodeMachine::init() - ERROR: Could not allocate memory for visibility table\n"); } - ClearVisibilityTable(); - // END: - - // Init Meredians - for (tMeredian (&Meredian)[64] : Meredians) - for (tMeredian& iMy : Meredian) - for (int& iNode : iMy.iNodes) - iNode = -1; +} - rblog("cNodeMachine::init() - END\n"); +void cNodeMachine::initMeredians() { + for (tMeredian (&Meredian)[64] : Meredians) { + for (tMeredian& iMy : Meredian) { + std::fill(std::begin(iMy.iNodes), std::end(iMy.iNodes), -1); + } + } } void cNodeMachine::initGoals() { @@ -2292,7 +2293,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based } - const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); + const Vector& INVALID_VECTOR = Vector(9999, 9999, 9999); // start or target vector may not be invalid if (Nodes[nodeStartIndex].origin == INVALID_VECTOR || @@ -2311,7 +2312,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // Our start waypoint is open constexpr float gCost = 0.0f; // distance from starting node const float hCost = func_distance(Nodes[nodeStartIndex].origin, - Nodes[nodeTargetIndex].origin); // distance from end node to node + Nodes[nodeTargetIndex].origin); // distance from end node to node const float cost = gCost + hCost; closeNode(nodeStartIndex, nodeStartIndex, cost); openNeighbourNodes(nodeStartIndex, nodeStartIndex, nodeTargetIndex, -1); @@ -2328,12 +2329,12 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // go through all OPEN waypoints for (nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { nodesEvaluated++; // increment nodesEvaluated each time a node is evaluated [APG]RoboCop[CL] - tNodestar &nodeStar = astar_list[nodeIndex]; + tNodestar& nodeStar = astar_list[nodeIndex]; if (nodeStar.state == CLOSED || nodeStar.state == AVAILABLE) continue; // OPEN waypoint - tNode &node = Nodes[nodeIndex]; + tNode& node = Nodes[nodeIndex]; if (node.origin == INVALID_VECTOR) { rblog("Evaluating an INVALID vector!?!\n"); nodeStar.state = CLOSED; @@ -2364,7 +2365,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn } openNeighbourNodes(nodeStartIndex, nodeToClose, nodeTargetIndex, botTeam); - } else { + } + else { break; } } @@ -2379,7 +2381,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn } for (nodeIndex = 0; nodeIndex < MAX_PATH_NODES; nodeIndex++) { - const tNodestar &nodeStar = astar_list[nodeIndex]; + const tNodestar& nodeStar = astar_list[nodeIndex]; if (nodeStar.state == AVAILABLE) continue; } @@ -2408,7 +2410,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn if (wpta == nodeStartIndex) { // Check if we did not already had this waypoint before built = true; // We finished building this path. - } else { + } + else { // Whenever wpta is containing bad information... if (wpta < 0 || wpta > MAX_NODES) break; // ...get out aswell @@ -2432,7 +2435,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn // Now set the path up correctly for (nodeIndex = MAX_NODES - 1; nodeIndex > -1; nodeIndex--) { - const int node = temp_path[nodeIndex]; + const int node = temp_path[nodeIndex]; if (node < 0) continue; @@ -2460,7 +2463,8 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn pBot->beginWalkingPath(); pBot->setTimeToMoveToNode(2); // set timer (how much time do we allow ourselves to reach the following node) pBot->rprint("cNodeMachine::createPath", "Path creation finished successfully"); - } else { + } + else { rblog("createPath (without bot) - path creation finished\n"); } @@ -3607,7 +3611,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { node_vector(Goals[goalIndex].iNode) ); - const float score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; + score = distanceToC4FromCloseNode / distanceToC4FromThisGoalNode; goalscore = 1.5f + score; std::memset(msg, 0, sizeof(msg)); snprintf(msg, sizeof(msg), "Distance from C4 to closest node is %f, distance from evaluating node to C4 is %f, resulting into score of %f", @@ -3703,7 +3707,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { snprintf(msg, sizeof(msg), "Evaluating goal %s gives a score of %f, highest score so far is %f", Goals[goalIndex].name, score, highestScore); pBot->rprint_trace("path_think/determine goal", msg); - if (score == highestScore && RANDOM_LONG(0,100) < 50) { + if (static_cast(score) == static_cast(highestScore) && RANDOM_LONG(0,100) < 50) { pBot->rprint_trace("path_think/determine goal", "SCORE == HIGHEST SCORE and chosen to override randomly."); highestScore = score; iFinalGoalNode = Goals[goalIndex].iNode; diff --git a/NodeMachine.h b/NodeMachine.h index 22cf353..9a62799 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -68,6 +68,14 @@ class cNodeMachine { // ----------------- void init(); // Init (info)nodes + + void initNodes(); + void initializeNode(tNode& node); + void initTroubles(); + void initPaths(); + void initVisTable(); + void initMeredians(); + void save() const; // Save nodes on disk void load(); // Load nodes on disk void save_important() const; @@ -206,7 +214,14 @@ class cNodeMachine { static void makeAllWaypointsAvailable(); + bool isValidNodeIndex(int index) const; + + bool isInvalidNode(int index) const; + + void buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot); + static void closeNode(int nodeIndex, int parent, float cost); + void openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) const; static std::string getGoalTypeAsText(const tGoal& goal); diff --git a/bot.cpp b/bot.cpp index 7b38231..b8ddf02 100644 --- a/bot.cpp +++ b/bot.cpp @@ -3637,241 +3637,242 @@ void cBot::UpdateStatus() { //////////////////////////////////////////////////////////////////////////////// /// Radio Action - Response //////////////////////////////////////////////////////////////////////////////// -bool BotRadioAction() { - char name[64]; - bool unstood = false; - edict_t *plr = nullptr; - int team = -1; - int i; - int radios = 0; // Hold amount of replies here, so we don't flood :) - std::strcpy(name, radio_messenger); - - // First find the team messager name - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); // Get pEdict - if (pPlayer) // If player exists - { - char netname[64]; - std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname - if (std::strcmp(netname, name) == 0) // If - { - plr = pPlayer; - team = UTIL_GetTeam(pPlayer); - } - } - } - - // Check players and check if radio message applies to them - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - if (pPlayer) { - char netname[64]; - - std::strcpy(netname, STRING(pPlayer->v.netname)); - - if (std::strcmp(netname, name) != 0 && // When not the same name - team == UTIL_GetTeam(pPlayer) && // .. the same team... - pPlayer->v.deadflag == DEAD_NO && // .. not dead .. - UTIL_GetBotPointer(pPlayer) != nullptr) // and a RealBot - { - // here are all bots - cBot *BotPointer = UTIL_GetBotPointer(pPlayer); - - if (BotPointer == nullptr) - continue; // somehow this fucked up, bail out - - const float distance = func_distance(plr->v.origin, - BotPointer->pEdict->v.origin); // distance between the 2 - - // Same team, randomly, do we even listen to the radio? - // the more further away, the more chance it will not listen - bool bWantToListen = false; - - // Reply on distance check - if (RANDOM_LONG(0, 8192) > distance) - bWantToListen = true; - - // Hearrate (personality setting) - if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && - bWantToListen) - bool want_to_answer = true; - - // If we want to listen to the radio... then handle it! - if (bWantToListen) { - bool can_do_negative = false; - - // Report in team! - if (std::strstr(message, "#Report_in_team") != nullptr) { - // gives human knowledge who is on his team - } - - // Regroup team! - if (std::strstr(message, "#Regroup_team") != nullptr) { - // regroup now! - unstood = true; - - // get to the leader position - BotPointer->rprint("Setting goal from regroup team"); - BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); - BotPointer->forgetPath(); - } - - // Hold this position - if (std::strstr(message, "#Hold_this_position") != nullptr || - std::strstr(message, "#Get_in_position_and_wait") != nullptr) { - // do nothing - } - // Follow me!! - if (std::strstr(message, "#Follow_me") != nullptr) {} - - // You take the point! - // 23/06/04 - Stefan - Here the leader should break up his position? - // ie, the leader will be assigned to the bot this human/bot is facing? - if (std::strstr(message, "#You_take_the_point") != nullptr) { - can_do_negative = false; - } - // Enemy Sotted! - if (std::strstr(message, "#Enemy_spotted") != nullptr) { - can_do_negative = false; - - // Find player who issues this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - // Help this player - if (iBackupNode > -1) { - - unstood = true; - - BotPointer->rprint("Setting goal for backup"); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - // Enemy Down! - if (std::strstr(message, "#Enemy_down") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); - - unstood = true; - can_do_negative = false; - } - // Stick together team! - if (std::strstr(message, "#Stick_together_team") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); - unstood = true; - can_do_negative = false; - } - // cover me|| strstr (message, "#Cover_me") != NULL - - // Need backup / taking fire... - if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); - - unstood = true; - - // get source of backup - const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - - // Taking fire! - if (std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); - unstood = true; - - // Find player who issued this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - - } - // Team fall back! - if (std::strstr(message, "#Team_fall_back") != nullptr) { - - } - // Go Go Go, stop camping, stop following, get the heck out of there! - if (std::strstr(message, "#Go_go_go") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); - unstood = true; - BotPointer->f_camp_time = gpGlobals->time - 30; - BotPointer->f_walk_time = gpGlobals->time; - BotPointer->f_cover_time = gpGlobals->time - 10; - BotPointer->f_hold_duck = gpGlobals->time - 10; - BotPointer->f_jump_time = gpGlobals->time - 10; - BotPointer->forgetPath(); - BotPointer->forgetGoal(); - } - - if (FUNC_DoRadio(BotPointer) && unstood) { - const int maxAllowedRadios = gpGlobals->maxClients / 4; - if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { - constexpr bool report_back = false; - - if constexpr (!report_back) { - UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! - } else { - UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! - } - - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); - radios++; - } - } - } // they even listen to the radio command? - else { - /* - // filter out the commands where we cannot reply with negative - // You take the point! - if (strstr (message, "#You_take_the_point") != NULL) - can_do_negative = false; - - // Enemy Sotted! - if (strstr (message, "#Enemy_spotted") != NULL) - can_do_negative = false; - - // Enemy Down! - if (strstr (message, "#Enemy_down") != NULL) - can_do_negative = false; - - if ((FUNC_DoRadio(BotPointer)) - && (unstood) && (can_do_negative)) - - { - if (BotPointer->console_nr == 0 - && radios < (gpGlobals->maxClients / 4)) - - { - if (report_back == false) - - { - UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); - radios++; - } - } - } - */ - } - } // End check! - } // If (Player) - } // FOR Clients - return true; +bool BotRadioAction() { + char name[64]; + bool unstood = false; + edict_t* plr = nullptr; + int team = -1; + int i; + int radios = 0; // Hold amount of replies here, so we don't flood :) + std::strcpy(name, radio_messenger); + + // First find the team messager name + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); // Get pEdict + if (pPlayer) // If player exists + { + char netname[64]; + std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname + if (std::strcmp(netname, name) == 0) // If + { + plr = pPlayer; + team = UTIL_GetTeam(pPlayer); + } + } + } + + // Check players and check if radio message applies to them + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + if (pPlayer) { + char netname[64]; + + std::strcpy(netname, STRING(pPlayer->v.netname)); + + if (std::strcmp(netname, name) != 0 && // When not the same name + team == UTIL_GetTeam(pPlayer) && // .. the same team... + pPlayer->v.deadflag == DEAD_NO && // .. not dead .. + UTIL_GetBotPointer(pPlayer) != nullptr) // and a RealBot + { + // here are all bots + cBot* BotPointer = UTIL_GetBotPointer(pPlayer); + + if (BotPointer == nullptr) + continue; // somehow this fucked up, bail out + + const float distance = func_distance(plr->v.origin, + BotPointer->pEdict->v.origin); // distance between the 2 + + // Same team, randomly, do we even listen to the radio? + // the more further away, the more chance it will not listen + bool bWantToListen = false; + + // Reply on distance check + if (RANDOM_LONG(0, 8192) > distance) + bWantToListen = true; + + // Hearrate (personality setting) + if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && + bWantToListen) + bool want_to_answer = true; + + // If we want to listen to the radio... then handle it! + if (bWantToListen) { + bool can_do_negative = false; + + // Report in team! + if (std::strstr(message, "#Report_in_team") != nullptr) { + // gives human knowledge who is on his team + } + + // Regroup team! + if (std::strstr(message, "#Regroup_team") != nullptr) { + // regroup now! + unstood = true; + + // get to the leader position + BotPointer->rprint("Setting goal from regroup team"); + BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); + BotPointer->forgetPath(); + } + + // Hold this position + if (std::strstr(message, "#Hold_this_position") != nullptr || + std::strstr(message, "#Get_in_position_and_wait") != nullptr) { + // do nothing + } + // Follow me!! + if (std::strstr(message, "#Follow_me") != nullptr) {} + + // You take the point! + // 23/06/04 - Stefan - Here the leader should break up his position? + // ie, the leader will be assigned to the bot this human/bot is facing? + if (std::strstr(message, "#You_take_the_point") != nullptr) { + can_do_negative = false; + } + // Enemy Sotted! + if (std::strstr(message, "#Enemy_spotted") != nullptr) { + can_do_negative = false; + + // Find player who issues this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + // Help this player + if (iBackupNode > -1) { + + unstood = true; + + BotPointer->rprint("Setting goal for backup"); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + // Enemy Down! + if (std::strstr(message, "#Enemy_down") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); + + unstood = true; + can_do_negative = false; + } + // Stick together team! + if (std::strstr(message, "#Stick_together_team") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); + unstood = true; + can_do_negative = false; + } + // cover me|| strstr (message, "#Cover_me") != NULL + + // Need backup / taking fire... + if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); + + unstood = true; + + // get source of backup + const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + + // Taking fire! + if (std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); + unstood = true; + + // Find player who issued this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + + } + // Team fall back! + if (std::strstr(message, "#Team_fall_back") != nullptr) { + + } + // Go Go Go, stop camping, stop following, get the heck out of there! + if (std::strstr(message, "#Go_go_go") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); + unstood = true; + BotPointer->f_camp_time = gpGlobals->time - 30; + BotPointer->f_walk_time = gpGlobals->time; + BotPointer->f_cover_time = gpGlobals->time - 10; + BotPointer->f_hold_duck = gpGlobals->time - 10; + BotPointer->f_jump_time = gpGlobals->time - 10; + BotPointer->forgetPath(); + BotPointer->forgetGoal(); + } + + if (FUNC_DoRadio(BotPointer) && unstood) { + const int maxAllowedRadios = gpGlobals->maxClients / 4; + if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { + constexpr bool report_back = false; + + if constexpr (!report_back) { + UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! + } + else { + UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! + } + + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); + radios++; + } + } + } // they even listen to the radio command? + else { + /* + // filter out the commands where we cannot reply with negative + // You take the point! + if (strstr (message, "#You_take_the_point") != NULL) + can_do_negative = false; + + // Enemy Sotted! + if (strstr (message, "#Enemy_spotted") != NULL) + can_do_negative = false; + + // Enemy Down! + if (strstr (message, "#Enemy_down") != NULL) + can_do_negative = false; + + if ((FUNC_DoRadio(BotPointer)) + && (unstood) && (can_do_negative)) + + { + if (BotPointer->console_nr == 0 + && radios < (gpGlobals->maxClients / 4)) + + { + if (report_back == false) + + { + UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); + radios++; + } + } + } + */ + } + } // End check! + } // If (Player) + } // FOR Clients + return true; } // Is entity visible? (from Entity view) diff --git a/bot_func.cpp b/bot_func.cpp index 993d2ed..4561046 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -858,27 +858,46 @@ bool FUNC_IsOnLadder(const edict_t *pEntity) { return false; } -void FUNC_FindBreakable(edict_t* pEntity) //TODO: not functioning, bots won't shoot windows nor vent doors to proceed [APG]RoboCop[CL] +void FUNC_FindBreakable(cBot* pBot) //TODO: not functioning, bots won't shoot windows nor vent doors to proceed [APG]RoboCop[CL] { // The "func_breakable" entity required for glass breaking and weak doors for bots to recognise, - // in order to attack breakable objects that would block their way. - - for (int i = 0; i < gpGlobals->maxEntities; i++) { - edict_t* pEdict = INDEXENT(i); + // in order to attack breakable objects that would block their way. - if (pEdict == nullptr) - continue; + if (pBot == nullptr) { + return; // Ensure pBot is not null + } - if (pEdict->v.flags & FL_DORMANT) - continue; + for (int i = 0; i < gpGlobals->maxEntities; ++i) { + edict_t* pEdict = INDEXENT(i); + if (pEdict == nullptr || (pEdict->v.flags & FL_DORMANT)) { + continue; // Skip null or dormant entities + } - if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "func_breakable") == 0) { - if (pEdict->v.origin == pEntity->v.origin) { - pEntity->v.enemy = pEdict; - return; + const char* classname = STRING(pEdict->v.classname); + + if (classname != nullptr && std::strcmp(classname, "func_breakable") == 0) { + if (pBot->canSeeEntity(pEdict)) { + + constexpr float SHOOT_WAIT_TIME = 1.0f; + constexpr float SHOOT_DELAY = 0.1f; + + // Set the breakable entity as the bot's enemy + pBot->pEdict->v.enemy = pEdict; + + // Set shooting times + pBot->f_shoot_time = gpGlobals->time + SHOOT_DELAY; + pBot->f_shoot_wait_time = gpGlobals->time + SHOOT_WAIT_TIME; + + // Aim at the breakable entity + pBot->vBody = pEdict->v.origin; + pBot->vHead = pEdict->v.origin; + + // Shoot at the breakable entity + UTIL_BotPressKey(pBot, IN_ATTACK); + return; // Exit after finding the first breakable entity } } - } + } } /*bool IsShootableBreakable(edict_t* pent) // KWo - 08.02.2006 diff --git a/bot_func.h b/bot_func.h index 87eba12..75a82bd 100644 --- a/bot_func.h +++ b/bot_func.h @@ -35,6 +35,7 @@ void BotThink(cBot * pBot); void botFixIdealPitch(edict_t * pEdict); void botFixIdealYaw(edict_t * pEdict); +bool traceLine(const Vector& v_source, const Vector& v_dest, const edict_t* pEdict, TraceResult& tr); bool BotCanJumpUp(const cBot * pBot); bool BotCanDuckUnder(const cBot * pBot); diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 1a1a222..ca8b57c 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -39,14 +39,11 @@ #include "bot_func.h" #include "game.h" #include "NodeMachine.h" -extern int mod_id; -extern edict_t *pHostEdict; +extern int mod_id; +extern edict_t* pHostEdict; -enum : std::uint8_t -{ - SCAN_RADIUS = 60 // Radius to scan to prevent blocking with players -}; +constexpr std::uint8_t SCAN_RADIUS = 60; // Radius to scan to prevent blocking with players /** * Given an angle, makes sure it wraps around properly @@ -59,241 +56,246 @@ float fixAngle(float angle) { return angle; } -void botFixIdealPitch(edict_t * pEdict) { +void botFixIdealPitch(edict_t* pEdict) { pEdict->v.idealpitch = fixAngle(pEdict->v.idealpitch); } -void botFixIdealYaw(edict_t * pEdict) { +void botFixIdealYaw(edict_t* pEdict) { pEdict->v.ideal_yaw = fixAngle(pEdict->v.ideal_yaw); } -bool BotCanJumpUp(const cBot * pBot) { - // What I do here is trace 3 lines straight out, one unit higher than - // the highest normal jumping distance. I trace once at the center of - // the body, once at the right side, and once at the left side. If all - // three of these TraceLines don't hit an obstruction then I know the - // area to jump to is clear. I then need to trace from head level, - // above where the bot will jump to, downward to see if there is anything - // blocking the jump. There could be a narrow opening that the body - // will not fit into. These horizontal and vertical TraceLines seem - // to catch most of the problems with falsely trying to jump on something - // that the bot can not get onto. +bool traceLine(const Vector& v_source, const Vector& v_dest, const edict_t* pEdict, TraceResult& tr) { + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pEdict->v.pContainingEntity, &tr); + return tr.flFraction >= 1.0f; +} + +bool BotCanJumpUp(const cBot* pBot) { + // What I do here is trace 3 lines straight out, one unit higher than + // the highest normal jumping distance. I trace once at the center of + // the body, once at the right side, and once at the left side. If all + // three of these TraceLines don't hit an obstruction then I know the + // area to jump to is clear. I then need to trace from head level, + // above where the bot will jump to, downward to see if there is anything + // blocking the jump. There could be a narrow opening that the body + // will not fit into. These horizontal and vertical TraceLines seem + // to catch most of the problems with falsely trying to jump on something + // that the bot can not get onto. - TraceResult tr; - const edict_t *pEdict = pBot->pEdict; + TraceResult tr; + const edict_t* pEdict = pBot->pEdict; - // convert current view angle to vectors for TraceLine math... + // convert current view angle to vectors for TraceLine math... - Vector v_jump = pEdict->v.v_angle; - v_jump.x = 0; // reset pitch to 0 (level horizontally) - v_jump.z = 0; // reset roll to 0 (straight up and down) + Vector v_jump = pEdict->v.v_angle; + v_jump.x = 0; // reset pitch to 0 (level horizontally) + v_jump.z = 0; // reset roll to 0 (straight up and down) - UTIL_MakeVectors(v_jump); + UTIL_MakeVectors(v_jump); - // use center of the body first... + // use center of the body first... - // maximum jump height is 45, so check one unit above that (46) - Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT); - Vector v_dest = v_source + gpGlobals->v_forward * 24; + // maximum jump height is 45, so check one unit above that (46) + Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT); + Vector v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at maximum jump height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, + // now check same height to one side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + MAX_JUMPHEIGHT); - v_dest = v_source + gpGlobals->v_forward * 24; + v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at maximum jump height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, + // now check same height on the other side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + MAX_JUMPHEIGHT); - v_dest = v_source + gpGlobals->v_forward * 24; + v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at maximum jump height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now trace from head level downward to check for obstructions... + // now trace from head level downward to check for obstructions... - // start of trace is 24 units in front of bot, 72 units above head... - v_source = pEdict->v.origin + gpGlobals->v_forward * 24; + // start of trace is 24 units in front of bot, 72 units above head... + v_source = pEdict->v.origin + gpGlobals->v_forward * 24; - // offset 72 units from top of head (72 + 36) - v_source.z = v_source.z + 108; + // offset 72 units from top of head (72 + 36) + v_source.z = v_source.z + 108; - // end point of trace is 99 units straight down from start... - // (99 is 108 minus the jump limit height which is 45 - 36 = 9) - // fix by stefan, max jump height is 63 , not 45! (using duckjump) - // 108 - (63-36) = 81 - v_dest = v_source + Vector(0, 0, -81); + // end point of trace is 99 units straight down from start... + // (99 is 108 minus the jump limit height which is 45 - 36 = 9) + // fix by stefan, max jump height is 63 , not 45! (using duckjump) + // 108 - (63-36) = 81 + v_dest = v_source + Vector(0, 0, -81); - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight down toward the ground... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z + 108; - v_dest = v_source + Vector(0, 0, -81); + // now check same height to one side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * 16 + + gpGlobals->v_forward * 24; + v_source.z = v_source.z + 108; + v_dest = v_source + Vector(0, 0, -81); - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight down toward the ground... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z + 108; - v_dest = v_source + Vector(0, 0, -81); + // now check same height on the other side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * -16 + + gpGlobals->v_forward * 24; + v_source.z = v_source.z + 108; + v_dest = v_source + Vector(0, 0, -81); - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight down toward the ground... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - return true; + return true; } -bool BotCanDuckUnder(const cBot * pBot) { - // What I do here is trace 3 lines straight out, one unit higher than - // the ducking height. I trace once at the center of the body, once - // at the right side, and once at the left side. If all three of these - // TraceLines don't hit an obstruction then I know the area to duck to - // is clear. I then need to trace from the ground up, 72 units, to make - // sure that there is something blocking the TraceLine. Then we know - // we can duck under it. +bool BotCanDuckUnder(const cBot* pBot) { + // What I do here is trace 3 lines straight out, one unit higher than + // the ducking height. I trace once at the center of the body, once + // at the right side, and once at the left side. If all three of these + // TraceLines don't hit an obstruction then I know the area to duck to + // is clear. I then need to trace from the ground up, 72 units, to make + // sure that there is something blocking the TraceLine. Then we know + // we can duck under it. - TraceResult tr; - const edict_t *pEdict = pBot->pEdict; + TraceResult tr; + const edict_t* pEdict = pBot->pEdict; - // convert current view angle to vectors for TraceLine math... + // convert current view angle to vectors for TraceLine math... - Vector v_duck = pEdict->v.v_angle; - v_duck.x = 0; // reset pitch to 0 (level horizontally) - v_duck.z = 0; // reset roll to 0 (straight up and down) + Vector v_duck = pEdict->v.v_angle; + v_duck.x = 0; // reset pitch to 0 (level horizontally) + v_duck.z = 0; // reset roll to 0 (straight up and down) - UTIL_MakeVectors(v_duck); + UTIL_MakeVectors(v_duck); - // use center of the body first... + // use center of the body first... - // duck height is 36, so check one unit above that (37) - Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + 37); - Vector v_dest = v_source + gpGlobals->v_forward * 24; + // duck height is 36, so check one unit above that (37) + Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + 37); + Vector v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at duck height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37); - v_dest = v_source + gpGlobals->v_forward * 24; + // now check same height to one side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37); + v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at duck height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, + // now check same height on the other side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, -36 + 37); - v_dest = v_source + gpGlobals->v_forward * 24; + v_dest = v_source + gpGlobals->v_forward * 24; - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line forward at duck height... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; + // if trace hit something, return FALSE + if (tr.flFraction < 1.0f) + return false; - // now trace from the ground up to check for object to duck under... + // now trace from the ground up to check for object to duck under... - // start of trace is 24 units in front of bot near ground... - v_source = pEdict->v.origin + gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up + // start of trace is 24 units in front of bot near ground... + v_source = pEdict->v.origin + gpGlobals->v_forward * 24; + v_source.z = v_source.z - 35; // offset to feet + 1 unit up - // end point of trace is 72 units straight up from start... - v_dest = v_source + Vector(0, 0, 72); + // end point of trace is 72 units straight up from start... + v_dest = v_source + Vector(0, 0, 72); - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight up in the air... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) - return false; + // if trace didn't hit something, return FALSE + if (tr.flFraction >= 1.0f) + return false; - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up - v_dest = v_source + Vector(0, 0, 72); + // now check same height to one side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * 16 + + gpGlobals->v_forward * 24; + v_source.z = v_source.z - 35; // offset to feet + 1 unit up + v_dest = v_source + Vector(0, 0, 72); - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight up in the air... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) - return false; + // if trace didn't hit something, return FALSE + if (tr.flFraction >= 1.0f) + return false; - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up - v_dest = v_source + Vector(0, 0, 72); + // now check same height on the other side of the bot... + v_source = + pEdict->v.origin + gpGlobals->v_right * -16 + + gpGlobals->v_forward * 24; + v_source.z = v_source.z - 35; // offset to feet + 1 unit up + v_dest = v_source + Vector(0, 0, 72); - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + // trace a line straight up in the air... + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, + pEdict->v.pContainingEntity, &tr); - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) - return false; + // if trace didn't hit something, return FALSE + if (tr.flFraction >= 1.0f) + return false; - return true; + return true; } diff --git a/engine.cpp b/engine.cpp index 32630a9..8605cc6 100644 --- a/engine.cpp +++ b/engine.cpp @@ -416,6 +416,9 @@ void pfnWriteString(const char *sz) { else if (std::strstr(sz, "Need backup") != nullptr) { std::strcpy(message, "#Need_backup"); } + else if (std::strstr(sz, "Enemy spotted") != nullptr) { + std::strcpy(message, "#Enemy_spotted"); + } else if (std::strstr(sz, "Taking Fire.. Need Assistance!") != nullptr) { std::strcpy(message, "#Taking_fire"); } diff --git a/game.cpp b/game.cpp index 1b8e03d..393fe5e 100644 --- a/game.cpp +++ b/game.cpp @@ -127,7 +127,7 @@ void cGame::InitNewRound() { DetermineMapGoal(); // initialize bots for new round - for (auto& bot : bots) + for (cBot& bot : bots) { if (bot.bIsUsed) { bot.NewRound(); From f124f08a0ea5d8cf93c17c3ae7cc76766e9139f9 Mon Sep 17 00:00:00 2001 From: Ryan Hunter Date: Fri, 27 Dec 2024 17:20:52 +0000 Subject: [PATCH 088/114] Experimental fixes to bot's navigation --- AMBuildScript | 16 +++----- bot.cpp | 9 +++++ bot.h | 1 + bot_func.cpp | 2 +- bot_func.h | 11 +++++ bot_navigate.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 128 insertions(+), 13 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index 5ff7ea3..3b34b49 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -35,14 +35,6 @@ if builder.cxx.target.platform == 'linux': '-mtune=generic', '-pipe', '-fPIC', - '-mmmx', - '-msse', - '-msse2', - '-msse3', - '-mssse3', - '-msse4', - '-msse4a', - '-msse4.1', '-msse4.2', '-mfpmath=sse', '-fno-strict-aliasing', @@ -99,12 +91,14 @@ if builder.options.optimize == '1': builder.cxx.defines += ['NDEBUG'] if builder.cxx.target.platform == 'linux': # Linux optimization flags - builder.cxx.cflags += ['-O2'] + builder.cxx.cflags += ['-O3'] elif builder.cxx.target.platform == 'windows': - # Windows optimization flags - builder.cxx.cflags += ['/Ox', '/Zo'] + # Windows optimization flags - /Ob3 needs to be after /Ox, enables aggressive function inling -caxanga334 + builder.cxx.cflags += ['/Ox', '/Zo', '/Ob3', '/GF'] # Windows optimization link flags builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + # This needs to be after our optimization flags which could otherwise disable it. + builder.cxx.cflags += ['/Oy-'] # Compiler options for debugging ( --enable-debug ) if builder.options.debug == '1': diff --git a/bot.cpp b/bot.cpp index b8ddf02..172f120 100644 --- a/bot.cpp +++ b/bot.cpp @@ -4404,6 +4404,15 @@ bool cBot::isJumping() { // Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] // +void cBot::doDuckJump(const Vector& vector) { + rprint_trace("doDuckJump", "With vector"); + // stay focussed with body and head to this vector + this->vHead = vector; + this->vBody = vector; + + doDuckJump(); +} + void cBot::doDuckJump(){ rprint_trace("doDuckJump", "no vector"); UTIL_BotPressKey(this, IN_DUCK); diff --git a/bot.h b/bot.h index 1f4ba1a..a49cc74 100644 --- a/bot.h +++ b/bot.h @@ -572,6 +572,7 @@ class cBot { bool isJumping(); // Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] + void doDuckJump(const Vector& vector); void doDuckJump(); bool isDuckJumping(); diff --git a/bot_func.cpp b/bot_func.cpp index 4561046..38f3b81 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -1197,7 +1197,7 @@ bool BOT_DecideTakeCover(cBot *pBot) { // logs into a file void rblog(const char* txt) { // output to stdout - printf("%s", txt); + //printf("%s", txt); // Excessive log spewing [APG]RoboCop[CL] // and to reallog file if (fpRblog) { diff --git a/bot_func.h b/bot_func.h index 75a82bd..1e79a78 100644 --- a/bot_func.h +++ b/bot_func.h @@ -33,12 +33,23 @@ //prototypes of bot functions... void BotThink(cBot * pBot); +float fixAngle(float angle); + void botFixIdealPitch(edict_t * pEdict); void botFixIdealYaw(edict_t * pEdict); bool traceLine(const Vector& v_source, const Vector& v_dest, const edict_t* pEdict, TraceResult& tr); bool BotCanJumpUp(const cBot * pBot); bool BotCanDuckUnder(const cBot * pBot); +bool isBotNearby(const cBot* pBot, float radius); +void adjustBotAngle(const cBot* pBot, float angle); +void avoidClustering(const cBot* pBot); +bool isPathBlocked(const cBot* pBot, const Vector& v_dest); +void adjustPathIfBlocked(const cBot* pBot); +bool performTrace(const Vector& v_source, const Vector& v_dest, edict_t* pEntity, TraceResult& tr); +bool isPathClear(const cBot* pBot, const Vector& v_dest); +void BotNavigate(const cBot* pBot); + bool EntityIsVisible(edict_t * pEntity, const Vector& dest); // bot_func.cpp diff --git a/bot_navigate.cpp b/bot_navigate.cpp index ca8b57c..240a044 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -43,6 +43,8 @@ extern int mod_id; extern edict_t* pHostEdict; +constexpr float TURN_ANGLE = 75.0f; // Degrees to turn when avoiding obstacles +constexpr float MOVE_DISTANCE = 24.0f; // Distance to move forward constexpr std::uint8_t SCAN_RADIUS = 60; // Radius to scan to prevent blocking with players /** @@ -50,7 +52,7 @@ constexpr std::uint8_t SCAN_RADIUS = 60; // Radius to scan to prevent blocking w * @param angle * @return */ -float fixAngle(float angle) { +float fixAngle(const float angle) { if (angle > 180.0f) return angle - 360.0f; if (angle < -180.0f) return angle + 360.0f; return angle; @@ -299,3 +301,101 @@ bool BotCanDuckUnder(const cBot* pBot) { return true; } + +bool isBotNearby(const cBot* pBot, const float radius) { + if (!pBot || !pBot->pEdict) { + return false; // Validate input + } + + for (int i = 0; i < gpGlobals->maxClients; ++i) { + edict_t* pPlayer = INDEXENT(i + 1); + + if (pPlayer && !pPlayer->free && pPlayer != pBot->pEdict) { + float distance = (pPlayer->v.origin - pBot->pEdict->v.origin).Length(); + if (distance < radius) { + return true; + } + } + } + + return false; +} + +void adjustBotAngle(const cBot* pBot, const float angle) { + if (!pBot || !pBot->pEdict) { + return; + } + + pBot->pEdict->v.v_angle.y += angle; + UTIL_MakeVectors(pBot->pEdict->v.v_angle); +} + +void avoidClustering(const cBot* pBot) { + if (!pBot) { + return; + } + + if (isBotNearby(pBot, SCAN_RADIUS)) { + adjustBotAngle(pBot, TURN_ANGLE); + } +} + +bool isPathBlocked(const cBot* pBot, const Vector& v_dest) { + if (!pBot || !pBot->pEdict) { + return true; // Assume blocked if input is invalid + } + + TraceResult tr; + const Vector v_source = pBot->pEdict->v.origin; + + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pBot->pEdict->v.pContainingEntity, &tr); + + return tr.flFraction < 1.0f; +} + +void adjustPathIfBlocked(const cBot* pBot) { + if (!pBot) { + return; + } + + Vector v_dest = pBot->pEdict->v.origin + gpGlobals->v_forward * MOVE_DISTANCE; + + if (isPathBlocked(pBot, v_dest)) { + adjustBotAngle(pBot, TURN_ANGLE); + } +} + +bool performTrace(const Vector& v_source, const Vector& v_dest, edict_t* pEntity, TraceResult& tr) { + UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pEntity, &tr); + + return tr.flFraction >= 1.0f; +} + +bool isPathClear(const cBot* pBot, const Vector& v_dest) { + if (!pBot || !pBot->pEdict) { + return false; // Invalid input, assume path is not clear + } + TraceResult tr; + + return performTrace(pBot->pEdict->v.origin, v_dest, pBot->pEdict->v.pContainingEntity, tr); +} + +void BotNavigate(const cBot* pBot) { + if (!pBot) { + return; + } + + // Avoid clustering + avoidClustering(pBot); + + // Adjust path if blocked + adjustPathIfBlocked(pBot); + + // Check if the path is clear before moving + Vector v_dest = pBot->pEdict->v.origin + gpGlobals->v_forward * MOVE_DISTANCE; + + if (!isPathBlocked(pBot, v_dest)) { + // Move the bot + pBot->pEdict->v.origin = v_dest; + } +} \ No newline at end of file From 15c5c33a31708ad0cd6b5c8d70af8b6e68953f27 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 27 Mar 2025 22:38:59 +0000 Subject: [PATCH 089/114] String modernisation --- AMBuildScript | 14 +- NodeMachine.cpp | 4 +- bot.cpp | 474 ++++++++++++++++++++++++------------------------ bot.h | 6 +- util.cpp | 10 +- 5 files changed, 254 insertions(+), 254 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index 3b34b49..2c92433 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -22,8 +22,8 @@ builder.cxx.defines += [ if builder.cxx.like('gcc'): builder.cxx.defines += [ - 'stricmp=strcasecmp', - 'strcmpi=strcasecmp' + 'stricmp=strcasecmp', + 'strcmpi=strcasecmp' ] builder.cxx.c_only_flags += ['-std=gnu99'] @@ -72,11 +72,11 @@ elif builder.cxx.target.platform == 'windows': builder.cxx.cflags += [] # Windows compiler C++ flags builder.cxx.cxxflags += [ - '/std:c++17', - '/arch:SSE2', + '/std:c++17', + '/arch:SSE2', '/fp:precise', - '/Qspectre', - '/EHsc' + '/Qspectre', + '/EHsc' ] # Windows linker flags builder.cxx.linkflags += [ @@ -97,7 +97,7 @@ if builder.options.optimize == '1': builder.cxx.cflags += ['/Ox', '/Zo', '/Ob3', '/GF'] # Windows optimization link flags builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] - # This needs to be after our optimization flags which could otherwise disable it. + # This needs to be after our optimization flags which could otherwise disable it. builder.cxx.cflags += ['/Oy-'] # Compiler options for debugging ( --enable-debug ) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 328db28..04bd503 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -4454,8 +4454,8 @@ void cNodeMachine::FindMinMax() const miny -= NODE_ZONE; // first compute the X and Y divider scale, and take the greatest of both - const float scalex = (1 + maxx - minx) / DEBUG_BMP_WIDTH; - const float scaley = (1 + maxy - miny) / DEBUG_BMP_WIDTH; + const float scalex = (1 + maxx - minx) / static_cast(DEBUG_BMP_WIDTH); + const float scaley = (1 + maxy - miny) / static_cast(DEBUG_BMP_WIDTH); if (scalex > scaley) scale = scalex + scalex / 100; // add a little offset (margin) for safety else diff --git a/bot.cpp b/bot.cpp index 172f120..2a91a0c 100644 --- a/bot.cpp +++ b/bot.cpp @@ -558,7 +558,7 @@ int cBot::FindEnemy() { // bCanSee = true; } - if (fDistance < fNearestDistance && bCanSee) { + if (fDistance < fNearestDistance && bCanSee) { fNearestDistance = fDistance; pNewEnemy = pPlayer; } @@ -3637,242 +3637,242 @@ void cBot::UpdateStatus() { //////////////////////////////////////////////////////////////////////////////// /// Radio Action - Response //////////////////////////////////////////////////////////////////////////////// -bool BotRadioAction() { - char name[64]; - bool unstood = false; - edict_t* plr = nullptr; - int team = -1; - int i; - int radios = 0; // Hold amount of replies here, so we don't flood :) - std::strcpy(name, radio_messenger); - - // First find the team messager name - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t* pPlayer = INDEXENT(i); // Get pEdict - if (pPlayer) // If player exists - { - char netname[64]; - std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname - if (std::strcmp(netname, name) == 0) // If - { - plr = pPlayer; - team = UTIL_GetTeam(pPlayer); - } - } - } - - // Check players and check if radio message applies to them - for (i = 1; i <= gpGlobals->maxClients; i++) { - edict_t* pPlayer = INDEXENT(i); - if (pPlayer) { - char netname[64]; - - std::strcpy(netname, STRING(pPlayer->v.netname)); - - if (std::strcmp(netname, name) != 0 && // When not the same name - team == UTIL_GetTeam(pPlayer) && // .. the same team... - pPlayer->v.deadflag == DEAD_NO && // .. not dead .. - UTIL_GetBotPointer(pPlayer) != nullptr) // and a RealBot - { - // here are all bots - cBot* BotPointer = UTIL_GetBotPointer(pPlayer); - - if (BotPointer == nullptr) - continue; // somehow this fucked up, bail out - - const float distance = func_distance(plr->v.origin, - BotPointer->pEdict->v.origin); // distance between the 2 - - // Same team, randomly, do we even listen to the radio? - // the more further away, the more chance it will not listen - bool bWantToListen = false; - - // Reply on distance check - if (RANDOM_LONG(0, 8192) > distance) - bWantToListen = true; - - // Hearrate (personality setting) - if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && - bWantToListen) - bool want_to_answer = true; - - // If we want to listen to the radio... then handle it! - if (bWantToListen) { - bool can_do_negative = false; - - // Report in team! - if (std::strstr(message, "#Report_in_team") != nullptr) { - // gives human knowledge who is on his team - } - - // Regroup team! - if (std::strstr(message, "#Regroup_team") != nullptr) { - // regroup now! - unstood = true; - - // get to the leader position - BotPointer->rprint("Setting goal from regroup team"); - BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); - BotPointer->forgetPath(); - } - - // Hold this position - if (std::strstr(message, "#Hold_this_position") != nullptr || - std::strstr(message, "#Get_in_position_and_wait") != nullptr) { - // do nothing - } - // Follow me!! - if (std::strstr(message, "#Follow_me") != nullptr) {} - - // You take the point! - // 23/06/04 - Stefan - Here the leader should break up his position? - // ie, the leader will be assigned to the bot this human/bot is facing? - if (std::strstr(message, "#You_take_the_point") != nullptr) { - can_do_negative = false; - } - // Enemy Sotted! - if (std::strstr(message, "#Enemy_spotted") != nullptr) { - can_do_negative = false; - - // Find player who issues this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - // Help this player - if (iBackupNode > -1) { - - unstood = true; - - BotPointer->rprint("Setting goal for backup"); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - // Enemy Down! - if (std::strstr(message, "#Enemy_down") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); - - unstood = true; - can_do_negative = false; - } - // Stick together team! - if (std::strstr(message, "#Stick_together_team") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); - unstood = true; - can_do_negative = false; - } - // cover me|| strstr (message, "#Cover_me") != NULL - - // Need backup / taking fire... - if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); - - unstood = true; - - // get source of backup - const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - } - - // Taking fire! - if (std::strstr(message, "#Taking_fire") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); - unstood = true; - - // Find player who issued this message and go to it - const int iBackupNode = - NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); - - if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); - BotPointer->setGoalNode(iBackupNode); - BotPointer->forgetPath(); - BotPointer->f_camp_time = gpGlobals->time - 1; - BotPointer->f_walk_time = gpGlobals->time; - } - - } - // Team fall back! - if (std::strstr(message, "#Team_fall_back") != nullptr) { - - } - // Go Go Go, stop camping, stop following, get the heck out of there! - if (std::strstr(message, "#Go_go_go") != nullptr) { - BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); - unstood = true; - BotPointer->f_camp_time = gpGlobals->time - 30; - BotPointer->f_walk_time = gpGlobals->time; - BotPointer->f_cover_time = gpGlobals->time - 10; - BotPointer->f_hold_duck = gpGlobals->time - 10; - BotPointer->f_jump_time = gpGlobals->time - 10; - BotPointer->forgetPath(); - BotPointer->forgetGoal(); - } - - if (FUNC_DoRadio(BotPointer) && unstood) { - const int maxAllowedRadios = gpGlobals->maxClients / 4; - if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { - constexpr bool report_back = false; - - if constexpr (!report_back) { - UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! - } - else { - UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! - } - - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); - radios++; - } - } - } // they even listen to the radio command? - else { - /* - // filter out the commands where we cannot reply with negative - // You take the point! - if (strstr (message, "#You_take_the_point") != NULL) - can_do_negative = false; - - // Enemy Sotted! - if (strstr (message, "#Enemy_spotted") != NULL) - can_do_negative = false; - - // Enemy Down! - if (strstr (message, "#Enemy_down") != NULL) - can_do_negative = false; - - if ((FUNC_DoRadio(BotPointer)) - && (unstood) && (can_do_negative)) - - { - if (BotPointer->console_nr == 0 - && radios < (gpGlobals->maxClients / 4)) - - { - if (report_back == false) - - { - UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! - BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); - radios++; - } - } - } - */ - } - } // End check! - } // If (Player) - } // FOR Clients - return true; +bool BotRadioAction() { + char name[64]; + bool unstood = false; + edict_t* plr = nullptr; + int team = -1; + int i; + int radios = 0; // Hold amount of replies here, so we don't flood :) + std::strcpy(name, radio_messenger); + + // First find the team messager name + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); // Get pEdict + if (pPlayer) // If player exists + { + char netname[64]; + std::strcpy(netname, STRING(pPlayer->v.netname)); // Copy netname + if (std::strcmp(netname, name) == 0) // If + { + plr = pPlayer; + team = UTIL_GetTeam(pPlayer); + } + } + } + + // Check players and check if radio message applies to them + for (i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + if (pPlayer) { + char netname[64]; + + std::strcpy(netname, STRING(pPlayer->v.netname)); + + if (std::strcmp(netname, name) != 0 && // When not the same name + team == UTIL_GetTeam(pPlayer) && // .. the same team... + pPlayer->v.deadflag == DEAD_NO && // .. not dead .. + UTIL_GetBotPointer(pPlayer) != nullptr) // and a RealBot + { + // here are all bots + cBot* BotPointer = UTIL_GetBotPointer(pPlayer); + + if (BotPointer == nullptr) + continue; // somehow this fucked up, bail out + + const float distance = func_distance(plr->v.origin, + BotPointer->pEdict->v.origin); // distance between the 2 + + // Same team, randomly, do we even listen to the radio? + // the more further away, the more chance it will not listen + bool bWantToListen = false; + + // Reply on distance check + if (RANDOM_LONG(0, 8192) > distance) + bWantToListen = true; + + // Hearrate (personality setting) + if (RANDOM_LONG(0, 100) < BotPointer->ipHearRate && + bWantToListen) + bool want_to_answer = true; + + // If we want to listen to the radio... then handle it! + if (bWantToListen) { + bool can_do_negative = false; + + // Report in team! + if (std::strstr(message, "#Report_in_team") != nullptr) { + // gives human knowledge who is on his team + } + + // Regroup team! + if (std::strstr(message, "#Regroup_team") != nullptr) { + // regroup now! + unstood = true; + + // get to the leader position + BotPointer->rprint("Setting goal from regroup team"); + BotPointer->setGoalNode(NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE * 2, plr)); + BotPointer->forgetPath(); + } + + // Hold this position + if (std::strstr(message, "#Hold_this_position") != nullptr || + std::strstr(message, "#Get_in_position_and_wait") != nullptr) { + // do nothing + } + // Follow me!! + if (std::strstr(message, "#Follow_me") != nullptr) {} + + // You take the point! + // 23/06/04 - Stefan - Here the leader should break up his position? + // ie, the leader will be assigned to the bot this human/bot is facing? + if (std::strstr(message, "#You_take_the_point") != nullptr) { + can_do_negative = false; + } + // Enemy Sotted! + if (std::strstr(message, "#Enemy_spotted") != nullptr) { + can_do_negative = false; + + // Find player who issues this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + // Help this player + if (iBackupNode > -1) { + + unstood = true; + + BotPointer->rprint("Setting goal for backup"); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + // Enemy Down! + if (std::strstr(message, "#Enemy_down") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Enemy down - no logic"); + + unstood = true; + can_do_negative = false; + } + // Stick together team! + if (std::strstr(message, "#Stick_together_team") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Stick together team - no logic"); + unstood = true; + can_do_negative = false; + } + // cover me|| strstr (message, "#Cover_me") != NULL + + // Need backup / taking fire... + if (std::strstr(message, "#Need_backup") != nullptr || std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Need backup or Taking fire"); + + unstood = true; + + // get source of backup + const int iBackupNode = NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + } + + // Taking fire! + if (std::strstr(message, "#Taking_fire") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Taking fire"); + unstood = true; + + // Find player who issued this message and go to it + const int iBackupNode = + NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); + + if (iBackupNode > -1) { + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->setGoalNode(iBackupNode); + BotPointer->forgetPath(); + BotPointer->f_camp_time = gpGlobals->time - 1; + BotPointer->f_walk_time = gpGlobals->time; + } + + } + // Team fall back! + if (std::strstr(message, "#Team_fall_back") != nullptr) { + + } + // Go Go Go, stop camping, stop following, get the heck out of there! + if (std::strstr(message, "#Go_go_go") != nullptr) { + BotPointer->rprint_trace("BotRadioAction", "Understood Go Go Go"); + unstood = true; + BotPointer->f_camp_time = gpGlobals->time - 30; + BotPointer->f_walk_time = gpGlobals->time; + BotPointer->f_cover_time = gpGlobals->time - 10; + BotPointer->f_hold_duck = gpGlobals->time - 10; + BotPointer->f_jump_time = gpGlobals->time - 10; + BotPointer->forgetPath(); + BotPointer->forgetGoal(); + } + + if (FUNC_DoRadio(BotPointer) && unstood) { + const int maxAllowedRadios = gpGlobals->maxClients / 4; + if (BotPointer->console_nr == 0 && radios < maxAllowedRadios) { + constexpr bool report_back = false; + + if constexpr (!report_back) { + UTIL_BotRadioMessage(BotPointer, 3, "1", ""); // Roger that! + } + else { + UTIL_BotRadioMessage(BotPointer, 3, "6", ""); // Reporting in! + } + + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT(0.8f, 2.0f); + radios++; + } + } + } // they even listen to the radio command? + else { + /* + // filter out the commands where we cannot reply with negative + // You take the point! + if (strstr (message, "#You_take_the_point") != NULL) + can_do_negative = false; + + // Enemy Sotted! + if (strstr (message, "#Enemy_spotted") != NULL) + can_do_negative = false; + + // Enemy Down! + if (strstr (message, "#Enemy_down") != NULL) + can_do_negative = false; + + if ((FUNC_DoRadio(BotPointer)) + && (unstood) && (can_do_negative)) + + { + if (BotPointer->console_nr == 0 + && radios < (gpGlobals->maxClients / 4)) + + { + if (report_back == false) + + { + UTIL_BotRadioMessage (BotPointer, 3, "8", ""); // Negative! + BotPointer->f_console_timer = gpGlobals->time + RANDOM_FLOAT (0.8, 2.0); + radios++; + } + } + } + */ + } + } // End check! + } // If (Player) + } // FOR Clients + return true; } // Is entity visible? (from Entity view) diff --git a/bot.h b/bot.h index a49cc74..7c5fbaf 100644 --- a/bot.h +++ b/bot.h @@ -110,7 +110,7 @@ extern weapon_price_table weapons_table[32]; #define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer // define some function prototypes... -void FakeClientCommand(edict_t *pBot, char *arg1, char *arg2, char *arg3); +void FakeClientCommand(edict_t *pBot, const char *arg1, const char *arg2, const char *arg3); #define LADDER_UNKNOWN 0 #define LADDER_UP 1 @@ -623,7 +623,7 @@ Vector VecBModelOrigin(edict_t *pEdict); void UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText); -void UTIL_SelectItem(edict_t *pEdict, char *item_name); +void UTIL_SelectItem(edict_t *pEdict, const char *item_name); void UTIL_BuildFileName(char *filename, char *arg1, char *arg2); @@ -633,7 +633,7 @@ unsigned short fixed_unsigned16(float value, float scale); //redundant declarati short fixed_signed16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] -void HUD_DrawString(int r, int g, int b, char *msg, edict_t *edict); +void HUD_DrawString(int r, int g, int b, const char *msg, edict_t *edict); void UTIL_FixAngles(Vector *Angles); diff --git a/util.cpp b/util.cpp index 78420d3..73d2d11 100644 --- a/util.cpp +++ b/util.cpp @@ -417,7 +417,7 @@ Vector GetGunPosition(edict_t* pEdict) { return pEdict->v.origin + pEdict->v.view_ofs; } -void UTIL_SelectItem(edict_t* pEdict, char* item_name) { +void UTIL_SelectItem(edict_t* pEdict, const char* item_name) { /*BotDebug( item_name); */ FakeClientCommand(pEdict, item_name, nullptr, nullptr); } @@ -692,7 +692,7 @@ int UTIL_GiveWeaponId(const char* name) { } // Return weapon ID (depended on mod) -char* UTIL_GiveWeaponName(int id) { +char* UTIL_GiveWeaponName(const int id) { if (mod_id == CSTRIKE_DLL) { switch (id) { case CS_WEAPON_C4: @@ -758,7 +758,7 @@ char* UTIL_GiveWeaponName(int id) { } // Thanks Botman for this code (from forum). -void UTIL_BotSprayLogo(edict_t* pEntity, char* logo_name) { +void UTIL_BotSprayLogo(edict_t* pEntity, const char* logo_name) { TraceResult pTrace; UTIL_MakeVectors(pEntity->v.v_angle); const Vector v_src = pEntity->v.origin + pEntity->v.view_ofs; @@ -871,7 +871,7 @@ short fixed_signed16(float value, float scale) { } // Using POD/SDK source to print nice messages on the client machine -void HUD_DrawString(int r, int g, int b, char* msg, edict_t* edict) { +void HUD_DrawString(int r, int g, int b, const char* msg, edict_t* edict) { // FROM PODBOT SOURCE // Hacked together Version of HUD_DrawString MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); @@ -892,7 +892,7 @@ void HUD_DrawString(int r, int g, int b, char* msg, edict_t* edict) { WRITE_SHORT(fixed_unsigned16(2, 1 << 8)); WRITE_SHORT(fixed_unsigned16(6, 1 << 8)); WRITE_SHORT(fixed_unsigned16(0.1f, 1 << 8)); - WRITE_STRING(static_cast(&msg[0])); + WRITE_STRING(&msg[0]); MESSAGE_END(); } From b31e67949565a7bd272dea8f836339cdc457c861 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 27 Mar 2025 22:49:57 +0000 Subject: [PATCH 090/114] Update util.cpp --- util.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/util.cpp b/util.cpp index 73d2d11..76f4cc9 100644 --- a/util.cpp +++ b/util.cpp @@ -216,8 +216,7 @@ void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { else std::sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); - const int j = sizeof(text) - 2 - std::strlen(text); // -2 for /n and null terminator - if (static_cast(std::strlen(message)) > j) + if (const unsigned j = sizeof(text) - 2 - std::strlen(text); std::strlen(message) > j) message[j] = 0; std::strcat(text, message); From b1c18983d892a68fc6bd76e61caae4a6782f63c9 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 29 Mar 2025 20:06:08 +0000 Subject: [PATCH 091/114] More optimisations and modernisations --- NodeDataTypes.h | 5 ++ NodeMachine.cpp | 68 +++++++++++++++++++++++++++- NodeMachine.h | 2 + bot.h | 118 ++++++++++++++++++++++++------------------------ dll.cpp | 4 +- util.cpp | 11 ++--- 6 files changed, 139 insertions(+), 69 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index cb38c1f..1b326cc 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -149,6 +149,11 @@ typedef struct { int parent; // Who opened this node? float cost; // Cost double danger; + + // Comparison operator for priority queue + /*bool operator<(const tNodestar& other) const { + return cost > other.cost; // Note: Use '>' for min-heap (lower cost has higher priority) + }*/ } tNodestar; diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 04bd503..30bfd2a 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -52,8 +52,6 @@ #include "NodeMachine.h" -#include - tNodestar astar_list[MAX_NODES]; const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); @@ -2554,6 +2552,72 @@ void cNodeMachine::makeAllWaypointsAvailable() // rblog("All nodes set to AVAILABLE\n"); } +bool cNodeMachine::isValidNodeIndex(int index) const //TODO: Experimental [APG]RoboCop[CL] +{ + return index >= 0 && index < MAX_NODES; +} + +bool cNodeMachine::isInvalidNode(int index) const //TODO: Experimental [APG]RoboCop[CL] +{ + return !isValidNodeIndex(index); +} + +//TODO: Implement this function - Experimental [APG]RoboCop[CL] +/*void cNodeMachine::buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot) +{ + if (!isValidNodeIndex(nodeStartIndex) || !isValidNodeIndex(nodeTargetIndex)) { + rblog("Invalid node index provided to buildPath"); + return; + } + + // Clear the current path for the bot + path_clear(botIndex); + + // Initialize the A* algorithm + std::priority_queue openList; + std::unordered_map closedList; + + constexpr tNodestar startNode = { OPEN, -1, 0.0f, 0.0 }; + openList.push(startNode); + + while (!openList.empty()) { + tNodestar currentNode = openList.top(); + openList.pop(); + + if (currentNode.state == CLOSED) { + continue; + } + + if (currentNode.parent == nodeTargetIndex) { + // Path found, reconstruct the path + int pathIndex = 0; + while (currentNode.parent != -1) { + iPath[botIndex][pathIndex++] = currentNode.parent; + currentNode = closedList[currentNode.parent]; + } + std::reverse(iPath[botIndex], iPath[botIndex] + pathIndex); + return; + } + + currentNode.state = CLOSED; + closedList[currentNode.parent] = currentNode; + + // Open neighbor nodes + for (int neighborIndex : Nodes[currentNode.parent].iNeighbour) + { + if (neighborIndex == -1 || closedList.find(neighborIndex) != closedList.end()) { + continue; + } + + const float cost = currentNode.cost + (node_vector(currentNode.parent) - node_vector(neighborIndex)).Length(); + tNodestar neighborNode = { OPEN, currentNode.parent, cost, 0.0 }; + openList.push(neighborNode); + } + } + + rblog("Failed to build path"); +}*/ + // Find a node which has almost no danger! int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const { diff --git a/NodeMachine.h b/NodeMachine.h index 9a62799..ca58b11 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -35,7 +35,9 @@ #ifndef NODEMACHINE_H #define NODEMACHINE_H +#include #include +#include #include "bot.h" diff --git a/bot.h b/bot.h index 7c5fbaf..6942e55 100644 --- a/bot.h +++ b/bot.h @@ -46,99 +46,99 @@ typedef struct { extern weapon_price_table weapons_table[32]; // BOT SPECIFIC / AUDIOABLE / VISUAL PROPERTIES -#define BOT_HEARDISTANCE 1500 -#define BOT_HEARFIREDISTANCE 2500 +constexpr int BOT_HEARDISTANCE = 1500; +constexpr int BOT_HEARFIREDISTANCE = 2500; // define constants used to identify the MOD we are playing... -#define VALVE_DLL 1 // Added "Half-Life DeathMatch" -#define CSTRIKE_DLL 3 // Added "Counter-Strike" +constexpr int VALVE_DLL = 1; // Added "Half-Life DeathMatch"; +constexpr int CSTRIKE_DLL = 3; // Added "Counter-Strike"; // max names in rb_names.txt -#define MAX_BOT_NAMES 100 +constexpr int MAX_BOT_NAMES = 100; // Define Join states for other mods -#define JOIN_TEAM 1 -#define JOIN_CLASS 2 -#define JOIN_NONE 9999 +constexpr int JOIN_TEAM = 1; +constexpr int JOIN_CLASS = 2; +constexpr int JOIN_NONE = 9999; // fix for steam (cs 1.6 bot will crash when FL_FAKECLIENT; // this is fixed later again in STEAM, but leave it in anway). -#define FL_THIRDPARTYBOT (1 << 27) +constexpr int FL_THIRDPARTYBOT = (1 << 27); // "Own predefined" item types (attached with buying code) -#define CS_WEAPON_ARMOR_LIGHT 199 -#define CS_WEAPON_ARMOR_HEAVY 299 +constexpr int CS_WEAPON_ARMOR_LIGHT = 199; +constexpr int CS_WEAPON_ARMOR_HEAVY = 299; // damage tolerance -#define CSTRIKE_MIN_DAMAGE 7 -#define CSTRIKE_MAX_DAMAGE 14 +constexpr int CSTRIKE_MIN_DAMAGE = 7; +constexpr int CSTRIKE_MAX_DAMAGE = 14; // The type of a weapon, not mod related. You can use these prefixed names // for your functions -#define SNIPER 10 // Sniper gun -#define RIFLE 20 // Rifle -#define HANDGUN 30 // Handgun -#define ARMOR 40 // Armor -#define PRIMARY 50 // Its a primary weapon (for CS Mods) -#define SECONDARY 60 // Its a secondary weapon (for CS Mods) -#define GRENADE 70 // Grenade (aka, HE, Flashbang, C4, etc) -#define KNIFE 80 // Knife / Crowbar etc -#define SHIELD 90 // Shield (CS 1.6) -#define NONE 99 // No type +constexpr int SNIPER = 10; // Sniper gun; +constexpr int RIFLE = 20; // Rifle; +constexpr int HANDGUN = 30; // Handgun; +constexpr int ARMOR = 40; // Armor; +constexpr int PRIMARY = 50; // Its a primary weapon (for CS Mods); +constexpr int SECONDARY = 60; // Its a secondary weapon (for CS Mods) +constexpr int GRENADE = 70; // Grenade (aka, HE, Flashbang, C4, etc); +constexpr int KNIFE = 80; // Knife / Crowbar etc +constexpr int SHIELD = 90; // Shield (CS 1.6) +constexpr int NONE = 99; // No type // Strafe //#define STRAFE_LEFT 0 //#define STRAFE_RIGHT 1 // zooming -#define ZOOM_NONE 0 -#define ZOOM_ONCE 1 -#define ZOOM_TWICE 2 +constexpr int ZOOM_NONE = 0; +constexpr int ZOOM_ONCE = 1; +constexpr int ZOOM_TWICE = 2; // instant damage (from cbase.h) -#define DMG_CRUSH (1 << 0) // crushed by falling or moving object -#define DMG_BURN (1 << 3) // heat burned -#define DMG_FREEZE (1 << 4) // frozen -#define DMG_FALL (1 << 5) // fell too far -#define DMG_SHOCK (1 << 8) // electric shock -#define DMG_DROWN (1 << 14) // Drowning -#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad -#define DMG_RADIATION (1 << 18) // radiation exposure -#define DMG_DROWNRECOVER (1 << 19) // drowning recovery -#define DMG_ACID (1 << 20) // toxic chemicals or acid burns -#define DMG_SLOWBURN (1 << 21) // in an oven -#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer +constexpr int DMG_CRUSH = (1 << 0); // crushed by falling or moving object +constexpr int DMG_BURN = (1 << 3); // heat burned +constexpr int DMG_FREEZE = (1 << 4); // frozen +constexpr int DMG_FALL = (1 << 5); // fell too far +constexpr int DMG_SHOCK = (1 << 8); // electric shock +constexpr int DMG_DROWN = (1 << 14); // Drowning +constexpr int DMG_NERVEGAS = (1 << 16); // nerve toxins, very bad +constexpr int DMG_RADIATION = (1 << 18); // radiation exposure +constexpr int DMG_DROWNRECOVER = (1 << 19); // drowning recovery +constexpr int DMG_ACID = (1 << 20); // toxic chemicals or acid burns +constexpr int DMG_SLOWBURN = (1 << 21); // in an oven +constexpr int DMG_SLOWFREEZE = (1 << 22); // in a subzero freezer; // define some function prototypes... void FakeClientCommand(edict_t *pBot, const char *arg1, const char *arg2, const char *arg3); -#define LADDER_UNKNOWN 0 -#define LADDER_UP 1 -#define LADDER_DOWN 2 +constexpr int LADDER_UNKNOWN = 0; +constexpr int LADDER_UP = 1; +constexpr int LADDER_DOWN = 2; -#define WANDER_LEFT 1 -#define WANDER_RIGHT 2 +constexpr int WANDER_LEFT = 1; +constexpr int WANDER_RIGHT = 2; -#define BOT_PITCH_SPEED 30 -#define BOT_YAW_SPEED 30 +constexpr int BOT_PITCH_SPEED = 30; +constexpr int BOT_YAW_SPEED = 30; -#define RESPAWN_NONE 0 // Added by Stefan -#define RESPAWN_IDLE 1 -#define RESPAWN_NEED_TO_RESPAWN 2 -#define RESPAWN_IS_RESPAWNING 3 +constexpr int RESPAWN_NONE = 0; // Added by Stefan; +constexpr int RESPAWN_IDLE = 1; +constexpr int RESPAWN_NEED_TO_RESPAWN = 2; +constexpr int RESPAWN_IS_RESPAWNING = 3; // game start messages for CS... -#define MSG_CS_IDLE 1 -#define MSG_CS_TEAM_SELECT 2 -#define MSG_CS_CT_SELECT 3 -#define MSG_CS_T_SELECT 4 +constexpr int MSG_CS_IDLE = 1; +constexpr int MSG_CS_TEAM_SELECT = 2; +constexpr int MSG_CS_CT_SELECT = 3; +constexpr int MSG_CS_T_SELECT = 4; -#define BOT_SKIN_LEN 32 -#define BOT_NAME_LEN 32 +constexpr int BOT_SKIN_LEN = 32; +constexpr int BOT_NAME_LEN = 32; -#define MAX_BOT_WHINE 100 +constexpr int MAX_BOT_WHINE = 100; -#define REMEMBER_ENEMY_TIME 20 // remember for 20 seconds +constexpr int REMEMBER_ENEMY_TIME = 20; // remember for 20 seconds typedef struct { int iId; // weapon ID @@ -621,11 +621,11 @@ Vector GetGunPosition(edict_t *pEdict); Vector VecBModelOrigin(edict_t *pEdict); -void UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, char *pText); +void UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, const char *pText); void UTIL_SelectItem(edict_t *pEdict, const char *item_name); -void UTIL_BuildFileName(char *filename, char *arg1, char *arg2); +void UTIL_BuildFileName(char *filename, const char *arg1, const char *arg2); void UTIL_BuildFileNameRB(const char *subdir, char *filename); diff --git a/dll.cpp b/dll.cpp index e6c9ca9..5fc7185 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1012,7 +1012,7 @@ void StartFrame() { RETURN_META(MRES_IGNORED); } -void FakeClientCommand(edict_t* pBot, char* arg1, char* arg2, char* arg3) { +void FakeClientCommand(edict_t* pBot, const char* arg1, const char* arg2, const char* arg3) { int length; std::memset(g_argv, 0, sizeof(g_argv)); @@ -1119,7 +1119,7 @@ void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) //T void ProcessBotCfgFile() { char cmd_line[256]; static char server_cmd[80]; - char *arg2, *arg3, *arg4; + const char *arg2, *arg3, *arg4; char msg[80]; if (bot_cfg_pause_time > gpGlobals->time) diff --git a/util.cpp b/util.cpp index 76f4cc9..2fab8be 100644 --- a/util.cpp +++ b/util.cpp @@ -422,12 +422,11 @@ void UTIL_SelectItem(edict_t* pEdict, const char* item_name) { } Vector VecBModelOrigin(edict_t* pEdict) { - return pEdict->v.absmin + (pEdict->v.size * 0.5); + return pEdict->v.absmin + (pEdict->v.size * 0.5f); } -void -UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, - char* pText) { +void UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, + const char* pText) { if (gmsgShowMenu == 0) gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); @@ -441,7 +440,7 @@ UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, MESSAGE_END(); } -void UTIL_BuildFileName(char* filename, char* arg1, char* arg2) { +void UTIL_BuildFileName(char* filename, const char* arg1, const char* arg2) { if (mod_id == VALVE_DLL) std::strcpy(filename, "valve/"); @@ -790,7 +789,7 @@ void UTIL_BotSprayLogo(edict_t* pEntity, const char* logo_name) { MESSAGE_END(); - EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0, + EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "player/sprayer.wav", 1.0f, ATTN_NORM, 0, 100); } } From 0ff643c768d82c775f65e018dbe8b92838d9c23e Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 29 Mar 2025 21:15:15 +0000 Subject: [PATCH 092/114] Adding experimental buildPath Function --- NodeDataTypes.h | 9 ++++----- NodeMachine.cpp | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 1b326cc..975d4dd 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -144,18 +144,17 @@ typedef struct { tPlayer; // Astar Node informaiton -typedef struct { +typedef struct tNodestar { int state; // OPEN/CLOSED int parent; // Who opened this node? float cost; // Cost double danger; // Comparison operator for priority queue - /*bool operator<(const tNodestar& other) const { + bool operator<(const tNodestar& other) const { return cost > other.cost; // Note: Use '>' for min-heap (lower cost has higher priority) - }*/ -} -tNodestar; + } +} tNodestar; // Additional Node Information typedef struct { diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 30bfd2a..27fc1ea 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2563,7 +2563,7 @@ bool cNodeMachine::isInvalidNode(int index) const //TODO: Experimental [APG]Robo } //TODO: Implement this function - Experimental [APG]RoboCop[CL] -/*void cNodeMachine::buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot) +void cNodeMachine::buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot) { if (!isValidNodeIndex(nodeStartIndex) || !isValidNodeIndex(nodeTargetIndex)) { rblog("Invalid node index provided to buildPath"); @@ -2616,7 +2616,7 @@ bool cNodeMachine::isInvalidNode(int index) const //TODO: Experimental [APG]Robo } rblog("Failed to build path"); -}*/ +} // Find a node which has almost no danger! int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const From 392a3c23a792d9c3f84833521a9966700029627a Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 29 Mar 2025 21:40:54 +0000 Subject: [PATCH 093/114] Updated FUNC_FindBreakable --- bot_func.cpp | 33 +++++++++++++-------------------- bot_func.h | 3 ++- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/bot_func.cpp b/bot_func.cpp index 38f3b81..ab2d84e 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -858,42 +858,35 @@ bool FUNC_IsOnLadder(const edict_t *pEntity) { return false; } -void FUNC_FindBreakable(cBot* pBot) //TODO: not functioning, bots won't shoot windows nor vent doors to proceed [APG]RoboCop[CL] +void FUNC_FindBreakable(cBot* pBot) // Updated function signature to accept cBot* { - // The "func_breakable" entity required for glass breaking and weak doors for bots to recognise, + // The "func_breakable" entity required for glass breaking and weak doors for bots to recognize, // in order to attack breakable objects that would block their way. - if (pBot == nullptr) { return; // Ensure pBot is not null } + edict_t* pEntity = pBot->pEdict; // Get the edict from the bot + for (int i = 0; i < gpGlobals->maxEntities; ++i) { - edict_t* pEdict = INDEXENT(i); - if (pEdict == nullptr || (pEdict->v.flags & FL_DORMANT)) { + edict_t* pent = INDEXENT(i); + if (pent == nullptr || (pent->v.flags & FL_DORMANT)) { continue; // Skip null or dormant entities } - const char* classname = STRING(pEdict->v.classname); + const char* classname = STRING(pent->v.classname); if (classname != nullptr && std::strcmp(classname, "func_breakable") == 0) { - if (pBot->canSeeEntity(pEdict)) { - - constexpr float SHOOT_WAIT_TIME = 1.0f; - constexpr float SHOOT_DELAY = 0.1f; - - // Set the breakable entity as the bot's enemy - pBot->pEdict->v.enemy = pEdict; - - // Set shooting times - pBot->f_shoot_time = gpGlobals->time + SHOOT_DELAY; - pBot->f_shoot_wait_time = gpGlobals->time + SHOOT_WAIT_TIME; + if (FVisible(pent->v.origin, pEntity)) { + // Set the breakable entity as the entity's enemy + pEntity->v.enemy = pent; // Aim at the breakable entity - pBot->vBody = pEdict->v.origin; - pBot->vHead = pEdict->v.origin; + Vector vBody = pent->v.origin; + Vector vHead = pent->v.origin; // Shoot at the breakable entity - UTIL_BotPressKey(pBot, IN_ATTACK); + UTIL_BotPressKey(pBot, IN_ATTACK); // Updated to use pBot instead of pEntity return; // Exit after finding the first breakable entity } } diff --git a/bot_func.h b/bot_func.h index 1e79a78..9806536 100644 --- a/bot_func.h +++ b/bot_func.h @@ -66,6 +66,7 @@ cBot *getCloseFellowBot(cBot * pBot); edict_t * getPlayerNearbyBotInFOV(cBot * pBot); edict_t * getEntityNearbyBotInFOV(cBot * pBot); +bool isAnyPlayerNearbyBot(cBot* pBot); bool BotShouldJump(cBot * pBot); bool BotShouldJumpIfStuck(cBot * pBot); bool BotShouldDuck(cBot * pBot); @@ -90,7 +91,7 @@ void FUNC_HearingTodo(cBot * pBot); void FUNC_ClearEnemyPointer(edict_t *pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] bool FUNC_IsOnLadder(const edict_t * pEntity); -void FUNC_FindBreakable(edict_t* pEntity); +void FUNC_FindBreakable(cBot* pBot); void FUNC_CheckForBombPlanted(edict_t* pEntity); int FUNC_GiveHostage(cBot * pBot); // gives any hostage we still have to go for From 499f87436c579eeeeb6879c3ff5f069c7572d8de Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 29 Mar 2025 22:33:33 +0000 Subject: [PATCH 094/114] Updating headers for missing functions --- bot.h | 35 +++++++++++++++++++++++++++++++++++ bot_func.h | 9 ++++++++- dll.cpp | 10 +--------- engine.cpp | 2 +- util.cpp | 2 +- 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/bot.h b/bot.h index 6942e55..a282ca8 100644 --- a/bot.h +++ b/bot.h @@ -646,8 +646,43 @@ int UTIL_GetBotIndex(edict_t *pEdict); cBot *UTIL_GetBotPointer(edict_t *pEdict); +// IniParser.ini +void INI_Section(char input[80], char section[30]); +void INI_Word(char input[80], char word[25]); +int INI_WordType(char word[25], int section); +void INI_Sentence(FILE* f, char result[80]); + +int INI_SectionType(char section[30], int last); +int INI_SectionType_BUYTABLE(char section[30], int last); + +int INI_WordValueINT(char result[80]); + +float INI_WordValueFLOAT(char result[80]); + +void INI_WordValueCHAR(char result[80], char value[80]); // dll.cpp +void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd); +void ProcessBotCfgFile(); bool BotRadioAction(); +void GameDLLInit(); + +#ifdef _WIN32 +int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); +#endif + +int ClientConnect(edict_t* pEntity, const char* pszName, const char* pszAddress, char szRejectReason[128]); + +void ClientDisconnect(edict_t* pEntity); +void ConsoleThink(cBot* pBot); +void ClientPutInServer(edict_t* pEntity); +void StartFrame(); +void RealBot_ServerCommand(); + +int Spawn(edict_t* pent); +int Spawn_Post(edict_t* pent); + +// util.cpp +void UTIL_BotSprayLogo(edict_t* pEntity, const char* logo_name); #endif // BOT_H diff --git a/bot_func.h b/bot_func.h index 9806536..0422bf9 100644 --- a/bot_func.h +++ b/bot_func.h @@ -114,8 +114,15 @@ bool VectorIsVisibleWithEdict(edict_t * pEdict, const Vector& dest, bool BOT_DecideTakeCover(cBot * pBot); // bot_buycode.cpp -void BotConsole(cBot * pBot); +int PriceWeapon(int weapon_id); +int ListIdWeapon(int weapon_id); + +void BotPrepareConsoleCommandsToBuyWeapon(cBot* pBot, const char* arg1, const char* arg2); +bool GoodWeaponForTeam(int weapon, int team); + +void BotConsole(cBot * pBot); +void BotDecideWhatToBuy(cBot* pBot); void rblog(const char* txt); // bot.cpp diff --git a/dll.cpp b/dll.cpp index 5fc7185..27b0150 100644 --- a/dll.cpp +++ b/dll.cpp @@ -100,10 +100,6 @@ int internet_min_interval = 10; // Counter-Strike 1.6 or 1.5 int counterstrike = 0; // Default 1.5 -void UpdateClientData(const edict_s *ent, int sendweapons, clientdata_s *cd); //Not used? [APG]RoboCop[CL] - -void ProcessBotCfgFile(); - // External added variables bool end_round = false; @@ -119,8 +115,6 @@ bool internet_addbot = false; // Add a bot? float add_timer = -1; // Timer for adding bots bool internet_play = false; -void RealBot_ServerCommand(); - // START of Metamod stuff enginefuncs_t meta_engfuncs; gamedll_funcs_t *gpGamedllFuncs; @@ -412,8 +406,7 @@ int Spawn(edict_t *pent) { RETURN_META_VALUE(MRES_IGNORED, 0); } -BOOL -ClientConnect(edict_t *pEntity, const char *pszName, +int ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) { if (gpGlobals->deathmatch) { // check if this client is the listen server client @@ -523,7 +516,6 @@ void ClientCommand(edict_t *pEntity) { RETURN_META(MRES_IGNORED); } -// TODO: Revise this method void StartFrame() { if (!gpGlobals->deathmatch) return; // bots only work in 'deathmatch mode' //REALBOT_PRINT("StartFrame", "BEGIN"); diff --git a/engine.cpp b/engine.cpp index 8605cc6..069e249 100644 --- a/engine.cpp +++ b/engine.cpp @@ -37,7 +37,7 @@ #include "bot_func.h" #include "ChatEngine.h" -//#include "engine.h" +#include "engine.h" #include "game.h" extern enginefuncs_t g_engfuncs; //Redundant? [APG]RoboCop[CL] diff --git a/util.cpp b/util.cpp index 2fab8be..b56ed5b 100644 --- a/util.cpp +++ b/util.cpp @@ -492,7 +492,7 @@ void UTIL_BuildFileNameRB(const char* subdir, char* filename) { // UTIL_LogPrintf - Prints a logged message to console. // Preceded by LOG: ( timestamp ) < message > //========================================================= -void UTIL_LogPrintf(char* fmt, ...) { +void UTIL_LogPrintf(const char* fmt, ...) { va_list argptr; static char string[1024]; From 8e083927d6a93e66d37b4291e6ba10f768b6674c Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 29 Mar 2025 22:52:14 +0000 Subject: [PATCH 095/114] Improved global coding --- NodeMachine.h | 1 + bot_func.h | 2 +- dll.cpp | 2 ++ globals.h | 60 ++++++++++++++++++++++++++++++++++++++ realbot_mm.vcxproj | 1 + realbot_mm.vcxproj.filters | 3 ++ util.cpp | 4 ++- 7 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 globals.h diff --git a/NodeMachine.h b/NodeMachine.h index ca58b11..1aac0ea 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -40,6 +40,7 @@ #include #include "bot.h" +#include "game.h" #include "NodeDataTypes.h" diff --git a/bot_func.h b/bot_func.h index 0422bf9..488dc2a 100644 --- a/bot_func.h +++ b/bot_func.h @@ -134,7 +134,7 @@ int UTIL_GetGrenadeType(edict_t * pEntity); bool UTIL_IsVip(edict_t * pEntity); -char* UTIL_GiveWeaponName(int id); +const char* UTIL_GiveWeaponName(int id); void UTIL_SpeechSynth(edict_t * pEdict, char *szMessage); void UTIL_BotRadioMessage(cBot * pBot, int radio, const char *arg1, const char *arg2); diff --git a/dll.cpp b/dll.cpp index 27b0150..24dcd72 100644 --- a/dll.cpp +++ b/dll.cpp @@ -34,6 +34,8 @@ #include #include +#include "globals.h" + #include "bot.h" #include "bot_func.h" #include "IniParser.h" diff --git a/globals.h b/globals.h new file mode 100644 index 0000000..712f16e --- /dev/null +++ b/globals.h @@ -0,0 +1,60 @@ +// globals.h + +#ifndef GLOBALS_H +#define GLOBALS_H + +#include + +#include "bot.h" +#include "NodeMachine.h" +#include "ChatEngine.h" +#include "game.h" + +extern cGame Game; +extern cNodeMachine NodeMachine; +extern cChatEngine ChatEngine; +extern FILE* fpRblog; + +extern float f_load_time; +extern float f_minplayers_think; +extern int mod_id; +extern int m_spriteTexture; +extern bool isFakeClientCommand; +extern int fake_arg_count; +extern float bot_check_time; +extern int min_bots; +extern int max_bots; +extern int min_players; +extern int num_bots; +extern int prev_num_bots; +extern bool g_GameRules; +extern edict_t* clients[32]; +extern edict_t* pHostEdict; +extern float welcome_time; +extern bool welcome_sent; + +extern FILE* bot_cfg_fp; +extern bool need_to_open_cfg; +extern float bot_cfg_pause_time; +extern float respawn_time; +extern bool spawn_time_reset; + +extern int internet_max_interval; +extern int internet_min_interval; + +extern int counterstrike; + +extern bool end_round; + +extern bool autoskill; +extern bool draw_nodes; +extern int draw_nodepath; +extern bool draw_connodes; +extern int kick_amount_bots; +extern int kick_bots_team; + +extern bool internet_addbot; +extern float add_timer; +extern bool internet_play; + +#endif // GLOBALS_H diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index 657e90e..d5186e6 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -112,6 +112,7 @@ + diff --git a/realbot_mm.vcxproj.filters b/realbot_mm.vcxproj.filters index 500cd92..ffb14df 100644 --- a/realbot_mm.vcxproj.filters +++ b/realbot_mm.vcxproj.filters @@ -82,6 +82,9 @@ Header Files + + Header Files + diff --git a/util.cpp b/util.cpp index b56ed5b..7ace596 100644 --- a/util.cpp +++ b/util.cpp @@ -49,6 +49,8 @@ #include #include +#include "globals.h" + #include "bot.h" #include "bot_weapons.h" #include "bot_func.h" @@ -690,7 +692,7 @@ int UTIL_GiveWeaponId(const char* name) { } // Return weapon ID (depended on mod) -char* UTIL_GiveWeaponName(const int id) { +const char* UTIL_GiveWeaponName(const int id) { if (mod_id == CSTRIKE_DLL) { switch (id) { case CS_WEAPON_C4: From 03b4870e6cb14f5bcf4957de7b3f447821a0af5a Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 22 May 2025 19:32:32 +0100 Subject: [PATCH 096/114] Experimental optimisations --- ChatEngine.cpp | 2 + IniParser.cpp | 4 +- NodeDataTypes.h | 183 ++++++++++++++++++++++++++++++----------------- NodeMachine.cpp | 87 +++++++++++----------- NodeMachine.h | 12 ++-- bot.cpp | 4 +- bot.h | 2 +- bot_buycode.cpp | 2 + bot_client.cpp | 2 + bot_func.cpp | 2 + bot_navigate.cpp | 2 + build.cpp | 2 + dll.cpp | 2 + engine.cpp | 2 + game.cpp | 2 + util.cpp | 2 + 16 files changed, 190 insertions(+), 122 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 16f1f87..a2c6bb2 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/IniParser.cpp b/IniParser.cpp index ff17b17..6539916 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress @@ -716,7 +718,7 @@ void INI_PARSE_IAD() { if (wordtype == WORD_AREAZ) AreaZ = static_cast(INI_WordValueINT(linefeed)); - if (AreaX != 9999 && AreaY != 9999 && AreaZ != 9999) { + if (AreaX != 9999.0f && AreaY != 9999.0f && AreaZ != 9999.0f) { // add this to goal rblog("IAD: Adding an important area/goal\n"); NodeMachine.addGoal(nullptr, GOAL_IMPORTANT, Vector(AreaX, AreaY, AreaZ)); diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 975d4dd..188be72 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -35,106 +35,157 @@ #ifndef NODEDATATYPES_H #define NODEDATATYPES_H - // player sizes for path_connection_walkable -#define MAX_JUMPHEIGHT 60 // confirmed // 45 without crouching -#define MAX_FALLHEIGHT 130 // not confirmed (200 is to high, adjusted) -#define MAX_STAIRHEIGHT 18 // confirmed -#define HEAD_HEIGHT 72 // confirmed -#define ORIGIN_HEIGHT 36 // confirmed (?) -#define CROUCHED_HEIGHT 37 // confirmed -#define PLAYER_WIDTH 32 // confirmed (?) +#include + +// player sizes for path_connection_walkable +enum : std::uint8_t +{ + MAX_JUMPHEIGHT = 60, // confirmed // 45 without crouching + MAX_FALLHEIGHT = 130, // not confirmed (200 is to high, adjusted) + MAX_STAIRHEIGHT = 18, // confirmed + HEAD_HEIGHT = 72, // confirmed + ORIGIN_HEIGHT = 36, // confirmed (?) + CROUCHED_HEIGHT = 37, // confirmed + PLAYER_WIDTH = 32 // confirmed (?) +}; // File version // Version 1.0 -#define FILE_NODE_VER1 1 -#define FILE_EXP_VER1 1 +enum : std::uint8_t +{ + FILE_NODE_VER1 = 1, + FILE_EXP_VER1 = 1 +}; // Version 2.0 -#define FILE_NODE_VER2 2 -#define FILE_EXP_VER2 2 +enum : std::uint8_t +{ + FILE_NODE_VER2 = 2, + FILE_EXP_VER2 = 2 +}; // Node bits (for navigational performance) -#define BIT_LADDER (1 << 0) -#define BIT_WATER (1 << 1) -#define BIT_JUMP (1 << 2) -#define BIT_DUCK (1 << 3) -#define BIT_DUCKJUMP (1 << 4) +enum : std::uint8_t +{ + BIT_LADDER = (1 << 0), + BIT_WATER = (1 << 1), + BIT_JUMP = (1 << 2), + BIT_DUCK = (1 << 3), + BIT_DUCKJUMP = (1 << 4) +}; // Path flags -#define PATH_DANGER 39 // Picked a random number here -#define PATH_CONTACT 37 // w0h00 -#define PATH_NONE 32 // - rushing -#define PATH_CAMP 31 // camp path +enum : std::uint8_t +{ + PATH_DANGER = 39, // Picked a random number here + PATH_CONTACT = 37, // w0h00 + PATH_NONE = 32, // - rushing + PATH_CAMP = 31 // camp path +}; // Visibility flags -#define VIS_INVALID 96 // BERKED -#define VIS_UNKNOWN 97 -#define VIS_VISIBLE 98 -#define VIS_BLOCKED 99 +enum : std::uint8_t +{ + VIS_INVALID = 96, // BERKED + VIS_UNKNOWN = 97, + VIS_VISIBLE = 98, + VIS_BLOCKED = 99 +}; // Goal types & info -#define MAX_GOALS 75 +constexpr int MAX_GOALS = 75; // Node types / goal types -#define GOAL_SPAWNCT 1 -#define GOAL_SPAWNT 2 -#define GOAL_BOMBSPOT 3 -#define GOAL_BOMB 4 // updates all the time -#define GOAL_HOSTAGE 5 // updates all the time -#define GOAL_RESCUEZONE 6 // rescue zone (for hostages) -#define GOAL_CONTACT 7 // zones where teams often have contact -#define GOAL_IMPORTANT 8 -#define GOAL_VIP 9 // as_ maps VIP starting point -#define GOAL_VIPSAFETY 10 // as_ maps VIP safety zone -#define GOAL_ESCAPEZONE 11 // es_ maps escape zone -#define GOAL_WEAPON 12 // pre-dropped weapons like in awp_map -#define GOAL_NONE 99 +enum : std::uint8_t +{ + GOAL_SPAWNCT = 1, + GOAL_SPAWNT = 2, + GOAL_BOMBSPOT = 3, + GOAL_BOMB = 4, // updates all the time + GOAL_HOSTAGE = 5, // updates all the time + GOAL_RESCUEZONE = 6, // rescue zone (for hostages) + GOAL_CONTACT = 7, // zones where teams often have contact + GOAL_IMPORTANT = 8, // important goals + GOAL_VIP = 9, // as_ maps VIP starting point + GOAL_VIPSAFETY = 10, // as_ maps VIP safety zone + GOAL_ESCAPEZONE = 11, // es_ maps escape zone + GOAL_WEAPON = 12, // pre-dropped weapons like in awp_map + GOAL_NONE = 99 +}; // Node costs -#define NODE_DANGER 8192 // Value -#define NODE_DANGER_STEP 0.5f // Step to take to get dangerous -#define NODE_DANGER_DIST 512.0f // Distance +enum : std::uint16_t +{ + NODE_DANGER = 8192 // Value +}; + +constexpr float NODE_DANGER_STEP = 0.5f; // Step to take to get dangerous; +constexpr float NODE_DANGER_DIST = 512.0f; // Distance; // Node contact costs -#define NODE_CONTACT 8192 -#define NODE_CONTACT_STEP 0.2 -#define NODE_CONTACT_DIST 128 +enum : std::uint16_t +{ + NODE_CONTACT = 8192 +}; + +constexpr float NODE_CONTACT_STEP = 0.2f; + +enum : std::uint8_t +{ + NODE_CONTACT_DIST = 128 +}; // Node boundries -#define MAX_NODES 4096 -#define MAX_NEIGHBOURS 16 // Maybe reduce it to 6 or 8 as 16 is maybe too much [APG]RoboCop[CL] -#define NODE_ZONE 45 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +enum : std::uint8_t +{ + NODE_ZONE = 45 // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] +}; + +constexpr int MAX_NODES = 4096; +constexpr int MAX_NEIGHBOURS = 16; // Maybe increase it to 128 or 144 to reduce the amount of excess nodes [APG]RoboCop[CL] + #define MAX_PATH_NODES MAX_NODES // Max troubled node connections we remember -#define MAX_TROUBLE 100 +constexpr int MAX_TROUBLE = 100; // Meridian stuff -#define SIZE_MEREDIAN 256 -#define MAP_MAX_SIZE 16384 +enum : std::uint16_t +{ + SIZE_MEREDIAN = 256, + MAP_MAX_SIZE = 16384 +}; + #define MAX_MEREDIANS (MAP_MAX_SIZE / SIZE_MEREDIAN) // Size of HL map divided by SIZE of a meridian to evenly spread -#define MAX_NODES_IN_MEREDIANS 120 // EVY: higher number, number of nodes per meredian +constexpr int MAX_NODES_IN_MEREDIANS = 120; // EVY: higher number, number of nodes per meredian; //#define MAX_NODES_IN_MEREDIANS 80 // (size meredian / zone (~6) times 2 (surface) , rounded to 80 // A* defines OPEN/CLOSED lists -#define OPEN 1 // open, can still re-evaluate -#define CLOSED 2 // closed, do nothing with it -#define AVAILABLE 3 // available, may open +enum : std::uint8_t +{ + OPEN = 1, // open, can still re-evaluate + CLOSED = 2, // closed, do nothing with it + AVAILABLE = 3 // available, may open +}; constexpr unsigned long g_iMaxVisibilityByte = MAX_NODES * MAX_NODES / 8; // doors (doors.cpp) HLSDK -#define SF_DOOR_ROTATE_Y 0 -#define SF_DOOR_START_OPEN 1 -#define SF_DOOR_ROTATE_BACKWARDS 2 -#define SF_DOOR_PASSABLE 8 -#define SF_DOOR_ONEWAY 16 -#define SF_DOOR_NO_AUTO_RETURN 32 -#define SF_DOOR_ROTATE_Z 64 -#define SF_DOOR_ROTATE_X 128 -#define SF_DOOR_USE_ONLY 256 // door must be opened by player's use button. -#define SF_DOOR_NOMONSTERS 512 // Monster can't open -#define SF_DOOR_SILENT 0x80000000 +enum : std::uint16_t +{ + SF_DOOR_ROTATE_Y = 0, + SF_DOOR_START_OPEN = 1, + SF_DOOR_ROTATE_BACKWARDS = 2, + SF_DOOR_PASSABLE = 8, + SF_DOOR_ONEWAY = 16, + SF_DOOR_NO_AUTO_RETURN = 32, + SF_DOOR_ROTATE_Z = 64, + SF_DOOR_ROTATE_X = 128, + SF_DOOR_USE_ONLY = 256, // door must be opened by player's use button. + SF_DOOR_NOMONSTERS = 512 // Monster can't open +}; + +constexpr unsigned SF_DOOR_SILENT = 0x80000000; // Player information on map typedef struct { diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 27fc1ea..eba133a 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress @@ -64,63 +66,52 @@ extern int draw_nodepath; //--------------------------------------------------------- //CODE: CHEESEMONSTER -int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const // BERKED -{ - // prevent negative indexes on iVisChecked below -- BERKED - if (iFrom >= 0 && iFrom < 4096 && iTo >= 0 && iTo < 4096) { - if (iVisChecked[iFrom] == 0) - return VIS_UNKNOWN; // we have no clue +int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const { + if (iFrom < 0 || iFrom >= MAX_NODES || iTo < 0 || iTo >= MAX_NODES) { + rblog("ERROR: Index out of bounds in GetVisibilityFromTo! Returning VIS_BLOCKED\n"); + return VIS_BLOCKED; } - else { - rblog("ERROR: Negative or out of bound index on iFrom! Returning Visibility NULL\n"); - return 0; + + if (iVisChecked[iFrom] == 0) { + return VIS_UNKNOWN; } - + // was int // work out the position const long iPosition = iFrom * MAX_NODES + iTo; - - const long iByte = static_cast(iPosition / 8); + const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - - if (iByte < static_cast(g_iMaxVisibilityByte)) { - // Get the Byte that this is in + + if (iByte < g_iMaxVisibilityByte) { const unsigned char* ToReturn = cVisTable + iByte; - // get the bit in the byte - return (*ToReturn & 1 << iBit) > 0 ? VIS_VISIBLE : VIS_BLOCKED; // BERKED + return (*ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; } - - return VIS_BLOCKED; // BERKED + + return VIS_BLOCKED; } void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { - // prevent negative indexes on iVisChecked below, fixing SEGV -- BERKED - if (iFrom < 0 || iFrom > MAX_NODES || iTo < 0 || iTo > MAX_NODES) { + if (iFrom < 0 || iFrom >= MAX_NODES || iTo < 0 || iTo >= MAX_NODES) { + rblog("ERROR: Index out of bounds in SetVisibilityFromTo!\n"); return; } - if (iFrom >= 0 && iFrom < 4096) { - iVisChecked[iFrom] = 1; // WE HAVE CHECKED THIS ONE - } - else { - rblog("ERROR: Negative or out of bound index on iFrom! Returning Visibility NULL\n"); - return; - } + iVisChecked[iFrom] = 1; // was int const long iPosition = iFrom * MAX_NODES + iTo; - - const long iByte = static_cast(iPosition / 8); + const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - if (iByte < static_cast(g_iMaxVisibilityByte)) { - unsigned char *ToChange = cVisTable + iByte; - - if (bVisible) - *ToChange |= 1 << iBit; - else + if (iByte < g_iMaxVisibilityByte) { + unsigned char* ToChange = cVisTable + iByte; + if (bVisible) { + *ToChange |= (1 << iBit); + } + else { *ToChange &= ~(1 << iBit); + } } } @@ -131,9 +122,11 @@ void cNodeMachine::ClearVisibilityTable() const } } -void cNodeMachine::FreeVisibilityTable() const -{ - free(cVisTable); +void cNodeMachine::FreeVisibilityTable() { + if (cVisTable) { + free(cVisTable); + cVisTable = nullptr; + } } //--------------------------------------------------------- @@ -738,7 +731,7 @@ static float horizontal_distance(const Vector& a, const Vector& b) { return std::sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } -#define STEP 20 //Incremental move +constexpr int STEP = 20; //Incremental move; // Return the floor below V // TO BE IMPROVED use pEntityCOntaining @@ -2552,12 +2545,12 @@ void cNodeMachine::makeAllWaypointsAvailable() // rblog("All nodes set to AVAILABLE\n"); } -bool cNodeMachine::isValidNodeIndex(int index) const //TODO: Experimental [APG]RoboCop[CL] +bool cNodeMachine::isValidNodeIndex(int index) //TODO: Experimental [APG]RoboCop[CL] { return index >= 0 && index < MAX_NODES; } -bool cNodeMachine::isInvalidNode(int index) const //TODO: Experimental [APG]RoboCop[CL] +bool cNodeMachine::isInvalidNode(int index) //TODO: Experimental [APG]RoboCop[CL] { return !isValidNodeIndex(index); } @@ -4176,7 +4169,7 @@ enum : std::uint16_t DEBUG_BMP_HEIGHT = 2048 }; -static char *bmp_buffer; +static unsigned char *bmp_buffer; static float maxx, maxy, minx, miny; static float scale; @@ -4187,7 +4180,7 @@ static void InitDebugBitmap() { free(bmp_buffer); // reliability check, free BMP buffer if already allocated bmp_buffer = nullptr; - bmp_buffer = static_cast(malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)); // allocate memory + bmp_buffer = static_cast(malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)); // allocate memory if (bmp_buffer == nullptr) { std::fprintf(stderr, "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", @@ -4578,7 +4571,7 @@ void cNodeMachine::MarkMeredians() { // Put a cross on all nodes in RBN + draw lines to all neighbours -void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) const +void cNodeMachine::PlotNodes(unsigned char NeighbourColor, unsigned char NodeColor) const { int i; @@ -4600,7 +4593,7 @@ void cNodeMachine::PlotNodes(int NeighbourColor, int NodeColor) const // Put a small cross at all goal points -void cNodeMachine::PlotGoals(int color) const +void cNodeMachine::PlotGoals(unsigned char color) const { for (int i = 0; i < MAX_GOALS && Goals[i].iNode >= 0; i++) { const Vector v = Nodes[Goals[i].iNode].origin; @@ -4609,7 +4602,7 @@ void cNodeMachine::PlotGoals(int color) const } // Plot the computed paths for all life bots -void cNodeMachine::PlotPaths(int Tcolor, int CTcolor) const +void cNodeMachine::PlotPaths(unsigned char Tcolor, unsigned char CTcolor) const { for (int iBot = 0; iBot < 32; iBot++) { if (bots[iBot].bIsUsed) { diff --git a/NodeMachine.h b/NodeMachine.h index 1aac0ea..30851bf 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -175,7 +175,7 @@ class cNodeMachine { void SetVisibilityFromTo(int iFrom, int iTo, bool bVisible); - void FreeVisibilityTable() const; + void FreeVisibilityTable(); // Some debugging by EVY void dump_goals() const; @@ -209,17 +209,17 @@ class cNodeMachine { static void MarkMeredians(); - void PlotNodes(int NeighbourColor, int NodeColor) const; + void PlotNodes(unsigned char NeighbourColor, unsigned char NodeColor) const; - void PlotPaths(int Tcolor, int CTcolor) const; + void PlotPaths(unsigned char Tcolor, unsigned char CTcolor) const; - void PlotGoals(int GoalColor) const; + void PlotGoals(unsigned char color) const; static void makeAllWaypointsAvailable(); - bool isValidNodeIndex(int index) const; + static bool isValidNodeIndex(int index); - bool isInvalidNode(int index) const; + static bool isInvalidNode(int index); void buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot); diff --git a/bot.cpp b/bot.cpp index 2a91a0c..7bc6c8d 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress @@ -1704,7 +1706,7 @@ void cBot::JoinTeam() { } } -int cBot::ReturnTurnedAngle(float speed, float current, float ideal) { +vec_t cBot::ReturnTurnedAngle(float speed, float current, float ideal) { // hope this fix the unnescesary turning of bots. // how? we save the values here, andc alculate the new value. diff --git a/bot.h b/bot.h index a282ca8..2ba44a7 100644 --- a/bot.h +++ b/bot.h @@ -408,7 +408,7 @@ class cBot { void FireWeapon(); - static int ReturnTurnedAngle(float speed, float current, float ideal); + static vec_t ReturnTurnedAngle(float speed, float current, float ideal); int FindEnemy(); diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 0f20482..4605de0 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/bot_client.cpp b/bot_client.cpp index 9aca41b..5c0106d 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/bot_func.cpp b/bot_func.cpp index ab2d84e..3c810de 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 240a044..857713d 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/build.cpp b/build.cpp index 3309b64..5def0bc 100644 --- a/build.cpp +++ b/build.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com // 14/11/04 // Updated Build nr; it compiles in MSVC again, and should compile in Linux... i did not // change that much. diff --git a/dll.cpp b/dll.cpp index 24dcd72..69fc677 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/engine.cpp b/engine.cpp index 069e249..4b246f4 100644 --- a/engine.cpp +++ b/engine.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/game.cpp b/game.cpp index 393fe5e..d20039a 100644 --- a/game.cpp +++ b/game.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * RealBot : Artificial Intelligence * Version : Work In Progress diff --git a/util.cpp b/util.cpp index 7ace596..994ff04 100644 --- a/util.cpp +++ b/util.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /*** * * Copyright (c) 1999, Valve LLC. All rights reserved. From edb6da8c2fee2a778a5236a148c1180423dc73ca Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 22 May 2025 21:47:11 +0100 Subject: [PATCH 097/114] Experimental Modernisation --- ChatEngine.cpp | 31 +++++++++++++--------------- NodeMachine.cpp | 50 +++++++++++++++++++++++----------------------- bot.cpp | 27 ++++++++++++++----------- bot_func.cpp | 6 +++--- dll.cpp | 20 +++++++++---------- engine.cpp | 2 +- game.cpp | 13 +++++------- realbot_mm.vcxproj | 2 +- 8 files changed, 74 insertions(+), 77 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index a2c6bb2..8dcc7ae 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -158,23 +158,21 @@ void cChatEngine::think() { // End of protection matters // Step: Check character to identify the end of a word. - if (sentence[c] == ' ' || sentence[c] == '\n' || - sentence[c] == '.' || sentence[c] == '?' || - sentence[c] == '!' || c == sentenceLength) { + if (c >= sentenceLength || sentence[c] == ' ' || sentence[c] == '\n' || + sentence[c] == '.' || sentence[c] == '?' || sentence[c] == '!') { // Now find the word and add up scores on the proper score blocks. - if (c == sentenceLength) - word[wc] = sentence[c]; + if (c >= sentenceLength) + word[wc] = '\0'; // Null-terminate the word properly. [APG]RoboCop[CL] - // not a good word (too small) + // not a good word (too small) if (std::strlen(word) <= 0) { - //SERVER_PRINT("This is not a good word!\n"); + // SERVER_PRINT("This is not a good word!\n"); } else { for (int iB = 0; iB < MAX_BLOCKS; iB++) { if (ReplyBlock[iB].bUsed) { - for (const char(&iBw)[25] : ReplyBlock[iB].word) - { + for (const char(&iBw)[25] : ReplyBlock[iB].word) { // skip any word in the reply block that is not valid if (iBw[0] == '\0') continue; // not filled in @@ -186,19 +184,18 @@ void cChatEngine::think() { // add score to matching word (evy: ignoring case) if (std::strcmp(iBw, word) == 0) WordBlockScore[iB]++; - } // all words in this block - } // any used block - } // for all blocks - } // good word - + } // all words in this block + } // any used block + } // for all blocks + } // good word // clear out entire word. //for (int cw=0; cw < 20; cw++) // word[cw] = '\0'; std::memset(word, 0, sizeof(word)); - wc = 0; // reset WC position (start writing 'word[WC]' at 0 again) - c++; // next position in sentence - continue; // go to top again. + wc = 0; // reset WC position (start writing 'word[WC]' at 0 again) + c++; // next position in sentence + continue; // go to top again. } // when we end up here, we are still reading a 'non finishing word' character. // we will fill that in word[wc]. Then add up wc and c, until we find a character diff --git a/NodeMachine.cpp b/NodeMachine.cpp index eba133a..39d42fd 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -35,6 +35,7 @@ **/ #include +#include #include #include #include @@ -78,17 +79,16 @@ int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const { // was int - // work out the position + // work out the position const long iPosition = iFrom * MAX_NODES + iTo; const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - if (iByte < g_iMaxVisibilityByte) { - const unsigned char* ToReturn = cVisTable + iByte; - return (*ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; - } + // Optional assertion + assert(iByte < g_iMaxVisibilityByte); + const unsigned char* ToReturn = cVisTable + iByte; - return VIS_BLOCKED; + return (*ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; } void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { @@ -97,21 +97,21 @@ void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { return; } - iVisChecked[iFrom] = 1; + iVisChecked[iFrom] = 1; - // was int + // work out the position const long iPosition = iFrom * MAX_NODES + iTo; const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - if (iByte < g_iMaxVisibilityByte) { - unsigned char* ToChange = cVisTable + iByte; - if (bVisible) { - *ToChange |= (1 << iBit); - } - else { - *ToChange &= ~(1 << iBit); - } + // Optional assertion + assert(iByte < g_iMaxVisibilityByte); + unsigned char* ToChange = cVisTable + iByte; + if (bVisible) { + *ToChange |= (1 << iBit); + } + else { + *ToChange &= ~(1 << iBit); } } @@ -279,13 +279,13 @@ int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) const { - if (index < 0) { + if (index < 0 || index >= MAX_TROUBLE) { // Use MAX_TROUBLE for bounds checking [APG]RoboCop[CL] rblog("(trouble) hasAttemptedConnectionTooManyTimes | invalid index for hasAttemptedConnectionTooManyTimes()\n"); // deal with invalid connection return false; } - const tTrouble &trouble = Troubles[index]; + const tTrouble& trouble = Troubles[index]; char msg[255]; snprintf(msg, sizeof(msg), "(trouble) hasAttemptedConnectionTooManyTimes | Connection %d (%d->%d) has %d tries.\n", index, trouble.iFrom, trouble.iTo, trouble.iTries); rblog(msg); @@ -803,7 +803,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const #endif // Just in case if (static_cast(Start.x) == 9999 || static_cast(End.x) == 9999) - return false; + return 0; // Quick & dirty check whether we can go through... // This is simply to quickly decide whether the move is impossible @@ -814,7 +814,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const #endif if (tr.flFraction < 1.0f) - return false; + return 0; // If either start/end is on ladder, assume we can fly without falling // but still check whether a human hull can go through @@ -856,14 +856,14 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const if (Height > PreviousHeight) { // Going upwards if (Height - PreviousHeight > MAX_JUMPHEIGHT) { //printf(" too high for upward jump\n") ; - return false; + return 0; } } else { // Going downwards if (PreviousHeight - Height > MAX_FALLHEIGHT) if (UTIL_PointContents(Floor + Vector(0, 0, 5)) != CONTENTS_WATER) //{printf(" too high for a downward fall not in water\n") ; - return false; // Falling from too high not in water + return 0; // Falling from too high not in water //} //else printf(" ouf we are in water\n") ; } @@ -882,13 +882,13 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const if (Height > PreviousHeight) { // Going upwards if (Height - PreviousHeight > MAX_JUMPHEIGHT) { //printf(" too high for upward jump\n") ; - return false; + return 0; } } else { // Going downwards if (PreviousHeight - Height > MAX_FALLHEIGHT) if (UTIL_PointContents(End) != CONTENTS_WATER) { //printf(" too high for a downward fall not in water\n") ; - return false; // Falling from too high not in water + return 0; // Falling from too high not in water } //else printf(" ouf we are in water\n") ; } @@ -901,7 +901,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const // TODO // Success ! - return true; + return 1; } // Adding a node: another way... diff --git a/bot.cpp b/bot.cpp index 7bc6c8d..4bd182c 100644 --- a/bot.cpp +++ b/bot.cpp @@ -75,6 +75,7 @@ bool CBaseBot::IsShootableThruObstacle(Vector vecDest) */ #include +#include #include #include #include @@ -633,12 +634,11 @@ bool cBot::isSeeingEnemy() { if (isBlindedByFlashbang()) { return false; } + Vector enemyBody = pEnemyEdict->v.origin; // Renamed from vBody to enemyBody - [APG]RoboCop[CL] + Vector enemyHead = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs; // Renamed from vHead to enemyHead - Vector vBody = pEnemyEdict->v.origin; - Vector vHead = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs; - - const bool bodyInFOV = FInViewCone(&vBody, pEdict) && FVisible(vBody, pEdict); - const bool headInFOV = FInViewCone(&vHead, pEdict) && FVisible(vHead, pEdict); + const bool bodyInFOV = FInViewCone(&enemyBody, pEdict) && FVisible(enemyBody, pEdict); + const bool headInFOV = FInViewCone(&enemyHead, pEdict) && FVisible(enemyHead, pEdict); if (bodyInFOV || headInFOV) { return true; } @@ -672,9 +672,9 @@ void cBot::AimAtEnemy() { Vector vTarget; if (bot_skill <= 1) vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-0.5f, 1.1f); // aim for the head - else if (bot_skill > 1 && bot_skill < 4) + else if (bot_skill < 4) // bot_skill > 1 is implied here? [APG]RoboCop[CL] vTarget = pEnemyEdict->v.origin + - pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy else vTarget = pEnemyEdict->v.origin; // aim for body @@ -1478,7 +1478,7 @@ void cBot::InteractWithPlayers() { // ------------------------------------------------ // RESULT > -1 ; ENEMY FOUND / NO SPECIFIC REACTION // ------------------------------------------------ - if (result > -1 && result < 4) { + if (result > -1 /*&& result < 4*/) { // VIP: When we found an enemy, we have a problem. if (vip) { @@ -1802,7 +1802,9 @@ bool cBot::Defuse() { // Remember, pent=c4 now! // Calculate the distance between our position to the c4 + assert(pent != nullptr); const Vector vC4 = pent->v.origin; + const float distance = func_distance(pEdict->v.origin, vC4); // can see C4 @@ -2440,9 +2442,9 @@ void cBot::rprint(const char *Function, const char *msg) * @param Function * @param msg */ -void cBot::rprint_trace(const char *Function, const char *msg) +void cBot::rprint_trace(const char* Function, const char* msg) { - if (Game.messageVerbosity > 1) { + if (Game.messageVerbosity > 2) { // Adjust verbosity level for trace REALBOT_PRINT(this, Function, msg); } } @@ -2452,8 +2454,9 @@ void cBot::rprint_trace(const char *Function, const char *msg) * @param Function * @param msg */ -void cBot::rprint_normal(const char *Function, const char *msg) { - if (Game.messageVerbosity > 1) { +void cBot::rprint_normal(const char* Function, const char* msg) +{ + if (Game.messageVerbosity > 1) { // Keep verbosity level for normal REALBOT_PRINT(this, Function, msg); } } diff --git a/bot_func.cpp b/bot_func.cpp index 3c810de..020c750 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -792,7 +792,7 @@ void FUNC_HearingTodo(cBot *pBot) { if (health < 25) action = 2; - else if (health >= 25 && health < 75) + else if (/*health >= 25 &&*/ health < 75) action = 1; else action = -1; @@ -1098,13 +1098,13 @@ int FUNC_GiveHostage(cBot* pBot) //Experimental [APG]RoboCop[CL] // by default run pBot->setMoveSpeed(pBot->f_max_speed); - if (distanceToHostage <= 80) + if (distanceToHostage <= 80.0f) { pBot->rprint_trace("GiveHostage", "I can see hostage AND really close!"); pBot->setMoveSpeed(0.0f); // too close, do not move } } - return true; //gives any hostage we still have to go for + return 1; //gives any hostage we still have to go for } bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { diff --git a/dll.cpp b/dll.cpp index 69fc677..b2acc21 100644 --- a/dll.cpp +++ b/dll.cpp @@ -179,7 +179,7 @@ C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, "metamod version is too old for this plugin; update metamod"); LOG_ERROR(PLID, "metamod version is too old for this plugin; update metamod"); - return false; + return 0; } // if plugin has older major interface version, it's incompatible (update plugin) if (pmajor < mmajor) { @@ -187,10 +187,10 @@ C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, "metamod version is incompatible with this plugin; please find a newer version of this plugin"); LOG_ERROR(PLID, "metamod version is incompatible with this plugin; please find a newer version of this plugin"); - return false; + return 0; } } - return true; // tell metamod this plugin looks safe + return 1; // tell metamod this plugin looks safe } C_DLLEXPORT int @@ -208,7 +208,7 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, LOG_ERROR(PLID, "%s: plugin NOT attaching (can't load plugin right now)", Plugin_info.name); - return false; // returning FALSE prevents metamod from attaching this plugin + return 0; // returning FALSE prevents metamod from attaching this plugin } // keep track of the pointers to engine function tables metamod gives us gpMetaGlobals = pMGlobals; @@ -225,7 +225,7 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, // Notify user that 'realbot' command is regged LOG_CONSOLE(PLID, "realbot - command prefix is now reserved."); LOG_MESSAGE(PLID, "realbot - command prefix is now reserved."); - return true; // returning TRUE enables metamod to attach this plugin + return 1; // returning TRUE enables metamod to attach this plugin } C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { @@ -240,12 +240,12 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { LOG_ERROR(PLID, "%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name); - return false; // returning FALSE prevents metamod from unloading this plugin + return 0; // returning FALSE prevents metamod from unloading this plugin } NodeMachine.FreeVisibilityTable(); free(message); - return true; // returning TRUE enables metamod to unload this plugin + return 1; // returning TRUE enables metamod to unload this plugin } // END of Metamod stuff @@ -253,7 +253,7 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { #ifdef _WIN32 // Required DLL entry point int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - return true; + return 1; } #endif /* */ @@ -2095,7 +2095,7 @@ GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable.pfnClientCommand = ClientCommand; gFunctionTable.pfnStartFrame = StartFrame; std::memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); - return true; + return 1; } // Whistler: @@ -2103,7 +2103,7 @@ C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { gFunctionTable_post.pfnSpawn = Spawn_Post; // need to declare another gFunctionTable_post in the top of the dll.cpp file std::memcpy(pFunctionTable, &gFunctionTable_post, sizeof(DLL_FUNCTIONS)); - return true; + return 1; } // Stefan says: You where right, i did not understand it properly. But now i see the little diff --git a/engine.cpp b/engine.cpp index 4b246f4..1925b88 100644 --- a/engine.cpp +++ b/engine.cpp @@ -632,5 +632,5 @@ GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, meta_engfuncs.pfnSetClientMaxspeed = pfnSetClientMaxspeed; meta_engfuncs.pfnGetPlayerUserId = pfnGetPlayerUserId; std::memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t)); - return true; + return 1; } diff --git a/game.cpp b/game.cpp index d20039a..e01fd01 100644 --- a/game.cpp +++ b/game.cpp @@ -346,12 +346,9 @@ void cGame::SelectName(char *name) const const int iLimit = iNameIndex; // remember this. // make sure it is not checked yet - while (iNameUsed[iNameIndex]) { - // check again - if (iNameUsed[iNameIndex] == false) - break; + while (iNameUsed[iNameIndex]) { - // add up + // add up iNameIndex++; // make sure that it does not check out of range @@ -370,11 +367,11 @@ void cGame::SelectName(char *name) const // check if this name is used for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - const edict_t* pPlayer = INDEXENT(iIndex); + const edict_t* pPlayer = INDEXENT(iIndex); if (pPlayer && !pPlayer->free) { if (std::strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) == 0) { - // atten tion, this namehas been used. + // attention, this name has been used. bUsed = true; break; } @@ -712,7 +709,7 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { if (Game.bDebug > -2) { if (Game.bDebug == -1) { rblog(cMessage); - } else if (Game.bDebug == botIndex && botIndex > -1) { + } else if (Game.bDebug == botIndex /*&& botIndex > -1*/) { rblog(cMessage); } } diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index d5186e6..bdae191 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -16,7 +16,7 @@ v143 false MultiByte - Spectre + false From 934cee24ccf02be0e30d546af8eacdb50a32b199 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 31 May 2025 12:17:09 +0100 Subject: [PATCH 098/114] Redundant Condition Check in ChatEngine removed --- ChatEngine.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index 8dcc7ae..f604de7 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -149,23 +149,15 @@ void cChatEngine::think() { // loop over the sentence character by character while (c < sentenceLength) { // protection matters: - // Stefan: this is weird, this can never happen?! - if (c > sentenceLength) - break; - if (c < 0) break; // End of protection matters // Step: Check character to identify the end of a word. - if (c >= sentenceLength || sentence[c] == ' ' || sentence[c] == '\n' || + if (sentence[c] == ' ' || sentence[c] == '\n' || sentence[c] == '.' || sentence[c] == '?' || sentence[c] == '!') { // Now find the word and add up scores on the proper score blocks. - - if (c >= sentenceLength) - word[wc] = '\0'; // Null-terminate the word properly. [APG]RoboCop[CL] - - // not a good word (too small) + // not a good word (too small) if (std::strlen(word) <= 0) { // SERVER_PRINT("This is not a good word!\n"); } @@ -207,7 +199,8 @@ void cChatEngine::think() { // add up. c++; wc++; - } // end of loop + } + // end of loop // now loop through all blocks and find the one with the most score: int iMaxScore = -1; From 28187649241168f1ded8394ff9e7d58d291355d0 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 31 May 2025 12:21:24 +0100 Subject: [PATCH 099/114] Improved Conditional Handling --- dll.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/dll.cpp b/dll.cpp index b2acc21..9e54457 100644 --- a/dll.cpp +++ b/dll.cpp @@ -1457,28 +1457,25 @@ void RealBot_ServerCommand() { "REALBOT: Removing %d counter-terrorist bots.", kick_amount_bots); } - } else if (FStrEq(pcmd, "roundlimit")) { - + } + else if (FStrEq(pcmd, "roundlimit")) { // Check if Arguments are valid - if (arg2 != nullptr && *arg2 != 0 - && (arg1 != nullptr && *arg1 != 0)) { - int s1 = -1, s2 = -1; - + if (arg2 != nullptr && *arg2 != 0 && arg1 != nullptr && *arg1 != 0) { // argument 1 - if (arg1 != nullptr && *arg1 != 0) - s1 = std::atoi(arg1); - + const int s1 = std::atoi(arg1); // argument 2 - if (arg2 != nullptr && *arg2 != 0) - s2 = std::atoi(arg2); + const int s2 = std::atoi(arg2); Game.SetPlayingRounds(s1, s2); snprintf(cMessage, sizeof(cMessage), - "REALBOT: Bots play at minimum %d and at maximum %d rounds.\n", - Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); - } else + "REALBOT: Bots play at minimum %d and at maximum %d rounds.\n", + Game.GetMinPlayRounds(), Game.GetMaxPlayRounds()); + } + else { snprintf(cMessage, sizeof(cMessage), - "REALBOT: No(t) (enough) valid arguments given."); - } else if (FStrEq(pcmd, "setrandom")) { + "REALBOT: No(t) (enough) valid arguments given."); + } + } + else if (FStrEq(pcmd, "setrandom")) { int s1 = -2, s2 = -2; // argument 1 From 2c1f6909fc11668e2f9ef752c5754f006ff1fc01 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Fri, 1 Aug 2025 23:58:10 +0100 Subject: [PATCH 100/114] CZ Bots should no longer team attack --- ChatEngine.cpp | 47 ++- IniParser.cpp | 2 +- NodeMachine.cpp | 132 +++++---- NodeMachine.h | 2 +- bot.cpp | 93 +++--- bot_client.cpp | 84 +++--- bot_func.cpp | 341 +++++++++++----------- bot_func.h | 116 ++++---- bot_navigate.cpp | 34 ++- bot_weapons.h | 71 ++--- dependencies/hlsdk/dlls/util.h | 33 ++- dll.cpp | 503 +++++++++++++++++---------------- engine.cpp | 106 ++++--- game.cpp | 54 ++-- game.h | 23 +- todo.txt | 1 - util.cpp | 179 +++++------- 17 files changed, 905 insertions(+), 916 deletions(-) diff --git a/ChatEngine.cpp b/ChatEngine.cpp index f604de7..a40dd07 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -203,7 +203,7 @@ void cChatEngine::think() { // end of loop // now loop through all blocks and find the one with the most score: - int iMaxScore = -1; + int iMaxScore = 0; int iTheBlock = -1; // for all blocks @@ -233,11 +233,9 @@ void cChatEngine::think() { edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) - if (pPlayer && !pPlayer->free && pSender != pPlayer) { - const bool bSenderAlive = IsAlive(pSender); // CRASH : it sometimes crashes here - const bool bPlayerAlive = IsAlive(pPlayer); - - if (bSenderAlive != bPlayerAlive) + if (pPlayer && !pPlayer->free && pSender != pPlayer) + { + if (!IsAlive(pSender) || !IsAlive(pPlayer)) continue; cBot* pBotPointer = UTIL_GetBotPointer(pPlayer); @@ -254,12 +252,9 @@ void cChatEngine::think() { the_c == iLastSentence) { // when this is the same, avoid it. Try to change again if (iMax > 0) - the_c++; + the_c = (the_c + 1) % (iMax + 1); else continue; // do not reply double - - if (the_c > iMax) - the_c = 0; } // the_c is choosen, it is the sentence we reply with. // do a check if its valid: @@ -333,9 +328,10 @@ void cChatEngine::think() { snprintf(chSentence, sizeof(chSentence), "%s \n", temp); } // when no name pos is found, we just copy the string and say that (works ok) - else + else { snprintf(chSentence, sizeof(chSentence), "%s \n", ReplyBlock[iTheBlock].sentence[the_c]); + } // reply: pBotPointer->PrepareChat(chSentence); @@ -394,16 +390,19 @@ void cChatEngine::handle_sentence() { } -void cChatEngine::set_sentence(char csender[MAX_NAME_LENGTH], char csentence[MAX_SENTENCE_LENGTH]) { - if (sender[0] == ' ' || sender[0] == '\0') { - std::strcpy(sender, csender); -#ifdef _WIN32 - _strupr(csentence); -#else - std::transform(csentence, csentence + std::strlen(csentence), csentence, ::toupper); -#endif - std::strcpy(sentence, csentence); - } +void cChatEngine::set_sentence(char csender[MAX_NAME_LENGTH], char csentence[MAX_SENTENCE_LENGTH]) { + if (sender[0] == ' ' || sender[0] == '\0') { + strncpy(sender, csender, sizeof(sender) - 1); + sender[sizeof(sender) - 1] = '\0'; + +#ifdef _WIN32 + _strupr(csentence); +#else + std::transform(csentence, csentence + std::strlen(csentence), csentence, ::toupper); +#endif + strncpy(sentence, csentence, sizeof(sentence) - 1); + sentence[sizeof(sentence) - 1] = '\0'; + } } diff --git a/IniParser.cpp b/IniParser.cpp index 6539916..46c6a9f 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -301,7 +301,7 @@ int INI_SectionType(char section[30], int last) { // Reads out section[], does a string compare and returns type id // BUYTABLE.INI SPECIFIC! -int INI_SectionType_BUYTABLE(char section[30], int last) { +int INI_SectionType_BUYTABLE(char section[30], const int last) { if (std::strcmp(section, "P228") == 0) return CS_WEAPON_P228; if (std::strcmp(section, "HEGRENADE") == 0) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 39d42fd..824c688 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -57,9 +57,9 @@ tNodestar astar_list[MAX_NODES]; -const Vector &INVALID_VECTOR = Vector(9999, 9999, 9999); +const Vector& INVALID_VECTOR = Vector(9999, 9999, 9999); -extern edict_t *pHostEdict; +extern edict_t* pHostEdict; extern cGame Game; extern cBot bots[32]; extern int draw_nodepath; @@ -67,7 +67,7 @@ extern int draw_nodepath; //--------------------------------------------------------- //CODE: CHEESEMONSTER -int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const { +int cNodeMachine::GetVisibilityFromTo(const int iFrom, const int iTo) const { if (iFrom < 0 || iFrom >= MAX_NODES || iTo < 0 || iTo >= MAX_NODES) { rblog("ERROR: Index out of bounds in GetVisibilityFromTo! Returning VIS_BLOCKED\n"); return VIS_BLOCKED; @@ -78,33 +78,33 @@ int cNodeMachine::GetVisibilityFromTo(int iFrom, int iTo) const { } // was int - - // work out the position + + // work out the position const long iPosition = iFrom * MAX_NODES + iTo; const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - // Optional assertion + // Optional assertion assert(iByte < g_iMaxVisibilityByte); const unsigned char* ToReturn = cVisTable + iByte; return (*ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; } -void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { +void cNodeMachine::SetVisibilityFromTo(const int iFrom, const int iTo, const bool bVisible) { if (iFrom < 0 || iFrom >= MAX_NODES || iTo < 0 || iTo >= MAX_NODES) { rblog("ERROR: Index out of bounds in SetVisibilityFromTo!\n"); return; } - iVisChecked[iFrom] = 1; + iVisChecked[iFrom] = 1; - // work out the position + // work out the position const long iPosition = iFrom * MAX_NODES + iTo; const long iByte = iPosition / 8; const unsigned int iBit = iPosition % 8; - // Optional assertion + // Optional assertion assert(iByte < g_iMaxVisibilityByte); unsigned char* ToChange = cVisTable + iByte; if (bVisible) { @@ -115,7 +115,7 @@ void cNodeMachine::SetVisibilityFromTo(int iFrom, int iTo, bool bVisible) { } } -void cNodeMachine::ClearVisibilityTable() const +void cNodeMachine::ClearVisibilityTable() { if (cVisTable) { std::memset(cVisTable, 0, g_iMaxVisibilityByte); @@ -205,7 +205,7 @@ void cNodeMachine::initGoals() { } } -void cNodeMachine::initGoal(int g) { +void cNodeMachine::initGoal(const int g) { Goals[g].iNode = -1; Goals[g].pGoalEdict = nullptr; Goals[g].iType = GOAL_NONE; @@ -240,7 +240,6 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const } } -// rblog("GetTroubleIndexForConnection | found no index matching from/to. Returning -1\n"); return -1; } @@ -251,7 +250,7 @@ int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const * @param iTo * @return index of newly created index */ -int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) +int cNodeMachine::AddTroubledConnection(const int iFrom, const int iTo) { const int existingIndex = GetTroubleIndexForConnection(iFrom, iTo); if (existingIndex > -1) @@ -277,7 +276,7 @@ int cNodeMachine::AddTroubledConnection(int iFrom, int iTo) return iNew; } -bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) const +bool cNodeMachine::hasAttemptedConnectionTooManyTimes(const int index) const { if (index < 0 || index >= MAX_TROUBLE) { // Use MAX_TROUBLE for bounds checking [APG]RoboCop[CL] rblog("(trouble) hasAttemptedConnectionTooManyTimes | invalid index for hasAttemptedConnectionTooManyTimes()\n"); @@ -306,7 +305,7 @@ bool cNodeMachine::hasAttemptedConnectionTooManyTimes(int index) const * @param iTo * @return */ -bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int iFrom, int iTo) +bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(const int iFrom, const int iTo) { const int index = AddTroubledConnection(iFrom, iTo); IncreaseAttemptsForTroubledConnection(index); @@ -326,7 +325,7 @@ bool cNodeMachine::IncreaseAttemptsForTroubledConnectionOrRemoveIfExceeded(int i return true; } -void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) +void cNodeMachine::IncreaseAttemptsForTroubledConnection(const int index) { if (index < 0 || index >= MAX_TROUBLE) return; @@ -342,7 +341,7 @@ void cNodeMachine::IncreaseAttemptsForTroubledConnection(int index) rblog(msg); } -bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) +bool cNodeMachine::ClearTroubledConnection(const int iFrom, const int iTo) { char msg[255]; snprintf(msg, sizeof(msg), "(trouble) NodeMachine::ClearTroubledConnection | %d -> %d - START\n", iFrom, iTo); @@ -367,7 +366,7 @@ bool cNodeMachine::ClearTroubledConnection(int iFrom, int iTo) return true; } -void cNodeMachine::path_clear(int botIndex) +void cNodeMachine::path_clear(const int botIndex) { for (int nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { iPath[botIndex][nodeIndex] = -1; @@ -375,7 +374,7 @@ void cNodeMachine::path_clear(int botIndex) } // Return -Vector cNodeMachine::node_vector(int iNode) const +Vector cNodeMachine::node_vector(const int iNode) const { if (iNode > -1) { return Nodes[iNode].origin; @@ -399,7 +398,7 @@ void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) *iY = static_cast(iCoordY); } -void cNodeMachine::AddToMeredian(int iX, int iY, int iNode) +void cNodeMachine::AddToMeredian(const int iX, const int iY, const int iNode) { int index = -1; for (int i = 0; i < MAX_NODES_IN_MEREDIANS; i++) @@ -496,7 +495,7 @@ int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDis * @param pEdict * @return */ -int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pEdict) const +int cNodeMachine::getClosestNode(const Vector& vOrigin, const float fDist, edict_t *pEdict) const { // REDO: Need faster method to find a node // TOADD: For secure results all nodes should be checked to figure out the real @@ -562,7 +561,7 @@ int cNodeMachine::getClosestNode(const Vector& vOrigin, float fDist, edict_t *pE * @param pEdict * @return */ -int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, const edict_t *pEdict) const +int cNodeMachine::getFurthestNode(const Vector& vOrigin, const float fDist, const edict_t *pEdict) const { // Use Meredians to search for nodes // TODO: we should take care in the situation where we're at the 'edge' of such a meridian (subspace). So we should @@ -619,7 +618,7 @@ int cNodeMachine::getFurthestNode(const Vector& vOrigin, float fDist, const edic } // Adds a neighbour connection to a node ID -bool cNodeMachine::add_neighbour_node(int iNode, int iToNode) { +bool cNodeMachine::add_neighbour_node(const int iNode, const int iToNode) { if (iNode < 0) return false; @@ -640,7 +639,7 @@ bool cNodeMachine::add_neighbour_node(int iNode, int iToNode) { * @param iTo * @return */ -bool cNodeMachine::removeConnection(int iFrom, int iTo) { +bool cNodeMachine::removeConnection(const int iFrom, const int iTo) { if (iFrom < 0 || iTo < 0) { return false; } @@ -683,7 +682,7 @@ bool cNodeMachine::removeConnection(int iFrom, int iTo) { } // Removes ALL neighbour connections on iNode -bool cNodeMachine::remove_neighbour_nodes(int iNode) { +bool cNodeMachine::remove_neighbour_nodes(const int iNode) { if (iNode < 0) return false; @@ -704,7 +703,7 @@ int cNodeMachine::freeNeighbourNodeIndex(const tNode *Node) { return -1; } -int cNodeMachine::is_neighbour_node(const tNode& node, int iNode) +int cNodeMachine::is_neighbour_node(const tNode& node, const int iNode) { for (int i = 0; i < MAX_NEIGHBOURS; i++) { if (node.iNeighbour[i] == iNode) { @@ -716,7 +715,7 @@ int cNodeMachine::is_neighbour_node(const tNode& node, int iNode) } // Return the node id from bot path on Index NR -int cNodeMachine::getNodeIndexFromBotForPath(int botIndex, int pathNodeIndex) const +int cNodeMachine::getNodeIndexFromBotForPath(const int botIndex, const int pathNodeIndex) const { if (botIndex > -1 && botIndex < MAX_BOTS && pathNodeIndex > -1 && pathNodeIndex < MAX_PATH_NODES) { @@ -905,7 +904,7 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const } // Adding a node: another way... -int cNodeMachine::add2(const Vector& vOrigin, int iType, edict_t *pEntity) { +int cNodeMachine::add2(const Vector& vOrigin, const int iType, edict_t *pEntity) { // Do not add a node when there is already one close if (getClosestNode(vOrigin, NODE_ZONE, pEntity) > -1) return -1; @@ -1284,7 +1283,7 @@ void cNodeMachine::init_round() { */ void cNodeMachine::addNodesForPlayers() { for (int index = 1; index <= gpGlobals->maxClients; index++) { - edict_t *pPlayer = INDEXENT(index); + edict_t* pPlayer = INDEXENT(index); // skip invalid (dead, not playing) players if (pPlayer && !pPlayer->free) { @@ -1485,7 +1484,7 @@ void cNodeMachine::experience_save() { FILE* rbl = std::fopen(filename, "wb"); if (rbl != nullptr) { - constexpr int iVersion = FILE_EXP_VER2; + constexpr int iVersion = FILE_EXP_VER2; std::fwrite(&iVersion, sizeof(int), 1, rbl); struct Node { @@ -1563,8 +1562,8 @@ void cNodeMachine::experience_load() { FILE* rbl = std::fopen(filename, "rb"); if (rbl != nullptr) { - int i; - int iVersion = FILE_EXP_VER1; + int i; + int iVersion = FILE_EXP_VER1; std::fread(&iVersion, sizeof(int), 1, rbl); struct Node { @@ -1852,7 +1851,7 @@ void cNodeMachine::path_draw(edict_t* pEntity) const } // Spread contact areas -void cNodeMachine::contact(int iNode, int iTeam) { +void cNodeMachine::contact(const int iNode, const int iTeam) { if (iNode < 0 || iNode >= MAX_NODES) return; @@ -1890,7 +1889,7 @@ void cNodeMachine::contact(int iNode, int iTeam) { } // Spread danger around -void cNodeMachine::danger(int iNode, int iTeam) { +void cNodeMachine::danger(const int iNode, const int iTeam) { if (iNode < 0 || iNode >= MAX_NODES) return; @@ -1929,7 +1928,7 @@ void cNodeMachine::danger(int iNode, int iTeam) { } // Adds a new goal to the array -void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { +void cNodeMachine::addGoal(edict_t *pEdict, const int goalType, const Vector& vVec) { // // 14/06/04 // Be carefull with adding SERVER_PRINT messages here @@ -1984,7 +1983,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, int goalType, const Vector& vVec) { rblog(msg); } -tGoal *cNodeMachine::getGoal(int index) { +tGoal *cNodeMachine::getGoal(const int index) { if (index < 0 || index >= MAX_GOALS) { rblog("ERROR: Asking to retrieve goal with invalid index! Returning goal NULL\n"); return nullptr; @@ -2041,7 +2040,7 @@ void cNodeMachine::resetCheckedValuesForGoals() { } // returns goal type from node, -1 for unknown -int cNodeMachine::getGoalIndexFromNode(int iNode) const +int cNodeMachine::getGoalIndexFromNode(const int iNode) const { for (const tGoal& Goal : Goals) if (Goal.iNode == iNode) @@ -2172,7 +2171,7 @@ void cNodeMachine::setUpInitialGoals() { } // Find a goal, and return the node close to it -tGoal* cNodeMachine::getRandomGoalByType(int goalType) { +tGoal* cNodeMachine::getRandomGoalByType(const int goalType) { if (goalType == GOAL_NONE) return nullptr; @@ -2265,7 +2264,7 @@ void cNodeMachine::scale_danger() { } // Pathfinder -bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot *pBot, int iFlags) { +bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetIndex, const int botIndex, cBot *pBot, int iFlags) { // Will create a path from nodeStartIndex to nodeTargetIndex, and store it into index number iPathId if (pBot) { @@ -2468,7 +2467,7 @@ bool cNodeMachine::createPath(int nodeStartIndex, int nodeTargetIndex, int botIn * @param parent * @param cost */ -void cNodeMachine::closeNode(int nodeIndex, int parent, float cost) { +void cNodeMachine::closeNode(const int nodeIndex, const int parent, const float cost) { astar_list[nodeIndex].state = CLOSED; astar_list[nodeIndex].parent = parent; astar_list[nodeIndex].cost = cost; @@ -2484,7 +2483,7 @@ void cNodeMachine::closeNode(int nodeIndex, int parent, float cost) { * @param parent * @param cost */ -void cNodeMachine::openNeighbourNodes(int startNodeIndex, int nodeToOpenNeighboursFrom, int destinationNodeIndex, int botTeam) const +void cNodeMachine::openNeighbourNodes(const int startNodeIndex, const int nodeToOpenNeighboursFrom, const int destinationNodeIndex, const int botTeam) const { const tNode &startNode = Nodes[startNodeIndex]; // very start of path const tNode &destNode = Nodes[destinationNodeIndex]; // destination for path @@ -2545,18 +2544,18 @@ void cNodeMachine::makeAllWaypointsAvailable() // rblog("All nodes set to AVAILABLE\n"); } -bool cNodeMachine::isValidNodeIndex(int index) //TODO: Experimental [APG]RoboCop[CL] +bool cNodeMachine::isValidNodeIndex(const int index) //TODO: Experimental [APG]RoboCop[CL] { return index >= 0 && index < MAX_NODES; } -bool cNodeMachine::isInvalidNode(int index) //TODO: Experimental [APG]RoboCop[CL] +bool cNodeMachine::isInvalidNode(const int index) //TODO: Experimental [APG]RoboCop[CL] { return !isValidNodeIndex(index); } //TODO: Implement this function - Experimental [APG]RoboCop[CL] -void cNodeMachine::buildPath(int nodeStartIndex, int nodeTargetIndex, int botIndex, cBot* pBot) +void cNodeMachine::buildPath(const int nodeStartIndex, const int nodeTargetIndex, const int botIndex, cBot* pBot) { if (!isValidNodeIndex(nodeStartIndex) || !isValidNodeIndex(nodeTargetIndex)) { rblog("Invalid node index provided to buildPath"); @@ -2612,7 +2611,7 @@ void cNodeMachine::buildPath(int nodeStartIndex, int nodeTargetIndex, int botInd } // Find a node which has almost no danger! -int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const +int cNodeMachine::node_camp(const Vector& vOrigin, const int iTeam) const { // Use Meredians to search for nodes int iX, iY; @@ -2664,7 +2663,7 @@ int cNodeMachine::node_camp(const Vector& vOrigin, int iTeam) const } // Check if iFrom is visible from other nodes (and opposite) -void cNodeMachine::vis_calculate(int iFrom) { +void cNodeMachine::vis_calculate(const int iFrom) { // Check around your area to see what is visible for (int i = 0; i < MAX_NODES; i++) @@ -2692,8 +2691,7 @@ void cNodeMachine::vis_calculate(int iFrom) { } // Find a node to look at when camping -int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, - edict_t *pEdict) { +int cNodeMachine::node_look_camp(const Vector& vOrigin, const int iTeam, edict_t *pEdict) { rblog("node_look_camp - start\n"); float fDanger = -0.1f; @@ -2755,7 +2753,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, int iTeam, * @param pBot * @param distanceMoved */ -void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { +void cNodeMachine::path_walk(cBot *pBot, const float distanceMoved) { pBot->rprint("cNodeMachine::path_walk", "START"); const int BotIndex = pBot->iBotIndex; @@ -2943,7 +2941,8 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } } - bool shouldDrawWaypointBeamsFromBot = false; + // No longer required? [APG]RoboCop[CL] + /*bool shouldDrawWaypointBeamsFromBot = false; if (shouldDrawWaypointBeamsFromBot) { const tNode *nodeHeadingFor = this->getNode(currentNodeToHeadFor); @@ -2982,7 +2981,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { } } } - } // Draw waypoint beams + }*/ // Draw waypoint beams // reached node if (bNearNode) { @@ -3095,7 +3094,7 @@ void cNodeMachine::path_walk(cBot *pBot, float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_walk", "Finished - really the end of the method"); } -void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, int currentNodeToHeadFor, const Vector &vector) { +void cNodeMachine::ExecuteIsStuckLogic(cBot *pBot, const int currentNodeToHeadFor, const Vector& vector) { pBot->rprint_trace("cNodeMachine::ExecuteIsStuckLogic", "START"); pBot->fNotStuckTime = gpGlobals->time + 0.25f; // give some time to unstuck @@ -3399,7 +3398,7 @@ bool cNodeMachine::isEntityWorldspawn(const edict_t *pEntityHit) } // Think about path creation here -void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { +void cNodeMachine::path_think(cBot *pBot, const float distanceMoved) { pBot->rprint_trace("cNodeMachine::path_think", "START"); if (pBot->shouldBeWandering()) { int currentNode = -1; @@ -3883,7 +3882,7 @@ void cNodeMachine::path_think(cBot *pBot, float distanceMoved) { } } -tNode *cNodeMachine::getNode(int index) { +tNode *cNodeMachine::getNode(const int index) { // safe-guard if (index < 0 || index >= MAX_NODES) return nullptr; return &Nodes[index]; @@ -3924,7 +3923,7 @@ std::string cNodeMachine::getGoalTypeAsText(const tGoal& goal) } // Find cover -int cNodeMachine::node_cover(int iFrom, int iTo, edict_t *pEdict) { +int cNodeMachine::node_cover(const int iFrom, const int iTo, edict_t *pEdict) { if (iFrom == iTo) return iFrom; // cover at current position @@ -3992,8 +3991,7 @@ int cNodeMachine::node_cover(int iFrom, int iTo, edict_t *pEdict) { } -int cNodeMachine::node_look_at_hear(int iFrom, int iOrigin, - edict_t *pEdict) { +int cNodeMachine::node_look_at_hear(const int iFrom, const int iOrigin, edict_t *pEdict) { if (iFrom == iOrigin) return iFrom; // impossible @@ -4128,7 +4126,7 @@ void cNodeMachine::dump_goals() const } // EVY: another dump -void cNodeMachine::dump_path(int iBot, int CurrentPath) const +void cNodeMachine::dump_path(const int iBot, const int CurrentPath) const { char buffer[80]; int i, CurrentNode; @@ -4192,7 +4190,7 @@ static void InitDebugBitmap() { } // Draw a small cross -static void DrawPoint(const Vector& v, unsigned char color) { +static void DrawPoint(const Vector& v, const unsigned char color) { if (bmp_buffer == nullptr) { std::fprintf(stderr, "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); @@ -4223,7 +4221,7 @@ static void DrawPoint(const Vector& v, unsigned char color) { // From PMB and Botman's code -static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, unsigned char color) { +static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, const unsigned char color) { // blind copy of botman's Bresenham(). This function prints a vector line into a bitmap dot // matrix. The dot matrix (bmp_buffer) is a global array. The size of the bitmap is always // assumed to be DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT pixels (currently 2000 * 2000 to fit with @@ -4571,7 +4569,7 @@ void cNodeMachine::MarkMeredians() { // Put a cross on all nodes in RBN + draw lines to all neighbours -void cNodeMachine::PlotNodes(unsigned char NeighbourColor, unsigned char NodeColor) const +void cNodeMachine::PlotNodes(const unsigned char NeighbourColor, const unsigned char NodeColor) const { int i; @@ -4593,7 +4591,7 @@ void cNodeMachine::PlotNodes(unsigned char NeighbourColor, unsigned char NodeCol // Put a small cross at all goal points -void cNodeMachine::PlotGoals(unsigned char color) const +void cNodeMachine::PlotGoals(const unsigned char color) const { for (int i = 0; i < MAX_GOALS && Goals[i].iNode >= 0; i++) { const Vector v = Nodes[Goals[i].iNode].origin; @@ -4602,7 +4600,7 @@ void cNodeMachine::PlotGoals(unsigned char color) const } // Plot the computed paths for all life bots -void cNodeMachine::PlotPaths(unsigned char Tcolor, unsigned char CTcolor) const +void cNodeMachine::PlotPaths(const unsigned char Tcolor, const unsigned char CTcolor) const { for (int iBot = 0; iBot < 32; iBot++) { if (bots[iBot].bIsUsed) { diff --git a/NodeMachine.h b/NodeMachine.h index 30851bf..7a94bf8 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -171,7 +171,7 @@ class cNodeMachine { // ------------------- // From cheesemonster: int GetVisibilityFromTo(int iFrom, int iTo) const; // BERKED - void ClearVisibilityTable() const; + void ClearVisibilityTable(); void SetVisibilityFromTo(int iFrom, int iTo, bool bVisible); diff --git a/bot.cpp b/bot.cpp index 4bd182c..f40ed21 100644 --- a/bot.cpp +++ b/bot.cpp @@ -118,9 +118,9 @@ cBot bots[32]; // max of 32 bots in a game // External added variables extern bool end_round; // End round -#ifndef _WIN32 +/*#ifndef _WIN32 #define snprintf std::snprintf //-V1059 -#endif +#endif*/ cBot::cBot() { pBotHostage = nullptr; @@ -499,7 +499,7 @@ void cBot::PrepareChat(char sentence[128]) { /****************************************************************************** Function purpose: Return reaction time based upon skill ******************************************************************************/ -float cBot::ReactionTime(int iSkill) { +float cBot::ReactionTime(const int iSkill) { const float time = RANDOM_FLOAT(fpMinReactTime, fpMaxReactTime); if (Game.messageVerbosity > 1) { char msg[255]; @@ -521,11 +521,11 @@ int cBot::FindEnemy() { if (fBlindedTime > gpGlobals->time) return -1; float fNearestDistance = 9999; // Nearest distance - edict_t *pNewEnemy = nullptr; // New enemy found + edict_t* pNewEnemy = nullptr; // New enemy found // SEARCH PLAYERS FOR ENEMIES for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { @@ -558,10 +558,10 @@ int cBot::FindEnemy() { // If the bot carries a sniper, always consider the enemy visible if (CarryWeaponType() != SNIPER) { - // bCanSee = true; + // bCanSee = true; } - if (fDistance < fNearestDistance && bCanSee) { + if (fDistance < fNearestDistance && bCanSee) { fNearestDistance = fDistance; pNewEnemy = pPlayer; } @@ -581,10 +581,12 @@ int cBot::FindEnemy() { // We have a reaction time to this new enemy rememberEnemyFound(); f_shoot_time = gpGlobals->time + ReactionTime(bot_skill); + + const bool hadNoEnemy = pEnemyEdict == nullptr; pEnemyEdict = pNewEnemy; // Update pointer // We did not have an enemy before - if (pEnemyEdict == nullptr) { + if (hadNoEnemy) { rprint_trace("FindEnemy()", "Found new enemy"); // RADIO: When we found a NEW enemy but NOT via a friend @@ -595,7 +597,7 @@ int cBot::FindEnemy() { // We found a new enemy return 0; } - + // we found an enemy that is newer/more dangerous then previous rprint_trace("FindEnemy()", "Found 'newer' enemy"); return 3; @@ -820,7 +822,7 @@ void cBot::FightEnemy() { } // visible } -void cBot::pickWeapon(int weaponId) { +void cBot::pickWeapon(const int weaponId) { UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(weaponId)); f_c4_time = gpGlobals->time - 1; // reset C4 timer data // give Counter-Strike time to switch weapon (animation, update state, etc) @@ -842,7 +844,7 @@ bool cBot::ownsFavoriteSecondaryWeapon() const * @param weaponId * @return */ -bool cBot::isOwningWeapon(int weaponId) const +bool cBot::isOwningWeapon(const int weaponId) const { return bot_weapons & 1 << weaponId; } @@ -852,7 +854,7 @@ bool cBot::isOwningWeapon(int weaponId) const * @param weaponId * @return */ -bool cBot::isHoldingWeapon(int weaponId) const +bool cBot::isHoldingWeapon(const int weaponId) const { return current_weapon.iId == weaponId; } @@ -867,7 +869,7 @@ bool cBot::hasFavoriteSecondaryWeaponPreference() const return ipFavoSecWeapon > -1; } -bool cBot::canAfford(int price) const //price muddled with weaponId? [APG]RoboCop[CL] +bool cBot::canAfford(const int price) const //price muddled with weaponId? [APG]RoboCop[CL] { return this->bot_money > price; } @@ -1485,7 +1487,7 @@ void cBot::InteractWithPlayers() { // We do not forget our enemy, but we will try to get the heck out of here. // TODO TODO TODO: code something here? - + } // Whenever we hold a knife, get our primary weapon if (CarryWeapon(CS_WEAPON_KNIFE)) { @@ -1567,17 +1569,18 @@ void cBot::InteractWithPlayers() { // Does our enemy (when a bot) has focus on us? bool focused; - const cBot *playerbot = UTIL_GetBotPointer(pEnemyEdict); + const cBot* playerbot = UTIL_GetBotPointer(pEnemyEdict); if (playerbot) { if (playerbot->pEnemyEdict == pEdict) focused = true; - } else // Its a human + } + else // Its a human { // When we are in his 'sight' of 25 degrees , we are pretty // much focussed for a first encounter. if (FUNC_InFieldOfView - (pEdict, (pEnemyEdict->v.origin - pEdict->v.origin)) < 25) + (pEdict, (pEnemyEdict->v.origin - pEdict->v.origin)) < 25) focused = true; } @@ -1706,7 +1709,7 @@ void cBot::JoinTeam() { } } -vec_t cBot::ReturnTurnedAngle(float speed, float current, float ideal) { +vec_t cBot::ReturnTurnedAngle(float speed, float current, const float ideal) { // hope this fix the unnescesary turning of bots. // how? we save the values here, andc alculate the new value. @@ -1814,7 +1817,7 @@ bool cBot::Defuse() { rprint_trace("Defuse()", "Cannot see planted C4 - bailing"); return false; } - + // it can be seen, so it has been discovered if (!Game.isPlantedC4Discovered()) { this->rprint_trace("Defuse()", "C4 is discovered, remembering its coordinates"); @@ -1887,7 +1890,7 @@ bool cBot::Defuse() { return true; } -int cBot::keyPressed(int key) const { +int cBot::keyPressed(const int key) const { return pEdict->v.button & key; } @@ -2132,7 +2135,7 @@ void cBot::CheckAround() { const Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; // TRACELINE: forward - UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); const bool bHitForward = tr.flFraction < 1.0f; // TRACELINE: Left @@ -2150,7 +2153,7 @@ void cBot::CheckAround() { // TRACELINE: Forward right UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); const bool bHitForwardRight = tr.flFraction < 1.0f; - + char msg[255]; snprintf(msg, sizeof(msg), "HIT results: forward: %d, left: %d, right: %d, forward left: %d, forward right: %d", bHitForward, bHitLeft, bHitRight, bHitForwardLeft, bHitForwardRight); rprint_trace("CheckAround", msg); @@ -2187,7 +2190,7 @@ void cBot::CheckAround() { // When checking around a bot also handles breakable stuff. // ------------------------------------------------------------- - edict_t *pent = nullptr; + edict_t* pent = nullptr; while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { char item_name[40]; std::strcpy(item_name, STRING(pent->v.classname)); @@ -2296,7 +2299,7 @@ bool cBot::hasEnemy() const */ bool cBot::hasEnemy(const edict_t * pEdict) const { - return this->pEnemyEdict == pEdict; + return this->pEnemyEdict == pEntity; } // Returns true if bot has a path to follow @@ -2310,14 +2313,14 @@ bool cBot::shouldBeWandering() { return false; } -void cBot::setMoveSpeed(float value) { +void cBot::setMoveSpeed(const float value) { // char msg[255]; // sprintf(msg, "setting to value %f / maxSpeed %f - sv_maxspeed = %f", value, this->f_max_speed, CVAR_GET_FLOAT("sv_maxspeed")); // rprint_trace("setMoveSpeed", msg); this->f_move_speed = value; } -void cBot::setStrafeSpeed(float value, float time) { +void cBot::setStrafeSpeed(const float value, const float time) { char msg[255]; snprintf(msg, sizeof(msg), "%f for %f seconds.", value, time); rprint_trace("setStrafeSpeed", msg); @@ -2329,17 +2332,17 @@ void cBot::setStrafeSpeed(float value, float time) { // } } -void cBot::strafeLeft(float time) +void cBot::strafeLeft(const float time) { setStrafeSpeed(-f_max_speed, time); } -void cBot::strafeRight(float time) +void cBot::strafeRight(const float time) { setStrafeSpeed(f_max_speed, time); } -void cBot::startWandering(float time) +void cBot::startWandering(const float time) { this->fWanderTime = gpGlobals->time + time; setMoveSpeed(f_max_speed); @@ -2391,7 +2394,7 @@ int cBot::getGoalNode() const return this->iGoalNode; } -void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { +void cBot::setGoalNode(const int nodeIndex, const int iGoalIndex) { if (nodeIndex < 0) { rprint("setGoalNode()", "WARN: Setting a goal lower than 0, assuming this is not intentional. If you need to forget a goal, use forgetGoal()"); } @@ -2414,7 +2417,7 @@ void cBot::setGoalNode(int nodeIndex, int iGoalIndex) { rprint("setGoalNode()", msg); } -void cBot::setGoalNode(int nodeIndex) +void cBot::setGoalNode(const int nodeIndex) { this->setGoalNode(nodeIndex, -1); } @@ -2498,15 +2501,15 @@ bool cBot::hasSecondaryWeaponEquiped() const return iSecondaryWeapon > -1; } -bool cBot::hasPrimaryWeapon(int weaponId) const +/*bool cBot::hasPrimaryWeapon(const int weaponId) const { return isOwningWeapon(weaponId); } -bool cBot::hasSecondaryWeapon(int weaponId) const +bool cBot::hasSecondaryWeapon(const int weaponId) const { return isOwningWeapon(weaponId); -} +}*/ void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { // To be sure the console will only change when we MAY change. @@ -2525,7 +2528,7 @@ void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { } } -void cBot::performBuyActions(int weaponIdToBuy) { +void cBot::performBuyActions(const int weaponIdToBuy) { if (weaponIdToBuy < 0) { return; } @@ -2988,7 +2991,7 @@ void cBot::Walk() //Experimental implementation [APG]RoboCop[CL] // BOT: Do i carry weapon # now? -bool cBot::CarryWeapon(int iType) const +bool cBot::CarryWeapon(const int iType) const { if (current_weapon.iId == iType) return true; @@ -3128,7 +3131,7 @@ int cBot::determineCurrentNodeWithTwoAttempts() { /** Find node close to bot, given range. Does not cache result. **/ -int cBot::determineCurrentNode(float range) const +int cBot::determineCurrentNode(const float range) const { return NodeMachine.getClosestNode(pEdict->v.origin, range, pEdict); } @@ -3925,7 +3928,7 @@ bool cBot::canSeeEntity(edict_t *pEntity) const * @param nodeIndex * @return */ -float cBot::getDistanceTo(int nodeIndex) { +float cBot::getDistanceTo(const int nodeIndex) { const tNode *nodePtr = NodeMachine.getNode(nodeIndex); if (nodePtr != nullptr) { return getDistanceTo(nodePtr->origin); @@ -4237,14 +4240,14 @@ float cBot::getDistanceToNextNode() const return MAP_MAX_SIZE; } -void cBot::setBodyToNode(int nodeIndex) { +void cBot::setBodyToNode(const int nodeIndex) { const tNode *node = NodeMachine.getNode(nodeIndex); if (node) { vBody = node->origin; } } -void cBot::lookAtNode(int nodeIndex) { +void cBot::lookAtNode(const int nodeIndex) { const tNode *node = NodeMachine.getNode(nodeIndex); if (node) { vHead = node->origin; @@ -4256,7 +4259,7 @@ void cBot::lookAtNode(int nodeIndex) { * we used. * @param timeInSeconds */ -void cBot::setTimeToMoveToNode(float timeInSeconds) { +void cBot::setTimeToMoveToNode(const float timeInSeconds) { char msg[255]; const float endTime = gpGlobals->time + timeInSeconds; snprintf(msg, sizeof(msg), "Set to %f so results into end time of %f", timeInSeconds, endTime); @@ -4270,7 +4273,7 @@ void cBot::setTimeToMoveToNode(float timeInSeconds) { * Whatever was set, increase the time given in function param. This expands the time a bit. * @param timeInSeconds */ -void cBot::increaseTimeToMoveToNode(float timeInSeconds) { +void cBot::increaseTimeToMoveToNode(const float timeInSeconds) { if (nodeTimeIncreasedAmount < 2) { nodeTimeIncreasedAmount++; this->fMoveToNodeTime += timeInSeconds; @@ -4299,7 +4302,7 @@ bool cBot::shouldWait() const return f_wait_time > gpGlobals->time; } -void cBot::setTimeToWait(float timeInSeconds) +void cBot::setTimeToWait(const float timeInSeconds) { this->f_wait_time = gpGlobals->time + timeInSeconds; } @@ -4324,7 +4327,7 @@ bool cBot::hasCurrentNode() const * @param destinationNode * @return */ -bool cBot::createPath(int destinationNode) { +bool cBot::createPath(const int destinationNode) { return createPath(destinationNode, PATH_NONE); } @@ -4334,7 +4337,7 @@ bool cBot::createPath(int destinationNode) { * @param flags * @return */ -bool cBot::createPath(int destinationNode, int flags) { +bool cBot::createPath(const int destinationNode, const int flags) { if (destinationNode < 0 || destinationNode >= MAX_NODES) { rprint("createPath()", "Unable to create path because destination node provided is < 0 or > MAX_NODES"); return false; diff --git a/bot_client.cpp b/bot_client.cpp index 5c0106d..edf038d 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -59,7 +59,7 @@ bot_weapon_t weapon_defs[MAX_WEAPONS]; // array of weapon definitions static FILE *fp; // This message is sent when the Counter-Strike VGUI menu is displayed. -void BotClient_CS_VGUI(void *p, int bot_index) { +void BotClient_CS_VGUI(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_VGUI()\n"); if (*static_cast(p) == 2) // is it a team select menu? bots[bot_index].start_action = MSG_CS_TEAM_SELECT; @@ -70,7 +70,7 @@ void BotClient_CS_VGUI(void *p, int bot_index) { } // This message is sent when a menu is being displayed in Counter-Strike. -void BotClient_CS_ShowMenu(void *p, int bot_index) { +void BotClient_CS_ShowMenu(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_ShowMenu()\n"); static int state = 0; // current state machine state @@ -153,19 +153,19 @@ void BotClient_Valve_WeaponList(void *p, int bot_index) { } } -void BotClient_CS_WeaponList(void *p, int bot_index) { +void BotClient_CS_WeaponList(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_WeaponList()\n"); // this is just like the Valve Weapon List message BotClient_Valve_WeaponList(p, bot_index); } -void BotClient_Gearbox_WeaponList(void *p, int bot_index) { +void BotClient_Gearbox_WeaponList(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_WeaponList()\n"); // this is just like the Valve Weapon List message BotClient_Valve_WeaponList(p, bot_index); } -void BotClient_FLF_WeaponList(void *p, int bot_index) { +void BotClient_FLF_WeaponList(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_WeaponList()\n"); // this is just like the Valve Weapon List message BotClient_Valve_WeaponList(p, bot_index); @@ -173,7 +173,7 @@ void BotClient_FLF_WeaponList(void *p, int bot_index) { // This message is sent when a weapon is selected (either by the bot chosing // a weapon or by the server auto assigning the bot a weapon). -void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { +void BotClient_Valve_CurrentWeapon(void *p, const int bot_index) { static int state = 0; // current state machine state static int iState; static int iId; @@ -210,26 +210,26 @@ void BotClient_Valve_CurrentWeapon(void *p, int bot_index) { } } -void BotClient_CS_CurrentWeapon(void *p, int bot_index) { +void BotClient_CS_CurrentWeapon(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_CurrentWeapon()\n"); // this is just like the Valve Current Weapon message BotClient_Valve_CurrentWeapon(p, bot_index); } -void BotClient_Gearbox_CurrentWeapon(void *p, int bot_index) { +void BotClient_Gearbox_CurrentWeapon(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_CurrentWeapon()\n"); // this is just like the Valve Current Weapon message BotClient_Valve_CurrentWeapon(p, bot_index); } -void BotClient_FLF_CurrentWeapon(void *p, int bot_index) { +void BotClient_FLF_CurrentWeapon(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_CurrentWeapon()\n"); // this is just like the Valve Current Weapon message BotClient_Valve_CurrentWeapon(p, bot_index); } // This message is sent whenever ammo ammounts are adjusted (up or down). -void BotClient_Valve_AmmoX(void *p, int bot_index) { +void BotClient_Valve_AmmoX(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_AmmoX()\n"); static int state = 0; // current state machine state static int index; @@ -257,19 +257,19 @@ void BotClient_Valve_AmmoX(void *p, int bot_index) { } } -void BotClient_CS_AmmoX(void *p, int bot_index) { +void BotClient_CS_AmmoX(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_AmmoX()\n"); // this is just like the Valve AmmoX message BotClient_Valve_AmmoX(p, bot_index); } -void BotClient_Gearbox_AmmoX(void *p, int bot_index) { +void BotClient_Gearbox_AmmoX(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_AmmoX()\n"); // this is just like the Valve AmmoX message BotClient_Valve_AmmoX(p, bot_index); } -void BotClient_FLF_AmmoX(void *p, int bot_index) { +void BotClient_FLF_AmmoX(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_AmmoX()\n"); // this is just like the Valve AmmoX message BotClient_Valve_AmmoX(p, bot_index); @@ -279,7 +279,7 @@ void BotClient_FLF_AmmoX(void *p, int bot_index) { // also sent so this message is probably not really necessary except it // allows the HUD to draw pictures of ammo that have been picked up. The // bots don't really need pictures since they don't have any eyes anyway. -void BotClient_Valve_AmmoPickup(void *p, int bot_index) { +void BotClient_Valve_AmmoPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_AmmoPickup()\n"); static int state = 0; // current state machine state static int index; @@ -305,45 +305,45 @@ void BotClient_Valve_AmmoPickup(void *p, int bot_index) { } } -void BotClient_CS_AmmoPickup(void *p, int bot_index) { +void BotClient_CS_AmmoPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_AmmoPickup()\n"); // this is just like the Valve Ammo Pickup message BotClient_Valve_AmmoPickup(p, bot_index); } -void BotClient_Gearbox_AmmoPickup(void *p, int bot_index) { +void BotClient_Gearbox_AmmoPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_AmmoPickup()\n"); // this is just like the Valve Ammo Pickup message BotClient_Valve_AmmoPickup(p, bot_index); } -void BotClient_FLF_AmmoPickup(void *p, int bot_index) { +void BotClient_FLF_AmmoPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_AmmoPickup()\n"); // this is just like the Valve Ammo Pickup message BotClient_Valve_AmmoPickup(p, bot_index); } // This message gets sent when the bot picks up a weapon. -void BotClient_Valve_WeaponPickup(void *p, int bot_index) { +void BotClient_Valve_WeaponPickup(void *p, const int bot_index) { const int index = *static_cast(p); // set this weapon bit to indicate that we are carrying this weapon bots[bot_index].bot_weapons |= (1 << index); } -void BotClient_CS_WeaponPickup(void *p, int bot_index) { +void BotClient_CS_WeaponPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_WeaponPickup()\n"); // this is just like the Valve Weapon Pickup message BotClient_Valve_WeaponPickup(p, bot_index); } -void BotClient_Gearbox_WeaponPickup(void *p, int bot_index) { +void BotClient_Gearbox_WeaponPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_WeaponPickup()\n"); // this is just like the Valve Weapon Pickup message BotClient_Valve_WeaponPickup(p, bot_index); } -void BotClient_FLF_WeaponPickup(void *p, int bot_index) { +void BotClient_FLF_WeaponPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_WeaponPickup()\n"); // this is just like the Valve Weapon Pickup message BotClient_Valve_WeaponPickup(p, bot_index); @@ -355,74 +355,74 @@ void BotClient_Valve_ItemPickup(void *p, int bot_index) { //DebugOut("bot_client: BotClient_Valve_ItemPickup()\n"); } -void BotClient_CS_ItemPickup(void *p, int bot_index) { +void BotClient_CS_ItemPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_ItemPickup()\n"); // this is just like the Valve Item Pickup message BotClient_Valve_ItemPickup(p, bot_index); } -void BotClient_Gearbox_ItemPickup(void *p, int bot_index) { +void BotClient_Gearbox_ItemPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_ItemPickup()\n"); // this is just like the Valve Item Pickup message BotClient_Valve_ItemPickup(p, bot_index); } -void BotClient_FLF_ItemPickup(void *p, int bot_index) { +void BotClient_FLF_ItemPickup(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_ItemPickup()\n"); // this is just like the Valve Item Pickup message BotClient_Valve_ItemPickup(p, bot_index); } // This message gets sent when the bots health changes. -void BotClient_Valve_Health(void *p, int bot_index) { +void BotClient_Valve_Health(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_Health()\n"); bots[bot_index].bot_health = *static_cast(p); // health ammount } -void BotClient_CS_Health(void *p, int bot_index) { +void BotClient_CS_Health(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_Health()\n"); // this is just like the Valve Health message BotClient_Valve_Health(p, bot_index); } -void BotClient_Gearbox_Health(void *p, int bot_index) { +void BotClient_Gearbox_Health(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_Health()\n"); // this is just like the Valve Health message BotClient_Valve_Health(p, bot_index); } -void BotClient_FLF_Health(void *p, int bot_index) { +void BotClient_FLF_Health(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_Health()\n"); // this is just like the Valve Health message BotClient_Valve_Health(p, bot_index); } // This message gets sent when the bots armor changes. -void BotClient_Valve_Battery(void *p, int bot_index) { +void BotClient_Valve_Battery(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_Battery()\n"); bots[bot_index].bot_armor = *static_cast(p); // armor ammount } -void BotClient_CS_Battery(void *p, int bot_index) { +void BotClient_CS_Battery(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_Battery()\n"); // this is just like the Valve Battery message BotClient_Valve_Battery(p, bot_index); } -void BotClient_Gearbox_Battery(void *p, int bot_index) { +void BotClient_Gearbox_Battery(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_Battery()\n"); // this is just like the Valve Battery message BotClient_Valve_Battery(p, bot_index); } -void BotClient_FLF_Battery(void *p, int bot_index) { +void BotClient_FLF_Battery(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_Battery()\n"); // this is just like the Valve Battery message BotClient_Valve_Battery(p, bot_index); } // This message gets sent when the bots are getting damaged. -void BotClient_Valve_Damage(void *p, int bot_index) { +void BotClient_Valve_Damage(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_Damage()\n"); static int state = 0; // current state machine state static int damage_armor; @@ -528,7 +528,7 @@ void BotClient_Valve_Damage(void *p, int bot_index) { } } -void BotClient_CS_Damage(void *p, int bot_index) { +void BotClient_CS_Damage(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_Damage()\n"); // this is just like the Valve Battery message BotClient_Valve_Damage(p, bot_index); @@ -548,7 +548,7 @@ void BotClient_FLF_Damage(void *p, int bot_index) { }*/ -void BotClient_CS_SayText(void *p, int bot_index) { +void BotClient_CS_SayText(void *p, const int bot_index) { static unsigned char ucEntIndex; /** @@ -651,7 +651,7 @@ void BotClient_CS_SayText(void *p, int bot_index) { // Converted to use switches. // This message gets sent when the bot enters a buyzone -void BotClient_CS_StatusIcon(void *p, int bot_index) { +void BotClient_CS_StatusIcon(void *p, const int bot_index) { /* FROM SDK 2.3 // Message handler for StatusIcon message @@ -741,7 +741,7 @@ void BotClient_CS_StatusIcon(void *p, int bot_index) { } // This message gets sent when the bots money ammount changes (for CS) -void BotClient_CS_Money(void *p, int bot_index) { +void BotClient_CS_Money(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_Money()\n"); static int state = 0; // current state machine state @@ -789,25 +789,25 @@ void BotClient_Valve_DeathMsg(void *p, int bot_index) { } } -void BotClient_CS_DeathMsg(void *p, int bot_index) { +void BotClient_CS_DeathMsg(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_DeathMsg()\n"); // this is just like the Valve DeathMsg message BotClient_Valve_DeathMsg(p, bot_index); } -void BotClient_Gearbox_DeathMsg(void *p, int bot_index) { +void BotClient_Gearbox_DeathMsg(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Gearbox_DeathMsg()\n"); // this is just like the Valve DeathMsg message BotClient_Valve_DeathMsg(p, bot_index); } -void BotClient_FLF_DeathMsg(void *p, int bot_index) { +void BotClient_FLF_DeathMsg(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_FLF_DeathMsg()\n"); // this is just like the Valve DeathMsg message BotClient_Valve_DeathMsg(p, bot_index); } -void BotClient_Valve_ScreenFade(void *p, int bot_index) { +void BotClient_Valve_ScreenFade(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_Valve_ScreenFade()\n"); static int state = 0; // current state machine state static int duration; @@ -851,7 +851,7 @@ void BotClient_Valve_ScreenFade(void *p, int bot_index) { } } -void BotClient_CS_ScreenFade(void *p, int bot_index) { +void BotClient_CS_ScreenFade(void *p, const int bot_index) { //DebugOut("bot_client: BotClient_CS_ScreenFade()\n"); // this is just like the Valve ScreenFade message BotClient_Valve_ScreenFade(p, bot_index); diff --git a/bot_func.cpp b/bot_func.cpp index 020c750..eacee65 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -48,13 +48,13 @@ extern int mod_id; extern int m_spriteTexture; // defined in dll.cpp -extern FILE *fpRblog; +extern FILE* fpRblog; // extern cNodeMachine NodeMachine; // For taking cover decision -#define TOTAL_SCORE 16300 // 16000 money + 100 health + 100 fear + 100 camp desire +constexpr int TOTAL_SCORE = 16300; // 16000 money + 100 health + 100 fear + 100 camp desire; bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *checkname) { TraceResult tr; @@ -63,7 +63,7 @@ bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *c // trace a line from bot's eyes to destination... UTIL_TraceLine(start, dest, ignore_monsters, - pEdict->v.pContainingEntity, &tr); + pEdict->v.pContainingEntity, &tr); // When our check string is not "none" and the traceline has a hit... if (std::strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { @@ -90,7 +90,7 @@ bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *c } -bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname) { +bool VectorIsVisible(const Vector& start, const Vector& dest, const char *checkname) { TraceResult tr; // trace a line from bot's eyes to destination... @@ -136,7 +136,7 @@ float func_distance(Vector v1, Vector v2) { * @param dest * @return */ -int FUNC_InFieldOfView(edict_t *pEntity, const Vector& dest) { +int FUNC_InFieldOfView(edict_t* pEntity, const Vector& dest) { // NOTE: Copy from Botman's BotInFieldOfView() routine. // find angles from source to destination... Vector entity_angles = UTIL_VecToAngles(dest); @@ -172,7 +172,7 @@ int FUNC_InFieldOfView(edict_t *pEntity, const Vector& dest) { * @param start * @param end */ -void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end) { +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end) { DrawBeam(visibleForWho, start, end, 25, 1, 255, 255, 255, 255, 1); } @@ -185,7 +185,7 @@ void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end) { * @param g * @param b */ -void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, int r, int g, int b) { +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end, const int r, const int g, const int b) { DrawBeam(visibleForWho, start, end, 25, 1, r, g, b, 255, 1); } @@ -202,9 +202,9 @@ void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, in * @param brightness * @param speed */ -void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, int width, - int noise, int red, int green, int blue, int brightness, - int speed) { +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end, const int width, const int noise, + const int red, const int green, const int blue, const int brightness, const int speed) +{ MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, visibleForWho); WRITE_BYTE(TE_BEAMPOINTS); WRITE_COORD(start.x); @@ -234,13 +234,14 @@ void DrawBeam(edict_t *visibleForWho, const Vector& start, const Vector& end, in * @param pBot * @return */ -cBot *getCloseFellowBot(cBot *pBot) { - const edict_t *pEdict = pBot->pEdict; - cBot *closestBot = nullptr; +cBot* getCloseFellowBot(cBot* pBot) { + const edict_t* pEdict = pBot->pEdict; + cBot* closestBot = nullptr; + float minDistance = NODE_ZONE; // Loop through all clients for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players if (pPlayer && !pPlayer->free && pPlayer != pEdict) { @@ -248,13 +249,15 @@ cBot *getCloseFellowBot(cBot *pBot) { if (!IsAlive(pPlayer)) continue; - cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + cBot* pBotPointer = UTIL_GetBotPointer(pPlayer); // skip anything that is not a RealBot if (pBotPointer == nullptr) // not using FL_FAKECLIENT here so it is multi-bot compatible continue; - if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < NODE_ZONE) { + const float distance = func_distance(pBot->pEdict->v.origin, pPlayer->v.origin); + if (distance < minDistance) { closestBot = pBotPointer; // set pointer + minDistance = distance; } } } @@ -267,27 +270,27 @@ cBot *getCloseFellowBot(cBot *pBot) { * @param pBot * @return */ -edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { - const edict_t *pEdict = pBot->pEdict; +edict_t* getPlayerNearbyBotInFOV(cBot* pBot) { + const edict_t* pEdict = pBot->pEdict; for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { - constexpr int fov = 90;// TODO: use server var "default_fov" ? - // skip this player if not alive (i.e. dead or dying) + constexpr int fov = 90;// TODO: use server var "default_fov" ? + // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; if (!(pPlayer->v.flags & FL_THIRDPARTYBOT - || pPlayer->v.flags & FL_FAKECLIENT - || pPlayer->v.flags & FL_CLIENT)) + || pPlayer->v.flags & FL_FAKECLIENT + || pPlayer->v.flags & FL_CLIENT)) continue; const int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, pPlayer->v.origin - pBot->pEdict->v.origin); - constexpr int distance = NODE_ZONE; + constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance && angleToPlayer < fov) { return pPlayer; } @@ -301,10 +304,10 @@ edict_t * getPlayerNearbyBotInFOV(cBot *pBot) { * @param pBot * @return */ -edict_t * getEntityNearbyBotInFOV(cBot *pBot) { - edict_t *pEdict = pBot->pEdict; +edict_t* getEntityNearbyBotInFOV(cBot* pBot) { + edict_t* pEdict = pBot->pEdict; - edict_t *pent = nullptr; + edict_t* pent = nullptr; while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 45)) != nullptr) { if (pent == pEdict) continue; // skip self @@ -319,13 +322,12 @@ edict_t * getEntityNearbyBotInFOV(cBot *pBot) { * Return TRUE of any players are near that could block him, regardless of FOV. Just checks distance * @param pBot * @return - */ //TODO: FOV and angleToPlayer are unused variables [APG]RoboCop[CL] -bool isAnyPlayerNearbyBot(cBot *pBot) { - const edict_t *pEdict = pBot->pEdict; - //int fov = 105; + */ +bool isAnyPlayerNearbyBot(cBot* pBot) { + const edict_t* pEdict = pBot->pEdict; for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { @@ -334,12 +336,10 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { continue; if (!(pPlayer->v.flags & FL_THIRDPARTYBOT - || pPlayer->v.flags & FL_FAKECLIENT - || pPlayer->v.flags & FL_CLIENT)) + || pPlayer->v.flags & FL_FAKECLIENT + || pPlayer->v.flags & FL_CLIENT)) continue; - //int angleToPlayer = FUNC_InFieldOfView(pBot->pEdict, (pPlayer->v.origin - pBot->pEdict->v.origin)); - constexpr int distance = NODE_ZONE; if (func_distance(pBot->pEdict->v.origin, pPlayer->v.origin) < distance) { return true; @@ -354,7 +354,7 @@ bool isAnyPlayerNearbyBot(cBot *pBot) { * @param pBot * @return */ -bool BotShouldJumpIfStuck(cBot *pBot) { +bool BotShouldJumpIfStuck(cBot* pBot) { if (pBot->isDefusing()) { pBot->rprint_trace("BotShouldJumpIfStuck", "Returning false because defusing."); return false; @@ -376,7 +376,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { } // should not jump, perhaps its a func_illusionary causing that we're stuck? - const edict_t *entityInFov = getEntityNearbyBotInFOV(pBot); + const edict_t* entityInFov = getEntityNearbyBotInFOV(pBot); if (entityInFov && std::strcmp("func_illusionary", STRING(entityInFov->v.classname)) == 0) { return true; // yes it is the case @@ -390,7 +390,7 @@ bool BotShouldJumpIfStuck(cBot *pBot) { * @param pBot * @return */ -bool BotShouldJump(cBot *pBot) { +bool BotShouldJump(cBot* pBot) { // When a bot should jump, something is blocking his way. // Most of the time it is a fence, or a 'half wall' that reaches from body to feet // However, the body most of the time traces above this wall. @@ -405,11 +405,11 @@ bool BotShouldJump(cBot *pBot) { return false; } - if (pBot->isJumping()) + if (pBot->isJumping()) return false; // already jumping TraceResult tr; - const edict_t *pEdict = pBot->pEdict; + const edict_t* pEdict = pBot->pEdict; // convert current view angle to vectors for TraceLine math... @@ -452,23 +452,23 @@ bool BotShouldJump(cBot *pBot) { v_dest = v_source + gpGlobals->v_forward * 40; // - // int player_index = 0; - // for (player_index = 1; player_index <= gpGlobals->maxClients; - // player_index++) { - // edict_t *pPlayer = INDEXENT(player_index); - // - // if (pPlayer && !pPlayer->free) { - // if (FBitSet(pPlayer->v.flags, FL_CLIENT)) { // do not draw for now - // - // DrawBeam( - // pPlayer, // player sees beam - // v_source, // + Vector(0, 0, 32) (head?) - // v_dest, - // 255, 255, 255 - // ); - // } - // } - // } + // int player_index = 0; + // for (player_index = 1; player_index <= gpGlobals->maxClients; + // player_index++) { + // edict_t *pPlayer = INDEXENT(player_index); + // + // if (pPlayer && !pPlayer->free) { + // if (FBitSet(pPlayer->v.flags, FL_CLIENT)) { // do not draw for now + // + // DrawBeam( + // pPlayer, // player sees beam + // v_source, // + Vector(0, 0, 32) (head?) + // v_dest, + // 255, 255, 255 + // ); + // } + // } + // } UTIL_TraceHull(v_source, v_dest, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -481,8 +481,8 @@ bool BotShouldJump(cBot *pBot) { if (tr.pHit) { pBot->rprint_trace("trace pHit", STRING(tr.pHit->v.classname)); if (std::strcmp("func_illusionary", STRING(tr.pHit->v.classname)) == 0) { - pBot->rprint_trace("BotShouldJump", "#1 Hit a func_illusionary, its a hit as well! (even though trace hit results no)"); - return true; + pBot->rprint_trace("BotShouldJump", "#1 Hit a func_illusionary, its a hit as well! (even though trace hit results no)"); + return true; } } @@ -491,7 +491,7 @@ bool BotShouldJump(cBot *pBot) { } // FUNCTION: Calculates angles as pEdict->v.v_angle should be when checking for body -Vector FUNC_CalculateAngles(const cBot *pBot) { +Vector FUNC_CalculateAngles(const cBot* pBot) { // aim for the head and/or body const Vector v_target = pBot->vBody - pBot->pEdict->v.origin; Vector v_body = UTIL_VecToAngles(v_target); @@ -566,9 +566,9 @@ bool BotShouldDuck(cBot *pBot) { bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboCop[CL] { - // This is crucial for bots to sneak inside vents and tight areas in order - // to inflitrate and prooceed on ahead. DuckJump is required for vaulting - // on top of crates, window ledges and edges as an important method. + // This is crucial for bots to sneak inside vents and tight areas in order + // to inflitrate and prooceed on ahead. DuckJump is required for vaulting + // on top of crates, window ledges and edges as an important method. if (pBot->isDefusing()) { pBot->rprint_trace("BotShouldDuckJump", "Returning false because defusing."); @@ -576,14 +576,14 @@ bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboC } if (pBot->iDuckJumpTries > 5) { - // tried to duck 5 times, so no longer! - pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); - return false; + // tried to duck 5 times, so no longer! + pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); + return false; } - - if (pBot->isDuckJumping()) + + if (pBot->isDuckJumping()) return false; // already duckjumping - + return false; } @@ -592,7 +592,7 @@ bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboC * @param pBot * @return */ -bool FUNC_DoRadio(const cBot *pBot) { +bool FUNC_DoRadio(const cBot* pBot) { if (pBot->fDoRadio > gpGlobals->time) // allowed? return false; @@ -603,7 +603,7 @@ bool FUNC_DoRadio(const cBot *pBot) { } // DECIDE: Take cover or not -bool FUNC_ShouldTakeCover(cBot *pBot) { +bool FUNC_ShouldTakeCover(cBot* pBot) { // Do not allow taking cover within 3 seconds again. if (pBot->f_cover_time + 3 > gpGlobals->time) return false; @@ -635,7 +635,7 @@ bool FUNC_TakeCover(cBot* pBot) //Experimental [APG]RoboCop[CL] return true; } -int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { +int FUNC_BotEstimateHearVector(cBot* pBot, const Vector& v_sound) { // here we normally figure out where to look at when we hear an enemy, RealBot AI PR 2 lagged a lot on this so we need another approach return -1; @@ -643,18 +643,15 @@ int FUNC_BotEstimateHearVector(cBot *pBot, const Vector& v_sound) { // Added Stefan // 7 November 2001 -int FUNC_PlayerSpeed(const edict_t *edict) { +int FUNC_PlayerSpeed(const edict_t* edict) { if (edict != nullptr) return static_cast(edict->v.velocity.Length2D()); // Return speed of any edict given return 0; } -bool FUNC_PlayerRuns(int speed) { - if (speed < 200) - return false; // We make no sound - - return true; // We make sound +bool FUNC_PlayerRuns(const int speed) { + return speed >= 200; } // return weapon type of edict. @@ -690,24 +687,24 @@ int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { return -1; } -int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest) //Experimental [APG]RoboCop[CL] +int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, const bool safest) //Experimental [APG]RoboCop[CL] { - // Find a waypoint that is far away from the enemy. - // If safest is true, then we want the safest waypoint. - // If safest is false, then we want the farthest waypoint. + // Find a waypoint that is far away from the enemy. + // If safest is true, then we want the safest waypoint. + // If safest is false, then we want the farthest waypoint. - // Find the farthest waypoint - int farthest = -1; - float farthest_distance = 0.0f; + // Find the farthest waypoint + int farthest = -1; + float farthest_distance = 0.0f; - for (int i = 0; i < gpGlobals->maxEntities; i++) { - const edict_t *pEdict = INDEXENT(i); + for (int i = 0; i < gpGlobals->maxEntities; i++) { + const edict_t* pEdict = INDEXENT(i); - if (pEdict == nullptr) - continue; + if (pEdict == nullptr) + continue; - if (pEdict->v.flags & FL_DORMANT) - continue; + if (pEdict->v.flags & FL_DORMANT) + continue; if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { if (farthest == -1) { @@ -729,29 +726,29 @@ int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest) //Experim } } } - } + } - return farthest; + return farthest; } int FUNC_FindCover(const cBot* pBot) //Experimental [APG]RoboCop[CL] { - // Find a waypoint that is far away from the enemy. - // If safest is true, then we want the safest waypoint. - // If safest is false, then we want the farthest waypoint. + // Find a waypoint that is far away from the enemy. + // If safest is true, then we want the safest waypoint. + // If safest is false, then we want the farthest waypoint. - // Find the farthest waypoint - int farthest = -1; - float farthest_distance = 0.0f; + // Find the farthest waypoint + int farthest = -1; + float farthest_distance = 0.0f; - for (int i = 0; i < gpGlobals->maxEntities; i++) { - const edict_t *pEdict = INDEXENT(i); + for (int i = 0; i < gpGlobals->maxEntities; i++) { + const edict_t* pEdict = INDEXENT(i); - if (pEdict == nullptr) - continue; + if (pEdict == nullptr) + continue; - if (pEdict->v.flags & FL_DORMANT) - continue; + if (pEdict->v.flags & FL_DORMANT) + continue; if (pEdict->v.classname != 0 && std::strcmp(STRING(pEdict->v.classname), "info_waypoint") == 0) { if (farthest == -1) { @@ -766,13 +763,13 @@ int FUNC_FindCover(const cBot* pBot) //Experimental [APG]RoboCop[CL] } } } - } + } - return farthest; + return farthest; } // Function to let a bot react on some sound which he cannot see -void FUNC_HearingTodo(cBot *pBot) { +void FUNC_HearingTodo(cBot* pBot) { // This is called every frame. if (pBot->f_hear_time > gpGlobals->time) return; // Do nothing, we need more time to think @@ -795,16 +792,18 @@ void FUNC_HearingTodo(cBot *pBot) { else if (/*health >= 25 &&*/ health < 75) action = 1; else - action = -1; + action = 0; if (action == 0) { etime = RANDOM_LONG(2, 6); pBot->f_camp_time = gpGlobals->time + etime; pBot->forgetGoal(); - } else if (action == 1) { + } + else if (action == 1) { etime = RANDOM_LONG(1, 7); pBot->f_walk_time = gpGlobals->time + etime; - } else if (action == 2) { + } + else { etime = RANDOM_LONG(1, 5); pBot->f_hold_duck = gpGlobals->time + etime; } @@ -820,11 +819,11 @@ void FUNC_HearingTodo(cBot *pBot) { * Created : 16/11/2001 * Changed : 16/11/2001 */ -void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG]RoboCop[CL] +void FUNC_ClearEnemyPointer(edict_t* pPtr) { //pPtr muddled with c_pointer? [APG]RoboCop[CL] // Go through all bots and remove their enemy pointer that matches the given // pointer pPtr for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // Skip invalid players. if (pPlayer && !pPlayer->free) { @@ -838,11 +837,11 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG continue; // check if it is a bot known to us (ie, not another metamod supported bot) - cBot *botpointer = UTIL_GetBotPointer(pPlayer); + cBot* botpointer = UTIL_GetBotPointer(pPlayer); if (botpointer && // Is a bot managed by us botpointer->hasEnemy(pPtr) // and has the pointer we want to get rid of - ) { + ) { botpointer->forgetEnemy(); // Clear its pointer } } @@ -850,46 +849,45 @@ void FUNC_ClearEnemyPointer(edict_t *pPtr) { //pPtr muddled with c_pointer? [APG } // Returns true/false if an entity is on a ladder -bool FUNC_IsOnLadder(const edict_t *pEntity) { +bool FUNC_IsOnLadder(const edict_t* pEntity) { if (pEntity == nullptr) return false; - if (pEntity->v.movetype == MOVETYPE_FLY) - return true; - - return false; + return pEntity->v.movetype == MOVETYPE_FLY; } -void FUNC_FindBreakable(cBot* pBot) // Updated function signature to accept cBot* +void FUNC_FindBreakable(cBot* pBot) { - // The "func_breakable" entity required for glass breaking and weak doors for bots to recognize, - // in order to attack breakable objects that would block their way. - if (pBot == nullptr) { - return; // Ensure pBot is not null + // The "func_breakable" entity is required for bots to recognize and attack + // breakable objects like glass or weak doors that block their path. + if (pBot == nullptr || pBot->pEdict == nullptr) { + return; // Ensure pBot and its edict are not null } - edict_t* pEntity = pBot->pEdict; // Get the edict from the bot + edict_t* pEntity = pBot->pEdict; + edict_t* pent = nullptr; - for (int i = 0; i < gpGlobals->maxEntities; ++i) { - edict_t* pent = INDEXENT(i); - if (pent == nullptr || (pent->v.flags & FL_DORMANT)) { - continue; // Skip null or dormant entities + // Search for entities within a 256-unit radius around the bot + while ((pent = UTIL_FindEntityInSphere(pent, pEntity->v.origin, 256.0f)) != nullptr) + { + if (pent == pEntity || (pent->v.flags & FL_DORMANT)) { + continue; // Skip self and dormant entities } const char* classname = STRING(pent->v.classname); if (classname != nullptr && std::strcmp(classname, "func_breakable") == 0) { if (FVisible(pent->v.origin, pEntity)) { - // Set the breakable entity as the entity's enemy - pEntity->v.enemy = pent; + // Set the breakable entity as the bot's enemy + pBot->pEdict->v.enemy = pent; // Aim at the breakable entity - Vector vBody = pent->v.origin; - Vector vHead = pent->v.origin; + pBot->vBody = pent->v.origin; + pBot->vHead = pent->v.origin; // Shoot at the breakable entity - UTIL_BotPressKey(pBot, IN_ATTACK); // Updated to use pBot instead of pEntity - return; // Exit after finding the first breakable entity + UTIL_BotPressKey(pBot, IN_ATTACK); + return; // Exit after finding the first visible breakable entity } } } @@ -913,21 +911,22 @@ void FUNC_FindBreakable(cBot* pBot) // Updated function signature to accept cBo void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] { - // Check if the bot has a bomb planted. - // If so, then we need to go to the bomb site. - // If not, then we need to go to the waypoint. - + // Check if the bot has a bomb planted. + // If so, then we need to go to the bomb site. + // If not, then we need to go to the waypoint. + // "models/w_c4.mdl" needed for CTs to see the bomb? [APG]RoboCop[CL] - if (pEntity->v.model != 0 && std::strcmp(STRING(pEntity->v.model), "models/w_c4.mdl") == 0) { - // Bot has a bomb planted. - // Go to the bomb site. - pEntity->v.button |= IN_USE; - pEntity->v.button |= IN_ATTACK; - } else { - // Bot does not have a bomb planted. - // Go to the waypoint. - pEntity->v.button |= IN_USE; - } + if (pEntity->v.model != 0 && std::strcmp(STRING(pEntity->v.model), "models/w_c4.mdl") == 0) { + // Bot has a bomb planted. + // Go to the bomb site. + pEntity->v.button |= IN_USE; + pEntity->v.button |= IN_ATTACK; + } + else { + // Bot does not have a bomb planted. + // Go to the waypoint. + pEntity->v.button |= IN_USE; + } } /** @@ -940,26 +939,26 @@ void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] bool isHostageFree(cBot* pBotWhoIsAsking, edict_t* pHostage) { if (pHostage == nullptr) return false; if (pBotWhoIsAsking == nullptr) return false; - + for (int i = 1; i <= gpGlobals->maxClients; i++) { edict_t* pPlayer = INDEXENT(i); if (!pPlayer || pPlayer->free) // free - ie no client continue; // next - + // skip this player if not alive (i.e. dead or dying) if (!IsAlive(pPlayer)) continue; - + // not a bot if (!(pPlayer->v.flags & FL_THIRDPARTYBOT)) continue; - + // Only check other bots (do not check self) cBot* botpointer = UTIL_GetBotPointer(pPlayer); if (botpointer && // a bot botpointer != pBotWhoIsAsking && // not self !botpointer->isDead()) { // not dead - + // other bot uses hostage, so hostage is not 'free' if (botpointer->isUsingHostage(pHostage)) { pBotWhoIsAsking->rprint("Looks like the hostage is used by another one"); @@ -968,11 +967,11 @@ bool isHostageFree(cBot* pBotWhoIsAsking, edict_t* pHostage) { } } } - + return true; } -void TryToGetHostageTargetToFollowMe(cBot *pBot) { +void TryToGetHostageTargetToFollowMe(cBot* pBot) { if (pBot->hasEnemy()) { return; // enemy, do not check } @@ -982,7 +981,7 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { return; } - edict_t *pHostage = pBot->getHostageToRescue(); + edict_t* pHostage = pBot->getHostageToRescue(); if (pHostage == nullptr) { pHostage = pBot->findHostageToRescue(); @@ -1044,15 +1043,15 @@ void TryToGetHostageTargetToFollowMe(cBot *pBot) { } } -bool isHostageRescued(cBot *pBot, const edict_t *pHostage) //pBot not used [APG]RoboCop[CL] +bool isHostageRescued(cBot* pBot, const edict_t* pHostage) //pBot not used [APG]RoboCop[CL] { if (pHostage == nullptr) return false; if (FBitSet(pHostage->v.effects, EF_NODRAW)) { -// pBot->rprint("isHostageRescued()", "Hostage is rescued"); + // pBot->rprint("isHostageRescued()", "Hostage is rescued"); return true; } -// pBot->rprint("isHostageRescued()", "Hostage is NOT rescued"); + // pBot->rprint("isHostageRescued()", "Hostage is NOT rescued"); return false; } @@ -1141,26 +1140,26 @@ bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { return true; } -bool FUNC_EdictIsAlive(edict_t *pEdict) { +bool FUNC_EdictIsAlive(edict_t* pEdict) { if (pEdict == nullptr) return false; return pEdict->v.health > 0; } // HostageNear() -bool FUNC_BotHoldsZoomWeapon(cBot *pBot) { +bool FUNC_BotHoldsZoomWeapon(cBot* pBot) { // Check if the bot holds a weapon that can zoom, but is not a sniper gun. return pBot->isHoldingWeapon(CS_WEAPON_AUG) || pBot->isHoldingWeapon(CS_WEAPON_SG552); } -void FUNC_BotChecksFalling(cBot *pBot) { +void FUNC_BotChecksFalling(cBot* pBot) { // This routine should never be filled with code. // - Bots should simply never fall // - If bots do fall, check precalculation routine. } // New function to display a message on the center of the screen -void CenterMessage(char *buffer) { +void CenterMessage(char* buffer) { //DebugOut("waypoint: CenterMessage():\n"); //DebugOut(buffer); //DebugOut("\n"); @@ -1168,7 +1167,7 @@ void CenterMessage(char *buffer) { } // Bot Takes Cover -bool BOT_DecideTakeCover(cBot *pBot) { +bool BOT_DecideTakeCover(cBot* pBot) { /* UTIL_ClientPrintAll( HUD_PRINTCENTER, "DECISION TO TAKE COVER\n" ); @@ -1192,7 +1191,7 @@ bool BOT_DecideTakeCover(cBot *pBot) { // logs into a file void rblog(const char* txt) { // output to stdout - //printf("%s", txt); // Excessive log spewing [APG]RoboCop[CL] + //printf("%s", txt); // Excessive log spewing [APG]RoboCop[CL] // and to reallog file if (fpRblog) { diff --git a/bot_func.h b/bot_func.h index 488dc2a..7535777 100644 --- a/bot_func.h +++ b/bot_func.h @@ -6,7 +6,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -18,9 +18,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -30,88 +30,84 @@ #ifndef BOT_FUNC_H #define BOT_FUNC_H -//prototypes of bot functions... -void BotThink(cBot * pBot); + //prototypes of bot functions... +void BotThink(cBot* pBot); float fixAngle(float angle); -void botFixIdealPitch(edict_t * pEdict); -void botFixIdealYaw(edict_t * pEdict); +void botFixIdealPitch(edict_t* pEdict); +void botFixIdealYaw(edict_t* pEdict); bool traceLine(const Vector& v_source, const Vector& v_dest, const edict_t* pEdict, TraceResult& tr); -bool BotCanJumpUp(const cBot * pBot); -bool BotCanDuckUnder(const cBot * pBot); +bool BotCanJumpUp(cBot* pBot); +bool BotCanDuckUnder(cBot* pBot); bool isBotNearby(const cBot* pBot, float radius); -void adjustBotAngle(const cBot* pBot, float angle); -void avoidClustering(const cBot* pBot); +void adjustBotAngle(cBot* pBot, float angle); bool isPathBlocked(const cBot* pBot, const Vector& v_dest); -void adjustPathIfBlocked(const cBot* pBot); -bool performTrace(const Vector& v_source, const Vector& v_dest, edict_t* pEntity, TraceResult& tr); -bool isPathClear(const cBot* pBot, const Vector& v_dest); -void BotNavigate(const cBot* pBot); +void BotNavigate(cBot* pBot); -bool EntityIsVisible(edict_t * pEntity, const Vector& dest); +bool EntityIsVisible(edict_t* pEntity, const Vector& dest); // bot_func.cpp -bool VectorIsVisible(const Vector& start, const Vector& dest, char *checkname); -float func_distance(Vector v1, Vector v2); +bool VectorIsVisible(const Vector& start, const Vector& dest, const char* checkname); +float func_distance(const Vector& v1, const Vector& v2); -void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end); -void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end, int red, int green, int blue); -void DrawBeam(edict_t * visibleForWho, const Vector& start, const Vector& end, - int width, int noise, int red, int green, int blue, - int brightness, int speed); +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end); +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end, int red, int green, int blue); +void DrawBeam(edict_t* visibleForWho, const Vector& start, const Vector& end, + int width, int noise, int red, int green, int blue, + int brightness, int speed); -cBot *getCloseFellowBot(cBot * pBot); -edict_t * getPlayerNearbyBotInFOV(cBot * pBot); -edict_t * getEntityNearbyBotInFOV(cBot * pBot); +cBot* getCloseFellowBot(cBot* pBot); +edict_t* getPlayerNearbyBotInFOV(cBot* pBot); +edict_t* getEntityNearbyBotInFOV(cBot* pBot); bool isAnyPlayerNearbyBot(cBot* pBot); -bool BotShouldJump(cBot * pBot); -bool BotShouldJumpIfStuck(cBot * pBot); -bool BotShouldDuck(cBot * pBot); +bool BotShouldJump(cBot* pBot); +bool BotShouldJumpIfStuck(cBot* pBot); +bool BotShouldDuck(cBot* pBot); bool BotShouldDuckJump(cBot* pBot); -void TryToGetHostageTargetToFollowMe(cBot * pBot); -Vector FUNC_CalculateAngles(const cBot * pBot); +void TryToGetHostageTargetToFollowMe(cBot* pBot); +Vector FUNC_CalculateAngles(const cBot* pBot); // New funcs -bool FUNC_DoRadio(const cBot * pBot); +bool FUNC_DoRadio(const cBot* pBot); -bool FUNC_ShouldTakeCover(cBot * pBot); -bool FUNC_TakeCover(cBot * pBot); +bool FUNC_ShouldTakeCover(cBot* pBot); +bool FUNC_TakeCover(cBot* pBot); -int FUNC_EdictHoldsWeapon(const edict_t * pEdict); +int FUNC_EdictHoldsWeapon(const edict_t* pEdict); -int FUNC_FindFarWaypoint(cBot * pBot, const Vector& avoid, bool safest); +int FUNC_FindFarWaypoint(cBot* pBot, const Vector& avoid, bool safest); int FUNC_FindCover(const cBot* pBot); -int FUNC_PlayerSpeed(const edict_t * edict); +int FUNC_PlayerSpeed(const edict_t* edict); bool FUNC_PlayerRuns(int speed); -void FUNC_HearingTodo(cBot * pBot); -void FUNC_ClearEnemyPointer(edict_t *pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] +void FUNC_HearingTodo(cBot* pBot); +void FUNC_ClearEnemyPointer(edict_t* pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] -bool FUNC_IsOnLadder(const edict_t * pEntity); +bool FUNC_IsOnLadder(const edict_t* pEntity); void FUNC_FindBreakable(cBot* pBot); void FUNC_CheckForBombPlanted(edict_t* pEntity); -int FUNC_GiveHostage(cBot * pBot); // gives any hostage we still have to go for +int FUNC_GiveHostage(cBot* pBot); // gives any hostage we still have to go for -bool isHostageRescueable(cBot *pBot, edict_t *pHostage); -bool isHostageRescued(cBot *pBot, const edict_t *pHostage); -bool isHostageFree(cBot * pBotWhoIsAsking, edict_t * pHostage); // is this hostage not used by any other bot? +bool isHostageRescueable(cBot* pBot, edict_t* pHostage); +bool isHostageRescued(cBot* pBot, const edict_t* pHostage); +bool isHostageFree(cBot* pBotWhoIsAsking, edict_t* pHostage); // is this hostage not used by any other bot? -int FUNC_BotEstimateHearVector(cBot * pBot, const Vector& v_sound); +int FUNC_BotEstimateHearVector(cBot* pBot, const Vector& v_sound); -bool FUNC_EdictIsAlive(edict_t *pEdict); +bool FUNC_EdictIsAlive(edict_t* pEdict); -bool FUNC_BotHoldsZoomWeapon(cBot * pBot); +bool FUNC_BotHoldsZoomWeapon(cBot* pBot); -int FUNC_InFieldOfView(edict_t * pEntity, const Vector& dest); +int FUNC_InFieldOfView(edict_t* pEntity, const Vector& dest); -bool VectorIsVisibleWithEdict(edict_t * pEdict, const Vector& dest, - const char *checkname); +bool VectorIsVisibleWithEdict(edict_t* pEdict, const Vector& dest, + const char* checkname); -bool BOT_DecideTakeCover(cBot * pBot); +bool BOT_DecideTakeCover(cBot* pBot); // bot_buycode.cpp int PriceWeapon(int weapon_id); @@ -121,27 +117,27 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot* pBot, const char* arg1, const ch bool GoodWeaponForTeam(int weapon, int team); -void BotConsole(cBot * pBot); +void BotConsole(cBot* pBot); void BotDecideWhatToBuy(cBot* pBot); void rblog(const char* txt); // bot.cpp // util.cpp -int UTIL_GiveWeaponId(const char *name); +int UTIL_GiveWeaponId(const char* name); int UTIL_GiveWeaponType(int weapon_id); -int UTIL_GetGrenadeType(edict_t * pEntity); +int UTIL_GetGrenadeType(edict_t* pEntity); -bool UTIL_IsVip(edict_t * pEntity); +bool UTIL_IsVip(edict_t* pEntity); const char* UTIL_GiveWeaponName(int id); -void UTIL_SpeechSynth(edict_t * pEdict, char *szMessage); -void UTIL_BotRadioMessage(cBot * pBot, int radio, const char *arg1, const char *arg2); -void UTIL_BotPressKey(cBot * pBot, int type); +void UTIL_SpeechSynth(edict_t* pEdict, const char* szMessage); +void UTIL_BotRadioMessage(cBot* pBot, int radio, const char* arg1, const char* arg2); +void UTIL_BotPressKey(cBot* pBot, int type); // bot_navigate.cpp // .. -void CenterMessage(char *buffer); +void CenterMessage(char* buffer); -#endif // BOT_FUNC_H +#endif // BOT_FUNC_H \ No newline at end of file diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 857713d..f7d5a91 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -45,10 +45,22 @@ extern int mod_id; extern edict_t* pHostEdict; +// Obstacle Avoidance constexpr float TURN_ANGLE = 75.0f; // Degrees to turn when avoiding obstacles constexpr float MOVE_DISTANCE = 24.0f; // Distance to move forward constexpr std::uint8_t SCAN_RADIUS = 60; // Radius to scan to prevent blocking with players +// Bot dimensions and movement capabilities +constexpr float BODY_SIDE_OFFSET = 16.0f; // Offset from center to check for body clearance +constexpr float FORWARD_CHECK_DISTANCE = 24.0f; // How far forward to check for obstacles +constexpr float STAND_VIEW_HEIGHT_OFFSET = -36.0f; // Eye level offset from origin when standing +constexpr float DUCK_VIEW_HEIGHT_OFFSET = -36.0f; // Eye level offset from origin when ducking +constexpr float DUCK_HEIGHT = 36.0f; // Height of the bot when ducking +constexpr float HEAD_CLEARANCE_CHECK_HEIGHT = 108.0f; // Height from origin to check for head clearance +constexpr float JUMP_CLEARANCE_CHECK_DROP = -81.0f; // Distance to trace down for jump clearance +constexpr float DUCK_CLEARANCE_CHECK_RISE = 72.0f; // Distance to trace up for duck clearance +constexpr float FEET_OFFSET = -35.0f; // Offset from origin to near the bot's feet + /** * Given an angle, makes sure it wraps around properly * @param angle @@ -193,7 +205,7 @@ bool BotCanJumpUp(const cBot* pBot) { return true; } -bool BotCanDuckUnder(const cBot* pBot) { +bool BotCanDuckUnder(cBot* pBot) { // What I do here is trace 3 lines straight out, one unit higher than // the ducking height. I trace once at the center of the body, once // at the right side, and once at the left side. If all three of these @@ -323,7 +335,7 @@ bool isBotNearby(const cBot* pBot, const float radius) { return false; } -void adjustBotAngle(const cBot* pBot, const float angle) { +void adjustBotAngle(cBot* pBot, const float angle) { if (!pBot || !pBot->pEdict) { return; } @@ -332,7 +344,7 @@ void adjustBotAngle(const cBot* pBot, const float angle) { UTIL_MakeVectors(pBot->pEdict->v.v_angle); } -void avoidClustering(const cBot* pBot) { +void avoidClustering(cBot* pBot) { if (!pBot) { return; } @@ -348,14 +360,10 @@ bool isPathBlocked(const cBot* pBot, const Vector& v_dest) { } TraceResult tr; - const Vector v_source = pBot->pEdict->v.origin; - - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pBot->pEdict->v.pContainingEntity, &tr); - - return tr.flFraction < 1.0f; + return !traceLine(pBot->pEdict->v.origin, v_dest, pBot->pEdict, tr); } -void adjustPathIfBlocked(const cBot* pBot) { +void adjustPathIfBlocked(cBot* pBot) { if (!pBot) { return; } @@ -387,7 +395,7 @@ void BotNavigate(const cBot* pBot) { return; } - // Avoid clustering + // Avoid clustering with other bots avoidClustering(pBot); // Adjust path if blocked diff --git a/bot_weapons.h b/bot_weapons.h index 6f45b3c..a062537 100644 --- a/bot_weapons.h +++ b/bot_weapons.h @@ -31,7 +31,7 @@ #define BOT_WEAPONS_H // weapon ID values for Valve's Team Fortress Classic & 1.5 -#define TF_WEAPON_UNKNOWN1 1 +/*#define TF_WEAPON_UNKNOWN1 1 #define TF_WEAPON_UNKNOWN2 2 #define TF_WEAPON_MEDIKIT 3 #define TF_WEAPON_SPANNER 4 @@ -54,48 +54,52 @@ #define TF_WEAPON_RAILGUN 21 #define TF_WEAPON_PL 22 #define TF_WEAPON_KNIFE 23 +*/ // weapon ID values for Counter-Strike -#define CS_WEAPON_P228 1 -#define CS_WEAPON_SHIELD 2 -#define CS_WEAPON_SCOUT 3 -#define CS_WEAPON_HEGRENADE 4 -#define CS_WEAPON_XM1014 5 -#define CS_WEAPON_C4 6 -#define CS_WEAPON_MAC10 7 -#define CS_WEAPON_AUG 8 -#define CS_WEAPON_SMOKEGRENADE 9 -#define CS_WEAPON_ELITE 10 -#define CS_WEAPON_FIVESEVEN 11 -#define CS_WEAPON_UMP45 12 -#define CS_WEAPON_SG550 13 -#define CS_WEAPON_GALIL 14 // CS 1.6 -#define CS_WEAPON_FAMAS 15 // CS 1.6 -#define CS_WEAPON_USP 16 -#define CS_WEAPON_GLOCK18 17 -#define CS_WEAPON_AWP 18 -#define CS_WEAPON_MP5NAVY 19 -#define CS_WEAPON_M249 20 -#define CS_WEAPON_M3 21 -#define CS_WEAPON_M4A1 22 -#define CS_WEAPON_TMP 23 -#define CS_WEAPON_G3SG1 24 -#define CS_WEAPON_FLASHBANG 25 -#define CS_WEAPON_DEAGLE 26 -#define CS_WEAPON_SG552 27 -#define CS_WEAPON_AK47 28 -#define CS_WEAPON_KNIFE 29 -#define CS_WEAPON_P90 30 +enum : std::uint8_t +{ + CS_WEAPON_P228 = 1, + CS_WEAPON_SHIELD = 2, + CS_WEAPON_SCOUT = 3, + CS_WEAPON_HEGRENADE = 4, + CS_WEAPON_XM1014 = 5, + CS_WEAPON_C4 = 6, + CS_WEAPON_MAC10 = 7, + CS_WEAPON_AUG = 8, + CS_WEAPON_SMOKEGRENADE = 9, + CS_WEAPON_ELITE = 10, + CS_WEAPON_FIVESEVEN = 11, + CS_WEAPON_UMP45 = 12, + CS_WEAPON_SG550 = 13, + CS_WEAPON_GALIL = 14, // CS 1.6 + CS_WEAPON_FAMAS = 15, // CS 1.6 + CS_WEAPON_USP = 16, + CS_WEAPON_GLOCK18 = 17, + CS_WEAPON_AWP = 18, + CS_WEAPON_MP5NAVY = 19, + CS_WEAPON_M249 = 20, + CS_WEAPON_M3 = 21, + CS_WEAPON_M4A1 = 22, + CS_WEAPON_TMP = 23, + CS_WEAPON_G3SG1 = 24, + CS_WEAPON_FLASHBANG = 25, + CS_WEAPON_DEAGLE = 26, + CS_WEAPON_SG552 = 27, + CS_WEAPON_AK47 = 28, + CS_WEAPON_KNIFE = 29, + CS_WEAPON_P90 = 30, //30.8.04 redefined by frashman -#define CS_DEFUSEKIT 98 // old value was 99, same as SHIELD -> Bug?? + CS_DEFUSEKIT = 98 // old value was 99, same as SHIELD -> Bug?? +}; // NOT CONFIRMED //#define CS_WEAPON_SHIELD 99 // Not used for detecting, only for // bot.dll // Woah, i rule! :D, figured out all Earth Special Forces Weapon ID's.. -#define ESF_WEAPON_MELEE 1 +/*#define ESF_WEAPON_MELEE 1 #define ESF_KIBLAST 2 #define ESF_GALLITGUN 3 #define ESF_KAMEHAMEHA 4 @@ -112,6 +116,7 @@ #define ESF_DEATHBALL 15 #define ESF_BURNINGATTACK 16 #define ESF_SENSU 17 +*/ typedef struct { char szClassname[64]; diff --git a/dependencies/hlsdk/dlls/util.h b/dependencies/hlsdk/dlls/util.h index ad3e000..a9c7541 100644 --- a/dependencies/hlsdk/dlls/util.h +++ b/dependencies/hlsdk/dlls/util.h @@ -134,7 +134,7 @@ inline entvars_t *VARS(entvars_t *pev) { return pev; } inline entvars_t *VARS(edict_t *pent) { if ( !pent ) - return NULL; + return nullptr; return &pent->v; } @@ -149,8 +149,8 @@ inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin, ent // Testing the three types of "entity" for nullity #define eoNullEntity 0 inline BOOL FNullEnt(EOFFSET eoffset) { return eoffset == 0; } -inline BOOL FNullEnt(const edict_t* pent) { return pent == NULL || FNullEnt(OFFSET(pent)); } -inline BOOL FNullEnt(entvars_t* pev) { return pev == NULL || FNullEnt(OFFSET(pev)); } +inline BOOL FNullEnt(const edict_t* pent) { return pent == nullptr || FNullEnt(OFFSET(pent)); } +inline BOOL FNullEnt(entvars_t* pev) { return pev == nullptr || FNullEnt(OFFSET(pev)); } // Testing strings for nullity #define iStringNull 0 @@ -159,13 +159,13 @@ inline BOOL FStringNull(int iString) { return iString == iStringNull; } #define cchMapNameMost 32 // Dot products for view cone checking -#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees -#define VIEW_FIELD_WIDE (float)-0.7 // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks -#define VIEW_FIELD_NARROW (float)0.7 // +-45 degrees, more narrow check used to set up ranged attacks -#define VIEW_FIELD_ULTRA_NARROW (float)0.9 // +-25 degrees, more narrow check used to set up ranged attacks +#define VIEW_FIELD_FULL (-1.0f) // +-180 degrees +#define VIEW_FIELD_WIDE (-0.7f) // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks +#define VIEW_FIELD_NARROW 0.7f // +-45 degrees, more narrow check used to set up ranged attacks +#define VIEW_FIELD_ULTRA_NARROW 0.9f // +-25 degrees, more narrow check used to set up ranged attacks // All monsters need this data -#define DONT_BLEED -1 +#define DONT_BLEED (-1) #define BLOOD_COLOR_RED (BYTE)247 #define BLOOD_COLOR_YELLOW (BYTE)195 #define BLOOD_COLOR_GREEN BLOOD_COLOR_YELLOW @@ -197,12 +197,21 @@ typedef enum } TOGGLE_STATE; // Misc useful -inline BOOL FStrEq(const char*sz1, const char*sz2) - { return (strcmp(sz1, sz2) == 0); } +inline BOOL FStrEq(const char* sz1, const char* sz2) +{ + return (strcmp(sz1, sz2) == 0); +} inline BOOL FClassnameIs(edict_t* pent, const char* szClassname) - { return FStrEq(STRING(VARS(pent)->classname), szClassname); } +{ + if (FNullEnt(pent)) + return FALSE; + + return FStrEq(STRING(VARS(pent)->classname), szClassname); +} inline BOOL FClassnameIs(entvars_t* pev, const char* szClassname) - { return FStrEq(STRING(pev->classname), szClassname); } +{ + return FStrEq(STRING(pev->classname), szClassname); +} class CBaseEntity; diff --git a/dll.cpp b/dll.cpp index 9e54457..614d042 100644 --- a/dll.cpp +++ b/dll.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,16 +20,15 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. * **/ -#include #include #include #include @@ -54,14 +53,14 @@ DLL_FUNCTIONS gFunctionTable; DLL_FUNCTIONS gFunctionTable_post; enginefuncs_t g_engfuncs; -globalvars_t *gpGlobals; +globalvars_t* gpGlobals; char g_argv[1024]; extern cBot bots[32]; extern bool radio_message; -extern const char *rb_version_nr; -extern char *message; +extern const char* rb_version_nr; +extern char* message; // DLL specific variables DLL_GLOBAL const Vector g_vecZero = Vector(0, 0, 0); @@ -70,7 +69,7 @@ DLL_GLOBAL const Vector g_vecZero = Vector(0, 0, 0); cGame Game; cNodeMachine NodeMachine; cChatEngine ChatEngine; -FILE *fpRblog = nullptr; +FILE* fpRblog = nullptr; float f_load_time = 0.0f; float f_minplayers_think = 0.0f; // timer used to add realbots if internet play enabled @@ -85,12 +84,12 @@ int min_players = -1; // minimum amount of players that should be in t int num_bots = 0; int prev_num_bots = 0; bool g_GameRules = false; -edict_t *clients[32]; -edict_t *pHostEdict = nullptr; +edict_t* clients[32]; +edict_t* pHostEdict = nullptr; float welcome_time = 0.0f; bool welcome_sent = false; -FILE *bot_cfg_fp = nullptr; +FILE* bot_cfg_fp = nullptr; bool need_to_open_cfg = true; float bot_cfg_pause_time = 0.0f; float respawn_time = 0.0f; @@ -121,19 +120,19 @@ bool internet_play = false; // START of Metamod stuff enginefuncs_t meta_engfuncs; -gamedll_funcs_t *gpGamedllFuncs; -mutil_funcs_t *gpMetaUtilFuncs; -meta_globals_t *gpMetaGlobals; +gamedll_funcs_t* gpGamedllFuncs; +mutil_funcs_t* gpMetaUtilFuncs; +meta_globals_t* gpMetaGlobals; META_FUNCTIONS gMetaFunctionTable = { - nullptr, // pfnGetEntityAPI() - nullptr, // pfnGetEntityAPI_Post() + nullptr, // pfnGetEntityAPI() + nullptr, // pfnGetEntityAPI_Post() GetEntityAPI2, // pfnGetEntityAPI2() GetEntityAPI2_Post, // pfnGetEntityAPI2_Post() - nullptr, // pfnGetNewDLLFunctions() - nullptr, // pfnGetNewDLLFunctions_Post() + nullptr, // pfnGetNewDLLFunctions() + nullptr, // pfnGetNewDLLFunctions_Post() GetEngineFunctions, // pfnGetEngineFunctions() - nullptr, // pfnGetEngineFunctions_Post() + nullptr, // pfnGetEngineFunctions_Post() }; plugin_info_t Plugin_info = { @@ -149,8 +148,8 @@ plugin_info_t Plugin_info = { }; -C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, - mutil_funcs_t *pMetaUtilFuncs) { +C_DLLEXPORT int Meta_Query(const char* ifvers, plugin_info_t** pPlugInfo, + mutil_funcs_t* pMetaUtilFuncs) { // this function is the first function ever called by metamod in the plugin DLL. Its purpose // is for metamod to retrieve basic information about the plugin, such as its meta-interface // version, for ensuring compatibility with the current version of the running metamod. @@ -163,39 +162,39 @@ C_DLLEXPORT int Meta_Query(const char *ifvers, plugin_info_t **pPlugInfo, if (std::strcmp(ifvers, Plugin_info.ifvers) != 0) { int mmajor = 0, mminor = 0, pmajor = 0, pminor = 0; LOG_CONSOLE(PLID, - "%s: meta-interface version mismatch (metamod: %s, %s: %s)", - Plugin_info.name, ifvers, Plugin_info.name, - Plugin_info.ifvers); + "%s: meta-interface version mismatch (metamod: %s, %s: %s)", + Plugin_info.name, ifvers, Plugin_info.name, + Plugin_info.ifvers); LOG_MESSAGE(PLID, - "%s: meta-interface version mismatch (metamod: %s, %s: %s)", - Plugin_info.name, ifvers, Plugin_info.name, - Plugin_info.ifvers); + "%s: meta-interface version mismatch (metamod: %s, %s: %s)", + Plugin_info.name, ifvers, Plugin_info.name, + Plugin_info.ifvers); // if plugin has later interface version, it's incompatible (update metamod) sscanf(ifvers, "%d:%d", &mmajor, &mminor); sscanf(META_INTERFACE_VERSION, "%d:%d", &pmajor, &pminor); if (pmajor > mmajor || (pmajor == mmajor && pminor > mminor)) { LOG_CONSOLE(PLID, - "metamod version is too old for this plugin; update metamod"); + "metamod version is too old for this plugin; update metamod"); LOG_ERROR(PLID, - "metamod version is too old for this plugin; update metamod"); + "metamod version is too old for this plugin; update metamod"); return 0; } - // if plugin has older major interface version, it's incompatible (update plugin) + // if plugin has older major interface version, it's incompatible (update plugin) if (pmajor < mmajor) { - LOG_CONSOLE(PLID, - "metamod version is incompatible with this plugin; please find a newer version of this plugin"); - LOG_ERROR(PLID, - "metamod version is incompatible with this plugin; please find a newer version of this plugin"); - return 0; + LOG_CONSOLE(PLID, + "metamod version is incompatible with this plugin; please find a newer version of this plugin"); + LOG_ERROR(PLID, + "metamod version is incompatible with this plugin; please find a newer version of this plugin"); + return 0; } } return 1; // tell metamod this plugin looks safe } C_DLLEXPORT int -Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, - meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) { +Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS* pFunctionTable, + meta_globals_t* pMGlobals, gamedll_funcs_t* pGamedllFuncs) { // this function is called when metamod attempts to load the plugin. Since it's the place // where we can tell if the plugin will be allowed to run or not, we wait until here to make // our initialization stuff, like registering CVARs and dedicated server commands. @@ -203,11 +202,11 @@ Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, // are we allowed to load this plugin now ? if (now > Plugin_info.loadable) { LOG_CONSOLE(PLID, - "%s: plugin NOT attaching (can't load plugin right now)", - Plugin_info.name); + "%s: plugin NOT attaching (can't load plugin right now)", + Plugin_info.name); LOG_ERROR(PLID, - "%s: plugin NOT attaching (can't load plugin right now)", - Plugin_info.name); + "%s: plugin NOT attaching (can't load plugin right now)", + Plugin_info.name); return 0; // returning FALSE prevents metamod from attaching this plugin } // keep track of the pointers to engine function tables metamod gives us @@ -235,11 +234,11 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { // is metamod allowed to unload the plugin ? if ((now > Plugin_info.unloadable) && (reason != PNL_CMD_FORCED)) { LOG_CONSOLE(PLID, - "%s: plugin NOT detaching (can't unload plugin right now)", - Plugin_info.name); + "%s: plugin NOT detaching (can't unload plugin right now)", + Plugin_info.name); LOG_ERROR(PLID, - "%s: plugin NOT detaching (can't unload plugin right now)", - Plugin_info.name); + "%s: plugin NOT detaching (can't unload plugin right now)", + Plugin_info.name); return 0; // returning FALSE prevents metamod from unloading this plugin } @@ -252,15 +251,15 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { #ifdef _WIN32 // Required DLL entry point -int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - return 1; +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + return TRUE; } #endif /* */ C_DLLEXPORT void WINAPI -GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, - globalvars_t *pGlobals) { +GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, + globalvars_t* pGlobals) { // get the engine functions from the engine... std::memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t)); @@ -270,7 +269,7 @@ GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, } void GameDLLInit() { - FILE* fplog = std::fopen("reallog.txt", "wt"); + FILE* fplog = std::fopen("reallog.txt", "wt"); if (fplog) { std::fprintf(fplog, "Realbot Logbook\n"); @@ -283,7 +282,7 @@ void GameDLLInit() { rblog("Initializing clients.."); for (edict_t*& client : clients) - client = nullptr; + client = nullptr; rblog("OK\n"); // initialize the bots array of structures... @@ -293,7 +292,7 @@ void GameDLLInit() { rblog("Verifying realbot is installed correctly.."); - bool bInstalledCorrectly = false; + bool bInstalledCorrectly = false; FILE* fp = std::fopen("realbot/dll/realbot_mm.dll", "rb"); if (fp != nullptr) { bInstalledCorrectly = true; @@ -314,14 +313,14 @@ void GameDLLInit() { // When installed correctly let the user know if (bInstalledCorrectly) REALBOT_PRINT(nullptr, "GAMEDLLINIT", - "Notice: RealBot is installed in the correct directory."); + "Notice: RealBot is installed in the correct directory."); else REALBOT_PRINT(nullptr, "GAMEDLLINIT", - "WARNING: RealBot is NOT installed in the correct directory."); + "WARNING: RealBot is NOT installed in the correct directory."); Game.Init(); Game.LoadNames(); - cGame::LoadBuyTable(); + cGame::LoadBuyTable(); // NodeMachine NodeMachine.init(); @@ -365,9 +364,9 @@ void GameDLLInit() { } // INITIALIZATION -int Spawn(edict_t *pent) { +int Spawn(edict_t* pent) { if (gpGlobals->deathmatch) { - const char *pClassname = const_cast(STRING(pent->v.classname)); + const char* pClassname = STRING(pent->v.classname); if (std::strcmp(pClassname, "worldspawn") == 0) { // do level initialization stuff here... @@ -400,7 +399,8 @@ int Spawn(edict_t *pent) { NodeMachine.experience_load(); ChatEngine.fThinkTimer = gpGlobals->time; - } else if (std::strcmp(pClassname, "trigger_multiple") == 0) { + } + else if (std::strcmp(pClassname, "trigger_multiple") == 0) { // make it a func_button? //sprintf(STRING(pent->v.classname), "func_button"); @@ -410,10 +410,10 @@ int Spawn(edict_t *pent) { RETURN_META_VALUE(MRES_IGNORED, 0); } -int ClientConnect(edict_t *pEntity, const char *pszName, - const char *pszAddress, char szRejectReason[128]) { +int ClientConnect(edict_t* pEntity, const char* pszName, + const char* pszAddress, char szRejectReason[128]) { if (gpGlobals->deathmatch) { - // check if this client is the listen server client + // check if this client is the listen server client if (std::strcmp(pszAddress, "loopback") == 0) { // save the edict of the listen server client... pHostEdict = pEntity; @@ -426,10 +426,10 @@ int ClientConnect(edict_t *pEntity, const char *pszName, // check if this is NOT a bot joining the server... if (std::strcmp(pszAddress, "127.0.0.1") != 0) { - int count = 0; - int i; + int count = 0; + int i; - // don't try to add bots for 60 seconds, give client time to get added + // don't try to add bots for 60 seconds, give client time to get added bot_check_time = gpGlobals->time + 60.0f; for (i = 0; i < 32; i++) { @@ -451,16 +451,17 @@ int ClientConnect(edict_t *pEntity, const char *pszName, } } } - } else {} + } + else {} } RETURN_META_VALUE(MRES_IGNORED, 0); } -void ClientDisconnect(edict_t *pEntity) { +void ClientDisconnect(edict_t* pEntity) { if (gpGlobals->deathmatch) { - int i = 0; + int i = 0; while (i < 32 && clients[i] != pEntity) i++; @@ -483,7 +484,7 @@ void ClientDisconnect(edict_t *pEntity) { RETURN_META(MRES_IGNORED); } -void ClientPutInServer(edict_t *pEntity) { +void ClientPutInServer(edict_t* pEntity) { int i = 0; while (i < 32 && (clients[i] != nullptr)) @@ -496,7 +497,7 @@ void ClientPutInServer(edict_t *pEntity) { } // CLIENT / CONSOLE / COMMANDS -void ClientCommand(edict_t *pEntity) { +void ClientCommand(edict_t* pEntity) { /* @@ -522,9 +523,9 @@ void ClientCommand(edict_t *pEntity) { void StartFrame() { if (!gpGlobals->deathmatch) return; // bots only work in 'deathmatch mode' - //REALBOT_PRINT("StartFrame", "BEGIN"); + //REALBOT_PRINT("StartFrame", "BEGIN"); - edict_t *pPlayer; + edict_t* pPlayer; static int i, player_index, bot_index; static float previous_time = -1.0f; static float client_update_time = 0.0f; @@ -539,8 +540,8 @@ void StartFrame() { if (max_bots < min_bots) min_bots = max_bots;*/ - // When a user - or anything else - specified a higher number of 0 to - // kick bots, then we will do as told. + // When a user - or anything else - specified a higher number of 0 to + // kick bots, then we will do as told. if (kick_amount_bots > 0) { int kicking_team = 0; // What team should we kick? @@ -551,10 +552,12 @@ void StartFrame() { { kicking_team = 1; kick_bots_team++; - } else if (kick_bots_team == 7) { + } + else if (kick_bots_team == 7) { kicking_team = 2; kick_bots_team = 6; - } else + } + else kicking_team = kick_bots_team; if (kick_bots_team > 7) @@ -569,9 +572,9 @@ void StartFrame() { for (i = 0; i < 32; i++) { if (bots[i].bIsUsed) // is this slot used? { - if (bots[i].iTeam == kicking_team) { - char cmd[80]; - snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", bots[i].name); + if (bots[i].iTeam == kicking_team) { + char cmd[80]; + snprintf(cmd, sizeof(cmd), "kick \"%s\"\n", bots[i].name); SERVER_COMMAND(cmd); // kick the bot using (kick "name") break; } @@ -580,7 +583,8 @@ void StartFrame() { } // I kick_amount_bots--; // next frame we kick another bot - } else { + } + else { kick_bots_team = 0; // its always 0 when we have no one to kick } @@ -589,16 +593,16 @@ void StartFrame() { // with the current time. If the current time somehow was less (before) the previous time, then we // assume a reset/restart/reload of a map. if (gpGlobals->time + 0.1f < previous_time) { - static int index; - static float check_server_cmd = 0.0f; - rblog("NEW MAP because time is reset #1\n"); + static int index; + static float check_server_cmd = 0.0f; + rblog("NEW MAP because time is reset #1\n"); check_server_cmd = 0.0f; // reset at start of map count = 0; // mark the bots as needing to be respawned... for (index = 0; index < 32; index++) { - cBot *pBot = &bots[index]; + cBot* pBot = &bots[index]; if (count >= prev_num_bots) { pBot->bIsUsed = false; pBot->respawn_state = RESPAWN_NONE; @@ -651,7 +655,7 @@ void StartFrame() { // go through all clients (except bots) for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - edict_t *pPlayer = INDEXENT(iIndex); + edict_t* pPlayer = INDEXENT(iIndex); // skip invalid players if (pPlayer && !pPlayer->free) { // we found a player which is alive. w00t @@ -677,7 +681,7 @@ void StartFrame() { */ for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - edict_t *pPlayer = INDEXENT(iIndex); + edict_t* pPlayer = INDEXENT(iIndex); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free) { // skip bots! @@ -686,7 +690,7 @@ void StartFrame() { // skip fake clients if (pPlayer->v.flags & FL_THIRDPARTYBOT - || pPlayer->v.flags & FL_FAKECLIENT) + || pPlayer->v.flags & FL_FAKECLIENT) continue; // random color @@ -755,7 +759,7 @@ void StartFrame() { // Search for human players, simple method... for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free) { // a bot @@ -780,7 +784,7 @@ void StartFrame() { SERVER_PRINT("RBSERVER: Too many players, kicking one bot.\n"); kick_amount_bots = 1; } - // total players is lower then min_players due BOTS, add a bot + // total players is lower then min_players due BOTS, add a bot else if (iTotal < min_players) { // add a bot SERVER_PRINT("RBSERVER: Too few player slots filled, adding one bot.\n"); @@ -819,8 +823,8 @@ void StartFrame() { if (max_serverbots == false) { if (add_timer < gpGlobals->time) { add_timer = - gpGlobals->time + RANDOM_LONG(internet_min_interval, - internet_max_interval); + gpGlobals->time + RANDOM_LONG(internet_min_interval, + internet_max_interval); internet_addbot = true; // add a bot! w00t } } @@ -847,7 +851,7 @@ void StartFrame() { Game.UpdateGameStatus(); for (bot_index = 0; bot_index < gpGlobals->maxClients; bot_index++) { - cBot &bot = bots[bot_index]; + cBot& bot = bots[bot_index]; if (bot.bIsUsed && // is this slot used AND bot.respawn_state == RESPAWN_IDLE) // not respawning { @@ -875,7 +879,7 @@ void StartFrame() { // FIX: Suggested by Greg, unnescesary loops. if (draw_nodes) { for (player_index = 1; player_index <= gpGlobals->maxClients; - player_index++) { + player_index++) { pPlayer = INDEXENT(player_index); if (pPlayer && !pPlayer->free) { @@ -889,7 +893,7 @@ void StartFrame() { if (draw_connodes) { for (player_index = 1; player_index <= gpGlobals->maxClients; - player_index++) { + player_index++) { pPlayer = INDEXENT(player_index); if (pPlayer && !pPlayer->free) { @@ -921,7 +925,7 @@ void StartFrame() { int index = 0; // find bot needing to be respawned... while (index < 32 - && bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN) + && bots[index].respawn_state != RESPAWN_NEED_TO_RESPAWN) index++; if (index < 32) { @@ -935,12 +939,12 @@ void StartFrame() { char c_team[2]; char c_class[3]; - snprintf(c_skill, sizeof(c_skill), "%d", bots[index].bot_skill); + snprintf(c_skill, sizeof(c_skill), "%d", bots[index].bot_skill); snprintf(c_team, sizeof(c_team), "%d", bots[index].iTeam); snprintf(c_class, sizeof(c_class), "%d", bots[index].bot_class); Game.createBot(nullptr, c_team, c_skill, c_class, - bots[index].name); + bots[index].name); // 01/07/04 - Stefan - make 100% sure we do not crash on this part with the auto-add function f_minplayers_think = gpGlobals->time + 15; // do not check this for 15 seconds from now @@ -956,8 +960,8 @@ void StartFrame() { if (g_GameRules) { if (need_to_open_cfg) // have we open bot.cfg file yet? { - char msg[256]; - char filename[256]; + char msg[256]; + char filename[256]; need_to_open_cfg = false; // only do this once!!! @@ -987,8 +991,8 @@ void StartFrame() { if (bot_cfg_pause_time >= 1.0f) bot_cfg_pause_time = - std::min(bot_cfg_pause_time, - gpGlobals->time + 1.0f); + std::min(bot_cfg_pause_time, + gpGlobals->time + 1.0f); } } } @@ -1004,7 +1008,7 @@ void StartFrame() { // remember the time previous_time = gpGlobals->time; - // REALBOT_PRINT("StartFrame", "END"); + // REALBOT_PRINT("StartFrame", "END"); RETURN_META(MRES_IGNORED); } @@ -1113,9 +1117,9 @@ void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) //T } void ProcessBotCfgFile() { - char cmd_line[256]; - static char server_cmd[80]; - const char *arg2, *arg3, *arg4; + char cmd_line[256]; + static char server_cmd[80]; + const char* arg2, * arg3, * arg4; char msg[80]; if (bot_cfg_pause_time > gpGlobals->time) @@ -1158,7 +1162,7 @@ void ProcessBotCfgFile() { bot_cfg_fp = nullptr; - bot_cfg_pause_time = 8.0f; // wait 8 seconds before starting + bot_cfg_pause_time = 8.0f; // wait 8 seconds before starting } cmd_line[cmd_index] = 0; // terminate the command line @@ -1171,8 +1175,8 @@ void ProcessBotCfgFile() { std::strcat(server_cmd, "\n"); cmd_index = 0; - const char* cmd = cmd_line; - const char* arg1 = arg2 = arg3 = arg4 = nullptr; + const char* cmd = cmd_line; + const char* arg1 = arg2 = arg3 = arg4 = nullptr; // skip to blank or end of string... while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) @@ -1201,7 +1205,7 @@ void ProcessBotCfgFile() { // skip to blank or end of string... while (cmd_line[cmd_index] != ' ' - && cmd_line[cmd_index] != 0) + && cmd_line[cmd_index] != 0) cmd_index++; if (cmd_line[cmd_index] == ' ') { @@ -1235,17 +1239,17 @@ void ProcessBotCfgFile() { // REALBOT COMMAND // SERVER Command: RealBot void RealBot_ServerCommand() { - const char *pcmd = CMD_ARGV(1); - const char *arg1 = CMD_ARGV(2); - const char *arg2 = CMD_ARGV(3); - const char *arg3 = CMD_ARGV(4); - const char *arg4 = CMD_ARGV(5); + const char* pcmd = CMD_ARGV(1); + const char* arg1 = CMD_ARGV(2); + const char* arg2 = CMD_ARGV(3); + const char* arg3 = CMD_ARGV(4); + const char* arg4 = CMD_ARGV(5); char cMessage[256]; bool bSendMessage = true; // When we need an edict to send messages to, we do that to the pHostEdict - edict_t *pEntity = pHostEdict; + edict_t* pEntity = pHostEdict; // Handle command here if (FStrEq(pcmd, "help")) { @@ -1270,18 +1274,19 @@ void RealBot_ServerCommand() { Game.iMaxSentences = std::min(Game.iMaxSentences, 10); snprintf(cMessage, sizeof(cMessage), "REALBOT: Chat-rate set to %d", - Game.iMaxSentences); - } else { + Game.iMaxSentences); + } + else { snprintf(cMessage, sizeof(cMessage), - "REALBOT: No argument given, current chat-rate is %d", - Game.iMaxSentences); + "REALBOT: No argument given, current chat-rate is %d", + Game.iMaxSentences); } } else if (FStrEq(pcmd, "sound")) { EMIT_SOUND_DYN2(pEntity, CHAN_VOICE, "misc/imgood12.wav", 1.0f, - ATTN_NORM, 0, 100); + ATTN_NORM, 0, 100); } else if (FStrEq(pcmd, "add")) { - const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); + const int iStatus = Game.createBot(pEntity, arg1, arg2, arg3, arg4); bot_check_time = gpGlobals->time + 8.0f; if (iStatus == GAME_MSG_SUCCESS) snprintf(cMessage, sizeof(cMessage), "REALBOT: Successfully created bot."); @@ -1291,10 +1296,10 @@ void RealBot_ServerCommand() { else if (iStatus == GAME_MSG_FAIL_SERVERFULL) snprintf(cMessage, sizeof(cMessage), - "REALBOT: Failed creating bot, server is full."); + "REALBOT: Failed creating bot, server is full."); } else if (FStrEq(pcmd, "walkwithknife")) { if (arg1 != nullptr && *arg1 != 0) { - const float fVar = std::atof(arg1); + const float fVar = static_cast(std::atof(arg1)); // Only set when valid if (fVar < 0) @@ -1306,12 +1311,12 @@ void RealBot_ServerCommand() { // Show amount set if (Game.fWalkWithKnife > 0) snprintf(cMessage, sizeof(cMessage), - "REALBOT: Bots may walk with knife for %f seconds.", - Game.fWalkWithKnife); + "REALBOT: Bots may walk with knife for %f seconds.", + Game.fWalkWithKnife); else snprintf(cMessage, sizeof(cMessage), - "REALBOT: Bots may not walk with knife (value=0)"); + "REALBOT: Bots may not walk with knife (value=0)"); } else snprintf(cMessage, sizeof(cMessage), "REALBOT: No valid argument given."); } else if (FStrEq(pcmd, "max")) { @@ -1322,12 +1327,12 @@ void RealBot_ServerCommand() { // Show amount set snprintf(cMessage, sizeof(cMessage), "REALBOT: Max amount of bots is set to %d.", - max_bots); + max_bots); } else { // sprintf (cMessage, "REALBOT: No valid argument given."); snprintf(cMessage, sizeof(cMessage), - "REALBOT: Max amount of bots is %d -- no valid argument given.", - max_bots); + "REALBOT: Max amount of bots is %d -- no valid argument given.", + max_bots); } } else if (FStrEq(pcmd, "important")) { // Broadcast @@ -1340,15 +1345,15 @@ void RealBot_ServerCommand() { } else if (FStrEq(arg1, "save")) { NodeMachine.save_important(); snprintf(cMessage, sizeof(cMessage), - "REALBOT: Important Area Definitions written to INI file"); + "REALBOT: Important Area Definitions written to INI file"); } else if (FStrEq(arg1, "init")) { // clear all goals that are 'goal_important' NodeMachine.ClearImportantGoals(); snprintf(cMessage, sizeof(cMessage), - "REALBOT: All important goals have been removed."); + "REALBOT: All important goals have been removed."); } else snprintf(cMessage, sizeof(cMessage), - "REALBOT: 'important' sub-commands are: add, save, init"); + "REALBOT: 'important' sub-commands are: add, save, init"); } else if (FStrEq(pcmd, "killall")) { @@ -1356,26 +1361,26 @@ void RealBot_ServerCommand() { end_round = true; } else if (FStrEq(pcmd, "csversion")) { if (arg1 != nullptr && *arg1 != 0) { - const int temp = std::atoi(arg1); + const int temp = std::atoi(arg1); if (temp <= 0) counterstrike = 0; // cs 1.5 else counterstrike = 1; // cs 1.6 if (counterstrike == 0) snprintf(cMessage, sizeof(cMessage), - "REALBOT: Set bot-rules for Counter-Strike 1.5."); + "REALBOT: Set bot-rules for Counter-Strike 1.5."); else snprintf(cMessage, sizeof(cMessage), - "REALBOT: Set bot-rules for Counter-Strike 1.6."); + "REALBOT: Set bot-rules for Counter-Strike 1.6."); } else { if (counterstrike == 0) snprintf(cMessage, sizeof(cMessage), - "REALBOT: bot-rules are set for Counter-Strike 1.5."); + "REALBOT: bot-rules are set for Counter-Strike 1.5."); else snprintf(cMessage, sizeof(cMessage), - "REALBOT: bot-rules are set for Counter-Strike 1.6."); + "REALBOT: bot-rules are set for Counter-Strike 1.6."); } } else if (FStrEq(pcmd, "internet")) { if (arg1 != nullptr && *arg1 != 0) { @@ -1402,8 +1407,8 @@ void RealBot_ServerCommand() { // switch on/off internet mode int temp = std::atoi(arg1); if (temp > -1) { - temp = std::max(temp, 1); - internet_min_interval = temp; + temp = std::max(temp, 1); + internet_min_interval = temp; } } // 2nd argument @@ -1412,14 +1417,14 @@ void RealBot_ServerCommand() { // switch on/off internet mode int temp = std::atoi(arg2); if (temp > -1) { - temp = std::max(temp, internet_min_interval); - internet_max_interval = temp; + temp = std::max(temp, internet_min_interval); + internet_max_interval = temp; } } // Create message snprintf(cMessage, sizeof(cMessage), - "REALBOT: Internet simulation - Interval set to, MIN %d - MAX %d", - internet_min_interval, internet_max_interval); + "REALBOT: Internet simulation - Interval set to, MIN %d - MAX %d", + internet_min_interval, internet_max_interval); } else if (FStrEq(pcmd, "remove") && kick_amount_bots == 0) { // ARG1 - Amount @@ -1445,17 +1450,17 @@ void RealBot_ServerCommand() { } if (kick_bots_team < 1) snprintf(cMessage, sizeof(cMessage), "REALBOT: Removing randomly %d bots.", - kick_amount_bots); + kick_amount_bots); else { if (kick_bots_team == 1) snprintf(cMessage, sizeof(cMessage), "REALBOT: Removing %d terrorist bots.", - kick_amount_bots); + kick_amount_bots); else snprintf(cMessage, sizeof(cMessage), - "REALBOT: Removing %d counter-terrorist bots.", - kick_amount_bots); + "REALBOT: Removing %d counter-terrorist bots.", + kick_amount_bots); } } else if (FStrEq(pcmd, "roundlimit")) { @@ -1474,7 +1479,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "REALBOT: No(t) (enough) valid arguments given."); } - } + } else if (FStrEq(pcmd, "setrandom")) { int s1 = -2, s2 = -2; @@ -1489,8 +1494,8 @@ void RealBot_ServerCommand() { // When first argument is invalid if (s1 < -1) { snprintf(cMessage, sizeof(cMessage), - "REALBOT: No valid argument(s) given. (minimum random skill=%d, maximum random skill=%d).", - Game.iRandomMinSkill, Game.iRandomMaxSkill); + "REALBOT: No valid argument(s) given. (minimum random skill=%d, maximum random skill=%d).", + Game.iRandomMinSkill, Game.iRandomMaxSkill); } else { if (s2 < -1) s2 = Game.iRandomMaxSkill; @@ -1502,12 +1507,12 @@ void RealBot_ServerCommand() { Game.iRandomMinSkill = s1; Game.iRandomMaxSkill = s2; snprintf(cMessage, sizeof(cMessage), - "REALBOT: minimum random skill=%d, maximum random skill=%d.", - Game.iRandomMinSkill, Game.iRandomMaxSkill); + "REALBOT: minimum random skill=%d, maximum random skill=%d.", + Game.iRandomMinSkill, Game.iRandomMaxSkill); } } else if (FStrEq(pcmd, "autoskill")) { if (arg1 != nullptr && *arg1 != 0) { - const int temp = std::atoi(arg1); + const int temp = std::atoi(arg1); if (temp == 1) autoskill = true; @@ -1521,7 +1526,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "REALBOT: Auto adjust skill - disabled."); } else if (FStrEq(pcmd, "override_skill")) { if (arg1 != nullptr && *arg1 != 0) { - const int temp = std::atoi(arg1); + const int temp = std::atoi(arg1); if (temp == 1) Game.iOverrideBotSkill = GAME_YES; @@ -1530,31 +1535,31 @@ void RealBot_ServerCommand() { } if (Game.iOverrideBotSkill == GAME_YES) snprintf(cMessage, sizeof(cMessage), - "REALBOT: Using personality skill (if present) instead of default bot skill."); + "REALBOT: Using personality skill (if present) instead of default bot skill."); else snprintf(cMessage, sizeof(cMessage), - "REALBOT: Using default bot skill at all times."); + "REALBOT: Using default bot skill at all times."); } else if (FStrEq(pcmd, "skill")) { if (arg1 != nullptr && *arg1 != 0) { - const int temp = std::atoi(arg1); + const int temp = std::atoi(arg1); if (temp < -1 || temp > 10) { snprintf(cMessage, sizeof(cMessage), - "REALBOT: Invalid argument given - default skill = %d.", - Game.iDefaultBotSkill); + "REALBOT: Invalid argument given - default skill = %d.", + Game.iDefaultBotSkill); } else { Game.iDefaultBotSkill = temp; snprintf(cMessage, sizeof(cMessage), "REALBOT: Default skill = %d", - Game.iDefaultBotSkill); + Game.iDefaultBotSkill); } } else { snprintf(cMessage, sizeof(cMessage), "REALBOT: Default skill = %d", - Game.iDefaultBotSkill); + Game.iDefaultBotSkill); } } - // ----------------------------------------- - // SERVER SUPPORT - // ----------------------------------------- + // ----------------------------------------- + // SERVER SUPPORT + // ----------------------------------------- else if (FStrEq(pcmd, "server")) { // Minimum amount of playing players... bots or not if (FStrEq(arg1, "players")) { @@ -1568,9 +1573,9 @@ void RealBot_ServerCommand() { } snprintf(cMessage, sizeof(cMessage), "RBSERVER: Minimum playing forced to %d.", - min_players); + min_players); } - // Broadcast + // Broadcast else if (FStrEq(arg1, "broadcast")) { // Broadcast what? if (FStrEq(arg2, "version")) { @@ -1582,11 +1587,11 @@ void RealBot_ServerCommand() { Game.iVersionBroadcasting = temp; if (Game.iVersionBroadcasting == BROADCAST_ROUND) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting RealBot version every round and map change.\n"); + "RBSERVER: Broadcasting RealBot version every round and map change.\n"); else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting RealBot version every map change only.\n"); + "RBSERVER: Broadcasting RealBot version every map change only.\n"); } } else if (FStrEq(arg2, "speech")) { if (arg2 != nullptr) { @@ -1615,24 +1620,24 @@ void RealBot_ServerCommand() { Game.iKillsBroadcasting = BROADCAST_KILLS_NONE; if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); + "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name of bot who killed human player.\n"); + "RBSERVER: Broadcasting name of bot who killed human player.\n"); else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Nothing will be sent to player.\n"); + "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iKillsBroadcasting == BROADCAST_KILLS_FULL) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); + "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iKillsBroadcasting == BROADCAST_KILLS_MIN) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name of bot who killed human player.\n"); + "RBSERVER: Broadcasting name of bot who killed human player.\n"); else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Nothing will be sent to player.\n"); + "RBSERVER: Nothing will be sent to player.\n"); } } else if (FStrEq(arg2, "deaths")) { // How do we broadcast deaths by bots. @@ -1648,35 +1653,35 @@ void RealBot_ServerCommand() { Game.iDeathsBroadcasting = BROADCAST_DEATHS_NONE; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); + "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name of bot who killed human player.\n"); + "RBSERVER: Broadcasting name of bot who killed human player.\n"); else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Nothing will be sent to player.\n"); + "RBSERVER: Nothing will be sent to player.\n"); } else { if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); + "RBSERVER: Broadcasting name and skill of bot who killed human player.\n"); else if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_MIN) snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcasting name of bot who killed human player.\n"); + "RBSERVER: Broadcasting name of bot who killed human player.\n"); else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Nothing will be sent to player.\n"); + "RBSERVER: Nothing will be sent to player.\n"); } } else { snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Broadcast what?\nversion\nspeech\nkills\ndeaths"); + "RBSERVER: Broadcast what?\nversion\nspeech\nkills\ndeaths"); } } else snprintf(cMessage, sizeof(cMessage), - "RBSERVER: Invalid sub-command.\nValid commands are:\nbroadcast (version/kill)\nplayers (keep ## player slots full)"); + "RBSERVER: Invalid sub-command.\nValid commands are:\nbroadcast (version/kill)\nplayers (keep ## player slots full)"); } - // ----------------------------------------- - // NODE EDITOR COMMANDS - // ----------------------------------------- + // ----------------------------------------- + // NODE EDITOR COMMANDS + // ----------------------------------------- else if (FStrEq(pcmd, "nodes")) { int iOnNode = -1; @@ -1691,20 +1696,20 @@ void RealBot_ServerCommand() { // check for valid argument if (arg2 != nullptr && *arg2 != 0) { - const int iTo = std::atoi(arg2); // add connection TO + const int iTo = std::atoi(arg2); // add connection TO // Add this connection if (iTo > -1) { - const bool bSuccess = - NodeMachine.add_neighbour_node(iOnNode, iTo); + const bool bSuccess = + NodeMachine.add_neighbour_node(iOnNode, iTo); if (bSuccess) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Added connection from node %d to node %d.", - iOnNode, iTo); + "NODES EDITOR: Added connection from node %d to node %d.", + iOnNode, iTo); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); + "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); bValidArg = true; } @@ -1712,27 +1717,27 @@ void RealBot_ServerCommand() { if (bValidArg == false) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Give argument to which node this connection is valid!"); + "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeto")) { // removes connection TO bool bValidArg = false; // check for valid argument if (arg2 != nullptr && *arg2 != 0) { - const int iTo = std::atoi(arg2); // remove connection TO + const int iTo = std::atoi(arg2); // remove connection TO // remove this connection if (iTo > -1) { - const bool bSuccess = - NodeMachine.removeConnection(iOnNode, iTo); + const bool bSuccess = + NodeMachine.removeConnection(iOnNode, iTo); if (bSuccess) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Removed connection from node %d to node %d.", - iOnNode, iTo); + "NODES EDITOR: Removed connection from node %d to node %d.", + iOnNode, iTo); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Could not remove connection, connection does not exist."); + "NODES EDITOR: Could not remove connection, connection does not exist."); bValidArg = true; } @@ -1740,15 +1745,15 @@ void RealBot_ServerCommand() { if (bValidArg == false) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Give argument to which node this connection is valid!"); + "NODES EDITOR: Give argument to which node this connection is valid!"); } else if (FStrEq(arg1, "removeall")) { - const bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); + const bool bSuccess = NodeMachine.remove_neighbour_nodes(iOnNode); if (bSuccess) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Removed all connections from node %d.", - iOnNode); + "NODES EDITOR: Removed all connections from node %d.", + iOnNode); } else if (FStrEq(arg1, "draw")) { if (draw_nodes == false) draw_nodes = true; @@ -1758,7 +1763,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - enabled."); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes - disabled."); + "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) draw_connodes = true; @@ -1767,10 +1772,10 @@ void RealBot_ServerCommand() { if (draw_connodes) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes connections - enabled."); + "NODES EDITOR: Drawing nodes connections - enabled."); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes connections - disabled."); + "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes initialized."); @@ -1782,7 +1787,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes loaded."); } else { snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Unknown command\n Valid commands are:\naddto,removeto,removeall,draw,connections,init,save,load."); + "NODES EDITOR: Unknown command\n Valid commands are:\naddto,removeto,removeall,draw,connections,init,save,load."); } } else { @@ -1796,7 +1801,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Drawing nodes - enabled."); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes - disabled."); + "NODES EDITOR: Drawing nodes - disabled."); } else if (FStrEq(arg1, "connections")) { if (draw_connodes == false) draw_connodes = true; @@ -1805,10 +1810,10 @@ void RealBot_ServerCommand() { if (draw_connodes) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes connections - enabled."); + "NODES EDITOR: Drawing nodes connections - enabled."); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Drawing nodes connections - disabled."); + "NODES EDITOR: Drawing nodes connections - disabled."); } else if (FStrEq(arg1, "init")) { NodeMachine.init(); snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes initialized."); @@ -1820,7 +1825,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "NODES EDITOR: Nodes loaded."); } else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Not close enough to a node to edit."); + "NODES EDITOR: Not close enough to a node to edit."); } // commands not needed for a node to be close // 17/07/04 @@ -1830,48 +1835,48 @@ void RealBot_ServerCommand() { // check for valid argument if (arg2 != nullptr && *arg2 != 0 && arg3 != nullptr && *arg3 != 0) { - const int Node1 = std::atoi(arg2); // add connection TO - const int Node2 = std::atoi(arg3); // add connection TO + const int Node1 = std::atoi(arg2); // add connection TO + const int Node2 = std::atoi(arg3); // add connection TO if (Node1 >= 0 && Node2 >= 0 && NodeMachine.add_neighbour_node(Node1, Node2)) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Added connection from node %d to node %d.", - Node1, Node2); + "NODES EDITOR: Added connection from node %d to node %d.", + Node1, Node2); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); + "NODES EDITOR: Connection could not be added, max amount of connections reached or connection already exists."); } else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: this command requires TWO numeric arguments!"); + "NODES EDITOR: this command requires TWO numeric arguments!"); } else if (FStrEq(arg1, "disconnect")) { // check for valid argument if (arg2 != nullptr && *arg2 != 0 && arg3 != nullptr && *arg3 != 0) { - const int Node1 = std::atoi(arg2); - const int Node2 = std::atoi(arg3); + const int Node1 = std::atoi(arg2); + const int Node2 = std::atoi(arg3); if (Node1 >= 0 && Node2 >= 0 && NodeMachine.removeConnection(Node1, Node2)) snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Removed connection from node %d to node %d.", - Node1, Node2); + "NODES EDITOR: Removed connection from node %d to node %d.", + Node1, Node2); else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: Connection could not be removed..."); + "NODES EDITOR: Connection could not be removed..."); } else snprintf(cMessage, sizeof(cMessage), - "NODES EDITOR: this command requires TWO numeric arguments!"); + "NODES EDITOR: this command requires TWO numeric arguments!"); } } - // ----------------------------------------- - // DEBUG COMMANDS - // ----------------------------------------- + // ----------------------------------------- + // DEBUG COMMANDS + // ----------------------------------------- else if (FStrEq(pcmd, "debug")) { // Arg 1 is command: if (FStrEq(arg1, "dontshoot")) { // realbot debug dontshoot [1/0] // check for valid argument if (arg2 != nullptr && *arg2 != 0) { - const int temp = std::atoi(arg2); + const int temp = std::atoi(arg2); if (temp) Game.bDoNotShoot = true; else @@ -1883,10 +1888,10 @@ void RealBot_ServerCommand() { else snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Bots will shoot."); } - // 17/07/04 + // 17/07/04 else if (FStrEq(arg1, "pistols")) { // realbot debug pistols [1/0] if (arg2 != nullptr && *arg2 != 0) { - const int temp = std::atoi(arg2); + const int temp = std::atoi(arg2); if (temp) Game.bPistols = true; else @@ -1904,7 +1909,7 @@ void RealBot_ServerCommand() { } else if (FStrEq(arg1, "bots")) // realbot debug bots // Print information about all current bots { - rblog("Dumping information about all bots:\n"); + rblog("Dumping information about all bots:\n"); for (int iBot = 0; iBot < 32 && bots[iBot].bIsUsed == true; iBot++) { bots[iBot].Dump(); } @@ -1917,7 +1922,7 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Debug messages off."); } else { if (arg2 != nullptr && *arg2 != 0) { - const int temp = std::atoi(arg2); + const int temp = std::atoi(arg2); Game.bDebug = temp; snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Debug messages on for bot [%d].", Game.bDebug); } else { @@ -1960,7 +1965,7 @@ void RealBot_ServerCommand() { if (iFrom > -1) { if (iTo < 0) { - const tGoal *ptr = NodeMachine.getRandomGoalByType(GOAL_SPAWNT); + const tGoal* ptr = NodeMachine.getRandomGoalByType(GOAL_SPAWNT); if (ptr) iTo = ptr->iNode; } @@ -1976,8 +1981,8 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Drawing path of bot id [%d].", draw_nodepath); } else snprintf(cMessage, sizeof(cMessage), - "RBDEBUG: Drawing path of bot id [%d] - no better or valid argument given.", - draw_nodepath); + "RBDEBUG: Drawing path of bot id [%d] - no better or valid argument given.", + draw_nodepath); } else if (FStrEq(arg2, "connections")) { if (draw_connodes == false) draw_connodes = true; @@ -1986,10 +1991,10 @@ void RealBot_ServerCommand() { if (draw_connodes) snprintf(cMessage, sizeof(cMessage), - "RBDEBUG: Drawing nodes connections - enabled."); + "RBDEBUG: Drawing nodes connections - enabled."); else snprintf(cMessage, sizeof(cMessage), - "RBDEBUG: Drawing nodes connections - disabled."); + "RBDEBUG: Drawing nodes connections - disabled."); } else if (FStrEq(arg2, "init")) { NodeMachine.init(); snprintf(cMessage, sizeof(cMessage), "RBDEBUG: Nodes initialized."); @@ -2003,13 +2008,13 @@ void RealBot_ServerCommand() { snprintf(cMessage, sizeof(cMessage), "RBDEBUG: No argument given."); } else { snprintf(cMessage, sizeof(cMessage), - "RBDEBUG: Unknown debug command.\n\nKnown commands are:\ndontshoot, pistols, nodes, print"); + "RBDEBUG: Unknown debug command.\n\nKnown commands are:\ndontshoot, pistols, nodes, print"); } } else { // Not a valid command snprintf(cMessage, sizeof(cMessage), - "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); + "REALBOT: Unknown command.\nValid commands are:\nhelp, add, remove, skill, max, debug, server"); bool bValidCommand = false; //Unused variable boolean [APG]RoboCop[CL] } @@ -2038,22 +2043,22 @@ void RealBot_ServerCommand() { } } -int Spawn_Post(edict_t *pent) { +int Spawn_Post(edict_t* pent) { // solves the bots unable to see through certain types of glass bug. // MAPPERS: NEVER ALLOW A TRANSPARENT ENTITY TO WEAR THE FL_WORLDBRUSH FLAG !!! // is this a transparent entity ? if (pent->v.rendermode == kRenderTransTexture //|| - // (pent->v.rendermode == kRenderTransAlpha && strcmp("func_illusionary", STRING(pent->v.classname)) == 0) + // (pent->v.rendermode == kRenderTransAlpha && strcmp("func_illusionary", STRING(pent->v.classname)) == 0) ) { // func_illusionary on cs_italy uses this rendermode pent->v.flags |= FL_WORLDBRUSH; // set WORLD BRUSH - // this seems to enforce solidness, and hence the tracehull/line will detect it now. - // pent->v.solid = SOLID_BSP; - // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much - // pent->v.rendermode == kRenderNormal; + // this seems to enforce solidness, and hence the tracehull/line will detect it now. + // pent->v.solid = SOLID_BSP; + // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much + // pent->v.rendermode == kRenderNormal; } else { } @@ -2070,12 +2075,12 @@ int Spawn_Post(edict_t *pent) { // Perhaps this fixes also the as_oilrig problem where a traceline goes through the button without // detecting?? // this seems to enforce solidness, and hence the tracehull/line will detect it now. - // pent->v.solid = SOLID_BSP; - // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much + // pent->v.solid = SOLID_BSP; + // pent->v.movetype = MOVETYPE_PUSHSTEP; // this seemed to be the best choice, does not do much - // pent->v.solid = SOLID_TRIGGER; - // pent->v.solid = SOLID_BSP; - // SERVER_PRINT("Adjusted a trigger_multiple!!\n"); + // pent->v.solid = SOLID_TRIGGER; + // pent->v.solid = SOLID_BSP; + // SERVER_PRINT("Adjusted a trigger_multiple!!\n"); } RETURN_META_VALUE(MRES_IGNORED, 0); @@ -2083,7 +2088,7 @@ int Spawn_Post(edict_t *pent) { C_DLLEXPORT int -GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { +GetEntityAPI2(DLL_FUNCTIONS* pFunctionTable, int* interfaceVersion) { gFunctionTable.pfnGameInit = GameDLLInit; gFunctionTable.pfnSpawn = Spawn; gFunctionTable.pfnClientConnect = ClientConnect; @@ -2097,7 +2102,7 @@ GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { // Whistler: C_DLLEXPORT int -GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { +GetEntityAPI2_Post(DLL_FUNCTIONS* pFunctionTable, int* interfaceVersion) { gFunctionTable_post.pfnSpawn = Spawn_Post; // need to declare another gFunctionTable_post in the top of the dll.cpp file std::memcpy(pFunctionTable, &gFunctionTable_post, sizeof(DLL_FUNCTIONS)); return 1; diff --git a/engine.cpp b/engine.cpp index 1925b88..ea8b279 100644 --- a/engine.cpp +++ b/engine.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -56,19 +56,19 @@ extern int fake_arg_count; // Ditlew's Radio extern char radio_messenger[30]; extern bool radio_message; -extern char *message; +extern char* message; bool radio_message_start = false; bool radio_message_from = false; bool show_beginmessage = true; // End Ditlew's Radio -void (*botMsgFunction)(void *, int) = nullptr; +void (*botMsgFunction)(void*, int) = nullptr; -void (*botMsgEndFunction)(void *, int) = nullptr; +void (*botMsgEndFunction)(void*, int) = nullptr; int botMsgIndex; -void pfnChangeLevel(const char *s1, const char *s2) { +void pfnChangeLevel(const char* s1, const char* s2) { // kick any bot off of the server after time/frag limit... for (cBot& bot : bots) { @@ -90,8 +90,8 @@ void pfnChangeLevel(const char *s1, const char *s2) { RETURN_META(MRES_IGNORED); } -edict_t *pfnFindEntityByString(edict_t *pEdictStartSearchAfter, - const char *pszField, const char *pszValue) { +edict_t* pfnFindEntityByString(edict_t* pEdictStartSearchAfter, + const char* pszField, const char* pszValue) { // Counter-Strike - New Round Started if (std::strcmp(pszValue, "info_map_parameters") == 0) { @@ -110,29 +110,29 @@ edict_t *pfnFindEntityByString(edict_t *pEdictStartSearchAfter, RETURN_META_VALUE(MRES_IGNORED, NULL); } -void pfnRemoveEntity(edict_t *e) { +void pfnRemoveEntity(edict_t* e) { #if DO_DEBUG == 2 { - fp = std::fopen("!rbdebug.txt", "a"); - std::fprintf(fp, R"(pfnRemoveEntity: %x)", e); - if (e->v.model != 0) - std::fprintf(fp, " model=%s\n", STRING(e->v.model)); - std::fclose(fp); + fp = std::fopen("!rbdebug.txt", "a"); + std::fprintf(fp, R"(pfnRemoveEntity: %x)", e); + if (e->v.model != 0) + std::fprintf(fp, " model=%s\n", STRING(e->v.model)); + std::fclose(fp); } #endif if (Game.bEngineDebug) { char msg[256]; snprintf(msg, sizeof(msg), "ENGINE: pfnRemoveEntity() - model -> '%s'\n", - STRING(e->v.model)); + STRING(e->v.model)); rblog(msg); } RETURN_META(MRES_IGNORED); } -void pfnClientCommand(edict_t *pEdict, const char *szFmt, ...) { +void pfnClientCommand(edict_t* pEdict, const char* szFmt, ...) { // new? if (pEdict->v.flags & (FL_FAKECLIENT | FL_THIRDPARTYBOT)) RETURN_META(MRES_SUPERCEDE); @@ -143,8 +143,7 @@ void pfnClientCommand(edict_t *pEdict, const char *szFmt, ...) { RETURN_META(MRES_IGNORED); } -void -pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict) { +void pfnMessageBegin(const int msg_dest, const int msg_type, const float* pOrigin, edict_t* edict) { if (Game.bEngineDebug) { char dmsg[256]; @@ -153,13 +152,13 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict } if (gpGlobals->deathmatch) { - // Fix this up for CS 1.6 weaponlists + // Fix this up for CS 1.6 weaponlists // 01/07/04 - Stefan - Thanks to Whistler for pointing this out! if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) botMsgFunction = BotClient_CS_WeaponList; if (edict) { - const int index = UTIL_GetBotIndex(edict); + const int index = UTIL_GetBotIndex(edict); // is this message for a bot? if (index != -1) { @@ -171,52 +170,54 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict if (msg_type == GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) botMsgFunction = BotClient_Valve_WeaponList; else if (msg_type == - GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) + GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) botMsgFunction = BotClient_Valve_CurrentWeapon; else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", nullptr)) botMsgFunction = BotClient_Valve_AmmoX; else if (msg_type == - GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) + GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) botMsgFunction = BotClient_Valve_AmmoPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) + GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) botMsgFunction = BotClient_Valve_WeaponPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) + GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) botMsgFunction = BotClient_Valve_ItemPickup; else if (msg_type == GET_USER_MSG_ID(PLID, "Health", nullptr)) botMsgFunction = BotClient_Valve_Health; else if (msg_type == GET_USER_MSG_ID(PLID, "Battery", nullptr)) botMsgFunction = BotClient_Valve_Battery; else if (msg_type == - GET_USER_MSG_ID(PLID, "DeathMsg", nullptr)) + GET_USER_MSG_ID(PLID, "DeathMsg", nullptr)) botMsgFunction = BotClient_Valve_Damage; else if (msg_type == - GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) + GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) botMsgFunction = BotClient_Valve_ScreenFade; - } else if (mod_id == CSTRIKE_DLL) { + } + else if (mod_id == CSTRIKE_DLL) { if (msg_type == GET_USER_MSG_ID(PLID, "VGUIMenu", nullptr)) botMsgFunction = BotClient_CS_VGUI; else if (msg_type == - GET_USER_MSG_ID(PLID, "ShowMenu", nullptr)) + GET_USER_MSG_ID(PLID, "ShowMenu", nullptr)) botMsgFunction = BotClient_CS_ShowMenu; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) { + GET_USER_MSG_ID(PLID, "WeaponList", nullptr)) { botMsgFunction = BotClient_CS_WeaponList; //DebugOut("BUGBUG: WEAPONLIST FUNCTION CALLED\n"); - } else if (msg_type == - GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) + } + else if (msg_type == + GET_USER_MSG_ID(PLID, "CurWeapon", nullptr)) botMsgFunction = BotClient_CS_CurrentWeapon; else if (msg_type == GET_USER_MSG_ID(PLID, "AmmoX", nullptr)) botMsgFunction = BotClient_CS_AmmoX; else if (msg_type == - GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) + GET_USER_MSG_ID(PLID, "WeapPickup", nullptr)) botMsgFunction = BotClient_CS_WeaponPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) + GET_USER_MSG_ID(PLID, "AmmoPickup", nullptr)) botMsgFunction = BotClient_CS_AmmoPickup; else if (msg_type == - GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) + GET_USER_MSG_ID(PLID, "ItemPickup", nullptr)) botMsgFunction = BotClient_CS_ItemPickup; else if (msg_type == GET_USER_MSG_ID(PLID, "Health", nullptr)) botMsgFunction = BotClient_CS_Health; @@ -225,7 +226,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict else if (msg_type == GET_USER_MSG_ID(PLID, "Damage", nullptr)) botMsgFunction = BotClient_CS_Damage; else if (msg_type == - GET_USER_MSG_ID(PLID, "StatusIcon", nullptr)) { + GET_USER_MSG_ID(PLID, "StatusIcon", nullptr)) { BotClient_CS_StatusIcon(nullptr, -1); // clear state -- redo this -- BERKED botMsgFunction = BotClient_CS_StatusIcon; } @@ -234,7 +235,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict } else if (msg_type == GET_USER_MSG_ID(PLID, "Money", nullptr)) botMsgFunction = BotClient_CS_Money; else if (msg_type == - GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) + GET_USER_MSG_ID(PLID, "ScreenFade", nullptr)) botMsgFunction = BotClient_CS_ScreenFade; } } @@ -252,7 +253,7 @@ pfnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *edict botMsgFunction = BotClient_CS_SayText; } } - // STEFAN + // STEFAN else if (msg_dest == MSG_SPEC) { botMsgFunction = nullptr; // no msg function until known otherwise botMsgIndex = -1; // index of bot receiving message (none) @@ -504,7 +505,7 @@ void pfnWriteString(const char *sz) { } */ if (radio_message_start) { - std::strcpy(radio_messenger, sz); // the messenger of the radio + std::strcpy(radio_messenger, sz); radio_message_start = false; radio_message_from = true; } else if (radio_message_from) { @@ -517,14 +518,9 @@ void pfnWriteString(const char *sz) { // End Ditlew's Radio - // here it is not radio - // here it is not radio - - - // if this message is for a bot, call the client message function... if (botMsgFunction) { - (*botMsgFunction)((void *) sz, botMsgIndex); + (*botMsgFunction)((void*)sz, botMsgIndex); } } @@ -541,27 +537,27 @@ void pfnWriteEntity(int iValue) { RETURN_META(MRES_IGNORED); } -void pfnClientPrintf(edict_t *pEdict, PRINT_TYPE ptype, const char *szMsg) { +void pfnClientPrintf(edict_t* pEdict, PRINT_TYPE ptype, const char* szMsg) { // prevent bots sending these kind of messages if (pEdict->v.flags & (FL_FAKECLIENT | FL_THIRDPARTYBOT)) RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_IGNORED); } -const char *pfnCmd_Args() { +const char* pfnCmd_Args() { if (isFakeClientCommand) RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[0]); RETURN_META_VALUE(MRES_IGNORED, NULL); } -const char *pfnCmd_Argv(int argc) { +const char* pfnCmd_Argv(const int argc) { if (isFakeClientCommand) { if (argc == 0) RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[64]); if (argc == 1) - RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[128]); + RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[128]); if (argc == 2) - RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[192]); + RETURN_META_VALUE(MRES_SUPERCEDE, &g_argv[192]); RETURN_META_VALUE(MRES_SUPERCEDE, NULL); } RETURN_META_VALUE(MRES_IGNORED, NULL); @@ -573,11 +569,11 @@ int pfnCmd_Argc() { RETURN_META_VALUE(MRES_IGNORED, 0); } -void pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed) { +void pfnSetClientMaxspeed(const edict_t* pEdict, const float fNewMaxspeed) { // Set client max speed (CS / All mods) // Check if edict_t is a bot, then set maxspeed - cBot *pPlayerBot = nullptr; + cBot* pPlayerBot = nullptr; int index; for (index = 0; index < 32; index++) { @@ -595,7 +591,7 @@ void pfnSetClientMaxspeed(const edict_t *pEdict, float fNewMaxspeed) { RETURN_META(MRES_IGNORED); } -int pfnGetPlayerUserId(edict_t *e) { +int pfnGetPlayerUserId(edict_t* e) { if (gpGlobals->deathmatch) { //if (mod_id == GEARBOX_DLL) //{ @@ -609,8 +605,8 @@ int pfnGetPlayerUserId(edict_t *e) { } C_DLLEXPORT int -GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, - int *interfaceVersion) { +GetEngineFunctions(enginefuncs_t* pengfuncsFromEngine, + int* interfaceVersion) { meta_engfuncs.pfnChangeLevel = pfnChangeLevel; meta_engfuncs.pfnFindEntityByString = pfnFindEntityByString; meta_engfuncs.pfnRemoveEntity = pfnRemoveEntity; diff --git a/game.cpp b/game.cpp index e01fd01..7b5e4b1 100644 --- a/game.cpp +++ b/game.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -131,7 +131,7 @@ void cGame::InitNewRound() { // initialize bots for new round for (cBot& bot : bots) { - if (bot.bIsUsed) { + if (bot.bIsUsed) { bot.NewRound(); } } @@ -166,7 +166,7 @@ char *cGame::RandomSentence() { void cGame::DetermineMapGoal() { rblog("DetermineMapGoal called\n"); - edict_t *pEnt = nullptr; + edict_t* pEnt = nullptr; int hostagesFound = 0; while ((pEnt = UTIL_FindEntityByClassname(pEnt, "hostage_entity")) != nullptr) { @@ -217,7 +217,7 @@ void cGame::resetRoundTime() { } // GAME: Set round time -void cGame::SetRoundTime(float fTime) { +void cGame::SetRoundTime(const float fTime) { fRoundTime = fTime; } @@ -237,7 +237,7 @@ float cGame::getRoundTimeElapsed() const } // GAME: Set new round flag -void cGame::SetNewRound(bool bState) { +void cGame::SetNewRound(const bool bState) { bNewRound = bState; } @@ -249,7 +249,7 @@ bool cGame::NewRound() const // GAME: Set min and max playing rounds -void cGame::SetPlayingRounds(int iMin, int iMax) { +void cGame::SetPlayingRounds(const int iMin, const int iMax) { if (iMin > -1) iMinPlayRounds = iMin; if (iMax > -1) @@ -394,7 +394,7 @@ void cGame::LoadBuyTable() { // GAME: Update global vars (called by StartFrame) void cGame::UpdateGameStatus() { - edict_t* pEnt = nullptr; + edict_t* pEnt = nullptr; // ------------------ // Update: Dropped C4 @@ -429,17 +429,17 @@ void cGame::UpdateGameStatus() { // all counter-terrorists should know this, and they should head for the bomb if (bPlanted && // found a planted bomb bPlanted != bBombPlanted // and previously we didn't know that - ) { - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); - cBot *bot = UTIL_GetBotPointer(pPlayer); + ) { + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + cBot* bot = UTIL_GetBotPointer(pPlayer); // valid bot if (bot) { if (bot->isCounterTerrorist()) { bot->forgetPath(); bot->rprint("Setting goal for bombspot"); - tGoal *bombSpotGoal = NodeMachine.getRandomGoalByType(GOAL_BOMBSPOT); + tGoal* bombSpotGoal = NodeMachine.getRandomGoalByType(GOAL_BOMBSPOT); if (bombSpotGoal) { bot->setGoalNode(bombSpotGoal); // picks a random bomb spot } @@ -448,12 +448,12 @@ void cGame::UpdateGameStatus() { } // through all clients // Now update bBombPlanted - bBombPlanted = bPlanted; + bBombPlanted = true; } // planted, and not planted before // Every 3 seconds update the goals if (gpGlobals->time > fUpdateGoalTimer + 3) { - // rblog("cGame::UpdateGameStatus - updateGoals\n"); + // rblog("cGame::UpdateGameStatus - updateGoals\n"); NodeMachine.updateGoals(); fUpdateGoalTimer = gpGlobals->time; } @@ -470,7 +470,7 @@ void cGame::UpdateGameStatus() { * @param nameArg * @return */ -int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg, const char *modelArg, const char *nameArg) const +int cGame::createBot(edict_t* pPlayer, const char* teamArg, const char* skillArg, const char* modelArg, const char* nameArg) const { // NAME @@ -533,7 +533,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg if (freeBotIndex == MAX_BOTS) { // failure return GAME_MSG_FAILURE; } - + // create the player entity by calling MOD's player function // (from LINK_ENTITY_TO_CLASS for player object) @@ -575,7 +575,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg // initialize all the variables for this bot... // Retrieve Pointer - cBot *pBot = &bots[freeBotIndex]; + cBot* pBot = &bots[freeBotIndex]; // TODO: Stefan 05/09/2019 - init function? (re-use, so much duplication here) // Set variables @@ -652,7 +652,7 @@ int cGame::createBot(edict_t *pPlayer, const char *teamArg, const char *skillArg } // CreateBot() // Debug message (without BOT) -void REALBOT_PRINT(const char *Function, const char *msg) { +void REALBOT_PRINT(const char* Function, const char* msg) { REALBOT_PRINT(nullptr, Function, msg); } @@ -703,14 +703,14 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { const int minutesLeft = static_cast(roundTimeRemaining) / 60; const int secondsLeft = static_cast(roundTimeRemaining) % 60; - snprintf(cMessage, sizeof(cMessage), "[rb] [%s] [%0d:%02d] - [%s|%d] [%s] [%s] : %s\n", mapName, minutesLeft, secondsLeft, name, botIndex, team, Function, msg); - // print in console only when on debug print if (Game.bDebug > -2) { - if (Game.bDebug == -1) { - rblog(cMessage); - } else if (Game.bDebug == botIndex /*&& botIndex > -1*/) { - rblog(cMessage); + if (Game.bDebug == -1 || Game.bDebug == botIndex) { + std::ostringstream oss; + oss << "[rb] [" << mapName << "] [" << minutesLeft << ":" << std::setw(2) << std::setfill('0') << secondsLeft << "] - [" + << name << "|" << botIndex << "] [" << team << "] [" << Function << "] : " << msg << "\n"; + const std::string cMessage = oss.str(); + rblog(cMessage.c_str()); } } } // REALBOT_PRINT() @@ -791,4 +791,4 @@ void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { // - Log() works properly now // - Clearing in dll.cpp of reallog.txt at dll init // - Logging works now, add REALBOT_PRINT() at every point you want to log something. -// +// \ No newline at end of file diff --git a/game.h b/game.h index 495ecdf..6e947cc 100644 --- a/game.h +++ b/game.h @@ -6,7 +6,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -18,9 +18,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -30,13 +30,16 @@ #ifndef GAME_H #define GAME_H +#include +#include +#include -/** - * GAME "handler" CLASS - * COPYRIGHTED BY STEFAN HENDRIKS (C) - **/ + /** + * GAME "handler" CLASS + * COPYRIGHTED BY STEFAN HENDRIKS (C) + **/ -// GAME MESSAGES + // GAME MESSAGES #define GAME_MSG_SUCCESS 0 // complete success #define GAME_MSG_FAILURE 1 // complete failure @@ -61,8 +64,8 @@ static constexpr int MAX_BOTS = 32; static constexpr int MAX_NAME_LENGTH = 32; // Debug messages for realbot -void REALBOT_PRINT(cBot * pBot, const char *Function, const char *msg); -void REALBOT_PRINT(const char *Function, const char *msg); +void REALBOT_PRINT(cBot* pBot, const char* Function, const char* msg); +void REALBOT_PRINT(const char* Function, const char* msg); class cGame { public: diff --git a/todo.txt b/todo.txt index e6bdea2..0242545 100644 --- a/todo.txt +++ b/todo.txt @@ -6,7 +6,6 @@ - Improve the way bots walk path and decide it is a bad connection - Improve 'unstucking'... when not stuck by hostages and how to attack glass or vent grills in order to proceed. - Allow bots to autovacate for human players -- Prevent bots from Team Killing when a player joins T in CZ - To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up diff --git a/util.cpp b/util.cpp index 994ff04..ca8ff9d 100644 --- a/util.cpp +++ b/util.cpp @@ -61,9 +61,9 @@ #include -#ifndef _WIN32 +/*#ifndef _WIN32 #define snprintf std::snprintf //-V1059 -#endif +#endif*/ extern int mod_id; extern cBot bots[32]; @@ -83,7 +83,7 @@ Vector UTIL_VecToAngles(const Vector& vec) { // Overloaded to add IGNORE_GLASS void UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, - IGNORE_MONSTERS igmon, IGNORE_GLASS ignoreGlass, + const IGNORE_MONSTERS igmon, const IGNORE_GLASS ignoreGlass, edict_t* pentIgnore, TraceResult* ptr) { TRACE_LINE(vecStart, vecEnd, (igmon == @@ -93,7 +93,7 @@ UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, void UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, - IGNORE_MONSTERS igmon, edict_t* pentIgnore, + const IGNORE_MONSTERS igmon, edict_t* pentIgnore, TraceResult* ptr) { TRACE_LINE(vecStart, vecEnd, (igmon == ignore_monsters), pentIgnore, ptr); @@ -101,8 +101,7 @@ UTIL_TraceLine(const Vector& vecStart, const Vector& vecEnd, void UTIL_TraceHull(const Vector& vecStart, const Vector& vecEnd, - IGNORE_MONSTERS igmon, int hullNumber, edict_t* pentIgnore, - TraceResult* ptr) { + const IGNORE_MONSTERS igmon, const int hullNumber, edict_t* pentIgnore,TraceResult* ptr) { TRACE_HULL(vecStart, vecEnd, (igmon == ignore_monsters), hullNumber, pentIgnore, ptr); } @@ -111,7 +110,7 @@ void UTIL_MakeVectors(const Vector& vecAngles) { } edict_t* UTIL_FindEntityInSphere(edict_t* pentStart, - const Vector& vecCenter, float flRadius) { + const Vector& vecCenter, const float flRadius) { edict_t* pentEntity = FIND_ENTITY_IN_SPHERE(pentStart, vecCenter, flRadius); if (!FNullEnt(pentEntity)) @@ -153,7 +152,7 @@ void UTIL_SetOrigin(entvars_t* pev, const Vector& vecOrigin) { SET_ORIGIN(ENT(pev), vecOrigin); } -void ClientPrint(edict_t* pEntity, int msg_dest, const char* msg_name) { +void ClientPrint(edict_t* pEntity, const int msg_dest, const char* msg_name) { if (gmsgTextMsg == 0) gmsgTextMsg = REG_USER_MSG("TextMsg", -1); @@ -165,7 +164,7 @@ void ClientPrint(edict_t* pEntity, int msg_dest, const char* msg_name) { MESSAGE_END(); } -void UTIL_ClientPrintAll(int msg_dest, const char* msg_name, const char* param1, +void UTIL_ClientPrintAll(const int msg_dest, const char* msg_name, const char* param1, const char* param2, const char* param3, const char* param4) { if (gmsgTextMsg == 0) @@ -199,7 +198,7 @@ void UTIL_SayText(const char* pText, edict_t* pEdict) { MESSAGE_END(); } -void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { +void UTIL_HostSay(edict_t* pEntity, const int teamonly, char* message) { char text[128]; char* pc; @@ -216,9 +215,9 @@ void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message) { // turn on color set 2 (color on, no sound) if (teamonly) - std::sprintf(text, "%c(TEAM) %s: ", 2, STRING(pEntity->v.netname)); + snprintf(text, sizeof(text), "%c(TEAM) %s: %s\n", 2, STRING(pEntity->v.netname), message); else - std::sprintf(text, "%c%s: ", 2, STRING(pEntity->v.netname)); + snprintf(text, sizeof(text), "%c%s: %s\n", 2, STRING(pEntity->v.netname), message); if (const unsigned j = sizeof(text) - 2 - std::strlen(text); std::strlen(message) > j) message[j] = 0; @@ -310,9 +309,9 @@ int UTIL_GetTeam(edict_t* pEntity) { std::strcmp(model_name, "arab") == 0 || // old L337 Krew std::strcmp(model_name, "leet") == 0 || // L337 Krew std::strcmp(model_name, "artic") == 0 || // Artic Avenger - std::strcmp(model_name, "arctic") == 0 || // Artic Avenger - fix for arctic? - seemed a typo? - std::strcmp(model_name, "guerilla") == 0) // Gorilla Warfare - //(strcmp(model_name, "militia") == 0)) // CZ Militia + std::strcmp(model_name, "arctic") == 0 || // Arctic Avenger - fix for arctic? - seemed a typo? + std::strcmp(model_name, "guerilla") == 0 || // Gorilla Warfare + std::strcmp(model_name, "militia") == 0) // CZ Militia { return 0; // team Terrorists } @@ -321,7 +320,7 @@ int UTIL_GetTeam(edict_t* pEntity) { std::strcmp(model_name, "sas") == 0 || // UK SAS std::strcmp(model_name, "gign") == 0 || // French GIGN std::strcmp(model_name, "vip") == 0 || // VIP - std::strcmp(model_name, "spetsnatz") == 0) // CZ Spetsnatz + std::strcmp(model_name, "spetsnaz") == 0) // CZ Spetsnaz { return 1; // team Counter-Terrorists } @@ -361,7 +360,7 @@ cBot* UTIL_GetBotPointer(edict_t* pEdict) { for (cBot& bot : bots) { if (bot.pEdict == pEdict) { - return (&bot); + return ⊥ } } @@ -429,7 +428,7 @@ Vector VecBModelOrigin(edict_t* pEdict) { return pEdict->v.absmin + (pEdict->v.size * 0.5f); } -void UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, +void UTIL_ShowMenu(edict_t* pEdict, const int slots, const int displaytime, const bool needmore, const char* pText) { if (gmsgShowMenu == 0) gmsgShowMenu = REG_USER_MSG("ShowMenu", -1); @@ -508,7 +507,7 @@ void UTIL_LogPrintf(const char* fmt, ...) { ALERT(at_logged, "%s", string); } -void UTIL_BotPressKey(cBot* pBot, int type) { +void UTIL_BotPressKey(cBot* pBot, const int type) { if (type == IN_JUMP || type == IN_DUCK) { if (pBot->isFreezeTime()) { pBot->rprint_trace("UTIL_BotPressKey", "IN_JUMP or IN_DUCK press requested, but in freezetime - IGNORING"); @@ -575,7 +574,7 @@ void UTIL_BotPressKey(cBot* pBot, int type) { pBot->pEdict->v.button |= type; } -int UTIL_GiveWeaponType(int weapon_id) { +int UTIL_GiveWeaponType(const int weapon_id) { int kind = NONE; // 30/07/04 by Josh // Use switch instead of multiple if @@ -620,73 +619,43 @@ int UTIL_GiveWeaponType(int weapon_id) { // Return weapon ID (depended on mod) int UTIL_GiveWeaponId(const char* name) { if (mod_id == CSTRIKE_DLL) { - if (name != nullptr && std::strcmp(name, "weapon_knife") == 0) - return CS_WEAPON_KNIFE; - if (name != nullptr && std::strcmp(name, "weapon_c4") == 0) - return CS_WEAPON_C4; - if (name != nullptr && std::strcmp(name, "weapon_mp5navy") == 0) - return CS_WEAPON_MP5NAVY; - if (name != nullptr && std::strcmp(name, "weapon_ak47") == 0) - return CS_WEAPON_AK47; - if (name != nullptr && std::strcmp(name, "weapon_m3") == 0) - return CS_WEAPON_M3; - if (name != nullptr && std::strcmp(name, "weapon_aug") == 0) - return CS_WEAPON_AUG; - if (name != nullptr && std::strcmp(name, "weapon_sg552") == 0) - return CS_WEAPON_SG552; - if (name != nullptr && std::strcmp(name, "weapon_m249") == 0) - return CS_WEAPON_M249; - if (name != nullptr && std::strcmp(name, "weapon_xm1014") == 0) - return CS_WEAPON_XM1014; - if (name != nullptr && std::strcmp(name, "weapon_p90") == 0) - return CS_WEAPON_P90; - if (name != nullptr && std::strcmp(name, "weapon_tmp") == 0) - return CS_WEAPON_TMP; - if (name != nullptr && std::strcmp(name, "weapon_m4a1") == 0) - return CS_WEAPON_M4A1; - if (name != nullptr && std::strcmp(name, "weapon_awp") == 0) - return CS_WEAPON_AWP; - if (name != nullptr && std::strcmp(name, "weapon_fiveseven") == 0) - return CS_WEAPON_FIVESEVEN; - if (name != nullptr && std::strcmp(name, "weapon_ump45") == 0) - return CS_WEAPON_UMP45; - if (name != nullptr && std::strcmp(name, "weapon_sg550") == 0) - return CS_WEAPON_SG550; - if (name != nullptr && std::strcmp(name, "weapon_scout") == 0) - return CS_WEAPON_SCOUT; - if (name != nullptr && std::strcmp(name, "weapon_mac10") == 0) - return CS_WEAPON_MAC10; - if (name != nullptr && std::strcmp(name, "weapon_g3sg1") == 0) - return CS_WEAPON_G3SG1; - if (name != nullptr && std::strcmp(name, "weapon_elite") == 0) - return CS_WEAPON_ELITE; - if (name != nullptr && std::strcmp(name, "weapon_p228") == 0) - return CS_WEAPON_P228; - if (name != nullptr && std::strcmp(name, "weapon_deagle") == 0) - return CS_WEAPON_DEAGLE; - if (name != nullptr && std::strcmp(name, "weapon_usp") == 0) - return CS_WEAPON_USP; - if (name != nullptr && std::strcmp(name, "weapon_glock18") == 0) - return CS_WEAPON_GLOCK18; - // Counter-Strike 1.6 - if (name != nullptr && std::strcmp(name, "weapon_famas") == 0) - return CS_WEAPON_FAMAS; - if (name != nullptr && std::strcmp(name, "weapon_galil") == 0) - return CS_WEAPON_GALIL; - - // 06/07/04 - // Unconfirmed for handling shield - // 31.08.04 Frashman: moved shield string before unknown weapon, not after it - if (name != nullptr && std::strcmp(name, "weapon_shield") == 0) - return CS_WEAPON_SHIELD; - - char buffer[80]; - if (name != nullptr) { - snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); - } - else { - snprintf(buffer, 79, "UTIL_GiveWeaponId: Unknown weapon name (null)\n"); + if (name == nullptr) { + rblog("UTIL_GiveWeaponId: Unknown weapon name (null)\n"); + return -1; } + + const std::string_view weaponName(name); + + if (weaponName == "weapon_knife") return CS_WEAPON_KNIFE; + if (weaponName == "weapon_c4") return CS_WEAPON_C4; + if (weaponName == "weapon_mp5navy") return CS_WEAPON_MP5NAVY; + if (weaponName == "weapon_ak47") return CS_WEAPON_AK47; + if (weaponName == "weapon_m3") return CS_WEAPON_M3; + if (weaponName == "weapon_aug") return CS_WEAPON_AUG; + if (weaponName == "weapon_sg552") return CS_WEAPON_SG552; + if (weaponName == "weapon_m249") return CS_WEAPON_M249; + if (weaponName == "weapon_xm1014") return CS_WEAPON_XM1014; + if (weaponName == "weapon_p90") return CS_WEAPON_P90; + if (weaponName == "weapon_tmp") return CS_WEAPON_TMP; + if (weaponName == "weapon_m4a1") return CS_WEAPON_M4A1; + if (weaponName == "weapon_awp") return CS_WEAPON_AWP; + if (weaponName == "weapon_fiveseven") return CS_WEAPON_FIVESEVEN; + if (weaponName == "weapon_ump45") return CS_WEAPON_UMP45; + if (weaponName == "weapon_sg550") return CS_WEAPON_SG550; + if (weaponName == "weapon_scout") return CS_WEAPON_SCOUT; + if (weaponName == "weapon_mac10") return CS_WEAPON_MAC10; + if (weaponName == "weapon_g3sg1") return CS_WEAPON_G3SG1; + if (weaponName == "weapon_elite") return CS_WEAPON_ELITE; + if (weaponName == "weapon_p228") return CS_WEAPON_P228; + if (weaponName == "weapon_deagle") return CS_WEAPON_DEAGLE; + if (weaponName == "weapon_usp") return CS_WEAPON_USP; + if (weaponName == "weapon_glock18") return CS_WEAPON_GLOCK18; + if (weaponName == "weapon_famas") return CS_WEAPON_FAMAS; + if (weaponName == "weapon_galil") return CS_WEAPON_GALIL; + if (weaponName == "weapon_shield") return CS_WEAPON_SHIELD; + + char buffer[80]; + snprintf(buffer, sizeof(buffer) - 1, "UTIL_GiveWeaponId: Unknown weapon name %s\n", name); rblog(buffer); } @@ -799,7 +768,7 @@ void UTIL_BotSprayLogo(edict_t* pEntity, const char* logo_name) { } // Give a radio message botty boy! -void UTIL_BotRadioMessage(cBot* pBot, int radio, const char* arg1, const char* arg2) { +void UTIL_BotRadioMessage(cBot* pBot, const int radio, const char* arg1, const char* arg2) { // To be sure the console will only change when we MAY change. // The values will only be changed when console_nr is 0 if (pBot->console_nr == 0) { @@ -830,31 +799,31 @@ void UTIL_BotRadioMessage(cBot* pBot, int radio, const char* arg1, const char* a // UTIL_getGrenadeType function // - Stefan ////////////////////////////////// int UTIL_GetGrenadeType(edict_t* pEntity) { - constexpr int length = 32; - - char model_name[length] = {}; + if (!pEntity || !pEntity->v.model) + { + return 0; + } - std::strncpy(model_name, STRING(pEntity->v.model), length - 1); - model_name[length - 1] = 0; // Make sure it is NULL terminated + const std::string_view model_name(STRING(pEntity->v.model)); - if (std::strcmp(model_name, "models/w_hegrenade.mdl") == 0) return 1; // He grenade - if (std::strcmp(model_name, "models/w_flashbang.mdl") == 0) return 2; // FlashBang - if (std::strcmp(model_name, "models/w_smokegrenade.mdl") == 0) return 3; // SmokeGrenade - if (std::strcmp(model_name, "models/w_c4.mdl") == 0) return 4; // C4 Explosive + if (model_name == "models/w_hegrenade.mdl") return 1; // He grenade + if (model_name == "models/w_flashbang.mdl") return 2; // FlashBang + if (model_name == "models/w_smokegrenade.mdl") return 3; // SmokeGrenade + if (model_name == "models/w_c4.mdl") return 4; // C4 Explosive // when an empty string, let us know we missed something - if (model_name[0] == '\0') { + if (model_name.empty()) { char msg[512] = {}; - snprintf(msg, sizeof(msg), "UTIL_GetGrenadeType unknown grenade model: %s\n", model_name); + snprintf(msg, sizeof(msg), "UTIL_GetGrenadeType unknown grenade model: %s\n", model_name.data() ? model_name.data() : "(null)"); } return 0; } // 2 functions from podbot source -unsigned short fixed_unsigned16(float value, float scale) { +unsigned short fixed_unsigned16(const float value, const float scale) { int output = static_cast(value * scale); output = std::max(output, 0); @@ -863,7 +832,7 @@ unsigned short fixed_unsigned16(float value, float scale) { return static_cast(output); } -short fixed_signed16(float value, float scale) { +short fixed_signed16(const float value, const float scale) { int output = static_cast(value * scale); output = std::min(output, 32767); @@ -873,7 +842,7 @@ short fixed_signed16(float value, float scale) { } // Using POD/SDK source to print nice messages on the client machine -void HUD_DrawString(int r, int g, int b, const char* msg, edict_t* edict) { +void HUD_DrawString(const int r, const int g, const int b, const char* msg, edict_t* edict) { // FROM PODBOT SOURCE // Hacked together Version of HUD_DrawString MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, edict); @@ -940,7 +909,7 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { { MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); - std::sprintf(&szTemp[1], "%s : %s", szName, pText); + snprintf(&szTemp[1], sizeof(szTemp) - 1, "%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } @@ -954,7 +923,7 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { if (!IsAlive(pPlayer)) { MESSAGE_BEGIN(MSG_ONE, gmsgSayText, nullptr, pPlayer); WRITE_BYTE(entind); - std::sprintf(&szTemp[1], "*DEAD*%s : %s", szName, pText); + snprintf(&szTemp[1], sizeof(szTemp) - 1, "*DEAD*%s : %s", szName, pText); WRITE_STRING(&szTemp[0]); MESSAGE_END(); } @@ -975,13 +944,13 @@ void UTIL_SayTextBot(const char* pText, cBot* pBot) { } // This UTIL_SpeechSynth() is taken from the POD source. -void UTIL_SpeechSynth(edict_t* pEdict, char* szMessage) { +void UTIL_SpeechSynth(edict_t* pEdict, const char* szMessage) { if (Game.bSpeechBroadcasting == false) return; char szSpeak[128]; - std::sprintf(szSpeak, "speak \"%s\"\n", szMessage); + snprintf(szSpeak, sizeof(szSpeak), "speak \"%s\"\n", szMessage); CLIENT_COMMAND(pEdict, szSpeak); } From b9968f26ff82a6af5f71ec4f48e44f6fb16fe83d Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 13 Sep 2025 00:43:06 +0100 Subject: [PATCH 101/114] Updating AMBuild --- .github/workflows/build.yml | 109 ++++++++++++++++++++++++++++++++++++ AMBuildScript | 4 +- 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..a9c1545 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,109 @@ +name: Build + +on: ["push", "workflow_dispatch"] + +jobs: + build_main: + name: Build for ${{ matrix.os_short }} + runs-on: ${{ matrix.os_version }} + + # skip build on '[ci skip]' + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + strategy: + fail-fast: false + matrix: + os: + - ubuntu-22.04 + - windows-x32 + include: + - os: ubuntu-22.04 + os_short: linux + os_version: ubuntu-22.04 + package_ext: tar.gz + dbg_ext: dbg + cc: clang + cxx: clang++ + vs_arch: unused + am_arch: x86 + + - os: windows-x32 + os_short: win32 + os_version: windows-latest + package_ext: zip + dbg_ext: pdb + cc: not-used + cxx: not-used + vs_arch: x32 + am_arch: x86 + + + steps: + - name: Install (Linux) + if: runner.os == 'Linux' + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y clang g++-multilib + echo "CC=clang" >> $GITHUB_ENV + echo "CXX=clang++" >> $GITHUB_ENV + + - name: Add msbuild to PATH (Windows) + if: runner.os == 'Windows' + uses: microsoft/setup-msbuild@v2 + + - name: Install (Windows) + if: runner.os == 'Windows' + shell: cmd + run: | + :: See https://github.com/microsoft/vswhere/wiki/Find-VC + for /f "usebackq delims=*" %%i in (`vswhere -latest -property installationPath`) do ( + call "%%i"\Common7\Tools\vsdevcmd.bat -arch=${{ matrix.vs_arch }} -host_arch=x64 + ) + + :: Loop over all environment variables and make them global. + for /f "delims== tokens=1,2" %%a in ('set') do ( + echo>>"%GITHUB_ENV%" %%a=%%b + ) + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Setup ambuild + run: | + python -m pip install --upgrade pip + python -m pip install wheel + pip install git+https://github.com/alliedmodders/ambuild + + - name: Fetch RealBot + uses: actions/checkout@v4 + with: + path: realbot + submodules: recursive + + - name: Build Files + working-directory: realbot + run: | + mkdir post + cd post + python3 ../configure.py --sdks=present --mm-path="${{ github.workspace }}/realbot/dependencies/metamod-hl1" --hl1sdk="${{ github.workspace }}/realbot/dependencies/hlsdk" --symbol-files --target ${{ matrix.am_arch }} --enable-optimize + ambuild + + - uses: benjlevesque/short-sha@v2.2 + id: short-sha + + - name: Upload Binary + uses: actions/upload-artifact@v4 + with: + name: realbot-${{ matrix.os_short }}-${{ steps.short-sha.outputs.sha }} + path: | + realbot/post/package/* + + - name: Upload Debug Symbols + uses: actions/upload-artifact@v4 + with: + name: realbot-dbgsym-${{ matrix.os_short }}-${{ steps.short-sha.outputs.sha }} + path: | + realbot/post/**/*.${{ matrix.dbg_ext }} diff --git a/AMBuildScript b/AMBuildScript index 2c92433..ca78f46 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -86,7 +86,7 @@ elif builder.cxx.target.platform == 'windows': ] # Compiler options for optimization ( --enable-optimize ) -if builder.options.optimize == '1': +if builder.options.optimize: # Shared optimization definitions builder.cxx.defines += ['NDEBUG'] if builder.cxx.target.platform == 'linux': @@ -101,7 +101,7 @@ if builder.options.optimize == '1': builder.cxx.cflags += ['/Oy-'] # Compiler options for debugging ( --enable-debug ) -if builder.options.debug == '1': +if builder.options.debug: # Shared debug definitions builder.cxx.defines += ['DEBUG', '_DEBUG'] if builder.cxx.target.platform == 'linux': From c846b770fb758f46a7a1faf1a1ed865f2677dd18 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 13 Sep 2025 00:45:21 +0100 Subject: [PATCH 102/114] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a9c1545..550508b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,7 +88,7 @@ jobs: run: | mkdir post cd post - python3 ../configure.py --sdks=present --mm-path="${{ github.workspace }}/realbot/dependencies/metamod-hl1" --hl1sdk="${{ github.workspace }}/realbot/dependencies/hlsdk" --symbol-files --target ${{ matrix.am_arch }} --enable-optimize + python3 ../configure.py --mm-path="${{ github.workspace }}/realbot/dependencies/metamod-hl1" --hl1sdk="${{ github.workspace }}/realbot/dependencies/hlsdk" --symbol-files --enable-optimize ambuild - uses: benjlevesque/short-sha@v2.2 From 37996b3f379d3047559855f285f5ed148814e1be Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 13 Sep 2025 00:46:29 +0100 Subject: [PATCH 103/114] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 550508b..cd4e5f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,7 +88,7 @@ jobs: run: | mkdir post cd post - python3 ../configure.py --mm-path="${{ github.workspace }}/realbot/dependencies/metamod-hl1" --hl1sdk="${{ github.workspace }}/realbot/dependencies/hlsdk" --symbol-files --enable-optimize + python3 ../configure.py --symbol-files --enable-optimize ambuild - uses: benjlevesque/short-sha@v2.2 From 9b26ec1f2958447ae515ce27f677cc838e274982 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sat, 13 Sep 2025 16:27:29 +0100 Subject: [PATCH 104/114] Experimental modernisation --- .github/workflows/build.yml | 7 +- ChatEngine.cpp | 196 ++++----------- IniParser.cpp | 221 ++++++----------- NodeDataTypes.h | 3 +- NodeMachine.cpp | 158 +++++------- NodeMachine.h | 3 +- bot.cpp | 125 ++++------ bot.h | 4 +- bot_buycode.cpp | 461 ++++++++++++++---------------------- bot_func.cpp | 238 +++++++------------ bot_func.h | 6 + bot_navigate.cpp | 272 +++++---------------- engine.cpp | 138 +++-------- game.cpp | 233 ++++++++---------- game.h | 156 ++++++------ 15 files changed, 773 insertions(+), 1448 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cd4e5f2..90cbab7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -84,11 +84,16 @@ jobs: submodules: recursive - name: Build Files + shell: bash working-directory: realbot run: | mkdir post cd post + + export AM_ARCH=${{ matrix.am_arch }} + python3 ../configure.py --symbol-files --enable-optimize + ambuild - uses: benjlevesque/short-sha@v2.2 @@ -99,7 +104,7 @@ jobs: with: name: realbot-${{ matrix.os_short }}-${{ steps.short-sha.outputs.sha }} path: | - realbot/post/package/* + realbot/post/* - name: Upload Debug Symbols uses: actions/upload-artifact@v4 diff --git a/ChatEngine.cpp b/ChatEngine.cpp index a40dd07..36ba7b6 100644 --- a/ChatEngine.cpp +++ b/ChatEngine.cpp @@ -34,7 +34,11 @@ #include // Some tests by EVYNCKE #include +#include #include +#include +#include + #include #include @@ -53,6 +57,24 @@ extern edict_t* pHostEdict; extern cGame Game; extern cBot bots[32]; +namespace { + edict_t* findPlayerEdictByName(const char* playerName) { + if (!playerName || *playerName == '\0') { + return nullptr; + } + + for (int i = 1; i <= gpGlobals->maxClients; i++) { + edict_t* pPlayer = INDEXENT(i); + if (pPlayer && !pPlayer->free) { + if (std::strcmp(STRING(pPlayer->v.netname), playerName) == 0) { + return pPlayer; + } + } + } + return nullptr; + } +} + // initialize all void cChatEngine::init() { // clear all blocks @@ -95,39 +117,12 @@ void cChatEngine::think() { // if no sender is set, do nothing if (sender[0] == '\0') return; - // 29/08/2019 Stefan: by using string compare on the name of the sender (ie sender[] is the name) we retrieve - // the edict pointer - edict_t* pSender = nullptr; - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t* pPlayer = INDEXENT(i); - - if (pPlayer && !pPlayer->free) { - char name[30] = {}, name2[30] = {}; - - // copy - std::strcpy(name, STRING(pPlayer->v.netname)); - std::strcpy(name2, sender); - - if (std::strcmp(name, name2) == 0) { - pSender = pPlayer; - break; - } - } - } - // Edict pointer established + edict_t* pSender = findPlayerEdictByName(sender); // Scan the message so we know in what block we should be to reply: - char word[20] = {}; - - int c = 0; - int wc = 0; - - const int sentenceLength = static_cast(std::strlen(sentence)); + std::string_view sentence_sv(sentence); - // When length is not valid, get out. - // 29/08/2019: Stefan, so let me get this. We declare the sentence to be max 128 chars, but then we still could end up with a longer one? - // how did we allow for this to happen? - if (sentenceLength == 0 || sentenceLength >= MAX_SENTENCE_LENGTH - 1) { + if (sentence_sv.empty() || sentence_sv.length() >= MAX_SENTENCE_LENGTH - 1) { // clear out sentence and sender std::memset(sentence, 0, sizeof(sentence)); std::memset(sender, 0, sizeof(sender)); @@ -138,69 +133,21 @@ void cChatEngine::think() { return; } - int WordBlockScore[MAX_BLOCKS]; + std::vector WordBlockScore(MAX_BLOCKS, 0); - // Init, none of the block has a score yet (set to -1) - for (int& wbs : WordBlockScore) - { - wbs = -1; - } - - // loop over the sentence character by character - while (c < sentenceLength) { - // protection matters: - if (c < 0) - break; - // End of protection matters - - // Step: Check character to identify the end of a word. - if (sentence[c] == ' ' || sentence[c] == '\n' || - sentence[c] == '.' || sentence[c] == '?' || sentence[c] == '!') { - // Now find the word and add up scores on the proper score blocks. - // not a good word (too small) - if (std::strlen(word) <= 0) { - // SERVER_PRINT("This is not a good word!\n"); + std::stringstream ss(sentence); + std::string word_str; + while (ss >> word_str) { + for (int iB = 0; iB < MAX_BLOCKS; iB++) { + if (ReplyBlock[iB].bUsed) { + for (const char (&iBw)[25] : ReplyBlock[iB].word) { + if (iBw[0] != '\0' && word_str == iBw) { + WordBlockScore[iB]++; + } + } } - else { - for (int iB = 0; iB < MAX_BLOCKS; iB++) { - if (ReplyBlock[iB].bUsed) { - for (const char(&iBw)[25] : ReplyBlock[iB].word) { - // skip any word in the reply block that is not valid - if (iBw[0] == '\0') - continue; // not filled in - - if (std::strlen(iBw) <= 0) - continue; // not long enough (a space?) - - // 03/07/04 - // add score to matching word (evy: ignoring case) - if (std::strcmp(iBw, word) == 0) - WordBlockScore[iB]++; - } // all words in this block - } // any used block - } // for all blocks - } // good word - // clear out entire word. - //for (int cw=0; cw < 20; cw++) - // word[cw] = '\0'; - std::memset(word, 0, sizeof(word)); - - wc = 0; // reset WC position (start writing 'word[WC]' at 0 again) - c++; // next position in sentence - continue; // go to top again. } - // when we end up here, we are still reading a 'non finishing word' character. - // we will fill that in word[wc]. Then add up wc and c, until we find a character - // that marks the end of a word again. - - // fill in the word: - word[wc] = sentence[c]; - - // add up. - c++; - wc++; } - // end of loop // now loop through all blocks and find the one with the most score: int iMaxScore = 0; @@ -263,69 +210,14 @@ void cChatEngine::think() { // chSentence is eventually what the bot will say. char chSentence[128]; - char temp[80]; - - std::memset(chSentence, 0, sizeof(chSentence)); - std::memset(temp, 0, sizeof(temp)); - - // get character position - const char* name_pos = - std::strstr(ReplyBlock[iTheBlock]. - sentence[the_c], "%n"); - - // when name_pos var is found, fill it in. - if (name_pos != nullptr) { - // when name is in this one: - int name_offset = - name_pos - - ReplyBlock[iTheBlock].sentence[the_c]; - name_offset--; - - // copy every character till name_offset - int nC; - for (nC = 0; nC < name_offset; nC++) { - //chSentence[nC] = ReplyBlock[iTheBlock].sentence[the_c][nC]; - temp[nC] = - ReplyBlock[iTheBlock]. - sentence[the_c][nC]; - } - - temp[nC] = ' '; - - // copy senders name to chSentence - std::strcat(temp, sender); - - // Skip %n part in ReplyBlock - nC = name_offset + 3; - - // we just copied a name to chSentence - // set our cursor after the name now (name length + 1) - int tc = static_cast(std::strlen(temp)); - - // now finish the sentence - // get entire length of ReplyBlock and go until we reach the end - const int length = - static_cast(std::strlen(ReplyBlock[iTheBlock]. - sentence[the_c])); - - - // for every nC , read character from ReplyBlock - for (; nC <= length; nC++) { - // ... and copy it into chSentence - temp[tc] = - ReplyBlock[iTheBlock]. - sentence[the_c][nC]; - //char tmsg[80]; - //sprintf(tmsg,"Copying char %c , tc = %d, nC = %d\n", temp[tc], tc, nC); - //SERVER_PRINT(tmsg); - - tc++; // add up tc. - } - - // terminate - temp[tc] = '\n'; - - snprintf(chSentence, sizeof(chSentence), "%s \n", temp); + std::string_view reply_template(ReplyBlock[iTheBlock].sentence[the_c]); + size_t name_pos = reply_template.find("%n"); + + if (name_pos != std::string_view::npos) { + std::string final_sentence = std::string(reply_template.substr(0, name_pos)); + final_sentence += sender; + final_sentence += reply_template.substr(name_pos + 2); + snprintf(chSentence, sizeof(chSentence), "%s \n", final_sentence.c_str()); } // when no name pos is found, we just copy the string and say that (works ok) else { diff --git a/IniParser.cpp b/IniParser.cpp index 46c6a9f..f65396c 100644 --- a/IniParser.cpp +++ b/IniParser.cpp @@ -50,6 +50,8 @@ #include "ChatEngine.h" #include +#include +#include extern int mod_id; extern edict_t* pHostEdict; @@ -119,121 +121,53 @@ void INI_Word(char input[80], char word[25]) { // Reads out word[], does a string compare and returns type id int INI_WordType(char word[25], int section) { - if (word[0] != '\0') { - if (std::strcmp(word, "Word") == 0) - return WORD_WORD; - if (std::strcmp(word, "Sentence") == 0) - return WORD_SENTENCE; - - if (std::strcmp(word, "X") == 0) - return WORD_AREAX; - if (std::strcmp(word, "Y") == 0) - return WORD_AREAY; - if (std::strcmp(word, "Z") == 0) - return WORD_AREAZ; - - // ------ personality stuff ------ - if (std::strcmp(word, "PrimaryWeapon") == 0) - return WORD_PRIWEAPON; - - if (std::strcmp(word, "SecondaryWeapon") == 0) - return WORD_SECWEAPON; - - if (std::strcmp(word, "SaveForWeapon") == 0) - return WORD_SAVEFORWEAP; - - if (std::strcmp(word, "Grenade") == 0) - return WORD_GRENADE; - - if (std::strcmp(word, "FlashBang") == 0) - return WORD_FLASHBANG; - - if (std::strcmp(word, "SmokeGrenade") == 0) - return WORD_SMOKEGREN; - - if (std::strcmp(word, "DefuseKit") == 0) - return WORD_DEFUSEKIT; - - if (std::strcmp(word, "Armour") == 0) - return WORD_ARMOUR; - - // ---- skill - - if (std::strcmp(word, "XOffset") == 0) - return WORD_XOFFSET; - - if (std::strcmp(word, "YOffset") == 0) - return WORD_YOFFSET; - - if (std::strcmp(word, "ZOffset") == 0) - return WORD_ZOFFSET; - - if (std::strcmp(word, "BotSkill") == 0) - return WORD_BOTSKILL; - - if (std::strcmp(word, "MaxReactionTime") == 0) - return WORD_MAXREACTTIME; - - if (std::strcmp(word, "MinReactionTime") == 0) - return WORD_MINREACTTIME; - - if (std::strcmp(word, "Turnspeed") == 0) - return WORD_TURNSPEED; - - // ---- Game - if (std::strcmp(word, "Hostage") == 0) - return WORD_HOSTAGERATE; - - if (std::strcmp(word, "BompSpot") == 0) - return WORD_BOMBSPOTRATE; - - if (std::strcmp(word, "Random") == 0) - return WORD_RANDOMRATE; - if (std::strcmp(word, "DroppedBomb") == 0) - return WORD_DROPPEDBOMB; - - // ---- Radio - if (std::strcmp(word, "Reply") == 0) - return WORD_REPLYRADIO; - - if (std::strcmp(word, "Create") == 0) - return WORD_CREATERADIO; - - // ---- Team - if (std::strcmp(word, "HelpTeammate") == 0) - return WORD_HELPTEAM; - - // ---- person - if (std::strcmp(word, "WalkWithKnife") == 0) - return WORD_WALKKNIFE; - if (std::strcmp(word, "FearRate") == 0) - return WORD_FEARRATE; - if (std::strcmp(word, "HearRate") == 0) - return WORD_HEARRATE; - if (std::strcmp(word, "ChatRate") == 0) - return WORD_CHATRATE; - - if (std::strcmp(word, "CampRate") == 0) - return WORD_CAMPRATE; - - // ------ buy table stuff ------- - if (std::strcmp(word, "Price") == 0) - return WORD_PRICE; - - if (std::strcmp(word, "Priority") == 0) - return WORD_PRIORITY; - - if (std::strcmp(word, "Ammo1Index") == 0) - return WORD_INDEX1; - - if (std::strcmp(word, "Ammo2Index") == 0) - return WORD_INDEX2; - - if (std::strcmp(word, "Ammo1Max") == 0) - return WORD_MAXAMMO1; + if (word[0] == '\0') { + return WORD_NONE; + } - if (std::strcmp(word, "Ammo2Max") == 0) - return WORD_MAXAMMO2; + static const std::unordered_map wordMap = { + {"Word", WORD_WORD}, + {"Sentence", WORD_SENTENCE}, + {"X", WORD_AREAX}, + {"Y", WORD_AREAY}, + {"Z", WORD_AREAZ}, + {"PrimaryWeapon", WORD_PRIWEAPON}, + {"SecondaryWeapon", WORD_SECWEAPON}, + {"SaveForWeapon", WORD_SAVEFORWEAP}, + {"Grenade", WORD_GRENADE}, + {"FlashBang", WORD_FLASHBANG}, + {"SmokeGrenade", WORD_SMOKEGREN}, + {"DefuseKit", WORD_DEFUSEKIT}, + {"Armour", WORD_ARMOUR}, + {"XOffset", WORD_XOFFSET}, + {"YOffset", WORD_YOFFSET}, + {"ZOffset", WORD_ZOFFSET}, + {"BotSkill", WORD_BOTSKILL}, + {"MaxReactionTime", WORD_MAXREACTTIME}, + {"MinReactionTime", WORD_MINREACTTIME}, + {"Turnspeed", WORD_TURNSPEED}, + {"Hostage", WORD_HOSTAGERATE}, + {"BompSpot", WORD_BOMBSPOTRATE}, + {"Random", WORD_RANDOMRATE}, + {"DroppedBomb", WORD_DROPPEDBOMB}, + {"Reply", WORD_REPLYRADIO}, + {"Create", WORD_CREATERADIO}, + {"HelpTeammate", WORD_HELPTEAM}, + {"WalkWithKnife", WORD_WALKKNIFE}, + {"FearRate", WORD_FEARRATE}, + {"HearRate", WORD_HEARRATE}, + {"ChatRate", WORD_CHATRATE}, + {"CampRate", WORD_CAMPRATE}, + {"Price", WORD_PRICE}, + {"Priority", WORD_PRIORITY}, + {"Ammo1Index", WORD_INDEX1}, + {"Ammo2Index", WORD_INDEX2}, + {"Ammo1Max", WORD_MAXAMMO1}, + {"Ammo2Max", WORD_MAXAMMO2} + }; + + if (const std::unordered_map::const_iterator it = wordMap.find(word); it != wordMap.end()) { + return it->second; } return WORD_NONE; @@ -263,36 +197,23 @@ void INI_Sentence(FILE* f, char result[80]) { } // Reads out section[], does a string compare and returns type id -int INI_SectionType(char section[30], int last) { - if (std::strcmp(section, "BLOCK") == 0) - return INI_BLOCK; - - if (std::strcmp(section, "DEATH") == 0) - return INI_DEATHS; - - if (std::strcmp(section, "WELCOME") == 0) - return INI_WELCOME; - - if (std::strcmp(section, "AREA") == 0) - return INI_AREA; - - if (std::strcmp(section, "WEAPON") == 0) - return INI_WEAPON; - - if (std::strcmp(section, "SKILL") == 0) - return INI_SKILL; - - if (std::strcmp(section, "GAME") == 0) - return INI_GAME; - - if (std::strcmp(section, "RADIO") == 0) - return INI_RADIO; - - if (std::strcmp(section, "TEAM") == 0) - return INI_TEAM; - - if (std::strcmp(section, "PERSON") == 0) - return INI_PERSON; +int INI_SectionType(char section[30], const int last) { + static const std::unordered_map sectionMap = { + {"BLOCK", INI_BLOCK}, + {"DEATH", INI_DEATHS}, + {"WELCOME", INI_WELCOME}, + {"AREA", INI_AREA}, + {"WEAPON", INI_WEAPON}, + {"SKILL", INI_SKILL}, + {"GAME", INI_GAME}, + {"RADIO", INI_RADIO}, + {"TEAM", INI_TEAM}, + {"PERSON", INI_PERSON} + }; + + if (const std::unordered_map::const_iterator it = sectionMap.find(section); it != sectionMap.end()) { + return it->second; + } // When nothing found; we assume its just a new ID tag for some unit or structure // Therefor we return the last known SECTION ID so we can assign the proper WORD ID's @@ -540,7 +461,6 @@ void INI_PARSE_CHATFILE() { char dirname[256]; char filename[256]; - FILE* stream; int section = INI_NONE; // Set Directory name + file @@ -552,12 +472,13 @@ void INI_PARSE_CHATFILE() { // make sure the engine knows... REALBOT_PRINT(nullptr, "INI_PARSE_CHATFILE", "Loading CHAT.INI\n"); - int iBlockId = -1; - int iBlockWord = -1; - int iBlockSentence = -1; - // load it - if ((stream = std::fopen(filename, "r+t")) != nullptr) { + if (FILE* stream; (stream = std::fopen(filename, "r+t")) != nullptr) { + + int iBlockId = -1; + int iBlockWord = -1; + int iBlockSentence = -1; + // infinite loop baby while (!feof(stream)) { char linesection[30]; diff --git a/NodeDataTypes.h b/NodeDataTypes.h index 188be72..5b00242 100644 --- a/NodeDataTypes.h +++ b/NodeDataTypes.h @@ -35,6 +35,7 @@ #ifndef NODEDATATYPES_H #define NODEDATATYPES_H +#include #include // player sizes for path_connection_walkable @@ -230,7 +231,7 @@ tTrouble; // Node (stored in RBN file, do not change casually) typedef struct { Vector origin; // Node origin - int iNeighbour[MAX_NEIGHBOURS]; // Reachable nodes for this node + std::array iNeighbour; // Reachable nodes for this node int iNodeBits; int index; } diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 824c688..d9afe80 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -45,6 +45,7 @@ // malloc stuff? #include +#include // --- #include "bot.h" @@ -86,9 +87,9 @@ int cNodeMachine::GetVisibilityFromTo(const int iFrom, const int iTo) const { // Optional assertion assert(iByte < g_iMaxVisibilityByte); - const unsigned char* ToReturn = cVisTable + iByte; + const unsigned char ToReturn = cVisTable[iByte]; - return (*ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; + return (ToReturn & (1 << iBit)) ? VIS_VISIBLE : VIS_BLOCKED; } void cNodeMachine::SetVisibilityFromTo(const int iFrom, const int iTo, const bool bVisible) { @@ -106,27 +107,22 @@ void cNodeMachine::SetVisibilityFromTo(const int iFrom, const int iTo, const boo // Optional assertion assert(iByte < g_iMaxVisibilityByte); - unsigned char* ToChange = cVisTable + iByte; + unsigned char& ToChange = cVisTable[iByte]; if (bVisible) { - *ToChange |= (1 << iBit); + ToChange |= (1 << iBit); } else { - *ToChange &= ~(1 << iBit); + ToChange &= ~(1 << iBit); } } void cNodeMachine::ClearVisibilityTable() { - if (cVisTable) { - std::memset(cVisTable, 0, g_iMaxVisibilityByte); - } + std::fill(cVisTable.begin(), cVisTable.end(), 0); } void cNodeMachine::FreeVisibilityTable() { - if (cVisTable) { - free(cVisTable); - cVisTable = nullptr; - } + cVisTable.clear(); } //--------------------------------------------------------- @@ -137,6 +133,7 @@ void cNodeMachine::init() { iMaxUsedNodes = 0; initNodes(); + initInfoNodes(); initTroubles(); initGoals(); initPaths(); @@ -147,10 +144,22 @@ void cNodeMachine::init() { } void cNodeMachine::initNodes() { + int currentIndex = 0; for (tNode& node : Nodes) { - initializeNode(node); + node.origin = INVALID_VECTOR; + std::fill(node.iNeighbour.begin(), node.iNeighbour.end(), -1); + node.iNodeBits = 0; + node.index = currentIndex++; + } +} + +void cNodeMachine::initInfoNodes() { + for (tInfoNode& infoNode : InfoNodes) { + std::fill(std::begin(infoNode.fDanger), std::end(infoNode.fDanger), 0.0f); + std::fill(std::begin(infoNode.fContact), std::end(infoNode.fContact), 0.0f); } } + void cNodeMachine::initializeNode(tNode& node) { node.origin = INVALID_VECTOR; std::fill(std::begin(node.iNeighbour), std::end(node.iNeighbour), -1); @@ -179,14 +188,7 @@ void cNodeMachine::initVisTable() { constexpr unsigned long iSize = g_iMaxVisibilityByte; //create a heap type thing... - FreeVisibilityTable(); // 16/07/04 - free it first - cVisTable = static_cast(malloc(iSize)); - if (cVisTable != nullptr) { - std::memset(cVisTable, 0, iSize); - } - else { - rblog("cNodeMachine::init() - ERROR: Could not allocate memory for visibility table\n"); - } + cVisTable.resize(iSize); ClearVisibilityTable(); } @@ -217,27 +219,18 @@ void cNodeMachine::initGoal(const int g) { int cNodeMachine::GetTroubleIndexForConnection(int iFrom, int iTo) const { - // sprintf(msg, "GetTroubleIndexForConnection | from %d to %d\n", iFrom, iTo); - // rblog(msg); - // in case of invalid values, return -1 - no need to loop - if (iFrom < -1 || iFrom >= MAX_NODES) { - rblog("GetTroubleIndexForConnection | invalid iFrom\n"); - return -1; - } - if (iTo < -1 || iTo >= MAX_NODES) { - rblog("GetTroubleIndexForConnection | invalid iTo\n"); + if (iFrom < 0 || iFrom >= MAX_NODES || iTo < 0 || iTo >= MAX_NODES) { return -1; } - for (int index = 0; index < MAX_TROUBLE; index++) { - if (Troubles[index].iFrom == iFrom && - Troubles[index].iTo == iTo) { - char msg[255] = {}; - snprintf(msg, sizeof(msg), "GetTroubleIndexForConnection | Found index [%d] for from %d to %d\n", index, iFrom, iTo); - rblog(msg); - // found troubled connection, return its index - return index; - } + const tTrouble* it = std::find_if(std::begin(Troubles), std::end(Troubles), + [iFrom, iTo](const tTrouble& trouble) + { + return trouble.iFrom == iFrom && trouble.iTo == iTo; + }); + + if (it != std::end(Troubles)) { + return std::distance(std::begin(Troubles), it); } return -1; @@ -1105,7 +1098,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { bool bNeighbourWater = false; // when pEntity is on ladder, it is NOT floating! - if (FUNC_IsOnLadder(pEntity)) + if (pEntity && FUNC_IsOnLadder(pEntity)) bNeighbourFloats = false; if (Nodes[nodeIndex].iNodeBits & BIT_LADDER) @@ -1164,7 +1157,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { int hull_type = head_hull; - if (FUNC_IsOnLadder(pEntity)) { + if (pEntity && FUNC_IsOnLadder(pEntity)) { hull_type = point_hull; } else { // falling @@ -1188,7 +1181,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // trace UTIL_TraceHull(Nodes[currentIndex].origin, Nodes[nodeIndex].origin, ignore_monsters, - hull_type, pEntity->v.pContainingEntity, &tr); + hull_type, pEntity ? pEntity->v.pContainingEntity : nullptr, &tr); // if nothing hit: if (tr.flFraction >= 1.0f) { @@ -1287,7 +1280,6 @@ void cNodeMachine::addNodesForPlayers() { // skip invalid (dead, not playing) players if (pPlayer && !pPlayer->free) { - if (pPlayer->free) continue; if (!IsAlive(pPlayer)) continue; const int iPlayerIndex = index - 1; @@ -1487,20 +1479,10 @@ void cNodeMachine::experience_save() { constexpr int iVersion = FILE_EXP_VER2; std::fwrite(&iVersion, sizeof(int), 1, rbl); - struct Node { - Vector fDanger[2]; - Vector fContact[2]; - }; - - //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] - for (int i = 0; i < MAX_NODES; i++) { - Node localInfoNodes[MAX_NODES]; - - std::fwrite(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fwrite(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - - std::fwrite(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fwrite(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + // Write the InfoNodes data directly using the correct struct + for (tInfoNode& InfoNode : InfoNodes) + { + std::fwrite(&InfoNode, sizeof(tInfoNode), 1, rbl); } if (iMaxUsedNodes > MAX_NODES) @@ -1566,20 +1548,9 @@ void cNodeMachine::experience_load() { int iVersion = FILE_EXP_VER1; std::fread(&iVersion, sizeof(int), 1, rbl); - struct Node { - Vector fDanger[2]; - Vector fContact[2]; - }; - Node localInfoNodes[MAX_NODES]; - if (iVersion == FILE_EXP_VER1) { - - //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - std::fread(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i], sizeof(tInfoNode), 1, rbl); } std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); @@ -1591,16 +1562,12 @@ void cNodeMachine::experience_load() { const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; // Read table from what we know - std::fread(cVisTable, iSize, 1, rbl); + std::fread(cVisTable.data(), iSize, 1, rbl); std::fread(iVisChecked, sizeof(iVisChecked), 1, rbl); } else if (iVersion == FILE_EXP_VER2) { - //TODO: To resolve the overflow of the buffer issue [APG]RoboCop[CL] for (i = 0; i < MAX_NODES; i++) { - std::fread(&localInfoNodes[i].fDanger[0], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fDanger[1], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fContact[0], sizeof(Vector), 1, rbl); - std::fread(&localInfoNodes[i].fContact[1], sizeof(Vector), 1, rbl); + std::fread(&InfoNodes[i], sizeof(tInfoNode), 1, rbl); } std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); @@ -2174,35 +2141,26 @@ void cNodeMachine::setUpInitialGoals() { tGoal* cNodeMachine::getRandomGoalByType(const int goalType) { if (goalType == GOAL_NONE) return nullptr; - - int possibleGoalNodes[MAX_GOALS]; - for (int& possibleGoalNode : possibleGoalNodes) - { - possibleGoalNode = -1; - } - - int possibleCandidateIndex = 0; - for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { - if (Goals[goalIndex].iType == goalType && // type equals requested type - Goals[goalIndex].iNode > -1) { // and it has a node - // possibleGoalNodes[possibleCandidateIndex] = Goals[goalIndex].iNode; - possibleGoalNodes[possibleCandidateIndex] = goalIndex; - possibleCandidateIndex++; + + std::vector possibleGoalIndices; + for (int goalIndex = 0; goalIndex < MAX_GOALS; ++goalIndex) { + if (Goals[goalIndex].iType == goalType && Goals[goalIndex].iNode > -1) { + possibleGoalIndices.push_back(goalIndex); } } - - if (possibleCandidateIndex == 0) - return nullptr; // nothing found :( - - // we have an amount of goals, pick one randomly - const int randomGoalIndex = RANDOM_LONG(0, possibleCandidateIndex - 1); - + + if (possibleGoalIndices.empty()) + return nullptr; + + const int randomIndex = RANDOM_LONG(0, static_cast(possibleGoalIndices.size()) - 1); + const int chosenGoalIndex = possibleGoalIndices[randomIndex]; + char msg[255]; - snprintf(msg, sizeof(msg), "cNodeMachine::getRandomGoalByType() - Found %d nodes of type %d and picked %d\n", - possibleCandidateIndex, goalType, randomGoalIndex); + snprintf(msg, sizeof(msg), "cNodeMachine::getRandomGoalByType() - Found %zu nodes of type %d and picked index %d (goal %d)\n", + possibleGoalIndices.size(), goalType, randomIndex, chosenGoalIndex); rblog(msg); - - return getGoal(possibleGoalNodes[randomGoalIndex]); + + return getGoal(chosenGoalIndex); } // Contact scaler (on round start) diff --git a/NodeMachine.h b/NodeMachine.h index 7a94bf8..dad1698 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -73,6 +73,7 @@ class cNodeMachine { void init(); // Init (info)nodes void initNodes(); + void initInfoNodes(); void initializeNode(tNode& node); void initTroubles(); void initPaths(); @@ -200,7 +201,7 @@ class cNodeMachine { int iMaxUsedNodes = 0; byte iVisChecked[MAX_NODES] = {}; - unsigned char * cVisTable = nullptr; + std::vector cVisTable; tTrouble Troubles[MAX_TROUBLE] = {}; void FindMinMax() const; diff --git a/bot.cpp b/bot.cpp index f40ed21..2181d81 100644 --- a/bot.cpp +++ b/bot.cpp @@ -1480,7 +1480,7 @@ void cBot::InteractWithPlayers() { // ------------------------------------------------ // RESULT > -1 ; ENEMY FOUND / NO SPECIFIC REACTION // ------------------------------------------------ - if (result > -1 /*&& result < 4*/) { + else { // result > -1 // VIP: When we found an enemy, we have a problem. if (vip) { @@ -1502,43 +1502,7 @@ void cBot::InteractWithPlayers() { f_update_weapon_time = gpGlobals->time + 0.7f; } } - // ------------------------------------------------ - // RESULT = 1 ; ENEMY FOUND, VIA FRIEND! - // ------------------------------------------------ - - // When we have found an enemy via a friend, we simply build a path to it. - if (result == 1) { - - /* - f_prim_weapon = gpGlobals->time; - - // DECIDE: - // Do we go into battle, or do we wait first a few seconds? - - // HEALTH: The less we have, the more we want to wait - int vHealth = 100-bot_health; - - // CAMP: The more we want to camp, the more we want to wait. - int vCamp = ipCampRate; - - if (RANDOM_LONG(0,200) < (vHealth+vCamp)) - { - // depending on how much we want, the longer we wait - float fWaitTime = ((200/(vHealth+vCamp))*5); - f_wait_time = gpGlobals->time + fWaitTime; - - // TODO TODO TODO; we might not even want to wait, but also take 'cover'? - } - // INITIALIZATION: - int iGoal = NodeMachine.getCloseNode(pBotEnemy->v.origin, NODE_ZONE, pBotEnemy); - if (iGoal > -1) - { - iGoalNode = iGoal; - pathNodeIndex = -1; - } - */ - } // ------------------------------------------------ // RESULT = 0 ; NEW ENEMY FOUND // ------------------------------------------------ @@ -1785,16 +1749,14 @@ bool cBot::Defuse() { // if this bot is close. If so, the bot should be defusing the bomb // if the timers are set. The above check makes sure that no other // bot will be defusing the bomb. - edict_t *pent = nullptr; - bool c4Found = false; + edict_t* pent = nullptr; while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != nullptr) { if (UTIL_GetGrenadeType(pent) == 4) { // It is a C4 - c4Found = true; break; } } - if (!c4Found) { + if (pent == nullptr) { rprint_normal("Defuse()", "No C4 planted yet"); return false; } @@ -1863,20 +1825,20 @@ bool cBot::Defuse() { } else { rprint_trace("Defuse()", "I can see C4, but it is out of reach."); - const int iGoalNode = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); - if (iGoalNode < 0) { + const int iC4Node = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); + if (iC4Node < 0) { rprint_normal("Defuse()", "No node close, so just look at it/body face at it and move towards it."); vHead = vC4; vBody = vC4; } - if (iGoalNode > -1) { + if (iC4Node > -1) { // we are not heading for this goal yet - if (getGoalNode() != iGoalNode) { + if (getGoalNode() != iC4Node) { rprint_normal("Defuse()", "I don't have a goal towards the C4, overriding it now to C4 destination!"); forgetPath(); forgetGoal(); - setGoalNode(iGoalNode); + setGoalNode(iC4Node); } else { rprint_normal("Defuse()", "I already have a goal towards the C4!"); } @@ -2159,31 +2121,18 @@ void cBot::CheckAround() { rprint_trace("CheckAround", msg); // Set 'act' properties - - // we are surrounded, so move backwards - if (bHitForward) { - rprint_trace("CheckAround", "Something in front of me blocks, so move back."); - // f_move_speed = -(f_max_speed); - } else { - rprint_trace("CheckAround", "Nothing in front of me"); + const float strafeAmount = DetermineStrafe(bHitForwardLeft, bHitForwardRight, bHitLeft, bHitRight); + if (strafeAmount != 0.0f) { + setStrafeSpeed(strafeAmount, 0.5f); } - if (!bHitForwardLeft && bHitForwardRight) { - strafeLeft(0.5f); - rprint_trace("CheckAround", "Can strafe left (forward left)"); - } else if (bHitForwardLeft && !bHitForwardRight) { - strafeRight(0.5f); - rprint_trace("CheckAround", "Can strafe right (forward right)"); + // we are surrounded, so move backwards, but only if we are not strafing + if (bHitForward && strafeAmount == 0.0f) { + rprint_trace("CheckAround", "Something in front of me blocks, so move back."); + setMoveSpeed(-f_max_speed); } - - if (bHitLeft && bHitRight) { - rprint_trace("CheckAround", "Can't strafe left or right"); - } else if (!bHitLeft && bHitRight) { - strafeLeft(0.5f); - rprint_trace("CheckAround", "Can strafe left"); - } else if (bHitLeft && !bHitRight) { - strafeRight(0.5f); - rprint_trace("CheckAround", "Can strafe right"); + else { + rprint_trace("CheckAround", "Nothing in front of me"); } // ------------------------------------------------------------- @@ -2292,12 +2241,12 @@ bool cBot::hasEnemy() const return this->pEnemyEdict != nullptr; } -/** - * Returns true when given edict == our enemy edict - * @param pEdict - * @return - */ -bool cBot::hasEnemy(const edict_t * pEdict) const + /** + * Returns true when given edict == our enemy edict + * @param pEntity + * @return + */ +bool cBot::hasEnemy(const edict_t* pEntity) const { return this->pEnemyEdict == pEntity; } @@ -4410,6 +4359,34 @@ bool cBot::isJumping() { return b; } +float cBot::DetermineStrafe(const bool bHitForwardLeft, const bool bHitForwardRight, const bool bHitLeft, const bool bHitRight) +{ + // Prioritize avoiding diagonal obstacles + if (!bHitForwardLeft && bHitForwardRight) { + rprint_trace("CheckAround", "Strafing left to avoid forward-right obstacle."); + return -f_max_speed; + } + + if (bHitForwardLeft && !bHitForwardRight) { + rprint_trace("CheckAround", "Strafing right to avoid forward-left obstacle."); + return f_max_speed; + } + + // If diagonals are clear, check for side obstacles + if (!bHitLeft && bHitRight) { + rprint_trace("CheckAround", "Strafing left to avoid right obstacle."); + return -f_max_speed; + } + + if (bHitLeft && !bHitRight) { + rprint_trace("CheckAround", "Strafing right to avoid left obstacle."); + return f_max_speed; + } + + rprint_trace("CheckAround", "No strafing needed or path is blocked on both sides."); + return 0.0f; +} + // Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] // void cBot::doDuckJump(const Vector& vector) { diff --git a/bot.h b/bot.h index 2ba44a7..5d3e1db 100644 --- a/bot.h +++ b/bot.h @@ -476,7 +476,7 @@ class cBot { // ------------------- bool hasEnemy() const; - bool hasEnemy(const edict_t * pEdict) const; + bool hasEnemy(const edict_t * pEntity) const; edict_t * getEnemyEdict() const; bool hasGoal() const; @@ -583,6 +583,8 @@ class cBot { bool isFreezeTime() const; void rememberEnemyFound(); +private: + float DetermineStrafe(bool bHitForwardLeft, bool bHitForwardRight, bool bHitLeft, bool bHitRight); }; // new UTIL.CPP functions... diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 4605de0..2c8994f 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -55,12 +56,12 @@ void LoadDefaultWeaponTable() { /* REMOVED */ } // Returns price of a weapon, checking on WEAPON_ID (of CS) -int PriceWeapon(int weapon_id) { +int PriceWeapon(const int weapon_id) { return weapons_table[weapons_table[weapon_id].iIdIndex].price; } // Returns the ID in the list, checking on WEAPON_ID (of CS) -int ListIdWeapon(int weapon_id) { +int ListIdWeapon(const int weapon_id) { return weapons_table[weapon_id].iIdIndex; } @@ -73,12 +74,16 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const ch if (pBot->console_nr == 0) { // set up first command and argument - std::strcpy(pBot->arg1, "buy"); - std::strcpy(pBot->arg2, arg1); + strncpy(pBot->arg1, "buy", sizeof(pBot->arg1) - 1); + pBot->arg1[sizeof(pBot->arg1) - 1] = '\0'; + strncpy(pBot->arg2, arg1, sizeof(pBot->arg2) - 1); + pBot->arg2[sizeof(pBot->arg2) - 1] = '\0'; // add argument - if (arg2 != nullptr) - std::strcpy(pBot->arg3, arg2); + if (arg2 != nullptr) { + strncpy(pBot->arg3, arg2, sizeof(pBot->arg3) - 1); + pBot->arg3[sizeof(pBot->arg3) - 1] = '\0'; + } pBot->console_nr = 1; // start console command sequence } @@ -91,57 +96,35 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const ch * @param team * @return */ -bool GoodWeaponForTeam(int weapon, int team) { +bool GoodWeaponForTeam(const int weapon, const int team) { // Mod CS: if (mod_id == CSTRIKE_DLL) { - - // When not playing Counter-Strike 1.6, these weapons are automaticly wrong for all teams. - if (counterstrike == 0) - if (weapon == CS_WEAPON_GALIL || weapon == CS_WEAPON_FAMAS - || weapon == CS_WEAPON_SHIELD) + // When not playing Counter-Strike 1.6, these weapons are automatically wrong for all teams. + if (counterstrike == 0) { + if (weapon == CS_WEAPON_GALIL || weapon == CS_WEAPON_FAMAS || weapon == CS_WEAPON_SHIELD) { return false; + } + } + + // Define team-specific restricted weapons + static const std::unordered_set ct_restricted = { + CS_WEAPON_SG552, CS_WEAPON_AK47, CS_WEAPON_DEAGLE, CS_WEAPON_MP5NAVY, + CS_WEAPON_GALIL, CS_WEAPON_P90, CS_WEAPON_G3SG1 + }; + + static const std::unordered_set t_restricted = { + CS_WEAPON_AUG, CS_WEAPON_DEAGLE, CS_WEAPON_M4A1, CS_WEAPON_MP5NAVY, + CS_WEAPON_FAMAS, CS_WEAPON_P90, CS_WEAPON_SG550, CS_DEFUSEKIT + }; - // Check the real thing - if (team == 2) // Counter-Terrorist - { - // 30/07/04 by Josh - // Use a switch instead of multiple if - switch (weapon) { - case CS_WEAPON_SG552: - return false; - case CS_WEAPON_AK47: - return false; - case CS_WEAPON_DEAGLE: - return false; - case CS_WEAPON_MP5NAVY: - return false; - case CS_WEAPON_GALIL: - return false; - case CS_WEAPON_P90: - return false; - // 30.8.04 added by frashman - case CS_WEAPON_G3SG1: - return false; + if (team == 2) { // Counter-Terrorist + if (ct_restricted.count(weapon)) { + return false; } - } else { - switch (weapon) { - case CS_WEAPON_AUG: - return false; - case CS_WEAPON_DEAGLE: - return false; - case CS_WEAPON_M4A1: - return false; - case CS_WEAPON_MP5NAVY: - return false; - case CS_WEAPON_FAMAS: - return false; - case CS_WEAPON_P90: - return false; - //30.8.04 added by Frashman - case CS_WEAPON_SG550: - return false; - case CS_DEFUSEKIT: - return false; + } + else { // Terrorist + if (t_restricted.count(weapon)) { + return false; } } } @@ -151,275 +134,195 @@ bool GoodWeaponForTeam(int weapon, int team) { /* BotDecideWhatToBuy() - + In this function the bot will choose what weapon to buy from the table. */ -void BotDecideWhatToBuy(cBot *pBot) { - /** - * Stefan 02/09/2018 - * - * This function is called multiple frames. And it basically checks boolean flags (buy_*) method, if true - * then a weapon to buy is choosen. Once choosen it is bought. The flag which was 'true' now became 'false'. - * - * Then the next frame, the boolean flag before will become 'false' and thus another if block is executed. - * - * Effectively doing: - * - buy primary weapon first - * - then secondary - * - ammo for primary - * - ammo for secondary - * - armor - * - defuse kit - * - etc. - * - * the order of if statements is leading - * - * In other words, it needs refactoring... - * - */ - const int money = pBot->bot_money; // Money - const int team = pBot->iTeam; // Team - +int BotBuyPrimaryWeapon(cBot *pBot) { + const int money = pBot->bot_money; + const int team = pBot->iTeam; int buy_weapon = -1; - // Buy a primary weapon, think of the best choice - if (pBot->buy_primary) { - pBot->rprint("BotDecideWhatToBuy()", "buy_primary"); - // Buy primary - - // Personality related: - // Check if we can buy our favorite weapon - if (pBot->hasFavoritePrimaryWeaponPreference()) { - pBot->rprint("BotDecideWhatToBuy()", "I have a primary weapon preference"); - - if (!pBot->ownsFavoritePrimaryWeapon()) { - pBot->rprint("BotDecideWhatToBuy()", "I do not own my primary weapon preference"); - - if (GoodWeaponForTeam(pBot->ipFavoPriWeapon, pBot->iTeam)) { // can we buy it for this team? - - if (pBot->canAfford(PriceWeapon(pBot->ipFavoPriWeapon))) { // can we afford it? - // Buy favorite weapon! - pBot->rprint("BotDecideWhatToBuy()", "Can buy my favorite primary weapon, doing it"); - buy_weapon = pBot->ipFavoPriWeapon; - } else { - pBot->rprint("BotDecideWhatToBuy()", "Can't afford my favorite primary weapon."); - - // bot personality: if we want to save money for our favorite weapon, then set other values to false - if (RANDOM_LONG(0, 100) < pBot->ipSaveForWeapon) { // 31.08.04 Frashman forgotten brace - pBot->rprint("Decided to save extra money"); - pBot->buy_primary = false; - pBot->buy_secondary = false; // don't buy a secondary - return; // get out of function, don't buy anything - } - } + // Personality related: + // Check if we can buy our favorite weapon + if (pBot->hasFavoritePrimaryWeaponPreference()) { + if (!pBot->ownsFavoritePrimaryWeapon()) { + if (GoodWeaponForTeam(pBot->ipFavoPriWeapon, pBot->iTeam)) { // can we buy it for this team? + if (pBot->canAfford(PriceWeapon(pBot->ipFavoPriWeapon))) { // can we afford it? + return pBot->ipFavoPriWeapon; + } + // bot personality: if we want to save money for our favorite weapon, then set other values to false + if (RANDOM_LONG(0, 100) < pBot->ipSaveForWeapon) { + pBot->rprint("Decided to save extra money"); + pBot->buy_secondary = false; // don't buy a secondary + return -2; // Special value to indicate "stop buying" } - } else { - pBot->rprint("BotDecideWhatToBuy()", "I already have my favorite primary weapon"); - // already have my favorite weapon - pBot->buy_primary = false; // do not buy a primary weapon - return; } } + else { + // already have my favorite weapon + return -2; // Stop buying + } + } - // not decided what to buy yet - if (buy_weapon < 0) { - pBot->rprint("BotDecideWhatToBuy()", "I have no primary weapon preference, deciding what to buy."); - - // Find weapon we can buy in the list of weapons - for (const weapon_price_table& i : weapons_table) - { - - // 31.08.04 Frashman Filter Out all except PRIMARY and SHIELD - // SHIELD is used as primary weapon + // Find weapon we can buy in the list of weapons + for (const weapon_price_table& i : weapons_table) { + if (UTIL_GiveWeaponType(i.iId) != PRIMARY && UTIL_GiveWeaponType(i.iId) != SHIELD) + continue; - if (UTIL_GiveWeaponType(i.iId) != PRIMARY - && UTIL_GiveWeaponType(i.iId) != SHIELD) - continue; + if (!GoodWeaponForTeam(i.iId, team)) + continue; - // must be a weapon that the team can buy (CT/T weapon) - if (!GoodWeaponForTeam(i.iId, team)) + if (i.price <= money) { + if (pBot->iPrimaryWeapon > -1) { + if (weapons_table[ListIdWeapon(pBot->iPrimaryWeapon)].priority >= i.priority) continue; + } - // can afford it - if (i.price <= money) { - - // owns a primary weapon - if (pBot->iPrimaryWeapon > -1) { - // and the primary weapon has a higher priority than the other primary weapon - if (weapons_table[ListIdWeapon(pBot->iPrimaryWeapon)].priority >= i.priority) - continue; - } - - // nothing to buy yet, so chose this one - if (buy_weapon == -1) { - buy_weapon = i.iId; - } else { - // randomly overrule it based on priority. The higher priority the more chance - // it will be bought. - if (RANDOM_LONG(0, 100) < i.priority) { - buy_weapon = i.iId; // randomly buy a different weapon - } - } + if (buy_weapon == -1) { + buy_weapon = i.iId; + } + else { + if (RANDOM_LONG(0, 100) < i.priority) { + buy_weapon = i.iId; } } } + } - pBot->buy_primary = false; - - // has decided which weapon to buy - if (buy_weapon != -1) { - pBot->rprint("BotDecideWhatToBuy()", "Found a primary weapon to buy"); + return buy_weapon; +} - // depending on amount of money we have left buy *also* secondary weapon - const int iMoneyLeft = money - PriceWeapon(buy_weapon); +int BotBuySecondaryWeapon(cBot *pBot) { + const int money = pBot->bot_money; + const int team = pBot->iTeam; + int buy_weapon = -1; - // TODO: this should be dependant on something else... not only money - // 01.09.04 Frashman if buyed a Shield, try to buy a good Pistol - if (iMoneyLeft >= 600) - if (RANDOM_LONG(0, 100) < 15 - || pBot->iPrimaryWeapon == CS_WEAPON_SHIELD) - pBot->buy_secondary = true; - } - } else if (pBot->buy_secondary) { - pBot->rprint("BotDecideWhatToBuy()", "buy_secondary"); - // Buy secondary - - // Personality related: - // Check if we can buy our favorite weapon - if (pBot->hasFavoriteSecondaryWeaponPreference()) { - pBot->rprint("BotDecideWhatToBuy()", "I have a secondary weapon preference"); - - if (!pBot->ownsFavoriteSecondaryWeapon()) { - pBot->rprint("BotDecideWhatToBuy()", "I do not own my secondary weapon preference"); - - if (GoodWeaponForTeam(pBot->ipFavoSecWeapon, pBot->iTeam)) { - if (pBot->canAfford(pBot->ipFavoSecWeapon)) { - pBot->rprint("BotDecideWhatToBuy()", "I can afford my favorite secondary weapon, buying it now"); - // Buy favorite weapon - buy_weapon = pBot->ipFavoPriWeapon; - } else { - pBot->rprint("BotDecideWhatToBuy()", "I cannot afford my favorite secondary weapon"); - - // do not buy a random secondary weapon - rather save money for it. - // We do here something to 'save' for our favorite weapon - if (RANDOM_LONG(0, 100) < pBot->ipSaveForWeapon) { // 31.08.04 Frashman forgotten brace - pBot->rprint("I have decided to save money for my favorite secondary weapon"); - pBot->buy_secondary = false; // don't buy a secondary - return; // get out of function, don't buy anything - } - } + if (pBot->hasFavoriteSecondaryWeaponPreference()) { + if (!pBot->ownsFavoriteSecondaryWeapon()) { + if (GoodWeaponForTeam(pBot->ipFavoSecWeapon, pBot->iTeam)) { + if (pBot->canAfford(pBot->ipFavoSecWeapon)) { + return pBot->ipFavoSecWeapon; + } + if (RANDOM_LONG(0, 100) < pBot->ipSaveForWeapon) { + return -2; // Stop buying } - } else { - pBot->rprint("BotDecideWhatToBuy()", "I already own my favorite secondary weapon"); - // we already own it, do nothing - return; } } + else { + return -2; // Stop buying + } + } - // no weapon choosen to buy yet - and no preference - if (buy_weapon < 0) { - pBot->rprint("BotDecideWhatToBuy()", "Deciding which secondary weapon to buy"); - // Buy secondary - // Find weapon we can buy in the list of weapons - for (const weapon_price_table& i : weapons_table) - { - - // When enough money and the priority is high enough.. - // Filter out Secondary and Grenades - if (UTIL_GiveWeaponType(i.iId) != SECONDARY) - continue; + for (const weapon_price_table& i : weapons_table) { + if (UTIL_GiveWeaponType(i.iId) != SECONDARY) + continue; + + if (!GoodWeaponForTeam(i.iId, team)) + continue; - if (GoodWeaponForTeam(i.iId, team) == false) + if (i.price <= money) { + if (pBot->iSecondaryWeapon > -1) { + const int index = weapons_table[pBot->iSecondaryWeapon].iIdIndex; + if (weapons_table[index].priority >= i.priority) continue; + } - if (i.price <= money) { - if (pBot->iSecondaryWeapon > -1) { - const int index = - weapons_table[pBot->iSecondaryWeapon].iIdIndex; - // 31.08.04 Frashman > corrected to >= , - // else the bot will buy another weapon with the same priority - if (weapons_table[index].priority >= - i.priority) - continue; - } - - if (buy_weapon == -1) - buy_weapon = i.iId; - else { - if (RANDOM_LONG(0, 100) < i.priority) - buy_weapon = i.iId; - } - if (RANDOM_LONG(0, 100) < i.priority) - break; + if (buy_weapon == -1) { + buy_weapon = i.iId; + } + else { + if (RANDOM_LONG(0, 100) < i.priority) { + buy_weapon = i.iId; } } + if (RANDOM_LONG(0, 100) < i.priority) + break; } + } + return buy_weapon; +} - pBot->buy_secondary = false; - - // found a secondary weapon to buy - if (buy_weapon != -1) { - pBot->rprint("Found a secondary weapon to buy"); - } - } else if (pBot->buy_ammo_primary == true) { - pBot->rprint("BotDecideWhatToBuy()", "buy_ammo_primary"); - // Buy primary ammo - BotPrepareConsoleCommandsToBuyWeapon(pBot, "6", nullptr); - pBot->buy_ammo_primary = false; - return; +int BotBuyEquipment(cBot *pBot) { + const int money = pBot->bot_money; - } else if (pBot->buy_ammo_secondary == true) { - pBot->rprint("BotDecideWhatToBuy()", "buy_ammo_secondary"); - // Buy secondary ammo - BotPrepareConsoleCommandsToBuyWeapon(pBot, "7", nullptr); - pBot->buy_ammo_secondary = false; - return; - } else if (pBot->buy_defusekit) { - pBot->rprint("BotDecideWhatToBuy()", "buy_defusekit"); + if (pBot->buy_defusekit) { pBot->buy_defusekit = false; - if (money >= 200) { - buy_weapon = CS_DEFUSEKIT; - } - } else if (pBot->buy_armor) { - pBot->rprint("BotDecideWhatToBuy()", "buy_armor"); - if (money < 1000 && money >= 650) { - // Buy light armor - buy_weapon = CS_WEAPON_ARMOR_LIGHT; - } else if (money >= 1000) { - // Buy heavy armor - buy_weapon = CS_WEAPON_ARMOR_HEAVY; - } + if (money >= 200) return CS_DEFUSEKIT; + } + + if (pBot->buy_armor) { pBot->buy_armor = false; - } else if (pBot->buy_grenade) { - pBot->rprint("BotDecideWhatToBuy()", "buy_grenade"); - // Buy grenade - if (money >= weapons_table[ListIdWeapon(CS_WEAPON_HEGRENADE)].price) { - buy_weapon = CS_WEAPON_HEGRENADE; - } + if (money >= 1000) return CS_WEAPON_ARMOR_HEAVY; + if (money >= 650) return CS_WEAPON_ARMOR_LIGHT; + } + if (pBot->buy_grenade) { pBot->buy_grenade = false; - } else if (pBot->buy_flashbang > 0) { - pBot->rprint("BotDecideWhatToBuy()", "buy_flashbang"); - // Buy flashbang + if (money >= weapons_table[ListIdWeapon(CS_WEAPON_HEGRENADE)].price) return CS_WEAPON_HEGRENADE; + } + + if (pBot->buy_flashbang > 0) { if (money >= weapons_table[ListIdWeapon(CS_WEAPON_FLASHBANG)].price) { - buy_weapon = CS_WEAPON_FLASHBANG; pBot->buy_flashbang--; - } else { - pBot->buy_flashbang = 0; // do not buy - } - } else if (pBot->buy_smokegrenade) //31.08.04 Frashman added Smoke Grenade support - { - pBot->rprint("BotDecideWhatToBuy()", "buy_smokegrenade"); - // Buy SmokeGrenade - if (money >= weapons_table[ListIdWeapon(CS_WEAPON_SMOKEGRENADE)].price) { - buy_weapon = CS_WEAPON_SMOKEGRENADE; + return CS_WEAPON_FLASHBANG; } + pBot->buy_flashbang = 0; + } + if (pBot->buy_smokegrenade) { pBot->buy_smokegrenade = false; + if (money >= weapons_table[ListIdWeapon(CS_WEAPON_SMOKEGRENADE)].price) return CS_WEAPON_SMOKEGRENADE; + } + + return -1; +} + + +/* + BotDecideWhatToBuy() + + In this function the bot will choose what weapon to buy from the table. + */ +void BotDecideWhatToBuy(cBot *pBot) { + const int money = pBot->bot_money; + int buy_weapon = -1; + + if (pBot->buy_primary) { + buy_weapon = BotBuyPrimaryWeapon(pBot); + pBot->buy_primary = false; + + if (buy_weapon == -2) return; // Stop buying + + if (buy_weapon != -1) { + const int iMoneyLeft = money - PriceWeapon(buy_weapon); + if (iMoneyLeft >= 600 && (RANDOM_LONG(0, 100) < 15 || pBot->iPrimaryWeapon == CS_WEAPON_SHIELD)) { + pBot->buy_secondary = true; + } + } + } + else if (pBot->buy_secondary) { + buy_weapon = BotBuySecondaryWeapon(pBot); + pBot->buy_secondary = false; + if (buy_weapon == -2) return; + } + else if (pBot->buy_ammo_primary) { + BotPrepareConsoleCommandsToBuyWeapon(pBot, "6", nullptr); + pBot->buy_ammo_primary = false; + return; + } + else if (pBot->buy_ammo_secondary) { + BotPrepareConsoleCommandsToBuyWeapon(pBot, "7", nullptr); + pBot->buy_ammo_secondary = false; + return; + } + else { + buy_weapon = BotBuyEquipment(pBot); } // Perform the actual buy commands to acquire weapon - pBot->performBuyActions(buy_weapon); + if (buy_weapon != -1) { + pBot->performBuyActions(buy_weapon); + } } /* diff --git a/bot_func.cpp b/bot_func.cpp index eacee65..240a6fd 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "bot.h" #include "game.h" @@ -68,26 +69,17 @@ bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *c // When our check string is not "none" and the traceline has a hit... if (std::strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. - char entity_blocker[128]; - const edict_t *pent = tr.pHit; // Ok now retrieve the entity - std::strcpy(entity_blocker, STRING(pent->v.classname)); // the classname + const edict_t* pent = tr.pHit; // Ok now retrieve the entity + const std::string entity_blocker = STRING(pent->v.classname); // the classname - if (std::strcmp(entity_blocker, checkname) == 0) + if (entity_blocker == checkname) return true; // We are blocked by our string, this means its ok. - else { - return false; // We are blocked, but by something differernt then 'checkname' its not ok - } - } else { - // check if line of sight to object is not blocked (i.e. visible) - if (tr.flFraction >= 1.0f) - return true; - else - return false; + return false; // We are blocked, but by something differernt then 'checkname' its not ok } - //return false; - + // check if line of sight to object is not blocked (i.e. visible) + return tr.flFraction >= 1.0f; } bool VectorIsVisible(const Vector& start, const Vector& dest, const char *checkname) { @@ -99,33 +91,23 @@ bool VectorIsVisible(const Vector& start, const Vector& dest, const char *checkn // Als we geblokt worden EN we checken voor een naam if (std::strcmp("none", checkname) != 0 && tr.flFraction < 1.0f) { // Check if the blocking entity is same as checkname.. - char entity_blocker[128]; - const edict_t *pent = tr.pHit; // Ok now retrieve the entity - std::strcpy(entity_blocker, STRING(pent->v.classname)); // the classname + const edict_t* pent = tr.pHit; // Ok now retrieve the entity + const std::string entity_blocker = STRING(pent->v.classname); // the classname - if (std::strcmp(entity_blocker, checkname) == 0) + if (entity_blocker == checkname) return false; // We worden geblokt door die naam.. - else - return true; // We worden NIET geblokt door die naam (dus we worden niet geblokt). - - } else { - // check if line of sight to object is not blocked (i.e. visible) - // Als er NONE wordt opgegeven dan checken we gewoon of we worden geblokt - if (tr.flFraction >= 1.0f) - return true; - else - return false; + return true; // We worden NIET geblokt door die naam (dus we worden niet geblokt). } + // check if line of sight to object is not blocked (i.e. visible) + // Als er NONE wordt opgegeven dan checken we gewoon of we worden geblokt + return tr.flFraction >= 1.0f; } -float func_distance(Vector v1, Vector v2) { +float func_distance(const Vector& v1, const Vector& v2) { // Returns distance between 2 vectors - if (v1 && v2) - return (v1 - v2).Length(); - else - return 0.0f; + return (v1 - v2).Length(); } /** @@ -511,57 +493,13 @@ Vector FUNC_CalculateAngles(const cBot* pBot) { } bool BotShouldDuck(cBot *pBot) { - // temp - // TODO: Deal with this, is it good code? remove the other stuff below the return statement? - if (pBot->iDuckTries > 3) { // tried to duck 3 times, so no longer! pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); return false; } - - //return BotCanDuckUnder(pBot); //Makes the code underneath unreachable? [APG]RoboCop[CL] - - // When a bot should jump, something is blocking his way. - // Most of the time it is a fence, or a 'half wall' that reaches from body to feet - // However, the body most of the time traces above this wall. - // What i do: - // Trace line from head - // When head blocked and waist is free, then we should duck... - - TraceResult tr; - const edict_t *pEdict = pBot->pEdict; - - // convert current view angle to vectors for TraceLine math... - - Vector v_duck = FUNC_CalculateAngles(pBot); - v_duck.x = 0; // reset pitch to 0 (level horizontally) - v_duck.z = 0; // reset roll to 0 (straight up and down) - - UTIL_MakeVectors(v_duck); - // Check if head is blocked - Vector v_source = pEdict->v.origin + Vector(0, 0, +37); - Vector v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction >= 1.0f) - return false; - - v_source = pEdict->v.origin; - v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - if (tr.flFraction < 1.0f) - return false; - - return true; + return BotCanDuckUnder(pBot); } bool BotShouldDuckJump(cBot* pBot) //Experimental DuckJump Incomplete [APG]RoboCop[CL] @@ -657,30 +595,31 @@ bool FUNC_PlayerRuns(const int speed) { // return weapon type of edict. // only when 'important enough'. int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { + const std::string weaponModel = STRING(pEdict->v.weaponmodel); // sniper guns - //if (strcmp("models/p_awp.mdl", STRING(pEdict->v.weaponmodel)) == 0) //Excluded for high prices and accuracy [APG]RoboCop[CL] + //if (weaponModel == "models/p_awp.mdl") //Excluded for high prices and accuracy [APG]RoboCop[CL] // return CS_WEAPON_AWP; - if (std::strcmp("models/p_scout.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_scout.mdl") return CS_WEAPON_SCOUT; // good weapons (ak, m4a1, mp5) - if (std::strcmp("models/p_ak47.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_ak47.mdl") return CS_WEAPON_AK47; - if (std::strcmp("models/p_m4a1.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_m4a1.mdl") return CS_WEAPON_M4A1; - if (std::strcmp("models/p_mp5navy.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_mp5navy.mdl") return CS_WEAPON_MP5NAVY; // grenade types - if (std::strcmp("models/p_smokegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_smokegrenade.mdl") return CS_WEAPON_SMOKEGRENADE; - if (std::strcmp("models/p_hegrenade.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_hegrenade.mdl") return CS_WEAPON_HEGRENADE; - if (std::strcmp("models/p_flashbang.mdl", STRING(pEdict->v.weaponmodel)) == 0) + if (weaponModel == "models/p_flashbang.mdl") return CS_WEAPON_FLASHBANG; // shield types //Most CS Veterans dislikes the shield [APG]RoboCop[CL] - //if (strcmp("models/p_shield.mdl", STRING(pEdict->v.weaponmodel)) == 0) + //if (weaponModel == "models/p_shield.mdl") // return CS_WEAPON_SHIELD; // unknown @@ -1057,86 +996,71 @@ bool isHostageRescued(cBot* pBot, const edict_t* pHostage) //pBot not used [APG] int FUNC_GiveHostage(cBot* pBot) //Experimental [APG]RoboCop[CL] { - if (pBot->isTerrorist()) { - return 0; - } - - // find a hostage to rescue - edict_t *pHostage = pBot->getHostageToRescue(); - - if (pHostage == nullptr) { - pHostage = pBot->findHostageToRescue(); - } - - // still NULL - if (pHostage == nullptr) { - // Note: this means a hostage that is near and visible and rescueable etc. - return 0; // nothing to do yet - } - - // Whenever we have a hostage to go after, verify it is still rescueable - const bool isRescueable = isHostageRescueable(pBot, pHostage); - - if (!isRescueable) { - pBot->rprint_trace("GiveHostage", "Hostage found, but not rescueable, forgetting..."); - pBot->forgetHostage(pHostage); - return 0; - } - pBot->rprint_trace("GiveHostage", "Remembering hostage (target) to rescue"); - pBot->rememberWhichHostageToRescue(pHostage); - - // Prevent bots getting to close here - const float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); - - // From here, we should get the hostage when still visible - if (pBot->canSeeEntity(pHostage)) - { - pBot->rprint_trace("GiveHostage", "I can see the hostage to rescue!"); - // set body to hostage! - pBot->vBody = pBot->vHead = pHostage->v.origin + Vector(0, 0, 36); - // by default run - pBot->setMoveSpeed(pBot->f_max_speed); - - if (distanceToHostage <= 80.0f) - { - pBot->rprint_trace("GiveHostage", "I can see hostage AND really close!"); - pBot->setMoveSpeed(0.0f); // too close, do not move - } + if (pBot->isTerrorist()) { + return 0; } - return 1; //gives any hostage we still have to go for -} -bool isHostageRescueable(cBot *pBot, edict_t *pHostage) { - if (pHostage == nullptr) return false; -// pBot->rprint("isHostageRescueable"); + // find a hostage to rescue + edict_t* pHostage = pBot->getHostageToRescue(); - // Already rescued? - if (isHostageRescued(pBot, pHostage)) { - return false; + if (pHostage == nullptr) { + pHostage = pBot->findHostageToRescue(); } - // dead - if (!FUNC_EdictIsAlive(pHostage)) { - return false; + // still NULL + if (pHostage == nullptr) { + // Note: this means a hostage that is near and visible and rescueable etc. + return 0; // nothing to do yet } - // Already moving? (used by human player?) - if (FUNC_PlayerSpeed(pHostage) > 2) { - return false; + // Whenever we have a hostage to go after, verify it is still rescueable + const bool isRescueable = isHostageRescueable(pBot, pHostage); + + if (!isRescueable) { + pBot->rprint_trace("GiveHostage", "Hostage found, but not rescueable, forgetting..."); + pBot->forgetHostage(pHostage); + return 0; } - // Already used by bot? - - if (pBot != nullptr) { - // rblog("isHostageRescueable - pBot is != NULL\n"); - if (pBot->isUsingHostage(pHostage)) return false; - // Is the hostage not used by *any other* bot? - if (!isHostageFree(pBot, pHostage)) { - rblog("isHostageRescueable - Hostage is not free"); - return false; + pBot->rprint_trace("GiveHostage", "Remembering hostage (target) to rescue"); + pBot->rememberWhichHostageToRescue(pHostage); + + // Prevent bots getting to close here + const float distanceToHostage = func_distance(pBot->pEdict->v.origin, pHostage->v.origin); + + // From here, we should get the hostage when still visible + if (pBot->canSeeEntity(pHostage)) + { + pBot->rprint_trace("GiveHostage", "I can see the hostage to rescue!"); + // set body to hostage! + pBot->vBody = pBot->vHead = pHostage->v.origin + Vector(0, 0, 36); + // by default run + pBot->setMoveSpeed(pBot->f_max_speed); + + if (distanceToHostage <= 80.0f) + { + pBot->rprint_trace("GiveHostage", "I can see hostage AND really close!"); + pBot->setMoveSpeed(0.0f); // too close, do not move } } + return 1; //gives any hostage we still have to go for +} + +bool isHostageRescueable(cBot* pBot, edict_t* pHostage) { + if (pHostage == nullptr || pBot == nullptr) { + return false; + } + + // A hostage is not rescueable if it has already been rescued, is dead, + // is already being moved by a human player, or is being rescued by another bot. + if (isHostageRescued(pBot, pHostage) || + !FUNC_EdictIsAlive(pHostage) || + FUNC_PlayerSpeed(pHostage) > 2 || + pBot->isUsingHostage(pHostage) || + !isHostageFree(pBot, pHostage)) { + return false; + } - // yes we can rescue this hostage + // If all checks pass, the hostage is rescueable return true; } diff --git a/bot_func.h b/bot_func.h index 7535777..f1eefda 100644 --- a/bot_func.h +++ b/bot_func.h @@ -119,6 +119,12 @@ bool GoodWeaponForTeam(int weapon, int team); void BotConsole(cBot* pBot); void BotDecideWhatToBuy(cBot* pBot); + +// Buying sub-functions +int BotBuyPrimaryWeapon(cBot* pBot); +int BotBuySecondaryWeapon(cBot* pBot); +int BotBuyEquipment(cBot* pBot); + void rblog(const char* txt); // bot.cpp diff --git a/bot_navigate.cpp b/bot_navigate.cpp index f7d5a91..3eb63ec 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -85,7 +85,35 @@ bool traceLine(const Vector& v_source, const Vector& v_dest, const edict_t* pEdi return tr.flFraction >= 1.0f; } -bool BotCanJumpUp(const cBot* pBot) { +// Helper function to perform a series of traces (center, left, right) +bool traceArea(const edict_t* pEdict, const Vector& base_source, const Vector& forward, const Vector& right, const bool check_hit) { + TraceResult tr; + + // Center trace + if (traceLine(base_source, base_source + forward, pEdict, tr) == check_hit) return false; + + // Left trace + Vector left_source = base_source - right * BODY_SIDE_OFFSET; + if (traceLine(left_source, left_source + forward, pEdict, tr) == check_hit) return false; + + // Right trace + Vector right_source = base_source + right * BODY_SIDE_OFFSET; + if (traceLine(right_source, right_source + forward, pEdict, tr) == check_hit) return false; + + return true; +} + +// Helper function to set up vectors for movement checks +void setupMovementVectors(const edict_t* pEdict, Vector& forward, Vector& right) { + Vector angle = pEdict->v.v_angle; + angle.x = 0; + angle.z = 0; + UTIL_MakeVectors(angle); + forward = gpGlobals->v_forward; + right = gpGlobals->v_right; +} + +bool BotCanJumpUp(cBot *pBot) { // What I do here is trace 3 lines straight out, one unit higher than // the highest normal jumping distance. I trace once at the center of // the body, once at the right side, and once at the left side. If all @@ -97,110 +125,22 @@ bool BotCanJumpUp(const cBot* pBot) { // to catch most of the problems with falsely trying to jump on something // that the bot can not get onto. - TraceResult tr; const edict_t* pEdict = pBot->pEdict; + Vector v_forward, v_right; + setupMovementVectors(pEdict, v_forward, v_right); - // convert current view angle to vectors for TraceLine math... - - Vector v_jump = pEdict->v.v_angle; - v_jump.x = 0; // reset pitch to 0 (level horizontally) - v_jump.z = 0; // reset roll to 0 (straight up and down) - - UTIL_MakeVectors(v_jump); - - // use center of the body first... - - // maximum jump height is 45, so check one unit above that (46) - Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT); - Vector v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, - -36 + MAX_JUMPHEIGHT); - v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) + // Horizontal check at jump height + Vector v_source_horizontal = pEdict->v.origin + Vector(0, 0, STAND_VIEW_HEIGHT_OFFSET + MAX_JUMPHEIGHT); + if (!traceArea(pEdict, v_source_horizontal, v_forward * FORWARD_CHECK_DISTANCE, v_right, true)) { return false; + } - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, - -36 + MAX_JUMPHEIGHT); - v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at maximum jump height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now trace from head level downward to check for obstructions... - - // start of trace is 24 units in front of bot, 72 units above head... - v_source = pEdict->v.origin + gpGlobals->v_forward * 24; - - // offset 72 units from top of head (72 + 36) - v_source.z = v_source.z + 108; - - // end point of trace is 99 units straight down from start... - // (99 is 108 minus the jump limit height which is 45 - 36 = 9) - // fix by stefan, max jump height is 63 , not 45! (using duckjump) - // 108 - (63-36) = 81 - v_dest = v_source + Vector(0, 0, -81); - - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z + 108; - v_dest = v_source + Vector(0, 0, -81); - - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z + 108; - v_dest = v_source + Vector(0, 0, -81); - - // trace a line straight down toward the ground... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) + // Vertical check for head clearance + Vector v_source_vertical = pEdict->v.origin + v_forward * FORWARD_CHECK_DISTANCE; + v_source_vertical.z += HEAD_CLEARANCE_CHECK_HEIGHT; + if (!traceArea(pEdict, v_source_vertical, Vector(0, 0, JUMP_CLEARANCE_CHECK_DROP), v_right, true)) { return false; + } return true; } @@ -214,104 +154,22 @@ bool BotCanDuckUnder(cBot* pBot) { // sure that there is something blocking the TraceLine. Then we know // we can duck under it. - TraceResult tr; const edict_t* pEdict = pBot->pEdict; + Vector v_forward, v_right; + setupMovementVectors(pEdict, v_forward, v_right); - // convert current view angle to vectors for TraceLine math... - - Vector v_duck = pEdict->v.v_angle; - v_duck.x = 0; // reset pitch to 0 (level horizontally) - v_duck.z = 0; // reset roll to 0 (straight up and down) - - UTIL_MakeVectors(v_duck); - - // use center of the body first... - - // duck height is 36, so check one unit above that (37) - Vector v_source = pEdict->v.origin + Vector(0, 0, -36 + 37); - Vector v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) + // Horizontal check at duck height + Vector v_source_horizontal = pEdict->v.origin + Vector(0, 0, DUCK_VIEW_HEIGHT_OFFSET + DUCK_HEIGHT + 1); + if (!traceArea(pEdict, v_source_horizontal, v_forward * FORWARD_CHECK_DISTANCE, v_right, true)) { return false; + } - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37); - v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0, - -36 + 37); - v_dest = v_source + gpGlobals->v_forward * 24; - - // trace a line forward at duck height... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace hit something, return FALSE - if (tr.flFraction < 1.0f) - return false; - - // now trace from the ground up to check for object to duck under... - - // start of trace is 24 units in front of bot near ground... - v_source = pEdict->v.origin + gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up - - // end point of trace is 72 units straight up from start... - v_dest = v_source + Vector(0, 0, 72); - - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) - return false; - - // now check same height to one side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * 16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up - v_dest = v_source + Vector(0, 0, 72); - - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) - return false; - - // now check same height on the other side of the bot... - v_source = - pEdict->v.origin + gpGlobals->v_right * -16 + - gpGlobals->v_forward * 24; - v_source.z = v_source.z - 35; // offset to feet + 1 unit up - v_dest = v_source + Vector(0, 0, 72); - - // trace a line straight up in the air... - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); - - // if trace didn't hit something, return FALSE - if (tr.flFraction >= 1.0f) + // Vertical check for something to duck under + Vector v_source_vertical = pEdict->v.origin + v_forward * FORWARD_CHECK_DISTANCE; + v_source_vertical.z += FEET_OFFSET; + if (!traceArea(pEdict, v_source_vertical, Vector(0, 0, DUCK_CLEARANCE_CHECK_RISE), v_right, false)) { return false; + } return true; } @@ -375,37 +233,23 @@ void adjustPathIfBlocked(cBot* pBot) { } } -bool performTrace(const Vector& v_source, const Vector& v_dest, edict_t* pEntity, TraceResult& tr) { - UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters, pEntity, &tr); - - return tr.flFraction >= 1.0f; -} - -bool isPathClear(const cBot* pBot, const Vector& v_dest) { +void BotNavigate(cBot* pBot) { if (!pBot || !pBot->pEdict) { - return false; // Invalid input, assume path is not clear - } - TraceResult tr; - - return performTrace(pBot->pEdict->v.origin, v_dest, pBot->pEdict->v.pContainingEntity, tr); -} - -void BotNavigate(const cBot* pBot) { - if (!pBot) { return; } // Avoid clustering with other bots avoidClustering(pBot); - // Adjust path if blocked - adjustPathIfBlocked(pBot); - - // Check if the path is clear before moving + // Check if the path is blocked and adjust angle if necessary Vector v_dest = pBot->pEdict->v.origin + gpGlobals->v_forward * MOVE_DISTANCE; + if (isPathBlocked(pBot, v_dest)) { + adjustBotAngle(pBot, TURN_ANGLE); + v_dest = pBot->pEdict->v.origin + gpGlobals->v_forward * MOVE_DISTANCE; // Recalculate destination + } + // If the path is clear, move the bot if (!isPathBlocked(pBot, v_dest)) { - // Move the bot pBot->pEdict->v.origin = v_dest; } } \ No newline at end of file diff --git a/engine.cpp b/engine.cpp index ea8b279..bbffa34 100644 --- a/engine.cpp +++ b/engine.cpp @@ -33,6 +33,8 @@ #include #include #include +#include + #include "bot.h" #include "bot_client.h" @@ -388,6 +390,13 @@ void pfnWriteCoord(float flValue) { } void pfnWriteString(const char *sz) { + if (sz == nullptr) + { + if (Game.bEngineDebug) + rblog("ENGINE: pfnWriteString() - sz is null\n"); + RETURN_META(MRES_IGNORED); + } + if (Game.bEngineDebug) { char msg[256]; snprintf(msg, sizeof(msg), "ENGINE: pfnWriteByte() - '%s'\n", sz); @@ -396,123 +405,50 @@ void pfnWriteString(const char *sz) { if (gpGlobals->deathmatch) { // Ditlew's Radio - if (sz != nullptr && std::strstr(sz, "(RADIO):") != nullptr && !radio_message) { - // We found an old radio message, we should convert the strings... - radio_message = true; // we found a radio message - - // Thank god Ditlew you already coded this... - const char* radio_ptr = std::strstr(sz, " (RADIO)"); - if (radio_ptr != nullptr) { - const unsigned length = std::strlen(sz) - std::strlen(radio_ptr); - std::strncpy(radio_messenger, sz, length); + std::string_view sz_sv(sz); + if (sz_sv.find("(RADIO):") != std::string_view::npos && !radio_message) { + radio_message = true; + + if (size_t radio_ptr_pos = sz_sv.find(" (RADIO)"); radio_ptr_pos != std::string_view::npos) { + std::string_view messenger_sv = sz_sv.substr(0, radio_ptr_pos); + strncpy(radio_messenger, messenger_sv.data(), messenger_sv.length()); + radio_messenger[messenger_sv.length()] = '\0'; } - // Now search for any compatible radio command (old string). - // if found then convert the message in the new way so the code - // thinks its CS 1.1 and thus every version lower then CS 1.1 should work too... - if (std::strstr(sz, "Follow Me") != nullptr) { - std::strcpy(message, "#Follow me"); + if (sz_sv.find("Follow Me") != std::string_view::npos) { + strcpy(message, "#Follow me"); } - else if (std::strstr(sz, "You Take the Point") != nullptr) { - std::strcpy(message, "#You_take_the_point"); + else if (sz_sv.find("You Take the Point") != std::string_view::npos) { + strcpy(message, "#You_take_the_point"); } - else if (std::strstr(sz, "Need backup") != nullptr) { - std::strcpy(message, "#Need_backup"); + else if (sz_sv.find("Need backup") != std::string_view::npos) { + strcpy(message, "#Need_backup"); } - else if (std::strstr(sz, "Enemy spotted") != nullptr) { - std::strcpy(message, "#Enemy_spotted"); + else if (sz_sv.find("Enemy spotted") != std::string_view::npos) { + strcpy(message, "#Enemy_spotted"); } - else if (std::strstr(sz, "Taking Fire.. Need Assistance!") != nullptr) { - std::strcpy(message, "#Taking_fire"); + else if (sz_sv.find("Taking Fire.. Need Assistance!") != std::string_view::npos) { + strcpy(message, "#Taking_fire"); } - else if (std::strstr(sz, "Team, fall back!") != nullptr) { - std::strcpy(message, "#Team_fall_back"); + else if (sz_sv.find("Team, fall back!") != std::string_view::npos) { + strcpy(message, "#Team_fall_back"); } - else if (std::strstr(sz, "Go go go") != nullptr) { - std::strcpy(message, "#Go_go_go"); + else if (sz_sv.find("Go go go") != std::string_view::npos) { + strcpy(message, "#Go_go_go"); } } - /* - else - { - - // normal text message - if (strstr(sz, " : ")) - { - - // Get sender - // Thank god Ditlew you already coded this... - int length = strlen (sz) - strlen (strstr (sz, " : ")); - - char messenger[30]; - char chMessage[80]; - for (int clear=0; clear < 80; clear ++) - { - if (clear < 30) - messenger[clear]='\0'; - - chMessage[clear]='\0'; - } - - // Find the sender (old fasioned way) - int iM=0; - bool SkippedFirst=false; - for (int scan=1; scan < 80; scan++) - { - if (sz[scan] == ':') - { - // now cut one from the messenger - //messenger[iM] = '\0'; - length=scan-1; - scan++; - break; - } - else if (sz[scan] != ' ' && SkippedFirst) - { - //messenger[iM] = sz[scan]; - iM++; - } - else if (sz[scan] == ' ') - { - if(SkippedFirst==false) - SkippedFirst=true; - else - { - // messenger[iM] = sz[scan]; - iM++; - } - } - } - - strncpy (messenger, sz, length); - SERVER_PRINT("MESSENGER:"); - SERVER_PRINT(messenger); - - - - // Everything else is just the sentence: - int chM=0; - for (scan; scan < 80; scan++) - { - chMessage[chM] = sz[scan]; - chM++; - } - - - ChatEngine.set_sentence(messenger, chMessage); - - } - } - */ + if (radio_message_start) { std::strcpy(radio_messenger, sz); radio_message_start = false; radio_message_from = true; - } else if (radio_message_from) { - std::strcpy(message, sz); // copy message and handle at bot.cpp radio routine. + } + else if (radio_message_from) { + std::strcpy(message, sz); radio_message = true; radio_message_from = false; - } else if (std::strcmp(sz, "#Game_radio") == 0) { + } + else if (sz_sv == "#Game_radio") { radio_message_start = true; } diff --git a/game.cpp b/game.cpp index 7b5e4b1..f47dd4a 100644 --- a/game.cpp +++ b/game.cpp @@ -31,6 +31,12 @@ #include #include +#include +#include +#include +#include +#include + #include #include #include @@ -96,22 +102,24 @@ void cGame::Init() { bPistols = false; // pistols only mode // Speech sentences (from POD and a *few* own made) - std::strcpy(cSpeechSentences[0], "hello user,communication is acquired"); - std::strcpy(cSpeechSentences[1], "your presence is acknowledged"); - std::strcpy(cSpeechSentences[2], "high man, your in command now"); - std::strcpy(cSpeechSentences[3], "blast your hostile for good"); - std::strcpy(cSpeechSentences[4], "high man, kill some idiot here"); - std::strcpy(cSpeechSentences[5], "is there a doctor in the area"); - std::strcpy(cSpeechSentences[6], "warning, experimental materials detected"); - std::strcpy(cSpeechSentences[7], "high amigo, shoot some but"); - std::strcpy(cSpeechSentences[8], "attention, hours of work software, detected"); - std::strcpy(cSpeechSentences[9], "time for some bad ass explosion"); - std::strcpy(cSpeechSentences[10], "bad ass son of a breach device activated"); - std::strcpy(cSpeechSentences[11], "high, do not question this great service"); - std::strcpy(cSpeechSentences[12], "engine is operative, hello and goodbye"); - std::strcpy(cSpeechSentences[13], "high amigo, your administration has been great last day"); - std::strcpy(cSpeechSentences[14], "attention, expect experimental armed hostile presence"); - std::strcpy(cSpeechSentences[15], "warning,medical attention required"); + cSpeechSentences = { { + "hello user,communication is acquired", + "your presence is acknowledged", + "high man, your in command now", + "blast your hostile for good", + "high man, kill some idiot here", + "is there a doctor in the area", + "warning, experimental materials detected", + "high amigo, shoot some but", + "attention, hours of work software, detected", + "time for some bad ass explosion", + "bad ass son of a breach device activated", + "high, do not question this great service", + "engine is operative, hello and goodbye", + "high amigo, your administration has been great last day", + "attention, expect experimental armed hostile presence", + "warning,medical attention required" + } }; InitNewRound(); } // Init() @@ -159,8 +167,9 @@ bool cGame::isPlantedC4Discovered() const } // Returns random sentence for speech -char *cGame::RandomSentence() { - return cSpeechSentences[RANDOM_LONG(0, 15)]; +const char* cGame::RandomSentence() const +{ + return cSpeechSentences[RANDOM_LONG(0, cSpeechSentences.size() - 1)].c_str(); } void cGame::DetermineMapGoal() @@ -189,7 +198,6 @@ void cGame::DetermineMapGoal() rescueZonesFound++; } - std::memset(msg, 0, sizeof(msg)); snprintf(msg, sizeof(msg), "DetermineMapGoal: There are %d rescue zones found\n", rescueZonesFound); rblog(msg); Game.bHostageRescueZoneFound = rescueZonesFound > 0; @@ -205,7 +213,6 @@ void cGame::DetermineMapGoal() while ((pEnt = UTIL_FindEntityByClassname(pEnt, "info_bomb_target")) != nullptr) { bombSpots++; } - std::memset(msg, 0, sizeof(msg)); snprintf(msg, sizeof(msg), "DetermineMapGoal: There are %d bomb spots in this level\n", bombSpots); Game.bBombPlantMap = bombSpots > 0; rblog(msg); @@ -284,107 +291,70 @@ void cGame::LoadCFG() { } // LoadCFG() // GAME: Load names file -// NOTE: This function is just a copy/paste stuff from Botmans template, nothing more, nothing less -// TODO: Rewrite this, can be done much cleaner. void cGame::LoadNames() { - char filename[256]; + char filename[256]; UTIL_BuildFileNameRB("rb_names.txt", filename); - FILE* bot_name_fp = std::fopen(filename, "r"); - if (bot_name_fp != nullptr) { - char name_buffer[80]; - while (iAmountNames < MAX_BOT_NAMES && - std::fgets(name_buffer, 80, bot_name_fp) != nullptr) { - int length = static_cast(std::strlen(name_buffer)); - if (length > 0 && name_buffer[length - 1] == '\n') { - name_buffer[length - 1] = 0; // remove '\n' - length--; - } - int str_index = 0; - while (str_index < length) { - if (name_buffer[str_index] < ' ' - || name_buffer[str_index] > '~' - || name_buffer[str_index] == '"') - for (int index = str_index; index < length; index++) - name_buffer[index] = name_buffer[index + 1]; - str_index++; - } + std::ifstream file(filename); + if (!file.is_open()) { + return; + } - if (name_buffer[0] != 0) { - std::strncpy(cBotNames[iAmountNames], name_buffer, BOT_NAME_LEN); - iAmountNames++; - } + cBotNames.clear(); + std::string line; + while (std::getline(file, line) && cBotNames.size() < MAX_BOT_NAMES) { + // Trim whitespace and remove invalid characters + line.erase(line.find_last_not_of(" \n\r\t") + 1); + line.erase(0, line.find_first_not_of(" \n\r\t")); + line.erase(std::remove_if(line.begin(), line.end(), [](const char c) { + return c < ' ' || c > '~' || c == '"'; + }), line.end()); + + if (!line.empty()) { + cBotNames.push_back(line); } - std::fclose(bot_name_fp); } + iAmountNames = cBotNames.size(); } // LoadNames() // Any names available? bool cGame::NamesAvailable() const { - if (iAmountNames > 0) - return true; - - return false; + return !cBotNames.empty(); } // NamesAvailable() // Picks a random name // rewritten on april 10th 2004 -void cGame::SelectName(char *name) const +std::string cGame::SelectName() const { - int iNameIndex = 0; // zero based (RANDOM_LONG (0, iAmountNames-1)) - - bool iNameUsed[MAX_BOT_NAMES]; - for (bool& i : iNameUsed) - { - i = false; + if (cBotNames.empty()) { + return "RealBot"; } - // check make sure this name isn't used - bool bUsed = true; - while (bUsed) { - iNameIndex = RANDOM_LONG(0, iAmountNames - 1); // pick random one - const int iLimit = iNameIndex; // remember this. - - // make sure it is not checked yet - while (iNameUsed[iNameIndex]) { - - // add up - iNameIndex++; - - // make sure that it does not check out of range - if (iNameIndex == iAmountNames) - iNameIndex = 0; // go to 0 (will be set to 0 next 'name') - - // when we are back to where we came from, get the fuck outta here - if (iNameIndex == iLimit) { - std::strcpy(name, "RealBot"); - return; - } + // Get all names of players currently in the game. + std::vector usedNames; + for (int i = 1; i <= gpGlobals->maxClients; i++) { + const edict_t* pPlayer = INDEXENT(i); + if (pPlayer && !pPlayer->free) { + usedNames.emplace_back(STRING(pPlayer->v.netname)); } + } - // so far we did not find evidence that this name has been used already - bUsed = false; - - // check if this name is used - for (int iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - const edict_t* pPlayer = INDEXENT(iIndex); - if (pPlayer && !pPlayer->free) { - if (std::strcmp(cBotNames[iNameIndex], STRING(pPlayer->v.netname)) - == 0) { - // attention, this name has been used. - bUsed = true; - break; - } + // Find a name that is not in use. + for (const std::string& botName : cBotNames) { + bool isNameInUse = false; + for (const std::string& usedName : usedNames) { + if (botName == usedName) { + isNameInUse = true; + break; } } - if (bUsed) - iNameUsed[iNameIndex] = true; // set on true - + if (!isNameInUse) { + return botName; + } } - // copy name into the name_buffer - std::strcpy(name, cBotNames[iNameIndex]); + return "RealBot"; // Fallback if all names are taken } // SelectName() // GAME: Load BUYTABLE.INI file @@ -474,32 +444,27 @@ int cGame::createBot(edict_t* pPlayer, const char* teamArg, const char* skillArg { // NAME - char botName[BOT_NAME_LEN + 1] = {}; - // if name given, use that + std::string botNameStr; if (nameArg != nullptr && *nameArg != 0) { - std::strncpy(botName, nameArg, BOT_NAME_LEN - 1); - botName[BOT_NAME_LEN] = 0; // make sure botName is null terminated - } else { // else pick random one or fallback to default "RealBot" - if (NamesAvailable()) { - SelectName(botName); - } else { - std::strcpy(botName, "RealBot"); - } + botNameStr = nameArg; + } + else { + botNameStr = SelectName(); } - // length of name - int lengthOfBotName = static_cast(std::strlen(botName)); + // Sanitize name + botNameStr.erase(std::remove_if(botNameStr.begin(), botNameStr.end(), [](const char c) { + return c <= ' ' || c > '~' || c == '"'; + }), botNameStr.end()); - for (int i = 0; i < lengthOfBotName; i++) { - if ((botName[i] <= ' ') || (botName[i] > '~') || (botName[i] == '"')) { - // move chars to the left (and null) - for (int j = i; j < lengthOfBotName; j++) { - botName[j] = botName[j + 1]; - } - lengthOfBotName--; - } + if (botNameStr.length() > BOT_NAME_LEN) { + botNameStr.resize(BOT_NAME_LEN); } + char botName[BOT_NAME_LEN + 1]; + std::strncpy(botName, botNameStr.c_str(), BOT_NAME_LEN); + botName[BOT_NAME_LEN] = '\0'; + int botSkill = -2; // -2, not valid // Skill argument provided @@ -517,6 +482,9 @@ int cGame::createBot(edict_t* pPlayer, const char* teamArg, const char* skillArg botSkill = RANDOM_LONG(iRandomMinSkill, iRandomMaxSkill); } + // Clamp skill value between 0 and 10 + botSkill = std::clamp(botSkill, 0, 10); + // CREATE fake client! edict_t *pBotEdict = (*g_engfuncs.pfnCreateFakeClient)(botName); if (FNullEnt(pBotEdict)) { @@ -658,37 +626,24 @@ void REALBOT_PRINT(const char* Function, const char* msg) { // Debug message void REALBOT_PRINT(cBot *pBot, const char *Function, const char *msg) { - char cMessage[512]; - char team[9]; - char name[MAX_NAME_LENGTH]; - char mapName[32]; + std::string team = "NONE"; + std::string name = "FUNCTION"; + std::string mapName = "NA"; int botIndex = -1; - std::memset(team, 0, sizeof(team)); // clear - std::memset(name, 0, sizeof(name)); // clear - std::memset(mapName, 0, sizeof(mapName)); // clear - - std::strcpy(team, "NONE"); - std::strcpy(name, "FUNCTION"); - if (gpGlobals->mapname) { - std::strcpy(mapName, STRING(gpGlobals->mapname)); - } else { - std::strcpy(mapName, "NA"); + mapName = STRING(gpGlobals->mapname); } if (pBot) { botIndex = pBot->iBotIndex; - std::memset(name, 0, sizeof(name)); // clear - - //TODO: To use std:string for this [APG]RoboCop[CL] - std::strncpy(name, pBot->name, sizeof(name)); - name[sizeof(name) - 1] = '\0'; + name = pBot->name; if (pBot->isCounterTerrorist()) { - std::strcpy(team, "COUNTER"); - } else if (pBot->isTerrorist()) { - std::strcpy(team, "TERROR"); + team = "COUNTER"; + } + else if (pBot->isTerrorist()) { + team = "TERROR"; } } diff --git a/game.h b/game.h index 6e947cc..04a2826 100644 --- a/game.h +++ b/game.h @@ -69,86 +69,86 @@ void REALBOT_PRINT(const char* Function, const char* msg); class cGame { public: - void Init(); - void InitNewRound(); - - // --------------------- - void LoadNames(); - static void LoadCFG(); - static void LoadBuyTable(); - - // --------------------- - void SelectName(char *name) const; - bool NamesAvailable() const; - void SetPlayingRounds(int iMin, int iMax); - void SetNewRound(bool bState); - void resetRoundTime(); - void SetRoundTime(float fTime); - static void DetermineMapGoal(); - - // --------------------- - char *RandomSentence(); - - // --------------------- - int GetMinPlayRounds() const; - int GetMaxPlayRounds() const; - - bool NewRound() const; // New round? - float getRoundStartedTime() const; // When did the round start? (time) - float getRoundTimeElapsed() const; // difference between now and round started time - - int createBot(edict_t * pPlayer, const char *teamArg, const char *skillArg, - const char *modelArg, const char *nameArg) const; - - // --------------------- - void UpdateGameStatus(); // Updates global game variables - bool isC4Dropped() const; - bool isPlantedC4Discovered() const; - - // --------------------- - // public variables - int iDefaultBotSkill; - int iRandomMinSkill; - int iRandomMaxSkill; - int iOverrideBotSkill; // Override "game botskill" with personality skill? - float fWalkWithKnife; // May bots walk with knife - - // Game related variables: - Vector vDroppedC4; // Dropped C4? - bool bBombPlanted; // Bomb planted? - bool bHostageRescueMap; // Hostage rescue map? (CS_...) - bool bHostageRescueZoneFound; // Is any rescue zone found? (CS_...) - bool bBombPlantMap; // Bomb plant map? (DE_...) - Vector vPlantedC4; // Is the bomb discovered? - - // Server vars - int iVersionBroadcasting; // 0 = every round , 1 = every new map - int iKillsBroadcasting; // 0 = full, 1 = min, 2 = none - int iDeathsBroadcasting; // 0 = full, 1 = min, 2 = none - bool bInstalledCorrectly; // false = RB is not in the correct directory - bool bSpeechBroadcasting; // true/false - - // DEBUG variables - bool bDoNotShoot; // Bots not shooting - int bDebug; // Print debug messages (if > -1, it prints messages for bot index...) - int messageVerbosity; // Print debug messages (verbosity) - bool bEngineDebug; // Print engine debug messages - bool bPistols; // 30/07/04 by Josh: bots will only use pistols - - // ChatEngine related - int iMaxSentences; // how many sentences may there be at max? - int iProducedSentences; + void Init(); + void InitNewRound(); + + // --------------------- + void LoadNames(); + static void LoadCFG(); + static void LoadBuyTable(); + + // --------------------- + std::string SelectName() const; + bool NamesAvailable() const; + void SetPlayingRounds(int iMin, int iMax); + void SetNewRound(bool bState); + void resetRoundTime(); + void SetRoundTime(float fTime); + static void DetermineMapGoal(); + + // --------------------- + const char* RandomSentence() const; + + // --------------------- + int GetMinPlayRounds() const; + int GetMaxPlayRounds() const; + + bool NewRound() const; // New round? + float getRoundStartedTime() const; // When did the round start? (time) + float getRoundTimeElapsed() const; // difference between now and round started time + + int createBot(edict_t* pPlayer, const char* teamArg, const char* skillArg, + const char* modelArg, const char* nameArg) const; + + // --------------------- + void UpdateGameStatus(); // Updates global game variables + bool isC4Dropped() const; + bool isPlantedC4Discovered() const; + + // --------------------- + // public variables + int iDefaultBotSkill; + int iRandomMinSkill; + int iRandomMaxSkill; + int iOverrideBotSkill; // Override "game botskill" with personality skill? + float fWalkWithKnife; // May bots walk with knife + + // Game related variables: + Vector vDroppedC4; // Dropped C4? + bool bBombPlanted; // Bomb planted? + bool bHostageRescueMap; // Hostage rescue map? (CS_...) + bool bHostageRescueZoneFound; // Is any rescue zone found? (CS_...) + bool bBombPlantMap; // Bomb plant map? (DE_...) + Vector vPlantedC4; // Is the bomb discovered? + + // Server vars + int iVersionBroadcasting; // 0 = every round , 1 = every new map + int iKillsBroadcasting; // 0 = full, 1 = min, 2 = none + int iDeathsBroadcasting; // 0 = full, 1 = min, 2 = none + bool bInstalledCorrectly; // false = RB is not in the correct directory + bool bSpeechBroadcasting; // true/false + + // DEBUG variables + bool bDoNotShoot; // Bots not shooting + int bDebug; // Print debug messages (if > -1, it prints messages for bot index...) + int messageVerbosity; // Print debug messages (verbosity) + bool bEngineDebug; // Print engine debug messages + bool bPistols; // 30/07/04 by Josh: bots will only use pistols + + // ChatEngine related + int iMaxSentences; // how many sentences may there be at max? + int iProducedSentences; private: - // --------------------- - // private variables - char cSpeechSentences[16][80] = {}; - int iAmountNames = 0; - char cBotNames[MAX_BOT_NAMES][BOT_NAME_LEN + 1] = {}; - int iMinPlayRounds = 0, iMaxPlayRounds = 0; // Min/Max playable rounds - bool bNewRound = false; // New round triggered? - float fRoundTime = 0.0f; // Round time - float fUpdateGoalTimer = 0.0f; + // --------------------- + // private variables + std::array cSpeechSentences; + int iAmountNames = 0; + std::vector cBotNames; + int iMinPlayRounds = 0, iMaxPlayRounds = 0; // Min/Max playable rounds + bool bNewRound = false; // New round triggered? + float fRoundTime = 0.0f; // Round time + float fUpdateGoalTimer = 0.0f; }; #endif // GAME_H \ No newline at end of file From 8e914a30740198774f0c2ee0ca942002633575df Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sun, 14 Sep 2025 16:00:28 +0100 Subject: [PATCH 105/114] Small tweaks --- bot.cpp | 2 +- bot_func.cpp | 4 ++-- bot_func.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot.cpp b/bot.cpp index 2181d81..09565db 100644 --- a/bot.cpp +++ b/bot.cpp @@ -3467,7 +3467,7 @@ bool cBot::isEscortingHostages() { void cBot::checkOfHostagesStillFollowMe() { if (fCheckHostageStatusTimer > gpGlobals->time) return; - fCheckHostageStatusTimer = gpGlobals->time + 5; + fCheckHostageStatusTimer = gpGlobals->time + 5.0f; //// this->rprint("checkOfHostagesStillFollowMe - START"); // if (hostage1) { diff --git a/bot_func.cpp b/bot_func.cpp index 240a6fd..cc80cd9 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -747,7 +747,7 @@ void FUNC_HearingTodo(cBot* pBot) { pBot->f_hold_duck = gpGlobals->time + etime; } - pBot->f_hear_time = gpGlobals->time + 6; // Always keep a 6 seconds + pBot->f_hear_time = gpGlobals->time + 6.0f; // Always keep a 6 seconds // think time. } @@ -1083,7 +1083,7 @@ void FUNC_BotChecksFalling(cBot* pBot) { } // New function to display a message on the center of the screen -void CenterMessage(char* buffer) { +void CenterMessage(const char* buffer) { //DebugOut("waypoint: CenterMessage():\n"); //DebugOut(buffer); //DebugOut("\n"); diff --git a/bot_func.h b/bot_func.h index f1eefda..1d250d9 100644 --- a/bot_func.h +++ b/bot_func.h @@ -144,6 +144,6 @@ void UTIL_BotPressKey(cBot* pBot, int type); // bot_navigate.cpp // .. -void CenterMessage(char* buffer); +void CenterMessage(const char* buffer); #endif // BOT_FUNC_H \ No newline at end of file From 61264f4ac23469029db5b084fad305f7f11d7e58 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 18 Sep 2025 21:24:12 +0100 Subject: [PATCH 106/114] Attempting to enhance Shoot Breakable code --- bot.cpp | 947 +++++++++++++++++++++++++-------------------------- bot.h | 146 ++++---- bot_func.cpp | 64 ++-- 3 files changed, 571 insertions(+), 586 deletions(-) diff --git a/bot.cpp b/bot.cpp index 09565db..4ef0336 100644 --- a/bot.cpp +++ b/bot.cpp @@ -8,7 +8,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -20,9 +20,9 @@ * * Pierre Marie Baty * Count - Floyd - * - * !! BOTS-UNITED FOREVER !! - * + * + * !! BOTS-UNITED FOREVER !! + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -30,49 +30,49 @@ **/ -/* + /* + + //========================================================= + // Returns if enemy can be shoot through some obstacle + //========================================================= + bool CBaseBot::IsShootableThruObstacle(Vector vecDest) + { + if (!WeaponShootsThru(m_iCurrentWeapon)) + return FALSE; + + Vector vecSrc = EyePosition(); + Vector vecDir = (vecDest - vecSrc).Normalize(); // 1 unit long + Vector vecPoint = g_vecZero; + int iThickness = 0; + int iHits = 0; + + edict_t *pentIgnore = pev->pContainingEntity; + TraceResult tr; + UTIL_TraceLine(vecSrc, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); + + while (tr.flFraction != 1.0 && iHits < 3) + { + iHits++; + iThickness++; + vecPoint = tr.vecEndPos + vecDir; + while (POINT_CONTENTS(vecPoint) == CONTENTS_SOLID && iThickness < 64) + { + vecPoint = vecPoint + vecDir; + iThickness++; + } + UTIL_TraceLine(vecPoint, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); + } + + if (iHits < 3 && iThickness < 64) + { + if (LengthSquared(vecDest - vecPoint) < 12544) + return TRUE; + } + + return FALSE; + } -//========================================================= -// Returns if enemy can be shoot through some obstacle -//========================================================= -bool CBaseBot::IsShootableThruObstacle(Vector vecDest) -{ - if (!WeaponShootsThru(m_iCurrentWeapon)) - return FALSE; - - Vector vecSrc = EyePosition(); - Vector vecDir = (vecDest - vecSrc).Normalize(); // 1 unit long - Vector vecPoint = g_vecZero; - int iThickness = 0; - int iHits = 0; - - edict_t *pentIgnore = pev->pContainingEntity; - TraceResult tr; - UTIL_TraceLine(vecSrc, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); - - while (tr.flFraction != 1.0 && iHits < 3) - { - iHits++; - iThickness++; - vecPoint = tr.vecEndPos + vecDir; - while (POINT_CONTENTS(vecPoint) == CONTENTS_SOLID && iThickness < 64) - { - vecPoint = vecPoint + vecDir; - iThickness++; - } - UTIL_TraceLine(vecPoint, vecDest, ignore_monsters, ignore_glass, pentIgnore, &tr); - } - - if (iHits < 3 && iThickness < 64) - { - if (LengthSquared(vecDest - vecPoint) < 12544) - return TRUE; - } - - return FALSE; -} - -*/ + */ #include #include @@ -94,7 +94,7 @@ bool CBaseBot::IsShootableThruObstacle(Vector vecDest) #include #include -extern edict_t *pHostEdict; +extern edict_t* pHostEdict; extern int mod_id; extern bool internet_play; extern cGame Game; @@ -107,7 +107,7 @@ extern bool autoskill; /* Radio issue Credit by Ditlew (NNBOT - Rest In Peace) */ bool radio_message = false; -char *message = static_cast(malloc(64 * sizeof(char))); +char* message = static_cast(malloc(64 * sizeof(char))); char radio_messenger[30]; // random boundries @@ -193,6 +193,7 @@ void cBot::SpawnInit() { pBotHostage = nullptr; clearHostages(); pEnemyEdict = nullptr; + pBreakableEdict = nullptr; // chat std::memset(chChatSentence, 0, sizeof(chChatSentence)); @@ -358,6 +359,7 @@ void cBot::NewRound() { pBotHostage = nullptr; clearHostages(); pEnemyEdict = nullptr; + pBreakableEdict = nullptr; // ------------------------ // INTEGERS @@ -369,7 +371,7 @@ void cBot::NewRound() { bot_health = 0; prev_health = 0; bot_armor = 0; -// bot_weapons = 0; // <- stefan: prevent from buying new stuff every round! + // bot_weapons = 0; // <- stefan: prevent from buying new stuff every round! console_nr = 0; pathIndex = -1; iGoalNode = -1; @@ -462,7 +464,7 @@ void cBot::NewRound() { // we should say something now? int iMax = -1; - for (const char (&tc)[128] : ChatEngine.ReplyBlock[98].sentence) + for (const char(&tc)[128] : ChatEngine.ReplyBlock[98].sentence) { if (tc[0] != '\0') iMax++; @@ -678,7 +680,7 @@ void cBot::AimAtEnemy() { vTarget = pEnemyEdict->v.origin + pEnemyEdict->v.view_ofs * RANDOM_FLOAT(-2.5f, 2.5f); // aim for the head more fuzzy else - vTarget = pEnemyEdict->v.origin; // aim for body + vTarget = pEdict->v.origin; // aim for body // Based upon how far, we make this fuzzy float fDy, fDz; @@ -696,9 +698,9 @@ void cBot::AimAtEnemy() { // fd* = 3 * 2 vTarget = vTarget + Vector( - RANDOM_FLOAT(-fDx, fDx), - RANDOM_FLOAT(-fDy, fDy), - RANDOM_FLOAT(-fDz, fDz) + RANDOM_FLOAT(-fDx, fDx), + RANDOM_FLOAT(-fDy, fDy), + RANDOM_FLOAT(-fDz, fDz) ); // Add Offset @@ -708,9 +710,9 @@ void cBot::AimAtEnemy() { // increase offset with personality x,y,z offsets randomly vTarget = vTarget + Vector( - RANDOM_FLOAT(-fDx, fDx), - RANDOM_FLOAT(-fDy, fDy), - RANDOM_FLOAT(-fDz, fDz) + RANDOM_FLOAT(-fDx, fDx), + RANDOM_FLOAT(-fDy, fDy), + RANDOM_FLOAT(-fDz, fDz) ); if (isHoldingGrenadeOrFlashbang()) { @@ -923,7 +925,7 @@ void cBot::PickBestWeapon() { UTIL_SelectItem(pEdict, "weapon_hegrenade"); // select grenade f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) f_gren_time = - gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon return; } @@ -938,7 +940,7 @@ void cBot::PickBestWeapon() { UTIL_SelectItem(pEdict, "weapon_flashbang"); // select grenade f_wait_time = gpGlobals->time + 1.0f; // wait 1 second (stand still 1 sec) f_gren_time = - gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it + gpGlobals->time + (1.0f + RANDOM_FLOAT(0.5f, 1.5f)); // and determine how long we should hold it zoomed = ZOOM_NONE; // Counter-Strike resets zooming when choosing another weapon return; } @@ -966,7 +968,7 @@ void cBot::PickBestWeapon() { if (iTotalAmmo > 0) { UTIL_BotPressKey(this, IN_RELOAD); f_update_weapon_time = gpGlobals->time + 0.7f; // update timer - // return; + // return; } else { // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code // a bit though. Btw, distance 600 is too far for slashing :) @@ -1010,7 +1012,7 @@ void cBot::FireWeapon() { f_update_weapon_time > gpGlobals->time) return; - if (!isSeeingEnemy()) { + if (pBreakableEdict == nullptr && !isSeeingEnemy()) { return; } @@ -1040,8 +1042,8 @@ void cBot::FireWeapon() { if (f_shoot_wait_time < gpGlobals->time) { // AK, COLT, STEYR AUG, SIG SG552 only when enough skill! if ((CarryWeapon(CS_WEAPON_AK47) || CarryWeapon(CS_WEAPON_M4A1) - || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) - && bot_skill < 3) { + || CarryWeapon(CS_WEAPON_SG552) || CarryWeapon(CS_WEAPON_AUG)) + && bot_skill < 3) { float f_burst = (2048 / fDistance) + 0.1f; f_burst = std::max(f_burst, 0.1f); f_burst = std::min(f_burst, 0.4f); @@ -1069,7 +1071,7 @@ void cBot::FireWeapon() { f_prim_weapon = gpGlobals->time + f_burst; } f_shoot_wait_time = - gpGlobals->time + f_burst + RANDOM_FLOAT(0.2f, 0.7f); + gpGlobals->time + f_burst + RANDOM_FLOAT(0.2f, 0.7f); } } } // give the bot alteast 0.3 seconds to fire its weapon @@ -1113,7 +1115,7 @@ void cBot::FireWeapon() { // get weapon here. if (hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { rblog - ("BOT: Enemy is close enough, i should withdraw shield to attack this enemy\n"); + ("BOT: Enemy is close enough, i should withdraw shield to attack this enemy\n"); UTIL_BotPressKey(this, IN_ATTACK2); f_allow_keypress = gpGlobals->time + 0.7f; } @@ -1128,6 +1130,20 @@ void cBot::FireWeapon() { Function purpose: The combat brain of the bot ( called by Think() ) ******************************************************************************/ void cBot::Combat() { + if (pBreakableEdict != nullptr) { + // If the breakable is no longer valid, forget it + if (pBreakableEdict->v.health <= 0 || (pBreakableEdict->v.flags & FL_DORMANT)) { + pBreakableEdict = nullptr; + return; + } + + // Aim and fire at the breakable + const Vector vBreakableOrigin = VecBModelOrigin(pBreakableEdict); + setHeadAiming(vBreakableOrigin); + FireWeapon(); + return; + } + if (!hasEnemy()) { rprint("Unexpected call to Combat because bot has no enemy!"); return; @@ -1136,7 +1152,7 @@ void cBot::Combat() { // Bot is on ladder if (isOnLadder()) { // TODO: Bot fights when on ladder - + return; } @@ -1149,7 +1165,7 @@ void cBot::Combat() { } // get bot pointer - const cBot *checkpointer = UTIL_GetBotPointer(pEnemyEdict); + const cBot* checkpointer = UTIL_GetBotPointer(pEnemyEdict); // This bot killed a human; adjust skill when 'autoskill' is on. if (checkpointer == nullptr) { @@ -1274,13 +1290,13 @@ void cBot::FindCover() { // Now check at the right again UTIL_TraceLine(v_src, v_right, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + pEdict->v.pContainingEntity, &tr); if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_right, dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt if (tr.flFraction < 1.0f) { @@ -1295,12 +1311,12 @@ void cBot::FindCover() { // Now check at the left UTIL_TraceLine(v_src, v_left, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + pEdict->v.pContainingEntity, &tr); if (tr.flFraction >= 1.0f) { // We can see it // Now trace from that vector to our threat UTIL_TraceLine(v_left, dest, dont_ignore_monsters, - pEdict->v.pContainingEntity, &tr); + pEdict->v.pContainingEntity, &tr); // If this is blocking.. then its a good wpt if (tr.flFraction < 1.0f) { @@ -1374,7 +1390,7 @@ void cBot::InteractWithFriends() { for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { @@ -1398,7 +1414,7 @@ void cBot::InteractWithFriends() { bCanSeePlayer = true; // there are tons of cases - const cBot *pBotPointer = UTIL_GetBotPointer(pPlayer); + const cBot* pBotPointer = UTIL_GetBotPointer(pPlayer); // It is a fellow bot if (pBotPointer != nullptr) { @@ -1595,9 +1611,11 @@ void cBot::JoinTeam() { // select the team the bot wishes to join... if (iTeam == 1) { std::strcpy(c_team, "1"); - } else if (iTeam == 2) { + } + else if (iTeam == 2) { std::strcpy(c_team, "2"); - } else { + } + else { std::strcpy(c_team, "5"); } @@ -1649,8 +1667,9 @@ void cBot::JoinTeam() { // Since cs 1.6 does not give us pretty random models // we do it ourselves - if (bot_class == 5) + if (bot_class == 5) { bot_class = RANDOM_LONG(1, 4); + } // select the class the bot wishes to use... if (bot_class == 1) @@ -1870,11 +1889,11 @@ void cBot::Act() { if (f_camp_time > gpGlobals->time) { // When camping we duck and we don't move UTIL_BotPressKey(this, IN_DUCK); - + setMoveSpeed(0.0f); // do not move PickBestWeapon(); // pick weapon, do not stare with knife - + // when dropped C4 and CT we look at C4 if (isCounterTerrorist() && Game.vDroppedC4 != Vector(9999, 9999, 9999)) { // look at dropped C4 @@ -1886,7 +1905,7 @@ void cBot::Act() { forgetPath(); forgetGoal(); vHead = vBody = NodeMachine.node_vector(iGoalNode); - } + } else { vHead = vBody = Game.vDroppedC4; } @@ -2134,39 +2153,6 @@ void cBot::CheckAround() { else { rprint_trace("CheckAround", "Nothing in front of me"); } - - // ------------------------------------------------------------- - // When checking around a bot also handles breakable stuff. - // ------------------------------------------------------------- - - edict_t* pent = nullptr; - while ((pent = UTIL_FindEntityInSphere(pent, pEdict->v.origin, 60.0f)) != nullptr) { - char item_name[40]; - std::strcpy(item_name, STRING(pent->v.classname)); - - // See if it matches our object name - if (std::strcmp("func_breakable", item_name) == 0) { - - // Found a func_breakable - const Vector vBreakableOrigin = VecBModelOrigin(pent); - - // Shoot - if ((pent->v.flags & FL_WORLDBRUSH) == 0) // can it be broken? - { - // Thx for CF by fixing breakable coding - if (pent->v.solid == SOLID_BSP && pent->v.takedamage == DAMAGE_YES && pent->v.impulse == 0 && - pent->v.health < 150) // has it NOT been broken yet? - { - // trace to vector to be sure we dont get blocked by anything else - if (VectorIsVisibleWithEdict(pEdict, vBreakableOrigin, "func_breakable")) { - setHeadAiming(vBreakableOrigin); - FireWeapon(); - } - return; - } - } - } // CAN BE BROKEN - } // FUNC_BREAKABLE } // BOT: Should be taking cover? @@ -2222,10 +2208,10 @@ bool cBot::hasGoalIndex() const * Returns goal data , if goal data exists * @return */ -tGoal *cBot::getGoalData() const +tGoal* cBot::getGoalData() const { if (!hasGoalIndex()) return nullptr; - tGoal *ptr = NodeMachine.getGoal(this->goalIndex); + tGoal* ptr = NodeMachine.getGoal(this->goalIndex); if (ptr == nullptr) return nullptr; // only goals with a node are valid @@ -2241,11 +2227,11 @@ bool cBot::hasEnemy() const return this->pEnemyEdict != nullptr; } - /** - * Returns true when given edict == our enemy edict - * @param pEntity - * @return - */ +/** + * Returns true when given edict == our enemy edict + * @param pEntity + * @return + */ bool cBot::hasEnemy(const edict_t* pEntity) const { return this->pEnemyEdict == pEntity; @@ -2263,9 +2249,9 @@ bool cBot::shouldBeWandering() { } void cBot::setMoveSpeed(const float value) { -// char msg[255]; -// sprintf(msg, "setting to value %f / maxSpeed %f - sv_maxspeed = %f", value, this->f_max_speed, CVAR_GET_FLOAT("sv_maxspeed")); -// rprint_trace("setMoveSpeed", msg); + // char msg[255]; + // sprintf(msg, "setting to value %f / maxSpeed %f - sv_maxspeed = %f", value, this->f_max_speed, CVAR_GET_FLOAT("sv_maxspeed")); + // rprint_trace("setMoveSpeed", msg); this->f_move_speed = value; } @@ -2333,7 +2319,7 @@ void cBot::forgetEnemy() { this->pEnemyEdict = nullptr; } -edict_t * cBot::getEnemyEdict() const +edict_t* cBot::getEnemyEdict() const { return this->pEnemyEdict; } @@ -2350,15 +2336,15 @@ void cBot::setGoalNode(const int nodeIndex, const int iGoalIndex) { this->iGoalNode = nodeIndex; this->goalIndex = iGoalIndex; - tGoal *goalPtr = getGoalData(); + tGoal* goalPtr = getGoalData(); char msg[255] = {}; if (goalPtr != nullptr) { snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - GOAL: type [%s], checked [%d]", - nodeIndex, - goalIndex, - goalPtr->name, - goalPtr->iChecked + nodeIndex, + goalIndex, + goalPtr->name, + goalPtr->iChecked ); } else { snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); @@ -2371,7 +2357,7 @@ void cBot::setGoalNode(const int nodeIndex) this->setGoalNode(nodeIndex, -1); } -void cBot::setGoalNode(tGoal *goal) +void cBot::setGoalNode(tGoal* goal) { if (goal != nullptr && goal->iNode > -1) { rprint("setGoalNode with goal pointer\n"); @@ -2384,7 +2370,7 @@ void cBot::setGoalNode(tGoal *goal) * @param Function * @param msg */ -void cBot::rprint(const char *Function, const char *msg) +void cBot::rprint(const char* Function, const char* msg) { REALBOT_PRINT(this, Function, msg); } @@ -2413,15 +2399,15 @@ void cBot::rprint_normal(const char* Function, const char* msg) } } -void cBot::rprint(const char *msg) { +void cBot::rprint(const char* msg) { rprint("rprint()", msg); } -void cBot::rprint_normal(const char *msg) { +void cBot::rprint_normal(const char* msg) { rprint_normal("rprint()", msg); } -void cBot::rprint_trace(const char *msg) { +void cBot::rprint_trace(const char* msg) { rprint_trace("rprint()", msg); } @@ -2460,7 +2446,7 @@ bool cBot::hasSecondaryWeapon(const int weaponId) const return isOwningWeapon(weaponId); }*/ -void cBot::performBuyWeapon(const char *menuItem, const char *subMenuItem) { +void cBot::performBuyWeapon(const char* menuItem, const char* subMenuItem) { // To be sure the console will only change when we MAY change. // The values will only be changed when console_nr is 0 if (Game.getRoundStartedTime() + 4 < gpGlobals->time) @@ -2489,93 +2475,93 @@ void cBot::performBuyActions(const int weaponIdToBuy) { // CS 1.5 only if (counterstrike == 0) { switch (weaponIdToBuy) { - case CS_WEAPON_AK47: - performBuyWeapon("4", "1"); - break; - case CS_WEAPON_DEAGLE: - performBuyWeapon("1", "3"); - break; - case CS_WEAPON_P228: - performBuyWeapon("1", "4"); - break; - case CS_WEAPON_SG552: - performBuyWeapon("4", "2"); - break; - case CS_WEAPON_SG550: - performBuyWeapon("4", "8"); - break; - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "5"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "6"); - break; - case CS_WEAPON_MP5NAVY: - performBuyWeapon("3", "1"); - break; - case CS_WEAPON_UMP45: - performBuyWeapon("3", "5"); - break; - case CS_WEAPON_ELITE: - performBuyWeapon("1", "5"); - break; // T only - case CS_WEAPON_MAC10: - performBuyWeapon("3", "4"); - break; // T only - case CS_WEAPON_AUG: - performBuyWeapon("4", "4"); - break; // CT Only - case CS_WEAPON_FIVESEVEN: - performBuyWeapon("1", "6"); - break; // CT only - case CS_WEAPON_M4A1: - performBuyWeapon("4", "3"); - break; // CT Only - case CS_WEAPON_TMP: - performBuyWeapon("3", "2"); - break; // CT only - case CS_WEAPON_HEGRENADE: - performBuyWeapon("8", "4"); - break; - case CS_WEAPON_XM1014: - performBuyWeapon("2", "2"); - break; - case CS_WEAPON_SMOKEGRENADE: - performBuyWeapon("8", "5"); - break; - case CS_WEAPON_USP: - performBuyWeapon("1", "1"); - break; - case CS_WEAPON_GLOCK18: - performBuyWeapon("1", "2"); - break; - case CS_WEAPON_M249: - performBuyWeapon("5", "1"); - break; - case CS_WEAPON_M3: - performBuyWeapon("2", "1"); - break; - case CS_WEAPON_G3SG1: - performBuyWeapon("4", "7"); - break; - case CS_WEAPON_FLASHBANG: - performBuyWeapon("8", "3"); - break; - case CS_WEAPON_P90: - performBuyWeapon("3", "3"); - break; + case CS_WEAPON_AK47: + performBuyWeapon("4", "1"); + break; + case CS_WEAPON_DEAGLE: + performBuyWeapon("1", "3"); + break; + case CS_WEAPON_P228: + performBuyWeapon("1", "4"); + break; + case CS_WEAPON_SG552: + performBuyWeapon("4", "2"); + break; + case CS_WEAPON_SG550: + performBuyWeapon("4", "8"); + break; + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "5"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "6"); + break; + case CS_WEAPON_MP5NAVY: + performBuyWeapon("3", "1"); + break; + case CS_WEAPON_UMP45: + performBuyWeapon("3", "5"); + break; + case CS_WEAPON_ELITE: + performBuyWeapon("1", "5"); + break; // T only + case CS_WEAPON_MAC10: + performBuyWeapon("3", "4"); + break; // T only + case CS_WEAPON_AUG: + performBuyWeapon("4", "4"); + break; // CT Only + case CS_WEAPON_FIVESEVEN: + performBuyWeapon("1", "6"); + break; // CT only + case CS_WEAPON_M4A1: + performBuyWeapon("4", "3"); + break; // CT Only + case CS_WEAPON_TMP: + performBuyWeapon("3", "2"); + break; // CT only + case CS_WEAPON_HEGRENADE: + performBuyWeapon("8", "4"); + break; + case CS_WEAPON_XM1014: + performBuyWeapon("2", "2"); + break; + case CS_WEAPON_SMOKEGRENADE: + performBuyWeapon("8", "5"); + break; + case CS_WEAPON_USP: + performBuyWeapon("1", "1"); + break; + case CS_WEAPON_GLOCK18: + performBuyWeapon("1", "2"); + break; + case CS_WEAPON_M249: + performBuyWeapon("5", "1"); + break; + case CS_WEAPON_M3: + performBuyWeapon("2", "1"); + break; + case CS_WEAPON_G3SG1: + performBuyWeapon("4", "7"); + break; + case CS_WEAPON_FLASHBANG: + performBuyWeapon("8", "3"); + break; + case CS_WEAPON_P90: + performBuyWeapon("3", "3"); + break; - // Armor - case CS_WEAPON_ARMOR_LIGHT: - performBuyWeapon("8", "1"); - break; - case CS_WEAPON_ARMOR_HEAVY: - performBuyWeapon("8", "2"); - break; + // Armor + case CS_WEAPON_ARMOR_LIGHT: + performBuyWeapon("8", "1"); + break; + case CS_WEAPON_ARMOR_HEAVY: + performBuyWeapon("8", "2"); + break; - case CS_DEFUSEKIT: - performBuyWeapon("8", "6"); - break; + case CS_DEFUSEKIT: + performBuyWeapon("8", "6"); + break; } } @@ -2583,99 +2569,99 @@ void cBot::performBuyActions(const int weaponIdToBuy) { else if (counterstrike == 1) { // FRASHMAN 30/08/04: redone switch block, it was full of errors switch (weaponIdToBuy) { //Pistols - case CS_WEAPON_GLOCK18: - performBuyWeapon("1", "1"); - break; - case CS_WEAPON_USP: - performBuyWeapon("1", "2"); - break; - case CS_WEAPON_P228: - performBuyWeapon("1", "3"); - break; - case CS_WEAPON_DEAGLE: - performBuyWeapon("1", "4"); - break; - case CS_WEAPON_FIVESEVEN: - performBuyWeapon("1", "5"); - break; // CT Only - case CS_WEAPON_ELITE: - performBuyWeapon("1", "5"); - break; // T Only - //ShotGUNS - case CS_WEAPON_M3: - performBuyWeapon("2", "1"); - break; - case CS_WEAPON_XM1014: - performBuyWeapon("2", "2"); - break; - //SMG - case CS_WEAPON_MAC10: - performBuyWeapon("3", "1"); - break; // T Only - case CS_WEAPON_TMP: - performBuyWeapon("3", "1"); - break; // CT Only - case CS_WEAPON_MP5NAVY: - performBuyWeapon("3", "2"); - break; - case CS_WEAPON_UMP45: - performBuyWeapon("3", "3"); - break; - case CS_WEAPON_P90: - performBuyWeapon("3", "4"); - break; - //rifles - case CS_WEAPON_GALIL: - performBuyWeapon("4", "1"); - break; // T Only - case CS_WEAPON_FAMAS: - performBuyWeapon("4", "1"); - break; // CT Only - case CS_WEAPON_AK47: - performBuyWeapon("4", "2"); - break; // T Only - case CS_WEAPON_M4A1: - performBuyWeapon("4", "3"); - break; // CT Only - case CS_WEAPON_SG552: - performBuyWeapon("4", "4"); - break; // T Only - case CS_WEAPON_AUG: - performBuyWeapon("4", "4"); - break; // CT Only - case CS_WEAPON_SG550: - performBuyWeapon("4", "5"); - break; // CT Only - case CS_WEAPON_G3SG1: - performBuyWeapon("4", "6"); - break; // T Only - //machinegun - case CS_WEAPON_M249: - performBuyWeapon("5", "1"); - break; - // equipment - case CS_WEAPON_ARMOR_LIGHT: - performBuyWeapon("8", "1"); - break; - case CS_WEAPON_ARMOR_HEAVY: - performBuyWeapon("8", "2"); - break; - case CS_WEAPON_FLASHBANG: - performBuyWeapon("8", "3"); - break; - case CS_WEAPON_HEGRENADE: - performBuyWeapon("8", "4"); - break; - case CS_WEAPON_SMOKEGRENADE: - performBuyWeapon("8", "5"); - break; - case CS_WEAPON_SHIELD: - performBuyWeapon("8", "8"); - break; + case CS_WEAPON_GLOCK18: + performBuyWeapon("1", "1"); + break; + case CS_WEAPON_USP: + performBuyWeapon("1", "2"); + break; + case CS_WEAPON_P228: + performBuyWeapon("1", "3"); + break; + case CS_WEAPON_DEAGLE: + performBuyWeapon("1", "4"); + break; + case CS_WEAPON_FIVESEVEN: + performBuyWeapon("1", "5"); + break; // CT Only + case CS_WEAPON_ELITE: + performBuyWeapon("1", "5"); + break; // T Only + //ShotGUNS + case CS_WEAPON_M3: + performBuyWeapon("2", "1"); + break; + case CS_WEAPON_XM1014: + performBuyWeapon("2", "2"); + break; + //SMG + case CS_WEAPON_MAC10: + performBuyWeapon("3", "1"); + break; // T Only + case CS_WEAPON_TMP: + performBuyWeapon("3", "1"); + break; // CT Only + case CS_WEAPON_MP5NAVY: + performBuyWeapon("3", "2"); + break; + case CS_WEAPON_UMP45: + performBuyWeapon("3", "3"); + break; + case CS_WEAPON_P90: + performBuyWeapon("3", "4"); + break; + //rifles + case CS_WEAPON_GALIL: + performBuyWeapon("4", "1"); + break; // T Only + case CS_WEAPON_FAMAS: + performBuyWeapon("4", "1"); + break; // CT Only + case CS_WEAPON_AK47: + performBuyWeapon("4", "2"); + break; // T Only + case CS_WEAPON_M4A1: + performBuyWeapon("4", "3"); + break; // CT Only + case CS_WEAPON_SG552: + performBuyWeapon("4", "4"); + break; // T Only + case CS_WEAPON_AUG: + performBuyWeapon("4", "4"); + break; // CT Only + case CS_WEAPON_SG550: + performBuyWeapon("4", "5"); + break; // CT Only + case CS_WEAPON_G3SG1: + performBuyWeapon("4", "6"); + break; // T Only + //machinegun + case CS_WEAPON_M249: + performBuyWeapon("5", "1"); + break; + // equipment + case CS_WEAPON_ARMOR_LIGHT: + performBuyWeapon("8", "1"); + break; + case CS_WEAPON_ARMOR_HEAVY: + performBuyWeapon("8", "2"); + break; + case CS_WEAPON_FLASHBANG: + performBuyWeapon("8", "3"); + break; + case CS_WEAPON_HEGRENADE: + performBuyWeapon("8", "4"); + break; + case CS_WEAPON_SMOKEGRENADE: + performBuyWeapon("8", "5"); + break; + case CS_WEAPON_SHIELD: + performBuyWeapon("8", "8"); + break; - case CS_DEFUSEKIT: - performBuyWeapon("8", "6"); - break; + case CS_DEFUSEKIT: + performBuyWeapon("8", "6"); + break; //default: //Just in case they use pistols but buy MP5 [APG]RoboCop[CL] // performBuyWeapon("3", "2"); // break; @@ -2686,24 +2672,24 @@ void cBot::performBuyActions(const int weaponIdToBuy) { if (iTeam == 2) // counter { switch (weaponIdToBuy) { - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "2"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "6"); - break; - //whats about nightvision? BuyWeapon (pBot, "8", "7") + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "2"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "6"); + break; + //whats about nightvision? BuyWeapon (pBot, "8", "7") } } else // terror { switch (weaponIdToBuy) { - case CS_WEAPON_SCOUT: - performBuyWeapon("4", "3"); - break; - case CS_WEAPON_AWP: - performBuyWeapon("4", "5"); - break; - //whats about nightvision? BuyWeapon (pBot, "8", "6") + case CS_WEAPON_SCOUT: + performBuyWeapon("4", "3"); + break; + case CS_WEAPON_AWP: + performBuyWeapon("4", "5"); + break; + //whats about nightvision? BuyWeapon (pBot, "8", "6") } } } // end of cs 1.6 part @@ -2726,12 +2712,12 @@ void cBot::Memory() { // we can hear them (estimated distance)). if (pEnemyEdict == nullptr) { Vector vHear = Vector(9999, 9999, 9999); - edict_t *pHearPlayer = nullptr; + edict_t* pHearPlayer = nullptr; //f_walk_time = gpGlobals->time + 1; for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free && pPlayer != pEdict) { @@ -2747,15 +2733,15 @@ void cBot::Memory() { if (FUNC_PlayerRuns(FUNC_PlayerSpeed(pPlayer))) { // check distance const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); + (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody if (fDistance < BOT_HEARDISTANCE) { // check if this 'hearing' vector is closer then our previous one if (vHear != Vector(9999, 9999, 9999)) { if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < + (pEdict->v.origin, + pPlayer->v.origin) < func_distance(pEdict->v.origin, vHear)) { // this one is closer, thus more important vHear = pPlayer->v.origin; @@ -2767,23 +2753,23 @@ void cBot::Memory() { } } } - + if (pPlayer->v.button & IN_ATTACK && (FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_HEGRENADE && FUNC_EdictHoldsWeapon(pEdict) != CS_WEAPON_FLASHBANG && FUNC_EdictHoldsWeapon(pEdict) != - CS_WEAPON_SMOKEGRENADE)) { + CS_WEAPON_SMOKEGRENADE)) { // check distance const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); + (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody if (fDistance < BOT_HEARFIREDISTANCE) { // check if this 'hearing' vector is closer then our previous one if (vHear != Vector(9999, 9999, 9999)) { if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < + (pEdict->v.origin, + pPlayer->v.origin) < func_distance(pEdict->v.origin, vHear)) { // this one is closer, thus more important vHear = pPlayer->v.origin; @@ -2799,15 +2785,15 @@ void cBot::Memory() { if (pPlayer->v.button & IN_ATTACK2) { // check distance const float fDistance = - (pPlayer->v.origin - pEdict->v.origin).Length(); + (pPlayer->v.origin - pEdict->v.origin).Length(); // estimated distance we can hear somebody if (fDistance < BOT_HEARDISTANCE) { // check if this 'hearing' vector is closer then our previous one if (vHear != Vector(9999, 9999, 9999)) { if (func_distance - (pEdict->v.origin, - pPlayer->v.origin) < + (pEdict->v.origin, + pPlayer->v.origin) < func_distance(pEdict->v.origin, vHear)) { // this one is closer, thus more important vHear = pPlayer->v.origin; @@ -2829,8 +2815,8 @@ void cBot::Memory() { // determine fuzzyness by distance: int iFuzz = - static_cast(func_distance(pEdict->v.origin, vHear) / - BOT_HEARDISTANCE) * 250; + static_cast(func_distance(pEdict->v.origin, vHear) / + BOT_HEARDISTANCE) * 250; // skill depended iFuzz /= bot_skill + 1; @@ -2841,14 +2827,14 @@ void cBot::Memory() { const float randZ = RANDOM_LONG(-iFuzz, iFuzz); vHear = vHear + Vector(randX, randY, randZ); - + TraceResult tr; UTIL_TraceHull(pEdict->v.origin, vHear, dont_ignore_monsters, - point_hull, pEdict, &tr); + point_hull, pEdict, &tr); int iNodeHearPlayer = - NodeMachine.getClosestNode(vHear, NODE_ZONE * 2, pHearPlayer); + NodeMachine.getClosestNode(vHear, NODE_ZONE * 2, pHearPlayer); // if nothing hit: if (tr.flFraction >= 1.0f) { @@ -2897,30 +2883,30 @@ void cBot::Memory() { } } else { vEar = Vector(9999, 9999, 9999); -// -// // check for any 'beeps' of the bomb! -// if (isCounterTerrorist() && Game.bBombPlanted) { -// // find the bomb vector -// edict_t *pent = NULL; -// Vector vC4 = Vector(9999, 9999, 9999); -// while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != NULL) { -// if (UTIL_GetGrenadeType(pent) == 4) // It is a C4 -// { -// vC4 = pent->v.origin; // store origin -// break; // done our part now -// } -// } // --- find the c4 -// -// if (vC4 != Vector(9999, 9999, 9999)) { -// -// if (func_distance(vC4, NodeMachine.node_vector(iGoalNode)) > 100 && -// func_distance(pEdict->v.origin, vC4) < 1024) { -// // set new goal node -// setGoalNode(NodeMachine.getCloseNode(vC4, NODE_ZONE, NULL)); -// forgetPath(); -// } -// } -// } + // + // // check for any 'beeps' of the bomb! + // if (isCounterTerrorist() && Game.bBombPlanted) { + // // find the bomb vector + // edict_t *pent = NULL; + // Vector vC4 = Vector(9999, 9999, 9999); + // while ((pent = UTIL_FindEntityByClassname(pent, "grenade")) != NULL) { + // if (UTIL_GetGrenadeType(pent) == 4) // It is a C4 + // { + // vC4 = pent->v.origin; // store origin + // break; // done our part now + // } + // } // --- find the c4 + // + // if (vC4 != Vector(9999, 9999, 9999)) { + // + // if (func_distance(vC4, NodeMachine.node_vector(iGoalNode)) > 100 && + // func_distance(pEdict->v.origin, vC4) < 1024) { + // // set new goal node + // setGoalNode(NodeMachine.getCloseNode(vC4, NODE_ZONE, NULL)); + // forgetPath(); + // } + // } + // } } } else { @@ -3019,17 +3005,17 @@ void cBot::ThinkAboutGoals() { // in Act() we find the 'acting' code when timers above are set. } -void cBot::rememberWhichHostageToRescue(edict_t *pHostage) { +void cBot::rememberWhichHostageToRescue(edict_t* pHostage) { this->pBotHostage = pHostage; } -edict_t * cBot::getHostageToRescue() const +edict_t* cBot::getHostageToRescue() const { return pBotHostage; } -edict_t * cBot::findHostageToRescue() { - edict_t *pent = nullptr; +edict_t* cBot::findHostageToRescue() { + edict_t* pent = nullptr; // Search for all hostages in the game while ((pent = UTIL_FindEntityByClassname(pent, "hostage_entity")) != nullptr) { @@ -3154,7 +3140,7 @@ void cBot::Think() { rprint("Dead, need to re-initialize"); // AUTOSKILL - const cBot *botPointerOfKiller = UTIL_GetBotPointer(killer_edict); + const cBot* botPointerOfKiller = UTIL_GetBotPointer(killer_edict); // not killed by a fellow bot, presumably a human player if (botPointerOfKiller == nullptr) { @@ -3173,11 +3159,11 @@ void cBot::Think() { char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) snprintf(msg, sizeof(msg), - "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", - name, bot_skill); + "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", + name, bot_skill); else snprintf(msg, sizeof(msg), "You have killed a RealBot named %s!", - name); + name); HUD_DrawString(r, g, b, msg, killer_edict); } @@ -3207,7 +3193,7 @@ void cBot::Think() { // we should say something now? int iMax = -1; - for (const char (&tc)[128] : ChatEngine.ReplyBlock[99].sentence) + for (const char(&tc)[128] : ChatEngine.ReplyBlock[99].sentence) { if (tc[0] != '\0') iMax++; } @@ -3325,7 +3311,7 @@ void cBot::Think() { rprint_trace("Think()", "Blinded"); return; } - + // NEW: When round time is over and still busy playing, kill bots const float roundTimeInSeconds = CVAR_GET_FLOAT("mp_roundtime") * 60.0f; const float freezeTimeCVAR = CVAR_GET_FLOAT("mp_freezetime"); @@ -3354,7 +3340,7 @@ void cBot::Think() { vHead = vBody = pEdict->v.origin; // find any spawnpoint to look at: - edict_t *pent = nullptr; + edict_t* pent = nullptr; if (isCounterTerrorist()) { while ((pent = UTIL_FindEntityByClassname(pent, "info_player_start")) != nullptr) { @@ -3384,9 +3370,14 @@ void cBot::Think() { // **---**---**---**---**---**---** // MAIN STATE: We have no enemy... // **---**---**---**---**---**---** - if (!hasEnemy()) { + if (!hasEnemy() && pBreakableEdict == nullptr) { if (!Game.bDoNotShoot) { + FUNC_FindBreakable(this); + if (pBreakableEdict != nullptr) { + Combat(); // Attack the breakable + return; + } InteractWithPlayers(); } @@ -3421,11 +3412,11 @@ void cBot::Think() { && f_update_weapon_time < gpGlobals->time) { if (iPrimaryWeapon > -1) UTIL_SelectItem(pEdict, - UTIL_GiveWeaponName(iPrimaryWeapon)); + UTIL_GiveWeaponName(iPrimaryWeapon)); else // pick secondary UTIL_SelectItem(pEdict, - UTIL_GiveWeaponName(iSecondaryWeapon)); + UTIL_GiveWeaponName(iSecondaryWeapon)); f_update_weapon_time = gpGlobals->time + 0.7f; } @@ -3469,33 +3460,33 @@ void cBot::checkOfHostagesStillFollowMe() { if (fCheckHostageStatusTimer > gpGlobals->time) return; fCheckHostageStatusTimer = gpGlobals->time + 5.0f; -//// this->rprint("checkOfHostagesStillFollowMe - START"); -// if (hostage1) { -// if (!isHostageRescued(this, hostage1) && FUNC_EdictIsAlive(hostage1) && !canSeeEntity(hostage1) && getDistanceTo(hostage1->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage1"); -// forgetHostage(hostage1); -// } -// } -// if (hostage2) { -// if (!isHostageRescued(this, hostage2) && FUNC_EdictIsAlive(hostage2) && !canSeeEntity(hostage2) && getDistanceTo(hostage2->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage2"); -// forgetHostage(hostage2); -// } -// } -// if (hostage3) { -// if (!isHostageRescued(this, hostage3) && FUNC_EdictIsAlive(hostage3) && !canSeeEntity(hostage3) && getDistanceTo(hostage3->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage3"); -// forgetHostage(hostage3); -// } -// } -// -// if (hostage4) { -// if (!isHostageRescued(this, hostage4) && FUNC_EdictIsAlive(hostage4) && !canSeeEntity(hostage4) && getDistanceTo(hostage4->v.origin) > NODE_ZONE*2.5) { -// rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage4"); -// forgetHostage(hostage4); -// } -// } -// rprint("checkOfHostagesStillFollowMe - END"); + //// this->rprint("checkOfHostagesStillFollowMe - START"); + // if (hostage1) { + // if (!isHostageRescued(this, hostage1) && FUNC_EdictIsAlive(hostage1) && !canSeeEntity(hostage1) && getDistanceTo(hostage1->v.origin) > NODE_ZONE*2.5) { + // rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage1"); + // forgetHostage(hostage1); + // } + // } + // if (hostage2) { + // if (!isHostageRescued(this, hostage2) && FUNC_EdictIsAlive(hostage2) && !canSeeEntity(hostage2) && getDistanceTo(hostage2->v.origin) > NODE_ZONE*2.5) { + // rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage2"); + // forgetHostage(hostage2); + // } + // } + // if (hostage3) { + // if (!isHostageRescued(this, hostage3) && FUNC_EdictIsAlive(hostage3) && !canSeeEntity(hostage3) && getDistanceTo(hostage3->v.origin) > NODE_ZONE*2.5) { + // rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage3"); + // forgetHostage(hostage3); + // } + // } + // + // if (hostage4) { + // if (!isHostageRescued(this, hostage4) && FUNC_EdictIsAlive(hostage4) && !canSeeEntity(hostage4) && getDistanceTo(hostage4->v.origin) > NODE_ZONE*2.5) { + // rprint_trace("checkOfHostagesStillFollowMe", "lost track of hostage4"); + // forgetHostage(hostage4); + // } + // } + // rprint("checkOfHostagesStillFollowMe - END"); } void cBot::clearHostages() { @@ -3579,9 +3570,9 @@ void cBot::UpdateStatus() { // Set max speed and such when CS 1.6 if (counterstrike == 1) { f_max_speed = pEdict->v.maxspeed; -// char msg[255]; -// sprintf(msg, "f_max_speed set to %f", f_max_speed); -// rprint_trace("UpdateStatus", msg); + // char msg[255]; + // sprintf(msg, "f_max_speed set to %f", f_max_speed); + // rprint_trace("UpdateStatus", msg); bot_health = static_cast(pEdict->v.health); bot_armor = static_cast(pEdict->v.armorvalue); } @@ -3833,14 +3824,14 @@ bool BotRadioAction() { } // Is entity visible? (from Entity view) -bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { +bool EntityIsVisible(edict_t* pEntity, const Vector& dest) { //DebugOut("bot: EntityIsVisible()\n"); TraceResult tr; // trace a line from bot's eyes to destination... UTIL_TraceLine(pEntity->v.origin + pEntity->v.view_ofs, dest, - dont_ignore_monsters, pEntity->v.pContainingEntity, &tr); + dont_ignore_monsters, pEntity->v.pContainingEntity, &tr); // check if line of sight to object is not blocked (i.e. visible) if (tr.flFraction >= 1.0f) @@ -3851,7 +3842,7 @@ bool EntityIsVisible(edict_t *pEntity, const Vector& dest) { } // Can see Edict? -bool cBot::canSeeEntity(edict_t *pEntity) const +bool cBot::canSeeEntity(edict_t* pEntity) const { if (pEntity == nullptr) return false; @@ -3878,7 +3869,7 @@ bool cBot::canSeeEntity(edict_t *pEntity) const * @return */ float cBot::getDistanceTo(const int nodeIndex) { - const tNode *nodePtr = NodeMachine.getNode(nodeIndex); + const tNode* nodePtr = NodeMachine.getNode(nodeIndex); if (nodePtr != nullptr) { return getDistanceTo(nodePtr->origin); } @@ -3896,7 +3887,7 @@ float cBot::getDistanceTo(const Vector& vDest) const return func_distance(pEdict->v.origin, vDest); } -bool cBot::isUsingHostage(edict_t *pHostage) { +bool cBot::isUsingHostage(edict_t* pHostage) { if (pHostage == nullptr) return false; // checks if the current pEdict is already 'in use' @@ -3924,27 +3915,27 @@ bool cBot::isUsingHostage(edict_t *pHostage) { return false; } -void cBot::forgetHostage(edict_t *pHostage) { +void cBot::forgetHostage(edict_t* pHostage) { // these are the hostages we are rescueing (ie, they are following this bot) - if (hostage1 == pHostage) { + if (hostage1 == pHostage) { rprint("forgetHostage", "hostage1"); hostage1 = nullptr; } - if (hostage2 == pHostage) { + if (hostage2 == pHostage) { rprint("forgetHostage", "hostage2"); hostage2 = nullptr; } - if (hostage3 == pHostage) { + if (hostage3 == pHostage) { rprint("forgetHostage", "hostage3"); hostage3 = nullptr; } - if (hostage4 == pHostage) { + if (hostage4 == pHostage) { rprint("forgetHostage", "hostage4"); hostage4 = nullptr; } // this is the hostage we have taken interest in - if (pBotHostage == pHostage) { + if (pBotHostage == pHostage) { rprint("forgetHostage", "pBotHostage"); pBotHostage = nullptr; } @@ -3975,7 +3966,7 @@ bool cBot::canSeeVector(const Vector& vDest) const if (tr.flFraction < 1.0f) return false; - + return true; } @@ -3998,13 +3989,13 @@ bool cBot::hasShieldDrawn() const } /* - BotThink() + BotThink() This function is the very general/main/simplified thinking function of the bot. Do NOT add/remove/change code here! If you want to give the bot information to work with. Put it in UpdateStatus(). When the bot has to think about it, do it int Think() and everything else (when all is set, how to 'do' it) in Act(). */ -void BotThink(cBot *pBot) { +void BotThink(cBot* pBot) { // STEP 1: Update status pBot->UpdateStatus(); @@ -4025,7 +4016,7 @@ void BotThink(cBot *pBot) { snprintf(msg, sizeof(msg), "moveSpeed %f, strafeSpeed %f, msecVal %f", pBot->f_move_speed, pBot->f_strafe_speed, msecval); pBot->rprint_trace("BotThink/pfnRunPlayerMove", msg); g_engfuncs.pfnRunPlayerMove(pBot->pEdict, pBot->vecMoveAngles, pBot->f_move_speed, pBot->f_strafe_speed, - upMove, pBot->pEdict->v.button, 0, msecval); + upMove, pBot->pEdict->v.button, 0, msecval); constexpr float fUpdateInterval = 1.0f / 60.0f; // update at 60 fps pBot->fUpdateTime = gpGlobals->time + fUpdateInterval; @@ -4038,30 +4029,30 @@ void BotThink(cBot *pBot) { void cBot::Dump() { char buffer[181]; const int iCurrentNode = - NodeMachine.getClosestNode(pEdict->v.origin, (NODE_ZONE * 2), pEdict); + NodeMachine.getClosestNode(pEdict->v.origin, (NODE_ZONE * 2), pEdict); snprintf(buffer, 180, - "%s (#%d %s): timers, now= %.0f, c4_time=%.0f, camp_time=%.0f, wait_time=%.0f, cover_time=%.0f, wander=%.0f, MoveToNodeTime=%.0f\n", - name, iBotIndex, (iTeam == 1) ? "T" : "CT", gpGlobals->time, - f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, fMoveToNodeTime); + "%s (#%d %s): timers, now= %.0f, c4_time=%.0f, camp_time=%.0f, wait_time=%.0f, cover_time=%.0f, wander=%.0f, MoveToNodeTime=%.0f\n", + name, iBotIndex, (iTeam == 1) ? "T" : "CT", gpGlobals->time, + f_c4_time, f_camp_time, f_wait_time, f_cover_time, fWanderTime, fMoveToNodeTime); rblog(buffer); snprintf(buffer, 180, " GoalNode=%d, CurrentNode=%d, iPathFlags=", - iGoalNode, iCurrentNode); + iGoalNode, iCurrentNode); switch (iPathFlags) { - case PATH_NONE: - std::strncat(buffer, "PATH_NONE ", 180); - break; - case PATH_DANGER: - std::strncat(buffer, "PATH_DANGER ", 180); - break; - case PATH_CONTACT: - std::strncat(buffer, "PATH_CONTACT ", 180); - break; - case PATH_CAMP: - std::strncat(buffer, "PATH_CAMP ", 180); - break; - default: - std::strncat(buffer, "???", 180); + case PATH_NONE: + std::strncat(buffer, "PATH_NONE ", 180); + break; + case PATH_DANGER: + std::strncat(buffer, "PATH_DANGER ", 180); + break; + case PATH_CONTACT: + std::strncat(buffer, "PATH_CONTACT ", 180); + break; + case PATH_CAMP: + std::strncat(buffer, "PATH_CAMP ", 180); + break; + default: + std::strncat(buffer, "???", 180); } std::strncat(buffer, "\n", 180); rblog(buffer); @@ -4093,20 +4084,23 @@ void cBot::clearHostageToRescueTarget() { } // Finds a free hostage pointer and assigns it. -void cBot::rememberHostageIsFollowingMe(edict_t *pHostage) { +void cBot::rememberHostageIsFollowingMe(edict_t* pHostage) { if (pHostage == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "ERROR assigning NULL pHostage pointer!?"); } if (hostage1 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage1 slot is free."); hostage1 = pHostage; - } else if (hostage2 == nullptr) { + } + else if (hostage2 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage2 slot is free."); hostage2 = pHostage; - } else if (hostage3 == nullptr) { + } + else if (hostage3 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage3 slot is free."); hostage3 = pHostage; - } else if (hostage4 == nullptr) { + } + else if (hostage4 == nullptr) { rprint_trace("rememberHostageIsFollowingMe", "hostage4 slot is free."); hostage4 = pHostage; } @@ -4119,7 +4113,7 @@ void cBot::checkIfHostagesAreRescued() { if (isHostageRescued(this, hostage4)) forgetHostage(hostage4); } -bool cBot::isOnSameTeamAs(const cBot *pBot) const +bool cBot::isOnSameTeamAs(const cBot* pBot) const { if (pBot == nullptr) return false; return pBot->iTeam == this->iTeam; @@ -4128,13 +4122,13 @@ bool cBot::isOnSameTeamAs(const cBot *pBot) const bool cBot::wantsToBuyStuff() const { return buy_secondary == true || - buy_primary == true || - buy_ammo_primary == true || - buy_ammo_secondary == true || - buy_armor == true || - buy_defusekit == true || - buy_grenade == true || - buy_flashbang > 0; + buy_primary == true || + buy_ammo_primary == true || + buy_ammo_secondary == true || + buy_armor == true || + buy_defusekit == true || + buy_grenade == true || + buy_flashbang > 0; } bool cBot::isUsingConsole() const @@ -4145,20 +4139,20 @@ bool cBot::isUsingConsole() const bool cBot::shouldBeAbleToMove() const { return !isDead() && - !isFreezeTime() && - !shouldCamp() && - !shouldWait() && - !shouldActWithC4(); - // !isDucking() && - // !isJumping(); + !isFreezeTime() && + !shouldCamp() && + !shouldWait() && + !shouldActWithC4(); + // !isDucking() && + // !isJumping(); } -edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const +edict_t* cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const { TraceResult tr; const Vector vOrigin = pEdict->v.origin; - const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + const tNode* node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); //Using TraceHull to detect de_aztec bridge and other entities. //DONT_IGNORE_MONSTERS, we reached it only when there are no other bots standing in our way! @@ -4182,7 +4176,7 @@ edict_t *cBot::getEntityBetweenMeAndCurrentPathNodeToHeadFor() const */ float cBot::getDistanceToNextNode() const { - const tNode *node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); + const tNode* node = NodeMachine.getNode(getCurrentPathNodeToHeadFor()); if (node) { return getDistanceTo(node->origin); } @@ -4190,14 +4184,14 @@ float cBot::getDistanceToNextNode() const } void cBot::setBodyToNode(const int nodeIndex) { - const tNode *node = NodeMachine.getNode(nodeIndex); + const tNode* node = NodeMachine.getNode(nodeIndex); if (node) { vBody = node->origin; } } void cBot::lookAtNode(const int nodeIndex) { - const tNode *node = NodeMachine.getNode(nodeIndex); + const tNode* node = NodeMachine.getNode(nodeIndex); if (node) { vHead = node->origin; } @@ -4229,9 +4223,10 @@ void cBot::increaseTimeToMoveToNode(const float timeInSeconds) { const float timeToMoveToNodeRemaining = getMoveToNodeTimeRemaining(); char msg[255] = {}; snprintf(msg, sizeof(msg), "increaseTimeToMoveToNode with %f for the %d time, making time to move to node remaining %f.", - timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); + timeInSeconds, nodeTimeIncreasedAmount, timeToMoveToNodeRemaining); rprint_trace("increaseTimeToMoveToNode", msg); - } else { + } + else { rprint_trace("increaseTimeToMoveToNode", "Refused to increase time"); } } @@ -4330,7 +4325,7 @@ bool cBot::isWalking() { return b; } -void cBot::doJump(const Vector &vector) { +void cBot::doJump(const Vector& vector) { rprint_trace("doJump", "With vector"); // stay focussed with body and head to this vector this->vHead = vector; @@ -4398,14 +4393,14 @@ void cBot::doDuckJump(const Vector& vector) { doDuckJump(); } -void cBot::doDuckJump(){ +void cBot::doDuckJump() { rprint_trace("doDuckJump", "no vector"); - UTIL_BotPressKey(this, IN_DUCK); + UTIL_BotPressKey(this, IN_DUCK); this->f_hold_duck = gpGlobals->time + 0.75f; UTIL_BotPressKey(this, IN_JUMP); this->f_jump_time = gpGlobals->time + 0.75f; - + this->increaseTimeToMoveToNode(0.75f); } @@ -4413,7 +4408,7 @@ void cBot::doDuckJump(){ // in order to properly duck jump. bool cBot::isDuckJumping() { const bool b = keyPressed(IN_JUMP) && keyPressed(IN_DUCK) || - this->f_hold_duck > gpGlobals->time && this->f_jump_time > gpGlobals->time ; + this->f_hold_duck > gpGlobals->time && this->f_jump_time > gpGlobals->time; if (b) { rprint_trace("isDuckJumping", "Yes I am DuckJumping"); } @@ -4536,4 +4531,4 @@ bool cBot::isDuckJumping() { // - Log() works properly now // - Clearing in dll.cpp of reallog.txt at dll init // - Logging works now, add REALBOT_PRINT() at every point you want to log something. -// +// \ No newline at end of file diff --git a/bot.h b/bot.h index 5d3e1db..b6e0b27 100644 --- a/bot.h +++ b/bot.h @@ -6,7 +6,7 @@ ** * DISCLAIMER * - * History, Information & Credits: + * History, Information & Credits: * RealBot is based partially upon the HPB-Bot Template #3 by Botman * Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3) * Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And @@ -18,9 +18,9 @@ * * Pierre Marie Baty * Count-Floyd - * + * * !! BOTS-UNITED FOREVER !! - * + * * This project is open-source, it is protected under the GPL license; * By using this source-code you agree that you will ALWAYS release the * source-code with your project. @@ -110,7 +110,7 @@ constexpr int DMG_SLOWBURN = (1 << 21); // in an oven constexpr int DMG_SLOWFREEZE = (1 << 22); // in a subzero freezer; // define some function prototypes... -void FakeClientCommand(edict_t *pBot, const char *arg1, const char *arg2, const char *arg3); +void FakeClientCommand(edict_t* pBot, const char* arg1, const char* arg2, const char* arg3); constexpr int LADDER_UNKNOWN = 0; constexpr int LADDER_UP = 1; @@ -146,10 +146,10 @@ typedef struct { int iAmmo1; // amount of ammo in primary reserve int iAmmo2; // amount of ammo in secondary reserve } - bot_current_weapon_t; +bot_current_weapon_t; /* - Bot is a class now + Bot is a class now */ class cBot { @@ -159,13 +159,13 @@ class cBot { int pathIndex; // Index on theWhich node we want to move to, derived from Path // Hostages edict - edict_t *pBotHostage; // the Hostage we will go after! - edict_t *hostage1; // we do not - edict_t *hostage2; // use - edict_t *hostage3; // any array - edict_t *hostage4; // here + edict_t* pBotHostage; // the Hostage we will go after! + edict_t* hostage1; // we do not + edict_t* hostage2; // use + edict_t* hostage3; // any array + edict_t* hostage4; // here - edict_t *pEnemyEdict; // Enemy edict + edict_t* pEnemyEdict; // Enemy edict float fMoveToNodeTime; // How long we should take to move to next node. int nodeTimeIncreasedAmount; // how many times did we increase the time to reach node? @@ -182,14 +182,14 @@ class cBot { cBot(); // Hostage related - bool isUsingHostage(edict_t *pHostage); - void forgetHostage(edict_t *pHostage); - void rememberHostageIsFollowingMe(edict_t *pHostage); - void rememberWhichHostageToRescue(edict_t *pHostage); + bool isUsingHostage(edict_t* pHostage); + void forgetHostage(edict_t* pHostage); + void rememberHostageIsFollowingMe(edict_t* pHostage); + void rememberWhichHostageToRescue(edict_t* pHostage); void clearHostageToRescueTarget(); int getAmountOfHostagesBeingRescued() const; - edict_t * findHostageToRescue(); // finds a hostage to rescue - edict_t * getHostageToRescue() const; // returns hostage state pointer + edict_t* findHostageToRescue(); // finds a hostage to rescue + edict_t* getHostageToRescue() const; // returns hostage state pointer bool isEscortingHostages(); // Does the bot has used any hostages yet? void checkOfHostagesStillFollowMe(); @@ -336,10 +336,12 @@ class cBot { char chChatSentence[160]; // ------------------------ - // - // ------------------------ - - edict_t *pEdict; // Edict_t of the bot + // POINTERS + // ------------------------ + edict_t* pBreakableEdict; // Breakable edict + edict_t* pButtonEdict; // button edict + edict_t* killer_edict; // Killer edict + edict_t* pEdict; // Edict_t of the bot char name[BOT_NAME_LEN + 1]; char skin[BOT_SKIN_LEN + 1]; @@ -370,10 +372,6 @@ class cBot { float f_bot_see_enemy_time; float f_bot_find_enemy_time; - edict_t *pButtonEdict; // button edict - - edict_t *killer_edict; // Killer edict - Vector vecMoveAngles; // Vector we move to @@ -417,7 +415,7 @@ class cBot { bool canSeeVector(const Vector& vDest) const; - bool canSeeEntity(edict_t *pEntity) const; + bool canSeeEntity(edict_t* pEntity) const; void InteractWithFriends(); @@ -454,8 +452,8 @@ class cBot { bool hasFavoriteSecondaryWeaponPreference() const; bool hasPrimaryWeaponEquiped() const; bool hasSecondaryWeaponEquiped() const; - bool hasPrimaryWeapon(int weaponId) const; - bool hasSecondaryWeapon(int weaponId) const; + //bool hasPrimaryWeapon(int weaponId) const; + //bool hasSecondaryWeapon(int weaponId) const; bool canAfford(int price) const; //price muddled with weaponId? [APG]RoboCop[CL] // ------------------- @@ -469,19 +467,19 @@ class cBot { // void / action methods void pickWeapon(int weaponId); void performBuyActions(int weaponIdToBuy); - void performBuyWeapon(const char *menuItem, const char *subMenuItem); + void performBuyWeapon(const char* menuItem, const char* subMenuItem); // ------------------- void CheckAround(); // Check around body // ------------------- - + bool hasEnemy() const; - bool hasEnemy(const edict_t * pEntity) const; - edict_t * getEnemyEdict() const; + bool hasEnemy(const edict_t* pEntity) const; + edict_t* getEnemyEdict() const; bool hasGoal() const; bool hasGoalIndex() const; - tGoal *getGoalData() const; + tGoal* getGoalData() const; bool shouldBeWandering(); bool hasBomb() const; @@ -495,7 +493,7 @@ class cBot { void forgetGoal(); void forgetPath(); void forgetEnemy(); - void setGoalNode(tGoal *goal); + void setGoalNode(tGoal* goal); void setGoalNode(int nodeIndex); void setGoalNode(int nodeIndex, int iGoalIndex); @@ -519,13 +517,13 @@ class cBot { void NewRound(); // When bot enters new round // Debug ------- - void rprint(const char *Function, const char *msg); // low - void rprint_normal(const char *Function, const char *msg); // normal - void rprint_trace(const char *Function, const char *msg); // trace + void rprint(const char* Function, const char* msg); // low + void rprint_normal(const char* Function, const char* msg); // normal + void rprint_trace(const char* Function, const char* msg); // trace - void rprint(const char *msg); - void rprint_normal(const char *msg); - void rprint_trace(const char *msg); + void rprint(const char* msg); + void rprint_normal(const char* msg); + void rprint_trace(const char* msg); void Dump(); bool hasHostageToRescue() const; @@ -534,11 +532,11 @@ class cBot { void checkIfHostagesAreRescued(); - bool isOnSameTeamAs(const cBot *pBot) const; + bool isOnSameTeamAs(const cBot* pBot) const; bool shouldBeAbleToMove() const; - edict_t *getEntityBetweenMeAndCurrentPathNodeToHeadFor() const; + edict_t* getEntityBetweenMeAndCurrentPathNodeToHeadFor() const; float getDistanceToNextNode() const; @@ -567,13 +565,13 @@ class cBot { bool createPath(int destinationNode, int flags); bool createPath(int destinationNode); - void doJump(const Vector &vector); + void doJump(const Vector& vector); void doJump(); bool isJumping(); // Experimental DuckJump added for the NodeMachine [APG]RoboCop[CL] void doDuckJump(const Vector& vector); - void doDuckJump(); + void doDuckJump(); bool isDuckJumping(); void doDuck(); @@ -588,65 +586,65 @@ class cBot { }; // new UTIL.CPP functions... -edict_t *UTIL_FindEntityInSphere(edict_t *pentStart, - const Vector &vecCenter, float flRadius); +edict_t* UTIL_FindEntityInSphere(edict_t* pentStart, + const Vector& vecCenter, float flRadius); -edict_t *UTIL_FindEntityByString(edict_t *pentStart, - const char *szKeyword, - const char *szValue); +edict_t* UTIL_FindEntityByString(edict_t* pentStart, + const char* szKeyword, + const char* szValue); -edict_t *UTIL_FindEntityByClassname(edict_t *pentStart, - const char *szName); +edict_t* UTIL_FindEntityByClassname(edict_t* pentStart, + const char* szName); -edict_t *UTIL_FindEntityByTargetname(edict_t *pentStart, - const char *szName); +edict_t* UTIL_FindEntityByTargetname(edict_t* pentStart, + const char* szName); -void ClientPrint(edict_t *pEdict, int msg_dest, const char *msg_name); +void ClientPrint(edict_t* pEdict, int msg_dest, const char* msg_name); -void UTIL_SayText(const char *pText, edict_t *pEdict); +void UTIL_SayText(const char* pText, edict_t* pEdict); -void UTIL_HostSay(edict_t *pEntity, int teamonly, char *message); +void UTIL_HostSay(edict_t* pEntity, int teamonly, char* message); -int UTIL_GetTeam(edict_t *pEntity); +int UTIL_GetTeam(edict_t* pEntity); -int UTIL_GetClass(edict_t *pEntity); +int UTIL_GetClass(edict_t* pEntity); -bool IsAlive(edict_t *pEdict); +bool IsAlive(edict_t* pEdict); -bool FInViewCone(Vector *pOrigin, edict_t *pEdict); +bool FInViewCone(Vector* pOrigin, edict_t* pEdict); -bool FVisible(const Vector &vecOrigin, edict_t *pEdict); +bool FVisible(const Vector& vecOrigin, edict_t* pEdict); -Vector Center(edict_t *pEdict); +Vector Center(edict_t* pEdict); -Vector GetGunPosition(edict_t *pEdict); +Vector GetGunPosition(edict_t* pEdict); -Vector VecBModelOrigin(edict_t *pEdict); +Vector VecBModelOrigin(edict_t* pEdict); -void UTIL_ShowMenu(edict_t *pEdict, int slots, int displaytime, bool needmore, const char *pText); +void UTIL_ShowMenu(edict_t* pEdict, int slots, int displaytime, bool needmore, const char* pText); -void UTIL_SelectItem(edict_t *pEdict, const char *item_name); +void UTIL_SelectItem(edict_t* pEdict, const char* item_name); -void UTIL_BuildFileName(char *filename, const char *arg1, const char *arg2); +void UTIL_BuildFileName(char* filename, const char* arg1, const char* arg2); -void UTIL_BuildFileNameRB(const char *subdir, char *filename); +void UTIL_BuildFileNameRB(const char* subdir, char* filename); unsigned short fixed_unsigned16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] short fixed_signed16(float value, float scale); //redundant declaration? [APG]RoboCop[CL] -void HUD_DrawString(int r, int g, int b, const char *msg, edict_t *edict); +void HUD_DrawString(int r, int g, int b, const char* msg, edict_t* edict); -void UTIL_FixAngles(Vector *Angles); +void UTIL_FixAngles(Vector* Angles); -void UTIL_SayTextBot(const char *pText, cBot *pBot); +void UTIL_SayTextBot(const char* pText, cBot* pBot); // combat.h // Bot specific -int UTIL_GetBotIndex(edict_t *pEdict); +int UTIL_GetBotIndex(edict_t* pEdict); -cBot *UTIL_GetBotPointer(edict_t *pEdict); +cBot* UTIL_GetBotPointer(edict_t* pEdict); // IniParser.ini void INI_Section(char input[80], char section[30]); diff --git a/bot_func.cpp b/bot_func.cpp index cc80cd9..3003128 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -57,7 +57,7 @@ extern cNodeMachine NodeMachine; // For taking cover decision constexpr int TOTAL_SCORE = 16300; // 16000 money + 100 health + 100 fear + 100 camp desire; -bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *checkname) { +bool VectorIsVisibleWithEdict(edict_t* pEdict, const Vector& dest, const char* checkname) { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -82,7 +82,7 @@ bool VectorIsVisibleWithEdict(edict_t *pEdict, const Vector& dest, const char *c return tr.flFraction >= 1.0f; } -bool VectorIsVisible(const Vector& start, const Vector& dest, const char *checkname) { +bool VectorIsVisible(const Vector& start, const Vector& dest, const char* checkname) { TraceResult tr; // trace a line from bot's eyes to destination... @@ -492,7 +492,7 @@ Vector FUNC_CalculateAngles(const cBot* pBot) { return v_body; } -bool BotShouldDuck(cBot *pBot) { +bool BotShouldDuck(cBot* pBot) { if (pBot->iDuckTries > 3) { // tried to duck 3 times, so no longer! pBot->rprint_trace("BotShouldDuck", "Returning false because ducked too many times."); @@ -594,7 +594,7 @@ bool FUNC_PlayerRuns(const int speed) { // return weapon type of edict. // only when 'important enough'. -int FUNC_EdictHoldsWeapon(const edict_t *pEdict) { +int FUNC_EdictHoldsWeapon(const edict_t* pEdict) { const std::string weaponModel = STRING(pEdict->v.weaponmodel); // sniper guns //if (weaponModel == "models/p_awp.mdl") //Excluded for high prices and accuracy [APG]RoboCop[CL] @@ -795,6 +795,24 @@ bool FUNC_IsOnLadder(const edict_t* pEntity) { return pEntity->v.movetype == MOVETYPE_FLY; } +bool IsShootableBreakable(edict_t* pent) +{ + if (FStrEq("func_breakable", STRING(pent->v.classname))) + { + // breakable glass etc. + if (pent->v.spawnflags & 1) // SF_BREAK_TRIGGER_ONLY + return false; + + if (pent->v.health > 0) + return true; + } + else if (FStrEq("func_pushable", STRING(pent->v.classname)) && (pent->v.spawnflags & 2)) // SF_PUSH_BREAKABLE + { + return true; + } + return false; +} + void FUNC_FindBreakable(cBot* pBot) { // The "func_breakable" entity is required for bots to recognize and attack @@ -809,45 +827,19 @@ void FUNC_FindBreakable(cBot* pBot) // Search for entities within a 256-unit radius around the bot while ((pent = UTIL_FindEntityInSphere(pent, pEntity->v.origin, 256.0f)) != nullptr) { - if (pent == pEntity || (pent->v.flags & FL_DORMANT)) { - continue; // Skip self and dormant entities + if (pent == pEntity || (pent->v.flags & FL_DORMANT) || pent->v.health <= 0) { + continue; // Skip self, dormant, and already broken entities } - const char* classname = STRING(pent->v.classname); - - if (classname != nullptr && std::strcmp(classname, "func_breakable") == 0) { - if (FVisible(pent->v.origin, pEntity)) { - // Set the breakable entity as the bot's enemy - pBot->pEdict->v.enemy = pent; - - // Aim at the breakable entity - pBot->vBody = pent->v.origin; - pBot->vHead = pent->v.origin; - - // Shoot at the breakable entity - UTIL_BotPressKey(pBot, IN_ATTACK); - return; // Exit after finding the first visible breakable entity + if (IsShootableBreakable(pent)) { + if (pBot->canSeeEntity(pent)) { + pBot->pBreakableEdict = pent; + return; } } } } -/*bool IsShootableBreakable(edict_t* pent) // KWo - 08.02.2006 -{ - if (pent == nullptr) - return false; - - return (FStrEq("func_breakable", STRING(pent->v.classname)) - && (pent->v.playerclass == 1 || pent->v.health == 0 - || pent->v.health > 1 && pent->v.health < 1000 - || pent->v.rendermode == 4) // KWo - 21.02.2006 - br. crates has rendermode 4 - || FStrEq("func_pushable", STRING(pent->v.classname)) - && pent->v.health < 1000 && pent->v.spawnflags & SF_PUSH_BREAKABLE) // KWo - 03.02.2007 - && pent->v.impulse == 0 - && pent->v.takedamage > 0 - && !(pent->v.spawnflags & SF_BREAK_TRIGGER_ONLY); -}*/ - void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] { // Check if the bot has a bomb planted. From 6648e670feb44528384ca48d88e6161e8a47f52d Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 18 Sep 2025 22:05:05 +0100 Subject: [PATCH 107/114] More attempts to func_breakable code --- bot.cpp | 169 +++++++++++++++++++++++++++++++++++++-------------- bot.h | 2 + bot_func.cpp | 22 ++++--- 3 files changed, 140 insertions(+), 53 deletions(-) diff --git a/bot.cpp b/bot.cpp index 4ef0336..9369e94 100644 --- a/bot.cpp +++ b/bot.cpp @@ -759,7 +759,8 @@ void cBot::FightEnemy() { if (zoomed > ZOOM_TWICE) zoomed = ZOOM_NONE; } - } else if (FUNC_BotHoldsZoomWeapon(this)) { + } + else if (FUNC_BotHoldsZoomWeapon(this)) { if (zoomed < ZOOM_ONCE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); f_allow_keypress = gpGlobals->time + 0.7f; @@ -779,13 +780,15 @@ void cBot::FightEnemy() { if (FUNC_DoRadio(this)) { UTIL_BotRadioMessage(this, 3, "3", ""); // need backup } - } else { + } + else { // DECIDE: Should we take cover or not. if (FUNC_ShouldTakeCover(this)) { FindCover(); } } - } else { + } + else { } @@ -800,7 +803,8 @@ void cBot::FightEnemy() { rprint_trace("FightEnemy()", "Lost enemy out of sight, forgetting path and goal"); forgetPath(); forgetGoal(); - } else { + } + else { // When we have the enemy for the first time out of sight // we calculate a path to the last seen position @@ -814,7 +818,8 @@ void cBot::FightEnemy() { } bFirstOutOfSight = true; - } else { + } + else { if (!hasGoal()) { rprint("Enemy out of sight and no goal, forgetting enemy"); forgetEnemy(); @@ -969,7 +974,8 @@ void cBot::PickBestWeapon() { UTIL_BotPressKey(this, IN_RELOAD); f_update_weapon_time = gpGlobals->time + 0.7f; // update timer // return; - } else { + } + else { // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code // a bit though. Btw, distance 600 is too far for slashing :) @@ -982,7 +988,8 @@ void cBot::PickBestWeapon() { // select primary weapon UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); // select the primary //return; - } else { + } + else { if (iSecondaryWeapon > -1 && current_weapon.iId != iSecondaryWeapon && // that's not the current, empty gun @@ -990,7 +997,8 @@ void cBot::PickBestWeapon() { { UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); // select the secondary //return; - } else { + } + else { if (isOwningWeapon(CS_WEAPON_KNIFE) && // we have a knife (for non-knife maps) !isHoldingWeapon(CS_WEAPON_KNIFE)) // but we do not carry it { @@ -1033,7 +1041,8 @@ void cBot::FireWeapon() { f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05f, 0.2f); } - } else if (CarryWeaponType() == PRIMARY) { + } + else if (CarryWeaponType() == PRIMARY) { // We may shoot, use shooting rate. // TODO TODO TODO: Add shooting rates in BUYTABLE.INI if (f_prim_weapon < gpGlobals->time) { @@ -1055,7 +1064,8 @@ void cBot::FireWeapon() { f_prim_weapon = gpGlobals->time + f_burst; f_shoot_wait_time = gpGlobals->time + (f_burst * 3); - } else // other weapons + } + else // other weapons { float f_burst = 0.1f; if (fDistance > 300 && bot_skill < 6) { @@ -1088,7 +1098,8 @@ void cBot::FireWeapon() { // COVER: Take cover, using tracelines all the time! FindCover(); } - } else if (f_gren_time + 0.5f < gpGlobals->time) { + } + else if (f_gren_time + 0.5f < gpGlobals->time) { // NOTE: Should not happen, a bot cannot 'forget' this... f_gren_time = gpGlobals->time + 1; } @@ -1106,12 +1117,14 @@ void cBot::FireWeapon() { if (fDistance > 550) { if (hasShieldDrawn()) { // when the enemy is far away, we keep it - } else { + } + else { // draw shield! UTIL_BotPressKey(this, IN_ATTACK2); // secondary attack makes shield draw f_allow_keypress = gpGlobals->time + 0.7f; } - } else { + } + else { // get weapon here. if (hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { rblog @@ -1120,7 +1133,8 @@ void cBot::FireWeapon() { f_allow_keypress = gpGlobals->time + 0.7f; } } - } else { + } + else { // debug print REALBOT_PRINT(this, "FireWeapon()", "Unknown weapon"); } @@ -1184,7 +1198,8 @@ void cBot::Combat() { char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { snprintf(msg, sizeof(msg), "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); - } else { + } + else { snprintf(msg, sizeof(msg), "A RealBot named %s has killed you!", name); } @@ -1278,7 +1293,8 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_left; - } else + } + else cover_vect = v_left; } } @@ -1304,7 +1320,8 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_right; - } else + } + else cover_vect = v_right; } } @@ -1324,7 +1341,8 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_left; - } else + } + else cover_vect = v_left; } } @@ -1347,7 +1365,8 @@ void cBot::FindCover() { createPath(iCoverNode); f_cover_time = gpGlobals->time + 8.0f; bTakenCover = true; - } else { + } + else { // -------------------------------------------------- // If cover_vect is found, we find a node close to it @@ -1430,7 +1449,8 @@ void cBot::InteractWithFriends() { } if (bCanSeePlayer) {} - } else // it is a teammate, but it is human (or a different bot) + } + else // it is a teammate, but it is human (or a different bot) { // when firing @@ -1474,7 +1494,8 @@ void cBot::InteractWithPlayers() { } if (zoomed > ZOOM_TWICE) zoomed = ZOOM_NONE; - } else if (FUNC_BotHoldsZoomWeapon(this)) { + } + else if (FUNC_BotHoldsZoomWeapon(this)) { // Unzoom (for other guns with only 1 zoom) if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { @@ -1482,7 +1503,8 @@ void cBot::InteractWithPlayers() { f_allow_keypress = gpGlobals->time + 0.7f; zoomed = ZOOM_NONE; } - } else { + } + else { // For any weapon that has a silencer (the colt for example), use it if we want that. if (isHoldingWeapon(CS_WEAPON_M4A1)) @@ -1722,21 +1744,24 @@ vec_t cBot::ReturnTurnedAngle(float speed, float current, const float ideal) { else current += speed; - } else if (current >= 0.0f && ideal < 0.0f) { + } + else if (current >= 0.0f && ideal < 0.0f) { current_180 = current - 180.0f; if (current_180 > ideal) current += speed; else current -= speed; - } else if (current < 0 && ideal >= 0) { + } + else if (current < 0 && ideal >= 0) { current_180 = current + 180; if (current_180 > ideal) current += speed; else current -= speed; - } else // (current < 0) && (ideal < 0) both negative + } + else // (current < 0) && (ideal < 0) both negative { if (current > ideal) current -= speed; @@ -1842,7 +1867,8 @@ bool cBot::Defuse() { UTIL_BotPressKey(this, IN_USE); } - } else { + } + else { rprint_trace("Defuse()", "I can see C4, but it is out of reach."); const int iC4Node = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); if (iC4Node < 0) { @@ -1858,10 +1884,12 @@ bool cBot::Defuse() { forgetPath(); forgetGoal(); setGoalNode(iC4Node); - } else { + } + else { rprint_normal("Defuse()", "I already have a goal towards the C4!"); } - } else { + } + else { rprint_normal("Defuse()", "C4 is somewhere without a close node."); } setMoveSpeed(f_max_speed); @@ -1910,7 +1938,8 @@ void cBot::Act() { vHead = vBody = Game.vDroppedC4; } } - } else { + } + else { // Look at iGoalNode if (iGoalNode > -1) { @@ -1941,7 +1970,8 @@ void cBot::Act() { // When no C4 selected yet, select it if (!isHoldingWeapon(CS_WEAPON_C4)) { UTIL_SelectItem(pEdict, "weapon_c4"); - } else { + } + else { UTIL_BotPressKey(this, IN_ATTACK); // plant it! } @@ -1953,7 +1983,8 @@ void cBot::Act() { iPathFlags = PATH_CAMP; forgetPath(); } - } else { + } + else { // counter-terrorist Defuse(); // old routine from RB AI V1.0 defusing, should get here and more cleaned up } @@ -2346,7 +2377,8 @@ void cBot::setGoalNode(const int nodeIndex, const int iGoalIndex) { goalPtr->name, goalPtr->iChecked ); - } else { + } + else { snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); } rprint("setGoalNode()", msg); @@ -2680,7 +2712,8 @@ void cBot::performBuyActions(const int weaponIdToBuy) { break; //whats about nightvision? BuyWeapon (pBot, "8", "7") } - } else // terror + } + else // terror { switch (weaponIdToBuy) { case CS_WEAPON_SCOUT: @@ -2747,7 +2780,8 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } else { + } + else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2775,7 +2809,8 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } else { + } + else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2799,7 +2834,8 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } else { + } + else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2855,7 +2891,8 @@ void cBot::Memory() { f_camp_time = gpGlobals->time + fTime; } - } else { + } + else { fMemoryTime = gpGlobals->time + 5.0f; } @@ -2881,7 +2918,8 @@ void cBot::Memory() { if (f_update_weapon_time + 2 < gpGlobals->time) { PickBestWeapon(); } - } else { + } + else { vEar = Vector(9999, 9999, 9999); // // // check for any 'beeps' of the bomb! @@ -2909,7 +2947,8 @@ void cBot::Memory() { // } } - } else { + } + else { vEar = Vector(9999, 9999, 9999); } } @@ -2983,17 +3022,20 @@ void cBot::ThinkAboutGoals() { // A dropped C4 is not a 'goal' (ie. it won't let you win the game // when you pick up the bomb. Therefor the 'pickup the dropped bomb // code is in cNodeMachine::path_walk(). - } else if (isCounterTerrorist()) { + } + else if (isCounterTerrorist()) { // COUNTER-TERRORISTS if (vip) { // VIP - } else { + } + else { if (Game.bBombPlanted) { if (isCounterTerrorist()) { // defuse (or set timers for it) Defuse(); } - } else { + } + else { if (Game.bHostageRescueMap) { TryToGetHostageTargetToFollowMe(this); checkIfHostagesAreRescued(); @@ -3208,7 +3250,8 @@ void cBot::Think() { PrepareChat(chSentence); } } - } else { + } + else { // we missed the chatrate chance if (fChatTime < gpGlobals->time) // time if (chChatSentence[0] == '\0') // we did not want to say anything @@ -3254,7 +3297,8 @@ void cBot::Think() { // prevent division by zero if (movedTwoTimes > 0.0f) { distanceMoved = movedTwoTimes / 2.0f; - } else { + } + else { distanceMoved = 0.0f; } @@ -3349,7 +3393,8 @@ void cBot::Think() { break; } } - } else { + } + else { while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && func_distance(pent->v.origin, pEdict->v.origin) > 50) { @@ -3367,6 +3412,29 @@ void cBot::Think() { return; } + // Check if bot is stuck + if (fNotStuckTime < gpGlobals->time) + { + if (isStuck()) + { + // The bot is stuck, find a breakable if it's in the way + FUNC_FindBreakable(this); + if (pBreakableEdict != nullptr) + { + // Found a breakable, attack it + Combat(); + // Reset stuck timer + fNotStuckTime = gpGlobals->time + 2.0f; + return; + } + } + else + { + // Bot is not stuck, reset stuck timer + fNotStuckTime = gpGlobals->time + 2.0f; + } + } + // **---**---**---**---**---**---** // MAIN STATE: We have no enemy... // **---**---**---**---**---**---** @@ -3422,7 +3490,8 @@ void cBot::Think() { // Think about objectives ThinkAboutGoals(); - } else { + } + else { // **---**---**---**---**---**---** // MAIN STATE: We have an enemy! // **---**---**---**---**---**---** @@ -4415,6 +4484,14 @@ bool cBot::isDuckJumping() { return b; } +bool cBot::isStuck() const +{ + if (distanceMoved < 1.0f && f_move_speed > 0.0f) { + return true; + } + return false; +} + // $Log: bot.cpp,v $ // Revision 1.21 2004/09/07 18:23:02 eric // - bumped version to 3061 diff --git a/bot.h b/bot.h index b6e0b27..42762c4 100644 --- a/bot.h +++ b/bot.h @@ -574,6 +574,8 @@ class cBot { void doDuckJump(); bool isDuckJumping(); + bool isStuck() const; + void doDuck(); bool isDucking(); bool isWalking(); diff --git a/bot_func.cpp b/bot_func.cpp index 3003128..fbb7cac 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -797,19 +797,27 @@ bool FUNC_IsOnLadder(const edict_t* pEntity) { bool IsShootableBreakable(edict_t* pent) { - if (FStrEq("func_breakable", STRING(pent->v.classname))) + if (!pent) { + return false; + } + + const char* classname = STRING(pent->v.classname); + + if (FStrEq("func_breakable", classname)) { - // breakable glass etc. - if (pent->v.spawnflags & 1) // SF_BREAK_TRIGGER_ONLY + // Not shootable if it's trigger-only or already broken (health <= 0) + if ((pent->v.spawnflags & 1) || pent->v.health <= 0) // SF_BREAK_TRIGGER_ONLY return false; - if (pent->v.health > 0) - return true; + return true; } - else if (FStrEq("func_pushable", STRING(pent->v.classname)) && (pent->v.spawnflags & 2)) // SF_PUSH_BREAKABLE + + if (FStrEq("func_pushable", classname)) { - return true; + // Shootable if it's a breakable pushable + return (pent->v.spawnflags & 2) != 0; // SF_PUSH_BREAKABLE } + return false; } From 6e58ce0c76b90d8760994d5e1528896c7ba7733d Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Thu, 18 Sep 2025 22:20:44 +0100 Subject: [PATCH 108/114] Neatening code --- bot.cpp | 143 +++++++++++++++++++------------------------------------- 1 file changed, 49 insertions(+), 94 deletions(-) diff --git a/bot.cpp b/bot.cpp index 9369e94..ab570f9 100644 --- a/bot.cpp +++ b/bot.cpp @@ -759,8 +759,7 @@ void cBot::FightEnemy() { if (zoomed > ZOOM_TWICE) zoomed = ZOOM_NONE; } - } - else if (FUNC_BotHoldsZoomWeapon(this)) { + } else if (FUNC_BotHoldsZoomWeapon(this)) { if (zoomed < ZOOM_ONCE && f_allow_keypress < gpGlobals->time) { UTIL_BotPressKey(this, IN_ATTACK2); f_allow_keypress = gpGlobals->time + 0.7f; @@ -780,15 +779,13 @@ void cBot::FightEnemy() { if (FUNC_DoRadio(this)) { UTIL_BotRadioMessage(this, 3, "3", ""); // need backup } - } - else { + } else { // DECIDE: Should we take cover or not. if (FUNC_ShouldTakeCover(this)) { FindCover(); } } - } - else { + } else { } @@ -803,8 +800,7 @@ void cBot::FightEnemy() { rprint_trace("FightEnemy()", "Lost enemy out of sight, forgetting path and goal"); forgetPath(); forgetGoal(); - } - else { + } else { // When we have the enemy for the first time out of sight // we calculate a path to the last seen position @@ -818,8 +814,7 @@ void cBot::FightEnemy() { } bFirstOutOfSight = true; - } - else { + } else { if (!hasGoal()) { rprint("Enemy out of sight and no goal, forgetting enemy"); forgetEnemy(); @@ -974,8 +969,7 @@ void cBot::PickBestWeapon() { UTIL_BotPressKey(this, IN_RELOAD); f_update_weapon_time = gpGlobals->time + 0.7f; // update timer // return; - } - else { + } else { // Thanks to dstruct2k for easy ctrl-c/v, i optimized the code // a bit though. Btw, distance 600 is too far for slashing :) @@ -988,8 +982,7 @@ void cBot::PickBestWeapon() { // select primary weapon UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iPrimaryWeapon)); // select the primary //return; - } - else { + } else { if (iSecondaryWeapon > -1 && current_weapon.iId != iSecondaryWeapon && // that's not the current, empty gun @@ -997,8 +990,7 @@ void cBot::PickBestWeapon() { { UTIL_SelectItem(pEdict, UTIL_GiveWeaponName(iSecondaryWeapon)); // select the secondary //return; - } - else { + } else { if (isOwningWeapon(CS_WEAPON_KNIFE) && // we have a knife (for non-knife maps) !isHoldingWeapon(CS_WEAPON_KNIFE)) // but we do not carry it { @@ -1041,8 +1033,7 @@ void cBot::FireWeapon() { f_sec_weapon = gpGlobals->time + RANDOM_FLOAT(0.05f, 0.2f); } - } - else if (CarryWeaponType() == PRIMARY) { + } else if (CarryWeaponType() == PRIMARY) { // We may shoot, use shooting rate. // TODO TODO TODO: Add shooting rates in BUYTABLE.INI if (f_prim_weapon < gpGlobals->time) { @@ -1064,8 +1055,7 @@ void cBot::FireWeapon() { f_prim_weapon = gpGlobals->time + f_burst; f_shoot_wait_time = gpGlobals->time + (f_burst * 3); - } - else // other weapons + } else // other weapons { float f_burst = 0.1f; if (fDistance > 300 && bot_skill < 6) { @@ -1098,8 +1088,7 @@ void cBot::FireWeapon() { // COVER: Take cover, using tracelines all the time! FindCover(); } - } - else if (f_gren_time + 0.5f < gpGlobals->time) { + } else if (f_gren_time + 0.5f < gpGlobals->time) { // NOTE: Should not happen, a bot cannot 'forget' this... f_gren_time = gpGlobals->time + 1; } @@ -1117,14 +1106,12 @@ void cBot::FireWeapon() { if (fDistance > 550) { if (hasShieldDrawn()) { // when the enemy is far away, we keep it - } - else { + } else { // draw shield! UTIL_BotPressKey(this, IN_ATTACK2); // secondary attack makes shield draw f_allow_keypress = gpGlobals->time + 0.7f; } - } - else { + } else { // get weapon here. if (hasShieldDrawn() && f_allow_keypress < gpGlobals->time) { rblog @@ -1133,8 +1120,7 @@ void cBot::FireWeapon() { f_allow_keypress = gpGlobals->time + 0.7f; } } - } - else { + } else { // debug print REALBOT_PRINT(this, "FireWeapon()", "Unknown weapon"); } @@ -1198,8 +1184,7 @@ void cBot::Combat() { char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { snprintf(msg, sizeof(msg), "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); - } - else { + } else { snprintf(msg, sizeof(msg), "A RealBot named %s has killed you!", name); } @@ -1293,8 +1278,7 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_left; - } - else + } else cover_vect = v_left; } } @@ -1320,8 +1304,7 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_right; - } - else + } else cover_vect = v_right; } } @@ -1341,8 +1324,7 @@ void cBot::FindCover() { if (cover_vect != Vector(9999, 9999, 9999)) { if (RANDOM_LONG(0, 100) < 50) cover_vect = v_left; - } - else + } else cover_vect = v_left; } } @@ -1365,8 +1347,7 @@ void cBot::FindCover() { createPath(iCoverNode); f_cover_time = gpGlobals->time + 8.0f; bTakenCover = true; - } - else { + } else { // -------------------------------------------------- // If cover_vect is found, we find a node close to it @@ -1449,8 +1430,7 @@ void cBot::InteractWithFriends() { } if (bCanSeePlayer) {} - } - else // it is a teammate, but it is human (or a different bot) + } else // it is a teammate, but it is human (or a different bot) { // when firing @@ -1494,8 +1474,7 @@ void cBot::InteractWithPlayers() { } if (zoomed > ZOOM_TWICE) zoomed = ZOOM_NONE; - } - else if (FUNC_BotHoldsZoomWeapon(this)) { + } else if (FUNC_BotHoldsZoomWeapon(this)) { // Unzoom (for other guns with only 1 zoom) if (zoomed > ZOOM_NONE && f_allow_keypress < gpGlobals->time) { @@ -1503,8 +1482,7 @@ void cBot::InteractWithPlayers() { f_allow_keypress = gpGlobals->time + 0.7f; zoomed = ZOOM_NONE; } - } - else { + } else { // For any weapon that has a silencer (the colt for example), use it if we want that. if (isHoldingWeapon(CS_WEAPON_M4A1)) @@ -1744,24 +1722,21 @@ vec_t cBot::ReturnTurnedAngle(float speed, float current, const float ideal) { else current += speed; - } - else if (current >= 0.0f && ideal < 0.0f) { + } else if (current >= 0.0f && ideal < 0.0f) { current_180 = current - 180.0f; if (current_180 > ideal) current += speed; else current -= speed; - } - else if (current < 0 && ideal >= 0) { + } else if (current < 0 && ideal >= 0) { current_180 = current + 180; if (current_180 > ideal) current += speed; else current -= speed; - } - else // (current < 0) && (ideal < 0) both negative + } else // (current < 0) && (ideal < 0) both negative { if (current > ideal) current -= speed; @@ -1867,8 +1842,7 @@ bool cBot::Defuse() { UTIL_BotPressKey(this, IN_USE); } - } - else { + } else { rprint_trace("Defuse()", "I can see C4, but it is out of reach."); const int iC4Node = NodeMachine.getClosestNode(vC4, distanceForC4ToBeInReach, nullptr); if (iC4Node < 0) { @@ -1884,12 +1858,10 @@ bool cBot::Defuse() { forgetPath(); forgetGoal(); setGoalNode(iC4Node); - } - else { + } else { rprint_normal("Defuse()", "I already have a goal towards the C4!"); } - } - else { + } else { rprint_normal("Defuse()", "C4 is somewhere without a close node."); } setMoveSpeed(f_max_speed); @@ -1910,7 +1882,7 @@ void cBot::Act() { if (chChatSentence[0] != '\0') { UTIL_SayTextBot(chChatSentence, this); std::memset(chChatSentence, 0, sizeof(chChatSentence)); - } + } } // camp @@ -2377,8 +2349,7 @@ void cBot::setGoalNode(const int nodeIndex, const int iGoalIndex) { goalPtr->name, goalPtr->iChecked ); - } - else { + } else { snprintf(msg, sizeof(msg), "Setting iGoalNode to [%d] and goalIndex [%d] - could not retrieve goal data.", nodeIndex, goalIndex); } rprint("setGoalNode()", msg); @@ -2712,8 +2683,7 @@ void cBot::performBuyActions(const int weaponIdToBuy) { break; //whats about nightvision? BuyWeapon (pBot, "8", "7") } - } - else // terror + } else // terror { switch (weaponIdToBuy) { case CS_WEAPON_SCOUT: @@ -2780,8 +2750,7 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } - else { + } else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2809,8 +2778,7 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } - else { + } else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2834,8 +2802,7 @@ void cBot::Memory() { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } - } - else { + } else { vHear = pPlayer->v.origin; pHearPlayer = pPlayer; } @@ -2891,8 +2858,7 @@ void cBot::Memory() { f_camp_time = gpGlobals->time + fTime; } - } - else { + } else { fMemoryTime = gpGlobals->time + 5.0f; } @@ -2918,8 +2884,7 @@ void cBot::Memory() { if (f_update_weapon_time + 2 < gpGlobals->time) { PickBestWeapon(); } - } - else { + } else { vEar = Vector(9999, 9999, 9999); // // // check for any 'beeps' of the bomb! @@ -2947,8 +2912,7 @@ void cBot::Memory() { // } } - } - else { + } else { vEar = Vector(9999, 9999, 9999); } } @@ -3022,20 +2986,17 @@ void cBot::ThinkAboutGoals() { // A dropped C4 is not a 'goal' (ie. it won't let you win the game // when you pick up the bomb. Therefor the 'pickup the dropped bomb // code is in cNodeMachine::path_walk(). - } - else if (isCounterTerrorist()) { + } else if (isCounterTerrorist()) { // COUNTER-TERRORISTS if (vip) { // VIP - } - else { + } else { if (Game.bBombPlanted) { if (isCounterTerrorist()) { // defuse (or set timers for it) Defuse(); } - } - else { + } else { if (Game.bHostageRescueMap) { TryToGetHostageTargetToFollowMe(this); checkIfHostagesAreRescued(); @@ -3199,13 +3160,11 @@ void cBot::Think() { const int g = RANDOM_LONG(30, 155); const int b = RANDOM_LONG(30, 155); char msg[128]; - if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) - snprintf(msg, sizeof(msg), - "You have killed a RealBot!\n\nName:%s\nSkill:%d\n", - name, bot_skill); - else - snprintf(msg, sizeof(msg), "You have killed a RealBot named %s!", - name); + if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { + snprintf(msg, sizeof(msg), "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); + } else { + snprintf(msg, sizeof(msg), "A RealBot named %s has killed you!", name); + } HUD_DrawString(r, g, b, msg, killer_edict); } @@ -3250,8 +3209,7 @@ void cBot::Think() { PrepareChat(chSentence); } } - } - else { + } else { // we missed the chatrate chance if (fChatTime < gpGlobals->time) // time if (chChatSentence[0] == '\0') // we did not want to say anything @@ -3297,8 +3255,7 @@ void cBot::Think() { // prevent division by zero if (movedTwoTimes > 0.0f) { distanceMoved = movedTwoTimes / 2.0f; - } - else { + } else { distanceMoved = 0.0f; } @@ -3393,8 +3350,7 @@ void cBot::Think() { break; } } - } - else { + } else { while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && func_distance(pent->v.origin, pEdict->v.origin) > 50) { @@ -3490,8 +3446,7 @@ void cBot::Think() { // Think about objectives ThinkAboutGoals(); - } - else { + } else { // **---**---**---**---**---**---** // MAIN STATE: We have an enemy! // **---**---**---**---**---**---** From 0e2bc06b3e7e547bc4c1991bffd4b7a04f45e3fe Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sun, 21 Sep 2025 15:07:19 +0100 Subject: [PATCH 109/114] Enhancing bot's function to attack breakable --- NodeMachine.cpp | 77 ++++++++++++++++++++++++++----------------------- bot.cpp | 63 +++++++++++++++++++++------------------- bot_func.cpp | 35 ++++++++++++++++++++++ bot_func.h | 2 ++ 4 files changed, 111 insertions(+), 66 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index d9afe80..835cd99 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -384,8 +384,8 @@ void cNodeMachine::VectorToMeredian(const Vector& vOrigin, int *iX, int *iY) float iCoordY = vOrigin.y + 8192.0f; // map width (converts from - to +) // Meredian: - iCoordX = iCoordX / SIZE_MEREDIAN; - iCoordY = iCoordY / SIZE_MEREDIAN; + iCoordX = iCoordX / static_cast(SIZE_MEREDIAN); + iCoordY = iCoordY / static_cast(SIZE_MEREDIAN); *iX = static_cast(iCoordX); *iY = static_cast(iCoordY); @@ -410,7 +410,7 @@ void cNodeMachine::AddToMeredian(const int iX, const int iY, const int iNode) bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, ORIGIN_HEIGHT * 1.2f); + const Vector tr_end = vOrigin - Vector(0, 0, static_cast(ORIGIN_HEIGHT) * 1.2f); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) //UTIL_TraceHull(vOrigin, tr_end, ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); @@ -443,7 +443,7 @@ bool cNodeMachine::node_float(const Vector& vOrigin, edict_t *pEdict) bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) { TraceResult tr; - const Vector tr_end = vOrigin - Vector(0, 0, ORIGIN_HEIGHT * 1.2f); + const Vector tr_end = vOrigin - Vector(0, 0, static_cast(ORIGIN_HEIGHT) * 1.2f); //Using TraceHull to detect de_aztec bridge and other entities. (skill self) if (pEdict) @@ -846,12 +846,12 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const #endif if (Height > PreviousHeight) { // Going upwards - if (Height - PreviousHeight > MAX_JUMPHEIGHT) { + if (Height - PreviousHeight > static_cast(MAX_JUMPHEIGHT)) { //printf(" too high for upward jump\n") ; return 0; } } else { // Going downwards - if (PreviousHeight - Height > MAX_FALLHEIGHT) + if (PreviousHeight - Height > static_cast(MAX_FALLHEIGHT)) if (UTIL_PointContents(Floor + Vector(0, 0, 5)) != CONTENTS_WATER) //{printf(" too high for a downward fall not in water\n") ; @@ -872,12 +872,12 @@ int cNodeMachine::Reachable(const int iStart, const int iEnd) const #endif if (Height > PreviousHeight) { // Going upwards - if (Height - PreviousHeight > MAX_JUMPHEIGHT) { + if (Height - PreviousHeight > static_cast(MAX_JUMPHEIGHT)) { //printf(" too high for upward jump\n") ; return 0; } } else { // Going downwards - if (PreviousHeight - Height > MAX_FALLHEIGHT) + if (PreviousHeight - Height > static_cast(MAX_FALLHEIGHT)) if (UTIL_PointContents(End) != CONTENTS_WATER) { //printf(" too high for a downward fall not in water\n") ; return 0; // Falling from too high not in water @@ -1120,14 +1120,14 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { const vec_t fallDistance = Nodes[currentIndex].origin.z - Nodes[nodeIndex].origin.z; if (indexNodeFloats - && fallDistance > MAX_FALLHEIGHT + && fallDistance > static_cast(MAX_FALLHEIGHT) && (!bNeighbourWater && !bIsInWater)) { // skip nodes that are not in water and too low (ie will cause fall damage) continue; } // skip nodes which are to high (fall damage) - if (fallDistance > MAX_FALLHEIGHT) { + if (fallDistance > static_cast(MAX_FALLHEIGHT)) { continue; } @@ -1138,7 +1138,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (indexNodeFloats == false && // we stand on something nodeIsHigherThanOrigin && // we MUST jump (not fall) bNeighbourWater == false && - std::fabs(slopeDistance) > MAX_JUMPHEIGHT) // and cannot jump to it + std::fabs(slopeDistance) > static_cast(MAX_JUMPHEIGHT)) // and cannot jump to it { // SERVER_PRINT("Cannot jump to it"); continue; // next neighbour @@ -1148,7 +1148,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (indexNodeFloats == false && // we stand on something nodeIsHigherThanOrigin && // we MUST jump (not fall) bNeighbourWater == false && - std::fabs(slopeDistance) > MAX_FALLHEIGHT) // and cannot jump to it + std::fabs(slopeDistance) > static_cast(MAX_FALLHEIGHT)) // and cannot jump to it { // SERVER_PRINT("Insanity jump not possible either!\n"); continue; // next neighbour @@ -1163,7 +1163,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { // falling // 14/06/05 - this code does not cause bad connections! - Stefan // 20/06/05 - oops, it does... because it blocks when we are NOT falling... - if (slopeDistance > MAX_FALLHEIGHT) { + if (slopeDistance > static_cast(MAX_FALLHEIGHT)) { hull_type = human_hull; // when we fall, be sure we can freely fall. } @@ -1210,7 +1210,7 @@ int cNodeMachine::addNode(const Vector& vOrigin, edict_t *pEntity) { if (bNeighbourFloats == false && // we stand on something Nodes[currentIndex].origin.z > Nodes[nodeIndex].origin.z && // we MUST jump (not fall) bIsInWater == false && - std::fabs(fallDistance) > MAX_JUMPHEIGHT) // and cannot jump to it + std::fabs(fallDistance) > static_cast(MAX_JUMPHEIGHT)) // and cannot jump to it bCanConnect = false; // cannot connect // All water stuff can connect to each other @@ -1285,7 +1285,7 @@ void cNodeMachine::addNodesForPlayers() { const int iPlayerIndex = index - 1; // within a certain distance no node found? add one - if (func_distance(pPlayer->v.origin, Players[iPlayerIndex].vPrevPos) > NODE_ZONE) { + if (func_distance(pPlayer->v.origin, Players[iPlayerIndex].vPrevPos) > static_cast(NODE_ZONE)) { Players[iPlayerIndex].vPrevPos = pPlayer->v.origin; add2(pPlayer->v.origin, 0, pPlayer); } @@ -1837,7 +1837,7 @@ void cNodeMachine::contact(const int iNode, const int iTeam) { for (int i = 0; i < MAX_NODES; i++) { if (Nodes[i].origin != Vector(9999, 9999, 9999) && i != iNode) { const float fDist = func_distance(Nodes[i].origin, Nodes[iNode].origin); - if (fDist < NODE_CONTACT_DIST) { + if (fDist < static_cast(NODE_CONTACT_DIST)) { //Using TraceHull to detect de_aztec bridge and other entities. TraceResult tr; @@ -1847,7 +1847,7 @@ void cNodeMachine::contact(const int iNode, const int iTeam) { // within distance and 'reachable' if (tr.flFraction >= 1.0f) { - const double costIncrease = fDist / NODE_CONTACT_DIST * NODE_CONTACT_STEP; + const double costIncrease = fDist / static_cast(NODE_CONTACT_DIST) * NODE_CONTACT_STEP; InfoNodes[i].fContact[iTeam] += static_cast(costIncrease); } } @@ -1895,7 +1895,7 @@ void cNodeMachine::danger(const int iNode, const int iTeam) { } // Adds a new goal to the array -void cNodeMachine::addGoal(edict_t *pEdict, const int goalType, const Vector& vVec) { +void cNodeMachine::addGoal(edict_t* pEdict, const int goalType, const Vector& vVec) { // // 14/06/04 // Be carefull with adding SERVER_PRINT messages here @@ -1913,14 +1913,14 @@ void cNodeMachine::addGoal(edict_t *pEdict, const int goalType, const Vector& vV return; } - float distance = NODE_ZONE * 2; + float distance = static_cast(NODE_ZONE) * 2.0f; // some goals require very close nodes if (goalType == GOAL_HOSTAGE || goalType == GOAL_VIPSAFETY || goalType == GOAL_RESCUEZONE || goalType == GOAL_BOMBSPOT) { - distance = NODE_ZONE * 0.8f; + distance = static_cast(NODE_ZONE) * 0.8f; } int nNode = getClosestNode(vVec, distance, pEdict); @@ -1934,7 +1934,7 @@ void cNodeMachine::addGoal(edict_t *pEdict, const int goalType, const Vector& vV } } - tGoal *goal = getGoal(index); + tGoal* goal = getGoal(index); if (goal == nullptr) { rblog("No valid goal index found - bailing\n"); return; @@ -3361,7 +3361,7 @@ void cNodeMachine::path_think(cBot *pBot, const float distanceMoved) { if (pBot->shouldBeWandering()) { int currentNode = -1; for (int attempts = 1; attempts < 5; attempts++) { - const float distance = NODE_ZONE + static_cast(attempts * NODE_ZONE); + const float distance = static_cast(NODE_ZONE) + static_cast(attempts * NODE_ZONE); currentNode = pBot->determineCurrentNode(distance); // this also sets current node in bot state if (currentNode > -1) break; } @@ -3555,28 +3555,33 @@ void cNodeMachine::path_think(cBot *pBot, const float distanceMoved) { } if (goalType == GOAL_HOSTAGE) { - // counter-terrorist should float goalscore = 0.0f; + + // Counter-Terrorist hostage rescue logic if (pBot->isCounterTerrorist()) { if (pBot->isEscortingHostages()) { pBot->rprint("I am escorting hostages - should ignore existing hostages"); - // already escorting hostages, low interest for other hostages + // Already escorting hostages, low interest for other hostages goalscore = 0.5f; - } else { - // always go to the most furthest hostage spot, and add some randomness here, else - // all bots go to there. - const float mul = MAX_GOAL_DISTANCE / fDistanceToGoal; - goalscore = 1 + mul; } - } else { - // Terrorist pick randomly this location + else { + // Prioritize closer hostages for a quicker rescue. + // The score is inversely proportional to the distance. + // Adding a small random factor to prevent all bots picking the same hostage. + goalscore = (MAX_GOAL_DISTANCE / std::max(fDistanceToGoal, 1.0f)) + RANDOM_FLOAT(0.1f, 0.2f); + } + } + // Terrorist logic for hostage locations + else { + // Terrorists have a low chance to guard a hostage location. if (RANDOM_LONG(0, 100) < 25) { goalscore = RANDOM_FLOAT(0.1f, 0.6f); } } score = (score + goalscore) / 2.0f; - } else if (goalType == GOAL_RESCUEZONE) { + } + else if (goalType == GOAL_RESCUEZONE) { if (pBot->isCounterTerrorist()) { if (pBot->isEscortingHostages()) { pBot->rprint("I am escorting hostages - prioritizing for rescue zone"); @@ -4461,10 +4466,10 @@ void cNodeMachine::FindMinMax() const } // Avoid having lines/points just on the bitmap border, add some more spaces - maxx += NODE_ZONE; - minx -= NODE_ZONE; - maxy += NODE_ZONE; - miny -= NODE_ZONE; + maxx += static_cast(NODE_ZONE); + minx -= static_cast(NODE_ZONE); + maxy += static_cast(NODE_ZONE); + miny -= static_cast(NODE_ZONE); // first compute the X and Y divider scale, and take the greatest of both const float scalex = (1 + maxx - minx) / static_cast(DEBUG_BMP_WIDTH); diff --git a/bot.cpp b/bot.cpp index ab570f9..0ee383e 100644 --- a/bot.cpp +++ b/bot.cpp @@ -708,7 +708,7 @@ void cBot::AimAtEnemy() { fDy = fpYOffset; fDz = fpZOffset; - // increase offset with personality x,y,z offsets randomly + // increase offset with personality x,y,z randomly vTarget = vTarget + Vector( RANDOM_FLOAT(-fDx, fDx), RANDOM_FLOAT(-fDy, fDy), @@ -1022,6 +1022,9 @@ void cBot::FireWeapon() { if (hasEnemy()) { fDistance = func_distance(pEdict->v.origin, pEnemyEdict->v.origin); } + else if (pBreakableEdict != nullptr) { + fDistance = func_distance(pEdict->v.origin, VecBModelOrigin(pBreakableEdict)); + } // Depending on weapon type if (CarryWeaponType() == SECONDARY) { @@ -1131,16 +1134,7 @@ void cBot::FireWeapon() { ******************************************************************************/ void cBot::Combat() { if (pBreakableEdict != nullptr) { - // If the breakable is no longer valid, forget it - if (pBreakableEdict->v.health <= 0 || (pBreakableEdict->v.flags & FL_DORMANT)) { - pBreakableEdict = nullptr; - return; - } - - // Aim and fire at the breakable - const Vector vBreakableOrigin = VecBModelOrigin(pBreakableEdict); - setHeadAiming(vBreakableOrigin); - FireWeapon(); + FUNC_AttackBreakable(this); return; } @@ -2119,23 +2113,23 @@ void cBot::CheckAround() { const Vector v_forwardleft = v_left + gpGlobals->v_forward * -distance; // TRACELINE: forward - UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_forward, dont_ignore_monsters, point_hull, pEdict, &tr); const bool bHitForward = tr.flFraction < 1.0f; // TRACELINE: Left - UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_left, dont_ignore_monsters, point_hull, pEdict, &tr); const bool bHitLeft = tr.flFraction < 1.0f; // TRACELINE: Right - UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_right, dont_ignore_monsters, point_hull, pEdict, &tr); const bool bHitRight = tr.flFraction < 1.0f; // TRACELINE: Forward left - UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_forwardleft, dont_ignore_monsters, point_hull, pEdict, &tr); const bool bHitForwardLeft = tr.flFraction < 1.0f; // TRACELINE: Forward right - UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict->v.pContainingEntity, &tr); + UTIL_TraceHull(v_source, v_forwardright, dont_ignore_monsters, point_hull, pEdict, &tr); const bool bHitForwardRight = tr.flFraction < 1.0f; char msg[255]; @@ -2911,7 +2905,6 @@ void cBot::Memory() { // } // } } - } else { vEar = Vector(9999, 9999, 9999); } @@ -3162,7 +3155,8 @@ void cBot::Think() { char msg[128]; if (Game.iDeathsBroadcasting == BROADCAST_DEATHS_FULL) { snprintf(msg, sizeof(msg), "A RealBot has killed you!\n\nName:%s\nSkill:%d\n", name, bot_skill); - } else { + } + else { snprintf(msg, sizeof(msg), "A RealBot named %s has killed you!", name); } @@ -3209,7 +3203,8 @@ void cBot::Think() { PrepareChat(chSentence); } } - } else { + } + else { // we missed the chatrate chance if (fChatTime < gpGlobals->time) // time if (chChatSentence[0] == '\0') // we did not want to say anything @@ -3255,7 +3250,8 @@ void cBot::Think() { // prevent division by zero if (movedTwoTimes > 0.0f) { distanceMoved = movedTwoTimes / 2.0f; - } else { + } + else { distanceMoved = 0.0f; } @@ -3350,7 +3346,8 @@ void cBot::Think() { break; } } - } else { + } + else { while ((pent = UTIL_FindEntityByClassname(pent, "info_player_deathmatch")) != nullptr) { if (func_distance(pent->v.origin, pEdict->v.origin) < 200 && func_distance(pent->v.origin, pEdict->v.origin) > 50) { @@ -3378,7 +3375,7 @@ void cBot::Think() { if (pBreakableEdict != nullptr) { // Found a breakable, attack it - Combat(); + FUNC_AttackBreakable(this); // Reset stuck timer fNotStuckTime = gpGlobals->time + 2.0f; return; @@ -3391,18 +3388,23 @@ void cBot::Think() { } } + // If the bot has a breakable target, attack it immediately. + if (pBreakableEdict != nullptr) { + FUNC_AttackBreakable(this); + return; + } + // **---**---**---**---**---**---** // MAIN STATE: We have no enemy... // **---**---**---**---**---**---** - if (!hasEnemy() && pBreakableEdict == nullptr) { + if (!hasEnemy()) { if (!Game.bDoNotShoot) { FUNC_FindBreakable(this); - if (pBreakableEdict != nullptr) { - Combat(); // Attack the breakable - return; + // If a breakable is found, the next think cycle will handle it + if (pBreakableEdict == nullptr) { + InteractWithPlayers(); } - InteractWithPlayers(); } bool bMayFromGame = true; @@ -3446,7 +3448,8 @@ void cBot::Think() { // Think about objectives ThinkAboutGoals(); - } else { + } + else { // **---**---**---**---**---**---** // MAIN STATE: We have an enemy! // **---**---**---**---**---**---** @@ -3765,7 +3768,7 @@ bool BotRadioAction() { NodeMachine.getClosestNode(plr->v.origin, NODE_ZONE, plr); if (iBackupNode > -1) { - BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); + BotPointer->rprint_trace("BotRadioAction", "Found node nearby player who requested backup/reported taking fire."); BotPointer->setGoalNode(iBackupNode); BotPointer->forgetPath(); BotPointer->f_camp_time = gpGlobals->time - 1; @@ -4361,7 +4364,7 @@ void cBot::doJump(const Vector& vector) { void cBot::doJump() { rprint_trace("doJump", "no vector"); UTIL_BotPressKey(this, IN_JUMP); - this->f_jump_time = gpGlobals->time + 0.5f; + this->f_jump_time = gpGlobals->time + 0.75f; // duck like this, because doDuck increases node time *again*, so no UTIL_BotPressKey(this, IN_DUCK); // DUCK jump by default diff --git a/bot_func.cpp b/bot_func.cpp index fbb7cac..518c191 100644 --- a/bot_func.cpp +++ b/bot_func.cpp @@ -848,6 +848,41 @@ void FUNC_FindBreakable(cBot* pBot) } } +void FUNC_AttackBreakable(cBot* pBot) +{ + if (pBot == nullptr || pBot->pBreakableEdict == nullptr) { + return; + } + + edict_t* pBreakable = pBot->pBreakableEdict; + + // If the breakable is no longer valid, forget it + if (pBreakable->v.health <= 0 || (pBreakable->v.flags & FL_DORMANT)) { + pBot->pBreakableEdict = nullptr; + return; + } + + const Vector vBreakableOrigin = VecBModelOrigin(pBreakable); + pBot->setHeadAiming(vBreakableOrigin); + + const float distance = (pBot->pEdict->v.origin - vBreakableOrigin).Length(); + + // Use knife if close enough, otherwise use the current weapon + if (distance < 64.0f) { + if (!pBot->isHoldingWeapon(CS_WEAPON_KNIFE)) { + pBot->pickWeapon(CS_WEAPON_KNIFE); + } + pBot->FireWeapon(); + } + else { + // If holding a knife but the breakable is not close, switch to a better weapon + if (pBot->isHoldingWeapon(CS_WEAPON_KNIFE)) { + pBot->PickBestWeapon(); + } + pBot->FireWeapon(); + } +} + void FUNC_CheckForBombPlanted(edict_t* pEntity) //Experimental [APG]RoboCop[CL] { // Check if the bot has a bomb planted. diff --git a/bot_func.h b/bot_func.h index 1d250d9..ecb399e 100644 --- a/bot_func.h +++ b/bot_func.h @@ -87,7 +87,9 @@ void FUNC_HearingTodo(cBot* pBot); void FUNC_ClearEnemyPointer(edict_t* pPtr); //pPtr muddled with c_pointer? [APG]RoboCop[CL] bool FUNC_IsOnLadder(const edict_t* pEntity); +bool IsShootableBreakable(edict_t* pent); void FUNC_FindBreakable(cBot* pBot); +void FUNC_AttackBreakable(cBot* pBot); void FUNC_CheckForBombPlanted(edict_t* pEntity); int FUNC_GiveHostage(cBot* pBot); // gives any hostage we still have to go for From 8b2e4a5ffdb5df791cdd6d4dcf63a52349c56c58 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sun, 21 Sep 2025 15:09:23 +0100 Subject: [PATCH 110/114] Update todo.txt --- todo.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/todo.txt b/todo.txt index 0242545..9abaa80 100644 --- a/todo.txt +++ b/todo.txt @@ -1,13 +1,13 @@ - Bots may not camp when last in team (or second last?) - Bots should know when others are near its waypoint, so it won't run into each other - Done but not fully tested! -- Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in and hostages) -- Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Not fully tested! +- Bots should have better knowledge about goals (mainly for investigating which bomb site got the live C4 in and hostages) - Almost done! +- Improve pathfinder by properly removing excessive connections, especially on ones that have blocked pathways - Almost done! - Allow bots to duck jump for vaulting upon crates or ledges, cs_italy, de_nuke and de_inferno are good examples - Almost done! - Improve the way bots walk path and decide it is a bad connection - Improve 'unstucking'... when not stuck by hostages and how to attack glass or vent grills in order to proceed. - Allow bots to autovacate for human players -- To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates +- To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Almost done! - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up -- To allow bots to use melee on breakables or "func_breakable" to infiltrate windows and vents +- To allow bots to use melee on breakables or "func_breakable" to infiltrate windows and vents - Almost done! - Ensure that the RealBot personality directories are correctly assigned \ No newline at end of file From f3fbabe0edf591811e69df97463164cca6ebcda9 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Fri, 26 Sep 2025 22:09:30 +0100 Subject: [PATCH 111/114] Modernising createPath (May need to revert) --- NodeMachine.cpp | 246 +++++++++++++++++------------------------------ bot.cpp | 2 +- bot_buycode.cpp | 16 +-- bot_navigate.cpp | 4 +- todo.txt | 1 - 5 files changed, 97 insertions(+), 172 deletions(-) diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 835cd99..13e2c38 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -2222,7 +2222,7 @@ void cNodeMachine::scale_danger() { } // Pathfinder -bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetIndex, const int botIndex, cBot *pBot, int iFlags) { +bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetIndex, const int botIndex, cBot* pBot, int iFlags) { // Will create a path from nodeStartIndex to nodeTargetIndex, and store it into index number iPathId if (pBot) { @@ -2231,8 +2231,10 @@ bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetInde pBot->rprint("cNodeMachine::createPath", msg); } - if (nodeStartIndex < 0 || nodeTargetIndex < 0 || botIndex < 0) + if (nodeStartIndex < 0 || nodeTargetIndex < 0 || botIndex < 0 || + nodeStartIndex >= MAX_NODES || nodeTargetIndex >= MAX_NODES) { return false; // do not create a path when invalid params given + } if (nodeStartIndex > iMaxUsedNodes || nodeTargetIndex > iMaxUsedNodes) return false; // do not create a path when invalid params given @@ -2241,86 +2243,70 @@ bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetInde UTIL_GetTeam(pBot->pEdict); // Stefan: yes we use 0-1 based, not 1-2 based } - const Vector& INVALID_VECTOR = Vector(9999, 9999, 9999); - - // start or target vector may not be invalid if (Nodes[nodeStartIndex].origin == INVALID_VECTOR || Nodes[nodeTargetIndex].origin == INVALID_VECTOR) { rblog("Invalid start and target index\n"); return false; } - int nodeIndex; - path_clear(botIndex); - // INIT: Start - makeAllWaypointsAvailable(); - - // Our start waypoint is open - constexpr float gCost = 0.0f; // distance from starting node - const float hCost = func_distance(Nodes[nodeStartIndex].origin, - Nodes[nodeTargetIndex].origin); // distance from end node to node - const float cost = gCost + hCost; - closeNode(nodeStartIndex, nodeStartIndex, cost); - openNeighbourNodes(nodeStartIndex, nodeStartIndex, nodeTargetIndex, -1); - - bool pathFound = false; // is it still valid to loop through the lists for pathfinding? - - int nodesEvaluated = 0; - // INIT: End - // PATHFINDER: Start - while (!pathFound) { - float lowestScore = 99999999.0f; - int nodeToClose = -1; - - // go through all OPEN waypoints - for (nodeIndex = 0; nodeIndex < MAX_NODES; nodeIndex++) { - nodesEvaluated++; // increment nodesEvaluated each time a node is evaluated [APG]RoboCop[CL] - tNodestar& nodeStar = astar_list[nodeIndex]; - - if (nodeStar.state == CLOSED || nodeStar.state == AVAILABLE) continue; - - // OPEN waypoint - tNode& node = Nodes[nodeIndex]; - if (node.origin == INVALID_VECTOR) { - rblog("Evaluating an INVALID vector!?!\n"); - nodeStar.state = CLOSED; - continue; // it is an invalid vector - } + std::priority_queue openList; + std::vector nodeData(MAX_NODES); - // nodeIndex is target, so target found - if (nodeIndex == nodeTargetIndex) { - pathFound = true; - rblog("Target found\n"); - break; // Get out of here - } + // Initialize node data + for (int i = 0; i < MAX_NODES; ++i) { + nodeData[i].state = AVAILABLE; + nodeData[i].parent = -1; + nodeData[i].cost = std::numeric_limits::max(); + } - // open is not target, so go over its neighbours (which have been opened) and find the lowest cost - if (nodeStar.cost < lowestScore) { - nodeToClose = nodeIndex; - lowestScore = nodeStar.cost; - } + // Setup start node + nodeData[nodeStartIndex].cost = func_distance(Nodes[nodeStartIndex].origin, Nodes[nodeTargetIndex].origin); + nodeData[nodeStartIndex].state = OPEN; + openList.push({ OPEN, nodeStartIndex, nodeData[nodeStartIndex].cost, 0.0f }); + + bool pathFound = false; + + while (!openList.empty()) { + const int currentNodeIndex = openList.top().parent; + openList.pop(); + + if (nodeData[currentNodeIndex].state == CLOSED) { + continue; } - // a node that should be closed is an evaluated node and the most preferred one. - // open up all neighbouring nodes, and close this one - if (nodeToClose > -1) { - astar_list[nodeToClose].state = CLOSED; - int botTeam = -1; + if (currentNodeIndex == nodeTargetIndex) { + pathFound = true; + break; + } + + nodeData[currentNodeIndex].state = CLOSED; + + const tNode& currentNode = Nodes[currentNodeIndex]; + for (const int neighborIndex : currentNode.iNeighbour) { + if (neighborIndex < 0 || Nodes[neighborIndex].origin == INVALID_VECTOR || nodeData[neighborIndex].state == CLOSED) { + continue; + } + + const float gCost = nodeData[currentNodeIndex].cost + func_distance(currentNode.origin, Nodes[neighborIndex].origin); + const float hCost = func_distance(Nodes[neighborIndex].origin, Nodes[nodeTargetIndex].origin); + float totalCost = gCost + hCost; + if (pBot) { - botTeam = pBot->iTeam; + const float dangerCost = InfoNodes[neighborIndex].fDanger[pBot->iTeam] * totalCost; + totalCost += dangerCost; } - openNeighbourNodes(nodeStartIndex, nodeToClose, nodeTargetIndex, botTeam); - } - else { - break; + if (totalCost < nodeData[neighborIndex].cost) { + nodeData[neighborIndex].parent = currentNodeIndex; + nodeData[neighborIndex].cost = totalCost; + nodeData[neighborIndex].state = OPEN; + openList.push({ OPEN, neighborIndex, totalCost, 0.0f }); + } } } - // PATHFINDER: End - // RESULT: Success if (!pathFound) { if (pBot) { pBot->rprint("cNodeMachine::createPath", "Failed to create path"); @@ -2328,84 +2314,26 @@ bool cNodeMachine::createPath(const int nodeStartIndex, const int nodeTargetInde return false; } - for (nodeIndex = 0; nodeIndex < MAX_PATH_NODES; nodeIndex++) { - const tNodestar& nodeStar = astar_list[nodeIndex]; - if (nodeStar.state == AVAILABLE) continue; + // Build path + std::vector temp_path; + int wpta = nodeTargetIndex; + while (wpta != -1) { + temp_path.push_back(wpta); + wpta = nodeData[wpta].parent; } - // Build path (from goal to start, read out parent waypoint to backtrace) - int temp_path[MAX_PATH_NODES]; - - // INIT: Start - for (nodeIndex = 0; nodeIndex < MAX_PATH_NODES; nodeIndex++) - temp_path[nodeIndex] = -1; - - // The path has been built yet? - bool built = false; - - // The variables needed to backtrace - // wpta = waypoint we use to backtrace (starting at goal) - // p = index for temp_path (the path will be GOAL-START, reversed later) - int wpta = nodeTargetIndex, p = 0; + std::reverse(temp_path.begin(), temp_path.end()); - // INIT: End - - // START: When path is not built yet - while (!built) { - temp_path[p] = wpta; // Copy the waypoint into temp_path[index] - - // IF: At current (start) waypoint - if (wpta == nodeStartIndex) { - // Check if we did not already had this waypoint before - built = true; // We finished building this path. - } - else { - // Whenever wpta is containing bad information... - if (wpta < 0 || wpta > MAX_NODES) - break; // ...get out aswell - } - - // waypoint we use to backtrace will be set to parent waypoint. - wpta = astar_list[wpta].parent; - - // Increase index for temp_path - p++; - - // Whenever we reach the limit, get out. - if (p >= MAX_PATH_NODES) - break; - - } - - // INIT: Start - int path_index = 0; // done above, but done again to be sure - // INIT: End - - // Now set the path up correctly - for (nodeIndex = MAX_NODES - 1; nodeIndex > -1; nodeIndex--) { - const int node = temp_path[nodeIndex]; - if (node < 0) - continue; - - iPath[botIndex][path_index] = node; - - // print out full path so we know what the order is - if (pBot != nullptr) { + // Copy to bot's path array + for (size_t i = 0; i < temp_path.size() && i < MAX_PATH_NODES; ++i) { + iPath[botIndex][i] = temp_path[i]; + if (pBot) { char pathMsg[255] = {}; - snprintf(pathMsg, sizeof(pathMsg), "Bot [%d] path index [%d] has node [%d]", botIndex, path_index, node); + snprintf(pathMsg, sizeof(pathMsg), "Bot [%d] path index [%zu] has node [%d]", botIndex, i, temp_path[i]); pBot->rprint("cNodeMachine::createPath", pathMsg); } - - path_index++; } - // Finally there is the goal - iPath[botIndex][path_index] = nodeTargetIndex; - - // terminate path - path_index++; - iPath[botIndex][path_index] = -1; - // And set bot in motion if (pBot != nullptr) { pBot->beginWalkingPath(); @@ -2512,7 +2440,7 @@ bool cNodeMachine::isInvalidNode(const int index) //TODO: Experimental [APG]Robo return !isValidNodeIndex(index); } -//TODO: Implement this function - Experimental [APG]RoboCop[CL] +//TODO: Experimental [APG]RoboCop[CL] void cNodeMachine::buildPath(const int nodeStartIndex, const int nodeTargetIndex, const int botIndex, cBot* pBot) { if (!isValidNodeIndex(nodeStartIndex) || !isValidNodeIndex(nodeTargetIndex)) { @@ -2623,29 +2551,27 @@ int cNodeMachine::node_camp(const Vector& vOrigin, const int iTeam) const // Check if iFrom is visible from other nodes (and opposite) void cNodeMachine::vis_calculate(const int iFrom) { // Check around your area to see what is visible + constexpr float MAX_VISIBILITY_DISTANCE = 1024.0f; + for (int i = 0; i < iMaxUsedNodes; ++i) { + if (i == iFrom || Nodes[i].origin == INVALID_VECTOR) { + continue; // Skip the current node or invalid nodes + } - for (int i = 0; i < MAX_NODES; i++) - if (i != iFrom && Nodes[i].origin != Vector(9999, 9999, 9999)) { - constexpr float fClosest = 1024.0f; - const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); - if (fDistance < fClosest) { - TraceResult tr; + const float fDistance = func_distance(Nodes[i].origin, Nodes[iFrom].origin); + if (fDistance >= MAX_VISIBILITY_DISTANCE) { + continue; // Skip if the node is too far + } - // Visibility is not yet calculated, so determine now - if (GetVisibilityFromTo(iFrom, i) == VIS_UNKNOWN) // BERKED - { - UTIL_TraceHull(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, point_hull, nullptr, &tr); + // Visibility is not yet calculated, so determine now + if (GetVisibilityFromTo(iFrom, i) == VIS_UNKNOWN) { + TraceResult tr; - if (tr.flFraction < 1.0f) { - SetVisibilityFromTo(iFrom, i, false); - SetVisibilityFromTo(i, iFrom, false); - } else { - SetVisibilityFromTo(iFrom, i, true); - SetVisibilityFromTo(i, iFrom, true); - } - } - } + UTIL_TraceHull(Nodes[iFrom].origin, Nodes[i].origin, ignore_monsters, point_hull, nullptr, &tr); + const bool isVisible = (tr.flFraction >= 1.0f); + SetVisibilityFromTo(iFrom, i, isVisible); + SetVisibilityFromTo(i, iFrom, isVisible); } + } } // Find a node to look at when camping @@ -4509,9 +4435,9 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (x = 0; x < DEBUG_BMP_WIDTH; x++) { - Meredian = - (x * scale + minx + - 8192.0f) / SIZE_MEREDIAN; + Meredian = static_cast( + (x * scale + minx + + 8192.0f) / static_cast(SIZE_MEREDIAN)); if (Meredian & 0x01) { for (y = 0; y < DEBUG_BMP_HEIGHT; y++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; @@ -4520,9 +4446,9 @@ void cNodeMachine::MarkMeredians() { // Mark some meredians for (y = 0; y < DEBUG_BMP_HEIGHT; y++) { - Meredian = - (y * scale + miny + - 8192.0f) / SIZE_MEREDIAN; + Meredian = static_cast( + (y * scale + miny + + 8192.0f) / static_cast(SIZE_MEREDIAN)); if (Meredian & 0x01) { for (x = 0; x < DEBUG_BMP_HEIGHT; x++) bmp_buffer[y * DEBUG_BMP_WIDTH + x]++; diff --git a/bot.cpp b/bot.cpp index 0ee383e..c4d6e99 100644 --- a/bot.cpp +++ b/bot.cpp @@ -3018,7 +3018,7 @@ edict_t* cBot::findHostageToRescue() { if (!isHostageRescueable(this, pent)) continue; if (!canSeeEntity(pent)) continue; // skip too far hostages, leave it up to the goal picking to get closer - if (getDistanceTo(pent->v.origin) > NODE_ZONE * 2.5f) continue; + if (getDistanceTo(pent->v.origin) > static_cast(NODE_ZONE) * 2.5f) continue; char msg[255]; snprintf(msg, sizeof(msg), "Found hostage to rescue at %f,%f,%f", pent->v.origin.x, pent->v.origin.y, pent->v.origin.z); diff --git a/bot_buycode.cpp b/bot_buycode.cpp index 2c8994f..6038bb3 100644 --- a/bot_buycode.cpp +++ b/bot_buycode.cpp @@ -66,7 +66,7 @@ int ListIdWeapon(const int weapon_id) { } // The bot will be buying this weapon -void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const char *arg2) { +void BotPrepareConsoleCommandsToBuyWeapon(cBot* pBot, const char* arg1, const char* arg2) { // To be sure the console will only change when we MAY change. // The values will only be changed when console_nr is 0 if (Game.getRoundStartedTime() + 4 < gpGlobals->time) @@ -74,15 +74,15 @@ void BotPrepareConsoleCommandsToBuyWeapon(cBot *pBot, const char *arg1, const ch if (pBot->console_nr == 0) { // set up first command and argument - strncpy(pBot->arg1, "buy", sizeof(pBot->arg1) - 1); - pBot->arg1[sizeof(pBot->arg1) - 1] = '\0'; - strncpy(pBot->arg2, arg1, sizeof(pBot->arg2) - 1); - pBot->arg2[sizeof(pBot->arg2) - 1] = '\0'; + snprintf(pBot->arg1, sizeof(pBot->arg1), "buy"); + snprintf(pBot->arg2, sizeof(pBot->arg2), "%s", arg1); // add argument if (arg2 != nullptr) { - strncpy(pBot->arg3, arg2, sizeof(pBot->arg3) - 1); - pBot->arg3[sizeof(pBot->arg3) - 1] = '\0'; + snprintf(pBot->arg3, sizeof(pBot->arg3), "%s", arg2); + } + else { + pBot->arg3[0] = '\0'; } pBot->console_nr = 1; // start console command sequence @@ -285,7 +285,7 @@ int BotBuyEquipment(cBot *pBot) { */ void BotDecideWhatToBuy(cBot *pBot) { const int money = pBot->bot_money; - int buy_weapon = -1; + int buy_weapon; if (pBot->buy_primary) { buy_weapon = BotBuyPrimaryWeapon(pBot); diff --git a/bot_navigate.cpp b/bot_navigate.cpp index 3eb63ec..7ac64ca 100644 --- a/bot_navigate.cpp +++ b/bot_navigate.cpp @@ -113,7 +113,7 @@ void setupMovementVectors(const edict_t* pEdict, Vector& forward, Vector& right) right = gpGlobals->v_right; } -bool BotCanJumpUp(cBot *pBot) { +bool BotCanJumpUp(cBot* pBot) { // What I do here is trace 3 lines straight out, one unit higher than // the highest normal jumping distance. I trace once at the center of // the body, once at the right side, and once at the left side. If all @@ -130,7 +130,7 @@ bool BotCanJumpUp(cBot *pBot) { setupMovementVectors(pEdict, v_forward, v_right); // Horizontal check at jump height - Vector v_source_horizontal = pEdict->v.origin + Vector(0, 0, STAND_VIEW_HEIGHT_OFFSET + MAX_JUMPHEIGHT); + Vector v_source_horizontal = pEdict->v.origin + Vector(0, 0, STAND_VIEW_HEIGHT_OFFSET + static_cast(MAX_JUMPHEIGHT)); if (!traceArea(pEdict, v_source_horizontal, v_forward * FORWARD_CHECK_DISTANCE, v_right, true)) { return false; } diff --git a/todo.txt b/todo.txt index 9abaa80..eadc9cf 100644 --- a/todo.txt +++ b/todo.txt @@ -9,5 +9,4 @@ - To allow bots to really, I mean REALLY ignore nodes from VERY hard to reach places - including non-vaultable edges and tall crates - Almost done! - Find an automated solution for removing redundant or excessive nodes that can make the connections less messy (if it doesn't already exist?) - To add a cvar to toggle Reallog.txt on or off to reduce printing too many texts in the console and to prevent that txt file building up -- To allow bots to use melee on breakables or "func_breakable" to infiltrate windows and vents - Almost done! - Ensure that the RealBot personality directories are correctly assigned \ No newline at end of file From a44376b995dc5a0ac67b7cc2b3fcad390560e11a Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Fri, 3 Oct 2025 21:00:20 +0100 Subject: [PATCH 112/114] Version 4.0.5-beta released! --- IniParser.h | 143 ++++++++-------- NodeMachine.cpp | 443 +++++++++++++++++++++++++----------------------- NodeMachine.h | 2 +- bot.cpp | 68 ++++++-- bot.h | 21 +-- bot_client.cpp | 13 +- dll.cpp | 164 ++++++------------ game.h | 36 ++-- 8 files changed, 452 insertions(+), 438 deletions(-) diff --git a/IniParser.h b/IniParser.h index 8d37d26..4a661ee 100644 --- a/IniParser.h +++ b/IniParser.h @@ -36,85 +36,96 @@ #ifndef INIPARSER_H #define INIPARSER_H -#define INI_NONE (-1) -#define INI_SKILL 0 // Bot skill -#define INI_WEAPON 1 // Bot weapon preference -#define INI_GAME 2 // Bot general game behaviour -#define INI_RADIO 3 // Bot radio behaviour -#define INI_TEAM 4 // Bot team behaviour -#define INI_PERSON 5 // Bot person itself - -#define INI_AREA 10 -#define INI_BLOCK 11 -#define INI_DEATHS 12 -#define INI_WELCOME 13 +enum : std::int8_t +{ + INI_NONE = (-1), + INI_SKILL = 0, // Bot skill + INI_WEAPON = 1, // Bot weapon preference + INI_GAME = 2, // Bot general game behaviour + INI_RADIO = 3, // Bot radio behaviour + INI_TEAM = 4, // Bot team behaviour + INI_PERSON = 5 // Bot person itself +}; + +enum : std::uint8_t +{ + INI_AREA = 10, + INI_BLOCK = 11, + INI_DEATHS = 12, + INI_WELCOME = 13 +}; // 'Weapon Sections' are the same as WEAPON ID in Counter-Strike. // NOTE: For weapon_buy_table.iId! // 'Words' -#define WORD_NONE (-1) -#define WORD_WALK 0 -#define WORD_RUN 1 -#define WORD_SHOOT 2 -#define WORD_WAIT 3 -#define WORD_RADIO 4 +enum : std::int8_t +{ + WORD_NONE = (-1), + WORD_WALK = 0, + WORD_RUN = 1, + WORD_SHOOT = 2, + WORD_WAIT = 3, + WORD_RADIO = 4 +}; // BOTPERSONALITY.INI words -#define WORD_PRIWEAPON 31 -#define WORD_SECWEAPON 32 -#define WORD_SAVEFORWEAP 33 -#define WORD_GRENADE 34 -#define WORD_FLASHBANG 35 -#define WORD_SMOKEGREN 36 -#define WORD_DEFUSEKIT 37 -#define WORD_ARMOUR 54 - -#define WORD_XOFFSET 38 -#define WORD_YOFFSET 39 -#define WORD_ZOFFSET 40 -#define WORD_BOTSKILL 41 -#define WORD_MAXREACTTIME 42 -#define WORD_MINREACTTIME 43 -#define WORD_TURNSPEED 44 - -#define WORD_HOSTAGERATE 45 -#define WORD_BOMBSPOTRATE 46 -#define WORD_RANDOMRATE 47 - -#define WORD_REPLYRADIO 48 -#define WORD_CREATERADIO 49 - -#define WORD_HELPTEAM 50 - -#define WORD_CAMPRATE 51 -#define WORD_CHATRATE 52 -#define WORD_WALKKNIFE 53 - -#define WORD_FEARRATE 55 -#define WORD_HEARRATE 56 - -#define WORD_DROPPEDBOMB 57 +enum : std::uint8_t +{ + WORD_PRIWEAPON = 31, + WORD_SECWEAPON = 32, + WORD_SAVEFORWEAP = 33, + WORD_GRENADE = 34, + WORD_FLASHBANG = 35, + WORD_SMOKEGREN = 36, + WORD_DEFUSEKIT = 37, + WORD_ARMOUR = 54, + WORD_XOFFSET = 38, + WORD_YOFFSET = 39, + WORD_ZOFFSET = 40, + WORD_BOTSKILL = 41, + WORD_MAXREACTTIME = 42, + WORD_MINREACTTIME = 43, + WORD_TURNSPEED = 44, + + WORD_HOSTAGERATE = 45, + WORD_BOMBSPOTRATE = 46, + WORD_RANDOMRATE = 47, + + WORD_REPLYRADIO = 48, + WORD_CREATERADIO = 49, + + WORD_HELPTEAM = 50, + + WORD_CAMPRATE = 51, + WORD_CHATRATE = 52, + WORD_WALKKNIFE = 53, + + WORD_FEARRATE = 55, + WORD_HEARRATE = 56, + + WORD_DROPPEDBOMB = 57, // AREA SHIT -#define WORD_AREAX 60 -#define WORD_AREAY 61 -#define WORD_AREAZ 62 + WORD_AREAX = 60, + WORD_AREAY = 61, + WORD_AREAZ = 62, // CHAT -#define WORD_SENTENCE 67 -#define WORD_WORD 68 + WORD_SENTENCE = 67, + WORD_WORD = 68, // BUYTABLE.INI Words (arguments per weapon) -#define WORD_PRIORITY 5 -#define WORD_PRICE 6 -#define WORD_MAXAMMO1 88 -#define WORD_MAXAMMO2 89 -#define WORD_ISLOT 90 -#define WORD_IPOSITION 91 -#define WORD_IFLAGS 92 -#define WORD_INDEX1 93 -#define WORD_INDEX2 94 + WORD_PRIORITY = 5, + WORD_PRICE = 6, + WORD_MAXAMMO1 = 88, + WORD_MAXAMMO2 = 89, + WORD_ISLOT = 90, + WORD_IPOSITION = 91, + WORD_IFLAGS = 92, + WORD_INDEX1 = 93, + WORD_INDEX2 = 94 +}; void INI_PARSE_BOTS(char cBotName[33], cBot * pBot); diff --git a/NodeMachine.cpp b/NodeMachine.cpp index 13e2c38..0e6d352 100644 --- a/NodeMachine.cpp +++ b/NodeMachine.cpp @@ -471,14 +471,44 @@ bool cNodeMachine::node_on_crate(const Vector& vOrigin, edict_t *pEdict) return false; } -int cNodeMachine::node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance) //TODO: Experimental & Incomplete [APG]RoboCop[CL] +int cNodeMachine::node_dangerous(const int iTeam, const Vector& vOrigin, const float fMaxDistance) //TODO: Experimental & Incomplete [APG]RoboCop[CL] { - // check if node is dangerous - //int iDangerous = 0; - //int iDangerousCount = 0; - //int iDangerousIndex = 0; - - return 0; + int iBestNode = -1; + float fMaxDanger = 0.0f; + + // Use Meredians to search for nodes + int iX, iY; + VectorToMeredian(vOrigin, &iX, &iY); + + if (iX < 0 || iY < 0) { + return -1; // Invalid coordinates + } + + // Search in the current and adjacent meridians to ensure we cover the full radius + for (int meredianX = iX - 1; meredianX <= iX + 1; ++meredianX) { + for (int meredianY = iY - 1; meredianY <= iY + 1; ++meredianY) { + // Ensure meridian coordinates are within bounds + if (meredianX < 0 || meredianX >= MAX_MEREDIANS || meredianY < 0 || meredianY >= MAX_MEREDIANS) { + continue; + } + + for (const int iNode : Meredians[meredianX][meredianY].iNodes) { + if (iNode < 0) continue; + + const float fDist = func_distance(vOrigin, Nodes[iNode].origin); + + if (fDist < fMaxDistance) { + const float fDanger = InfoNodes[iNode].fDanger[iTeam]; + if (fDanger > fMaxDanger) { + fMaxDanger = fDanger; + iBestNode = iNode; + } + } + } + } + } + + return iBestNode; } /** @@ -1485,8 +1515,7 @@ void cNodeMachine::experience_save() { std::fwrite(&InfoNode, sizeof(tInfoNode), 1, rbl); } - if (iMaxUsedNodes > MAX_NODES) - iMaxUsedNodes = MAX_NODES; + iMaxUsedNodes = std::min(iMaxUsedNodes, MAX_NODES); // Here write down the MAX amounts of nodes used from vis table! const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; @@ -1556,8 +1585,7 @@ void cNodeMachine::experience_load() { std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); // make sure we never exceed the limit - if (iMaxUsedNodes > MAX_NODES) - iMaxUsedNodes = MAX_NODES; + iMaxUsedNodes = std::min(iMaxUsedNodes, MAX_NODES); const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; @@ -1572,8 +1600,7 @@ void cNodeMachine::experience_load() { std::fread(&iMaxUsedNodes, sizeof(int), 1, rbl); // make sure we never exceed the limit - if (iMaxUsedNodes > MAX_NODES) - iMaxUsedNodes = MAX_NODES; + iMaxUsedNodes = std::min(iMaxUsedNodes, MAX_NODES); const unsigned long iSize = iMaxUsedNodes * MAX_NODES / 8; @@ -1984,19 +2011,13 @@ int cNodeMachine::getFreeGoalIndex() const { * @param pEdict * @return */ -bool cNodeMachine::hasGoalWithEdict(edict_t *pEdict) const +bool cNodeMachine::hasGoalWithEdict(edict_t* pEdict) const { if (pEdict == nullptr) return false; // no edict == by default no - for (const tGoal& Goal : Goals) - { - if (Goal.pGoalEdict == pEdict) { - return true; - } - } - - // Does not exist - return false; + return std::any_of(std::begin(Goals), std::end(Goals), [pEdict](const tGoal& goal) { + return goal.pGoalEdict == pEdict; + }); } void cNodeMachine::resetCheckedValuesForGoals() { @@ -2051,8 +2072,7 @@ void cNodeMachine::updateGoals() { // skip invalid players and skip self (i.e. this bot) if (pPlayer && !pPlayer->free) { // skip this player if not alive (i.e. dead or dying) - if (!IsAlive(pPlayer)) - continue; + if (!IsAlive(pPlayer)) continue; if (UTIL_IsVip(pPlayer)) { addGoal(pPlayer, GOAL_VIP, pPlayer->v.origin + Vector(0, 0, 32)); } @@ -2410,9 +2430,9 @@ void cNodeMachine::openNeighbourNodes(const int startNodeIndex, const int nodeTo // rblog(msg); nodeStar.parent = nodeToOpenNeighboursFrom; nodeStar.cost = cost; - } + } } - } + } } /** @@ -2545,7 +2565,6 @@ int cNodeMachine::node_camp(const Vector& vOrigin, const int iTeam) const } return iBestNode; - } // Check if iFrom is visible from other nodes (and opposite) @@ -2584,6 +2603,8 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, const int iTeam, edict_t // Theory: // Find a node, far, and a lot danger... + // and with less visibility + const int iFrom = getClosestNode(vOrigin, 75, pEdict); // Search in this meredian for (int i = 0; i < MAX_NODES; i++) { @@ -2603,11 +2624,7 @@ int cNodeMachine::node_look_camp(const Vector& vOrigin, const int iTeam, edict_t // Set to false SetVisibilityFromTo(iFrom, iNode, false); SetVisibilityFromTo(iNode, iFrom, false); - } else { - SetVisibilityFromTo(iFrom, iNode, true); - SetVisibilityFromTo(iNode, iFrom, true); } - } else { if (GetVisibilityFromTo(iFrom, iNode) == VIS_BLOCKED) // BERKED { @@ -2668,13 +2685,13 @@ void cNodeMachine::path_walk(cBot *pBot, const float distanceMoved) { pBot->setMoveSpeed(pBot->f_max_speed); // Walk the path - const int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); // Node we are heading for + const int currentNodeToHeadFor = pBot->getCurrentPathNodeToHeadFor(); // Node we are heading to // possibly end of path reached, overshoot destination? if (currentNodeToHeadFor < 0) { pBot->rprint_trace("cNodeMachine::path_walk", "Finished - there is no current node to head for"); pBot->forgetGoal(); - pBot->forgetPath(); + pBot->stopMoving(); return; } @@ -2700,19 +2717,18 @@ void cNodeMachine::path_walk(cBot *pBot, const float distanceMoved) { pBot->pEdict, &trb); } else { UTIL_TraceLine(pBot->pEdict->v.origin, vButtonVector, - ignore_monsters, dont_ignore_glass, - pBot->pEdict, &trb); + ignore_monsters, dont_ignore_glass, pBot->pEdict, &trb); } bool isGood = false; // if nothing hit: - if (trb.flFraction >= 1.0f) + if (trb.flFraction >= 1.0f) { + isGood = true; + } + // we hit this button we check for + if (trb.pHit == pBot->pButtonEdict) { isGood = true; - else { - // we hit this button we check for - if (trb.pHit == pBot->pButtonEdict) - isGood = true; } if (isGood || bTrigger) { @@ -3402,7 +3418,7 @@ void cNodeMachine::path_think(cBot *pBot, const float distanceMoved) { // A score of 1.0 is max. pBot->rprint_normal("cNodeMachine::path_think", "going to choose goal"); - for (int goalIndex = 0; goalIndex < MAX_GOALS; goalIndex++) { + for (int goalIndex = 0; goalIndex < MAX_GOALS; ++goalIndex) { constexpr int maxCheckedScore = 5; // Make sure this goal is valid @@ -3836,7 +3852,7 @@ int cNodeMachine::node_cover(const int iFrom, const int iTo, edict_t *pEdict) { // is no option. // Note: this function is only called once for finding some node to take cover from - // Most bad situation would be that 31 bots call this function in 1 frame. + // Most bad scenario would be that 31 bots call this function in 1 frame. // TEMP sollution: float fClosest = 512; @@ -3857,11 +3873,24 @@ int cNodeMachine::node_cover(const int iFrom, const int iTo, edict_t *pEdict) { if (tr.flFraction < 1.0f) bVisible = false; - } else { - if (GetVisibilityFromTo(iFrom, i) == VIS_BLOCKED) // BERKED + } + + if (GetVisibilityFromTo(i, iFrom) == VIS_UNKNOWN) // BERKED + { + UTIL_TraceLine(Nodes[i].origin, Nodes[iFrom].origin, + ignore_monsters, ignore_glass, pEdict, &tr); + + if (tr.flFraction < 1.0f) bVisible = false; } + // only when really blocked, count it as false. + if (GetVisibilityFromTo(iFrom, i) == VIS_BLOCKED) + bVisible = false; + + if (GetVisibilityFromTo(i, iFrom) == VIS_BLOCKED) + bVisible = false; + // Hit something if (bVisible == false) { // Update VisTable @@ -4017,33 +4046,29 @@ void cNodeMachine::dump_goals() const // EVY: another dump void cNodeMachine::dump_path(const int iBot, const int CurrentPath) const { - char buffer[80]; - int i, CurrentNode; - - if (CurrentPath >= 0) - CurrentNode = iPath[iBot][CurrentPath]; - else - CurrentNode = -1; - rblog(" Path is: "); - for (i = 0; i < MAX_NODES && iPath[iBot][i] >= 0; i++) { - if (i == CurrentPath) - snprintf(buffer, sizeof(buffer), "<%d> ", iPath[iBot][i]); - else - snprintf(buffer, sizeof(buffer), "%d ", iPath[iBot][i]); - rblog(buffer); - } - rblog("\n"); - if (CurrentNode < 0) - return; - rblog(" Current direct neighbours are:\n"); - for (i = 0; i < MAX_NEIGHBOURS; i++) - if (Nodes[CurrentNode].iNeighbour[i] >= 0) { - const int j = Nodes[CurrentNode].iNeighbour[i]; - const Vector v = Nodes[j].origin; - snprintf(buffer, sizeof(buffer), " %d (%.0f, %.0f, %.0f)\n", j, v.x, v.y, v.z); + char buffer[181]; + snprintf(buffer, 180, " Path for bot %d (current index %d): ", iBot, CurrentPath); + rblog(buffer); + + bool path_exists = false; + for (int i = 0; i < MAX_PATH_NODES; ++i) { + int node_index = iPath[iBot][i]; + if (node_index != -1) { + path_exists = true; + snprintf(buffer, 180, "%d ", node_index); rblog(buffer); } - rblog("\n"); + else { + break; // End of path + } + } + + if (!path_exists) { + rblog("No path.\n"); + } + else { + rblog("\n"); + } } // EVY a lot of things to draw: nodes, neighbours, goals, paths, ... @@ -4052,37 +4077,29 @@ void cNodeMachine::dump_path(const int iBot, const int CurrentPath) const // width and height of the debug bitmap image enum : std::uint16_t { - DEBUG_BMP_WIDTH = 2048, - DEBUG_BMP_HEIGHT = 2048 + DEBUG_BMP_WIDTH = 2048, + DEBUG_BMP_HEIGHT = 2048 }; -static unsigned char *bmp_buffer; +static std::vector bmp_buffer; static float maxx, maxy, minx, miny; static float scale; static void InitDebugBitmap() { // this function allocates memory and clears the debug bitmap buffer - -// if (bmp_buffer) - free(bmp_buffer); // reliability check, free BMP buffer if already allocated - - bmp_buffer = nullptr; - bmp_buffer = static_cast(malloc(DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT)); // allocate memory - if (bmp_buffer == nullptr) { - std::fprintf(stderr, - "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer!\n", - DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024); - exit(1); + try { + bmp_buffer.assign(static_cast(DEBUG_BMP_WIDTH) * DEBUG_BMP_HEIGHT, 14); + } + catch (const std::bad_alloc& e) { + std::fprintf(stderr, "InitDebugBitmap(): unable to allocate %d kbytes for BMP buffer! Error: %s\n", + DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT / 1024, e.what()); + bmp_buffer.clear(); // Ensure buffer is in a valid state } - - std::memset(bmp_buffer, 14, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); // Set all to all white (and allow for darker palette) } // Draw a small cross static void DrawPoint(const Vector& v, const unsigned char color) { - if (bmp_buffer == nullptr) { - std::fprintf(stderr, - "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); + if (bmp_buffer.empty()) { return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates @@ -4094,7 +4111,7 @@ static void DrawPoint(const Vector& v, const unsigned char color) { std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1); + std::exit(1); } bmp_buffer[offset] = color; // draw the point itself @@ -4119,9 +4136,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, cons int stepx, stepy; int fraction; - if (bmp_buffer == nullptr) { - std::fprintf(stderr, - "DrawLineInDebugBitmap(): function called with NULL BMP buffer!\n"); + if (bmp_buffer.empty()) { return; // reliability check: cancel if bmp buffer unallocated } // translate the world coordinates in image pixel coordinates @@ -4148,7 +4163,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, cons std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1); + std::exit(1); } bmp_buffer[offset] = color; // draw the first point of the line @@ -4177,7 +4192,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, cons std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1); + std::exit(1); } bmp_buffer[offset] = color; // set this point to have the specified color @@ -4205,7 +4220,7 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, cons std::fprintf(stderr, "DrawLineInDebugBitmap(): bad BMP buffer index %d (range 0 - %d)\n", offset, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT); - exit(1); + std::exit(1); } bmp_buffer[offset] = color; // set this point to have the specified color } @@ -4213,32 +4228,30 @@ static void DrawLineInDebugBitmap(const Vector& v_from, const Vector& v_to, cons //return; // finished, segment has been printed into the BMP dot matrix } -// from PMB & Botman code - -static void WriteDebugBitmap(const char *filename) { - int data_start, file_size; +static void WriteDebugBitmap(const char* filename) { + int data_start, file_size; unsigned long dummy; - if (bmp_buffer == nullptr) { + if (bmp_buffer.empty()) { std::fprintf(stderr, - "WriteDebugBitmap(): function called with NULL BMP buffer!\n"); + "WriteDebugBitmap(): function called with NULL BMP buffer!\n"); return; // reliability check: cancel if bmp buffer unallocated } // open (or create) the .bmp file for writing in binary mode... FILE* fp = std::fopen(filename, "wb"); if (fp == nullptr) { std::fprintf(stderr, "WriteDebugBitmap(): unable to open BMP file!\n"); - // if (bmp_buffer) - free(bmp_buffer); // cannot open file, free DXF buffer - bmp_buffer = nullptr; + bmp_buffer.clear(); // Ensure buffer is in a valid state return; // cancel if error creating file } // write the BMP header - fwrite("BM", 2, 1, fp); // write the BMP header tag - fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the file size field (will write it last) - fwrite("\0\0", sizeof(short), 1, fp); // dump zeros in the first reserved field (unused) - fwrite("\0\0", sizeof(short), 1, fp); // dump zeros in the second reserved field (unused) - fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the data start field (will write it last) + constexpr char bmp_magic[] = { 'B', 'M' }; + std::fwrite(bmp_magic, sizeof(bmp_magic), 1, fp); // write the BMP header tag + std::fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the file size field (will write it last) + constexpr short reserved = 0; + std::fwrite(&reserved, sizeof(short), 1, fp); // dump zeros in the first reserved field (unused) + std::fwrite(&reserved, sizeof(short), 1, fp); // dump zeros in the second reserved field (unused) + std::fseek(fp, sizeof(unsigned long), SEEK_CUR); // skip the data start field (will write it last) // write the info header dummy = 40; @@ -4263,114 +4276,113 @@ static void WriteDebugBitmap(const char *filename) { std::fwrite(&dummy, sizeof(unsigned long), 1, fp); // write the # of important colors (wtf ?) // write the color palette (B, G, R, reserved byte) - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 0=BLACK - fputc(0xFF, fp); - fputc(0xFF, fp); - fputc(0xFF, fp); - fputc(0x00, fp); // 1=WHITE - fputc(0x80, fp); - fputc(0x80, fp); - fputc(0x80, fp); - fputc(0x00, fp); // 2=GREY - fputc(0xC0, fp); - fputc(0xC0, fp); - fputc(0xC0, fp); - fputc(0x00, fp); // 3=SILVER - fputc(0x80, fp); - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 4=DARK BLUE - fputc(0xFF, fp); - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 5=BLUE - fputc(0x80, fp); - fputc(0x80, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 6=DARK YELLOW - fputc(0xFF, fp); - fputc(0xFF, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 7=YELLOW ? LIGHT BLUE - fputc(0x00, fp); - fputc(0x80, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 8=DARK GREEN - fputc(0x00, fp); - fputc(0xFF, fp); - fputc(0x00, fp); - fputc(0x00, fp); // 9=GREEN - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x80, fp); - fputc(0x00, fp); // 10=DARK RED - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0xFF, fp); - fputc(0x00, fp); // 11=RED - fputc(0x80, fp); - fputc(0x00, fp); - fputc(0x80, fp); - fputc(0x00, fp); // 12=DARK PURPLE - fputc(0xFF, fp); - fputc(0x00, fp); - fputc(0xFF, fp); - fputc(0x00, fp); // 13=PURPLE - fputc(0xFF, fp); - fputc(0xFF, fp); - fputc(0xFF, fp); - fputc(0x00, fp); // 14=WHITE - fputc(0xEF, fp); - fputc(0xEF, fp); - fputc(0xEF, fp); - fputc(0x00, fp); // 15=WHITE-GREY - fputc(0xDF, fp); - fputc(0xDF, fp); - fputc(0xDF, fp); - fputc(0x00, fp); // 16=GREY - fputc(0xCF, fp); - fputc(0xCF, fp); - fputc(0xCF, fp); - fputc(0x00, fp); // 17=DARKGREY - fputc(0xBF, fp); - fputc(0xBF, fp); - fputc(0xBF, fp); - fputc(0x00, fp); // 18=DARKGREY - fputc(0xAF, fp); - fputc(0xAF, fp); - fputc(0xAF, fp); - fputc(0x00, fp); // 19=DARKGREY + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 0=BLACK + std::fputc(0xFF, fp); + std::fputc(0xFF, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); // 1=WHITE + std::fputc(0x80, fp); + std::fputc(0x80, fp); + std::fputc(0x80, fp); + std::fputc(0x00, fp); // 2=GREY + std::fputc(0xC0, fp); + std::fputc(0xC0, fp); + std::fputc(0xC0, fp); + std::fputc(0x00, fp); // 3=SILVER + std::fputc(0x80, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 4=DARK BLUE + std::fputc(0xFF, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 5=BLUE + std::fputc(0x80, fp); + std::fputc(0x80, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 6=DARK YELLOW + std::fputc(0xFF, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 7=YELLOW ? LIGHT BLUE + std::fputc(0x00, fp); + std::fputc(0x80, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 8=DARK GREEN + std::fputc(0x00, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); // 9=GREEN + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x80, fp); + std::fputc(0x00, fp); // 10=DARK RED + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); // 11=RED + std::fputc(0x80, fp); + std::fputc(0x00, fp); + std::fputc(0x80, fp); + std::fputc(0x00, fp); // 12=DARK PURPLE + std::fputc(0xFF, fp); + std::fputc(0x00, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); // 13=PURPLE + std::fputc(0xFF, fp); + std::fputc(0xFF, fp); + std::fputc(0xFF, fp); + std::fputc(0x00, fp); // 14=WHITE + std::fputc(0xEF, fp); + std::fputc(0xEF, fp); + std::fputc(0xEF, fp); + std::fputc(0x00, fp); // 15=WHITE-GREY + std::fputc(0xDF, fp); + std::fputc(0xDF, fp); + std::fputc(0xDF, fp); + std::fputc(0x00, fp); // 16=GREY + std::fputc(0xCF, fp); + std::fputc(0xCF, fp); + std::fputc(0xCF, fp); + std::fputc(0x00, fp); // 17=DARKGREY + std::fputc(0xBF, fp); + std::fputc(0xBF, fp); + std::fputc(0xBF, fp); + std::fputc(0x00, fp); // 18=DARKGREY + std::fputc(0xAF, fp); + std::fputc(0xAF, fp); + std::fputc(0xAF, fp); + std::fputc(0x00, fp); // 19=DARKGREY for (dummy = 20; dummy < 256; dummy++) { // fill out the rest of the palette with zeros - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); - fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); + std::fputc(0x00, fp); } // write the actual image data data_start = ftell(fp); // get the data start position (that's where we are now) - std::fwrite(bmp_buffer, DEBUG_BMP_WIDTH * DEBUG_BMP_HEIGHT, 1, fp); // write the image + std::fwrite(bmp_buffer.data(), bmp_buffer.size(), 1, fp); // write the image file_size = ftell(fp); // get the file size now that the image is dumped // now that we've dumped our data, we know the file size and the data start position - fseek(fp, 0, SEEK_SET); // rewind - fseek(fp, 2, SEEK_CUR); // skip the BMP header tag "BM" + std::fseek(fp, 0, SEEK_SET); // rewind + std::fseek(fp, 2, SEEK_CUR); // skip the BMP header tag "BM" std::fwrite(&file_size, sizeof(unsigned long), 1, fp); // write the file size at its location - fseek(fp, sizeof(short), SEEK_CUR); // skip the first reserved field - fseek(fp, sizeof(short), SEEK_CUR); // skip the second reserved field + std::fseek(fp, sizeof(short), SEEK_CUR); // skip the first reserved field + std::fseek(fp, sizeof(short), SEEK_CUR); // skip the second reserved field std::fwrite(&data_start, sizeof(unsigned long), 1, fp); // write the data start at its location std::fclose(fp); // finished, close the BMP file - // if (bmp_buffer) - free(bmp_buffer); // and free the BMP buffer - bmp_buffer = nullptr; + bmp_buffer.clear(); // and free the BMP buffer + bmp_buffer.shrink_to_fit(); //return; // and return } @@ -4411,19 +4423,22 @@ void cNodeMachine::FindMinMax() const // Palette is defined such that increasing the palette index // Makes a slightly darker dark -void cNodeMachine::MarkAxis() { - const int x0 = static_cast((0 - minx) / scale); - const int y0 = static_cast((0 - miny) / scale); - - // Mark X axis by keeping X to 0 and varying Y - if (minx < 0 && 0 < maxx) - for (int y = 0; y < DEBUG_BMP_HEIGHT; y++) - bmp_buffer[y * DEBUG_BMP_WIDTH + x0] += 2; +// Mark X and Y axis +void cNodeMachine::MarkAxis() +{ + int x, y; - // Mark Y axis by keeping Y to 0 and varying X - if (miny < 0 && 0 < maxy) - for (int x = 0; x < DEBUG_BMP_WIDTH; x++) - bmp_buffer[y0 * DEBUG_BMP_WIDTH + x] += 2; + // Mark X axis + y = static_cast((0 - miny) / scale); + if (y >= 0 && y < DEBUG_BMP_HEIGHT) + for (x = 0; x < DEBUG_BMP_WIDTH; x++) + bmp_buffer[y * DEBUG_BMP_WIDTH + x] = 17; + + // Mark Y axis + x = static_cast((0 - minx) / scale); + if (x >= 0 && x < DEBUG_BMP_WIDTH) + for (y = 0; y < DEBUG_BMP_HEIGHT; y++) + bmp_buffer[y * DEBUG_BMP_WIDTH + x] = 17; } // 05/07/04 diff --git a/NodeMachine.h b/NodeMachine.h index dad1698..604ee82 100644 --- a/NodeMachine.h +++ b/NodeMachine.h @@ -119,7 +119,7 @@ class cNodeMachine { static bool node_on_crate(const Vector& vOrigin, edict_t *pEdict); - static int node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance); + int node_dangerous(int iTeam, const Vector& vOrigin, float fMaxDistance); int node_look_camp(const Vector& vOrigin, int iTeam, edict_t *pEdict); diff --git a/bot.cpp b/bot.cpp index c4d6e99..b81e57f 100644 --- a/bot.cpp +++ b/bot.cpp @@ -242,6 +242,7 @@ void cBot::SpawnInit() { bFirstOutOfSight = false; buy_grenade = false; buy_smokegrenade = false; + bIssuedInitialRadio = false; buy_flashbang = 0; if (RANDOM_LONG(0, 100) < ipWalkWithKnife) { @@ -433,7 +434,7 @@ void cBot::NewRound() { bFirstOutOfSight = false; - + bIssuedInitialRadio = false; f_strafe_speed = 0.0f; @@ -1145,8 +1146,22 @@ void cBot::Combat() { // Bot is on ladder if (isOnLadder()) { - // TODO: Bot fights when on ladder + // When on a ladder, the bot is vulnerable. + // It should stop moving and try to fight back if it can see the enemy. + stopMoving(); + if (isSeeingEnemy()) { + // Switch to a pistol if available, as it's more accurate on ladders. + if (hasSecondaryWeaponEquiped() && CarryWeaponType() != SECONDARY) { + pickWeapon(iSecondaryWeapon); + } + + // Aim and fire at the enemy. + AimAtEnemy(); + FireWeapon(); + } + + // Do not proceed with normal ground combat logic. return; } @@ -1496,7 +1511,13 @@ void cBot::InteractWithPlayers() { if (vip) { // We do not forget our enemy, but we will try to get the heck out of here. - // TODO TODO TODO: code something here? + // A VIP bot should prioritize survival. Upon spotting an enemy, it should + // immediately seek cover and call for backup. This increases the chances of + // the VIP surviving the encounter. + FindCover(); // Find a suitable cover position away from the enemy. + if (FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 3, "3", ""); // Radio for backup. + } } // Whenever we hold a knife, get our primary weapon @@ -1701,7 +1722,7 @@ vec_t cBot::ReturnTurnedAngle(float speed, float current, const float ideal) { // check if the bot is already facing the idealpitch direction... if (diff <= 1.0f) - return static_cast(current); // return number of degrees turned + return current; // return number of degrees turned // check if difference is less than the max degrees per turn speed = std::min(diff, speed); // just need to turn a little bit (less than max) @@ -1744,7 +1765,7 @@ vec_t cBot::ReturnTurnedAngle(float speed, float current, const float ideal) { current -= 360; if (current < -180) current += 360; - return static_cast(current); // return what it should be + return current; // return what it should be } // BOT: sub-function (DEFUSE) for ACT() @@ -1786,7 +1807,7 @@ bool cBot::Defuse() { const float distance = func_distance(pEdict->v.origin, vC4); // can see C4 - const bool canSeeC4 = canSeeVector(vC4); + const bool canSeeC4 = canSeeVector(vC4, pent); if (!canSeeC4) { rprint_trace("Defuse()", "Cannot see planted C4 - bailing"); @@ -2055,8 +2076,8 @@ void cBot::Act() { v_shouldbe.z = 0; //unused? [APG]RoboCop[CL] // set the body angles to point the gun correctly - pEdict->v.angles.x = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.x, v_shouldbe.x); - pEdict->v.angles.y = ReturnTurnedAngle(ipTurnSpeed, pEdict->v.angles.y, v_shouldbe.y); + pEdict->v.angles.x = ReturnTurnedAngle(static_cast(ipTurnSpeed), pEdict->v.angles.x, v_shouldbe.x); + pEdict->v.angles.y = ReturnTurnedAngle(static_cast(ipTurnSpeed), pEdict->v.angles.y, v_shouldbe.y); pEdict->v.angles.z = 0; // adjust the view angle pitch to aim correctly (MUST be after body v.angles stuff) @@ -3323,10 +3344,14 @@ void cBot::Think() { } // 1 SECOND START OF ROUND - if (Game.getRoundStartedTime() + 1 > gpGlobals->time && - Game.getRoundStartedTime() < gpGlobals->time) { - // TODO: Issue radio command? - this->rprint_trace("cBot::Think()", "First second of round"); + if (!bIssuedInitialRadio && + Game.getRoundStartedTime() < gpGlobals->time && + Game.getRoundStartedTime() + 1.0f > gpGlobals->time) { + if (RANDOM_LONG(0, 100) < 30 && FUNC_DoRadio(this)) { + UTIL_BotRadioMessage(this, 2, "1", ""); // "Go, Go, Go!" + } + bIssuedInitialRadio = true; + this->rprint_trace("cBot::Think()", "First second of round, issued initial radio."); } // SITUATION: In freezetime @@ -3981,9 +4006,7 @@ int cBot::getAmountOfHostagesBeingRescued() const } // Will return true when the vector is visible. -// TODO: Make this function more flexible, ie able to hit an entity that it searches -// and return true on that as well. (mix it with the above function) -bool cBot::canSeeVector(const Vector& vDest) const +bool cBot::canSeeVector(const Vector& vDest, edict_t* pTargetEntity) const { TraceResult tr; const Vector start = pEdict->v.origin + pEdict->v.view_ofs; @@ -3991,10 +4014,19 @@ bool cBot::canSeeVector(const Vector& vDest) const // trace a line from bot's eyes to destination... UTIL_TraceLine(start, vDest, ignore_monsters, pEdict->v.pContainingEntity, &tr); - if (tr.flFraction < 1.0f) - return false; + // if trace is not blocked, the vector is visible + if (tr.flFraction >= 1.0f) + { + return true; + } - return true; + // if we have a target entity, check if we hit it + if (pTargetEntity != nullptr && tr.pHit == pTargetEntity) + { + return true; // we hit our target, so we can "see" it + } + + return false; // something is blocking the view } // The coming 2 shield functions where originaly created by Whistler; diff --git a/bot.h b/bot.h index 42762c4..63576f8 100644 --- a/bot.h +++ b/bot.h @@ -312,20 +312,21 @@ class cBot { // ------------------------ // BOOLEANS // ------------------------ - bool buy_primary; - bool buy_secondary; + bool vip; + bool bWalkKnife; bool buy_ammo_primary; bool buy_ammo_secondary; + bool buy_primary; + bool buy_secondary; bool buy_armor; - bool buy_grenade; - bool buy_smokegrenade; //31.08.04 Frashman added support for Smoke Grenade - bool bIsUsed; // Bot is 'used'/'playing' (if set to true, the bot is active) - bool bInitialize; bool buy_defusekit; - bool bWalkKnife; // likes to walk around with knife - bool vip; - bool bFirstOutOfSight; + bool buy_grenade; + bool buy_smokegrenade; + bool bIssuedInitialRadio; + + bool bInitialize; // Has the bot been initialized yet? + bool bIsUsed; // Is this bot slot used? // ------------------------ // HUD @@ -413,7 +414,7 @@ class cBot { float ReactionTime(int iSkill); // Reaction time based upon skill void FindCover(); - bool canSeeVector(const Vector& vDest) const; + bool canSeeVector(const Vector& vDest, edict_t* pTargetEntity = nullptr) const; bool canSeeEntity(edict_t* pEntity) const; diff --git a/bot_client.cpp b/bot_client.cpp index edf038d..3c91511 100644 --- a/bot_client.cpp +++ b/bot_client.cpp @@ -610,9 +610,16 @@ void BotClient_CS_SayText(void *p, const int bot_index) { else if (state == 1) { // here must be some team check so we do not let bots // of the other team react to this somehow.. - // - after playing with the dll i did not notice any weird stuff yet... - // - so only when people discover some bugs with this we are going to fix this - // - thing... ie "Only fix it when its broken". + edict_t* pPlayer = INDEXENT(ucEntIndex); + if (pPlayer) + { + const cBot* pBot = &bots[bot_index]; + if (UTIL_GetTeam(pPlayer) != pBot->iTeam - 1) + { + // message is from another team, don't process it + state = -1; // reset state machine + } + } } // don't know? else if (state == 2) { diff --git a/dll.cpp b/dll.cpp index 614d042..ca7c9a0 100644 --- a/dll.cpp +++ b/dll.cpp @@ -30,6 +30,11 @@ **/ #include +#include +#include +#include +#include + #include #include #include @@ -135,13 +140,16 @@ META_FUNCTIONS gMetaFunctionTable = { nullptr, // pfnGetEngineFunctions_Post() }; +constexpr const char* REALBOT_AUTHOR = "Stefan Hendriks"; +constexpr const char* REALBOT_URL = "http://realbot.bots-united.com/"; + plugin_info_t Plugin_info = { META_INTERFACE_VERSION, // interface version "RealBot", // plugin name - rb_version_nr, // plugin version + rb_version_nr, // plugin version __DATE__, // date of creation - "Stefan Hendriks", // plugin author - "http://realbot.bots-united.com/", // plugin URL + REALBOT_AUTHOR, // plugin author + REALBOT_URL, // plugin URL "REALBOT", // plugin logtag PT_CHANGELEVEL, // when loadable <-- FIX PT_ANYTIME, // when unloadable @@ -171,8 +179,8 @@ C_DLLEXPORT int Meta_Query(const char* ifvers, plugin_info_t** pPlugInfo, Plugin_info.ifvers); // if plugin has later interface version, it's incompatible (update metamod) - sscanf(ifvers, "%d:%d", &mmajor, &mminor); - sscanf(META_INTERFACE_VERSION, "%d:%d", &pmajor, &pminor); + std::sscanf(ifvers, "%d:%d", &mmajor, &mminor); + std::sscanf(META_INTERFACE_VERSION, "%d:%d", &pmajor, &pminor); if (pmajor > mmajor || (pmajor == mmajor && pminor > mminor)) { LOG_CONSOLE(PLID, "metamod version is too old for this plugin; update metamod"); @@ -655,9 +663,9 @@ void StartFrame() { // go through all clients (except bots) for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - edict_t* pPlayer = INDEXENT(iIndex); + edict_t* p_player = INDEXENT(iIndex); // skip invalid players - if (pPlayer && !pPlayer->free) { + if (p_player && !p_player->free) { // we found a player which is alive. w00t welcome_time = gpGlobals->time + 10.0f; break; @@ -681,26 +689,26 @@ void StartFrame() { */ for (iIndex = 1; iIndex <= gpGlobals->maxClients; iIndex++) { - edict_t* pPlayer = INDEXENT(iIndex); + edict_t* p_player = INDEXENT(iIndex); // skip invalid players and skip self (i.e. this bot) - if (pPlayer && !pPlayer->free) { + if (p_player && !p_player->free) { // skip bots! - if (UTIL_GetBotPointer(pPlayer)) + if (UTIL_GetBotPointer(p_player)) continue; // skip fake clients - if (pPlayer->v.flags & FL_THIRDPARTYBOT - || pPlayer->v.flags & FL_FAKECLIENT) + if (p_player->v.flags & FL_THIRDPARTYBOT + || p_player->v.flags & FL_FAKECLIENT) continue; // random color r = RANDOM_LONG(30, 255); g = RANDOM_LONG(30, 255); b = RANDOM_LONG(30, 255); - HUD_DrawString(r, g, b, total_welcome, pPlayer); + HUD_DrawString(r, g, b, total_welcome, p_player); // use speak command - if (pPlayer == pHostEdict) + if (p_player == pHostEdict) UTIL_SpeechSynth(pHostEdict, Game.RandomSentence()); } } @@ -758,15 +766,15 @@ void StartFrame() { int iHumans = 0, iBots = 0; // Search for human players, simple method... - for (int i = 1; i <= gpGlobals->maxClients; i++) { - edict_t* pPlayer = INDEXENT(i); + for (int j = 1; j <= gpGlobals->maxClients; j++) { + edict_t* p_player = INDEXENT(j); // skip invalid players and skip self (i.e. this bot) - if (pPlayer && !pPlayer->free) { + if (p_player && !p_player->free) { // a bot - if (UTIL_GetBotPointer(pPlayer) != nullptr) + if (UTIL_GetBotPointer(p_player) != nullptr) iBots++; else { - if (pPlayer->v.flags & FL_CLIENT) + if (p_player->v.flags & FL_CLIENT) iHumans++; // it is 'human' (well unless some idiot uses another bot, i cannot detect that!) } } @@ -1117,123 +1125,57 @@ void UpdateClientData(const edict_s* ent, int sendweapons, clientdata_s* cd) //T } void ProcessBotCfgFile() { - char cmd_line[256]; - static char server_cmd[80]; - const char* arg2, * arg3, * arg4; - char msg[80]; - if (bot_cfg_pause_time > gpGlobals->time) return; if (bot_cfg_fp == nullptr) return; - int cmd_index = 0; - cmd_line[cmd_index] = 0; - - int ch = fgetc(bot_cfg_fp); - - // skip any leading blanks - while (ch == ' ') - ch = fgetc(bot_cfg_fp); - - while (ch != EOF && ch != '\r' && ch != '\n') { - if (ch == '\t') // convert tabs to spaces - ch = ' '; - - cmd_line[cmd_index] = ch; - - ch = fgetc(bot_cfg_fp); - - // skip multiple spaces in input file - while (cmd_line[cmd_index] == ' ' && ch == ' ') - ch = fgetc(bot_cfg_fp); - - cmd_index++; - } - - if (ch == '\r') // is it a carriage return? - { - ch = fgetc(bot_cfg_fp); // skip the linefeed - } - // if reached end of file, then close it - if (ch == EOF) { + char line_buffer[256]; + if (fgets(line_buffer, sizeof(line_buffer), bot_cfg_fp) == nullptr) { + // End of file or error std::fclose(bot_cfg_fp); - bot_cfg_fp = nullptr; - bot_cfg_pause_time = 8.0f; // wait 8 seconds before starting + return; } - cmd_line[cmd_index] = 0; // terminate the command line - - // copy the command line to a server command buffer... - //TODO: To use std:string for this [APG]RoboCop[CL] - std::strncpy(server_cmd, cmd_line, sizeof(server_cmd)); - server_cmd[sizeof(server_cmd) - 1] = '\0'; - - std::strcat(server_cmd, "\n"); - - cmd_index = 0; - const char* cmd = cmd_line; - const char* arg1 = arg2 = arg3 = arg4 = nullptr; - - // skip to blank or end of string... - while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) - cmd_index++; - - if (cmd_line[cmd_index] == ' ') { - cmd_line[cmd_index++] = 0; - arg1 = &cmd_line[cmd_index]; - - // skip to blank or end of string... - while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) - cmd_index++; - - if (cmd_line[cmd_index] == ' ') { - cmd_line[cmd_index++] = 0; - arg2 = &cmd_line[cmd_index]; - + std::string cmd_line(line_buffer); - // skip to blank or end of string... - while (cmd_line[cmd_index] != ' ' && cmd_line[cmd_index] != 0) - cmd_index++; + // Trim leading and trailing whitespace, and remove carriage returns + cmd_line.erase(0, cmd_line.find_first_not_of(" \t\n\r")); + cmd_line.erase(cmd_line.find_last_not_of(" \t\n\r") + 1); - if (cmd_line[cmd_index] == ' ') { - cmd_line[cmd_index++] = 0; - arg3 = &cmd_line[cmd_index]; - - // skip to blank or end of string... - while (cmd_line[cmd_index] != ' ' - && cmd_line[cmd_index] != 0) - cmd_index++; - - if (cmd_line[cmd_index] == ' ') { - cmd_line[cmd_index++] = 0; - arg4 = &cmd_line[cmd_index]; - } - } - } + if (cmd_line.empty() || cmd_line[0] == '#') { + return; // return if comment or blank line } - if (cmd_line[0] == '#' || cmd_line[0] == 0) - return; // return if comment or blank line + std::stringstream ss(cmd_line); + std::string command; + ss >> command; - if (std::strcmp(cmd, "pause") == 0) { - bot_cfg_pause_time = gpGlobals->time + std::atoi(arg1); + if (command == "pause") { + float pause_duration = 0.0f; + if (ss >> pause_duration) { + bot_cfg_pause_time = gpGlobals->time + pause_duration; + } return; } + // 07/02/04 - This gives a user theoreticly the power as in the console // use 'realbot addbot' to add a bot, etc. I dont think we need more // it would double the work. - snprintf(msg, sizeof(msg), "BOT.CFG >> Executing command: %s", server_cmd); // removed \n + char msg[256]; + snprintf(msg, sizeof(msg), "BOT.CFG >> Executing command: %s", cmd_line.c_str()); ALERT(at_console, msg); - if (IS_DEDICATED_SERVER()) - printf("%s", msg); + if (IS_DEDICATED_SERVER()) { + printf("%s\n", msg); + } - SERVER_COMMAND(server_cmd); + std::string server_cmd = cmd_line + "\n"; + SERVER_COMMAND(server_cmd.c_str()); } // REALBOT COMMAND diff --git a/game.h b/game.h index 04a2826..168ceed 100644 --- a/game.h +++ b/game.h @@ -40,25 +40,31 @@ **/ // GAME MESSAGES -#define GAME_MSG_SUCCESS 0 // complete success -#define GAME_MSG_FAILURE 1 // complete failure +enum : std::uint8_t +{ + GAME_MSG_SUCCESS = 0, // complete success + GAME_MSG_FAILURE = 1, // complete failure -#define GAME_MSG_FAIL_SERVERFULL 2 // failure + reason -//#define GAME_MSG_WHATEVERYOUWANTTOPUTHERE + GAME_MSG_FAIL_SERVERFULL = 2, // failure + reason + //#define GAME_MSG_WHATEVERYOUWANTTOPUTHERE -// SITUATIONS -#define GAME_YES 99 -#define GAME_NO 98 + // SITUATIONS + GAME_YES = 99, + GAME_NO = 98 +}; // BROADCASTING -#define BROADCAST_ROUND 0 -#define BROADCAST_MAP 1 -#define BROADCAST_KILLS_FULL 3 // killed, show full info (name+skill) -#define BROADCAST_KILLS_MIN 4 // killed, show min info (name) -#define BROADCAST_KILLS_NONE 5 // killed, show no information -#define BROADCAST_DEATHS_FULL 6 // died, show full info (name+skill) -#define BROADCAST_DEATHS_MIN 7 // died, show min info (name) -#define BROADCAST_DEATHS_NONE 8 // died, show no information +enum : std::uint8_t +{ + BROADCAST_ROUND = 0, + BROADCAST_MAP = 1, + BROADCAST_KILLS_FULL = 3, // killed, show full info (name+skill) + BROADCAST_KILLS_MIN = 4, // killed, show min info (name) + BROADCAST_KILLS_NONE = 5, // killed, show no information + BROADCAST_DEATHS_FULL = 6, // died, show full info (name+skill) + BROADCAST_DEATHS_MIN = 7, // died, show min info (name) + BROADCAST_DEATHS_NONE = 8 // died, show no information +}; static constexpr int MAX_BOTS = 32; static constexpr int MAX_NAME_LENGTH = 32; From f6727b076b5538b9d9d15c584a7a8feb47429e9d Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Fri, 3 Oct 2025 21:12:28 +0100 Subject: [PATCH 113/114] Update build.cpp --- build.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cpp b/build.cpp index 5def0bc..4831227 100644 --- a/build.cpp +++ b/build.cpp @@ -10,4 +10,4 @@ // 07/07/04 - Comment changed, it was moved from dll.cpp, not bot.cpp ;) (nitpicking) :D // BUILD NR & Version -const char *rb_version_nr = "4.0.5-beta4"; +const char *rb_version_nr = "4.0.5-beta5"; From 7d6e4fc51eca8bf8bce46e90d05f6ac548808838 Mon Sep 17 00:00:00 2001 From: "R. Hunter" Date: Sun, 7 Dec 2025 14:55:32 +0000 Subject: [PATCH 114/114] Adding LTO --- AMBuildScript | 10 ++++++---- realbot_mm.vcxproj | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/AMBuildScript b/AMBuildScript index ca78f46..a5d68dd 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -57,7 +57,7 @@ if builder.cxx.target.platform == 'linux': '-std=c++17', ] # Linux linker flags - builder.cxx.linkflags += ['-m32', '-ldl', '-lm'] + builder.cxx.linkflags += ['-m32', '-ldl', '-lm', '-flto'] elif builder.cxx.target.platform == 'windows': # Windows defines builder.cxx.defines += [ @@ -92,11 +92,13 @@ if builder.options.optimize: if builder.cxx.target.platform == 'linux': # Linux optimization flags builder.cxx.cflags += ['-O3'] + # Linux optimization link flags #TODO + #builder.cxx.linkflags += ['-flto'] elif builder.cxx.target.platform == 'windows': # Windows optimization flags - /Ob3 needs to be after /Ox, enables aggressive function inling -caxanga334 - builder.cxx.cflags += ['/Ox', '/Zo', '/Ob3', '/GF'] + builder.cxx.cflags += ['/Ox', '/Zo', '/Ob3', '/GL'] # Windows optimization link flags - builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + builder.cxx.linkflags += ['/OPT:ICF', '/OPT:REF', '/LTCG'] # This needs to be after our optimization flags which could otherwise disable it. builder.cxx.cflags += ['/Oy-'] @@ -106,7 +108,7 @@ if builder.options.debug: builder.cxx.defines += ['DEBUG', '_DEBUG'] if builder.cxx.target.platform == 'linux': # Linux debug flags - builder.cxx.cflags += ['-g3', '-O0'] + builder.cxx.cflags += ['-g3', '-Og', '-ggdb3'] elif builder.cxx.target.platform == 'windows': # Windows debug flags builder.cxx.cflags += ['/Od', '/RTC1', '/MTd'] diff --git a/realbot_mm.vcxproj b/realbot_mm.vcxproj index bdae191..1ef8956 100644 --- a/realbot_mm.vcxproj +++ b/realbot_mm.vcxproj @@ -13,7 +13,7 @@ DynamicLibrary - v143 + v145 false MultiByte false