diff --git a/include/core.h b/include/core.h index 80e0a40..bdde176 100644 --- a/include/core.h +++ b/include/core.h @@ -189,7 +189,8 @@ enum TaskId_t TASK_SHOOTBREAKABLE, TASK_HIDE, TASK_BLINDED, - TASK_SPRAY + TASK_SPRAY, + TASK_MAX }; // supported cs's @@ -541,7 +542,6 @@ enum WaypointFlag enum PathFlag { PATHFLAG_JUMP = (1 << 0), // must jump for this connection - PATHFLAG_DOUBLEJUMP = (1 << 1) // must use friend for this connection }; // defines waypoint connection types @@ -672,28 +672,10 @@ struct WeaponSelect int buySelect; // select item in buy menu (standard map) int newBuySelectT; // for counter-strike v1.6 int newBuySelectCT; // for counter-strike v1.6 - bool shootsThru; // can shoot thru walls + int penetratePower; // penetrate power bool primaryFireHold; // hold down primary fire button to use? }; -// skill definitions -struct SkillDefinition -{ - float minSurpriseTime; // surprise delay (minimum) - float maxSurpriseTime; // surprise delay (maximum) - float campStartDelay; // delay befor start camping - float campEndDelay; // delay before end camping - float minTurnSpeed; // initial minimum turnspeed - float maxTurnSpeed; // initial maximum turnspeed - float aimOffs_X; // X/Y/Z maximum offsets - float aimOffs_Y; // X/Y/Z maximum offsets - float aimOffs_Z; // X/Y/Z maximum offsets - int headshotFrequency; // precent to aiming to player head - int heardShootThruProb; // precent to shooting throug wall when seen something - int seenShootThruProb; // precent to shooting throug wall when heard something - int recoilAmount; // amount of recoil when the bot should pause shooting -}; - // fire delay definiton struct FireDelay { @@ -753,7 +735,7 @@ struct ExperienceSave // bot creation tab struct CreateQueue { - int skill; + int difficulty; int team; int member; int personality; @@ -846,6 +828,7 @@ private: int m_messageQueue[32]; // stack for messages char m_tempStrings[160]; // space for strings (say text...) int m_radioSelect; // radio entry + float m_headedTime; float m_blindRecognizeTime; // time to recognize enemy float m_itemCheckTime; // time next search for items needs to be done @@ -862,6 +845,7 @@ private: float m_timeLogoSpray; // time bot last spray logo float m_knifeAttackTime; // time to rush with knife (at the beginning of the round) bool m_defendedBomb; // defend action issued + bool m_defendHostage; float m_askCheckTime; // time to ask team float m_collideTime; // time last collision @@ -886,7 +870,6 @@ private: int m_waypointFlags; // current waypoint flags int m_loosedBombWptIndex; // nearest to loosed bomb waypoint int m_plantedBombWptIndex;// nearest to planted bomb waypoint - float m_skillOffset; // offset to bots skill unsigned short m_currentTravelFlags; // connection flags like jumping bool m_jumpFinished; // has bot finished jumping @@ -931,6 +914,7 @@ private: float m_zoomCheckTime; // time to check zoom again float m_shieldCheckTime; // time to check shiled drawing again float m_grenadeCheckTime; // time to check grenade usage + float m_lastEquipTime; // last time we equipped in buyzone bool m_checkKnifeSwitch; // is time to check switch to knife action bool m_checkWeaponSwitch; // is time to check weapon switch @@ -1001,6 +985,7 @@ private: bool DoWaypointNav (void); bool EnemyIsThreat (void); void FacePosition (void); + void SetIdealReactionTimes (bool actual = false); bool IsRestricted (int weaponIndex); bool IsRestrictedAMX (int weaponIndex); @@ -1015,6 +1000,7 @@ private: int FindDefendWaypoint (Vector origin); int FindGoal (void); void FindItem (void); + void CheckTerrain (float movedDistance); void GetCampDirection (Vector *dest); void CollectGoalExperience (int damage, int team); @@ -1027,7 +1013,7 @@ private: bool IsBombDefusing (Vector bombOrigin); bool IsBlockedLeft (void); bool IsBlockedRight (void); - bool IsWaypointUsed (int index); + bool IsPointOccupied (int index); inline bool IsOnLadder (void) { return pev->movetype == MOVETYPE_FLY; } inline bool IsOnFloor (void) { return (pev->flags & (FL_ONGROUND | FL_PARTIALGROUND)) != 0; } inline bool IsInWater (void) { return pev->waterlevel >= 2; } @@ -1106,12 +1092,13 @@ public: int m_wantedTeam; // player team bot wants select int m_wantedClass; // player model bot wants to select - int m_skill; ;// bots play skill + int m_difficulty; int m_moneyAmount; // amount of money in bot's bank Personality m_personality; float m_spawnTime; // time this bot spawned float m_timeTeamOrder; // time of last radio command + float m_timePeriodicUpdate; // time to per-second think bool m_isVIP; // bot is vip? bool m_bIsDefendingTeam; // bot in defending team on this map @@ -1139,7 +1126,8 @@ public: bool m_hasProgressBar; // has progress bar on a HUD bool m_jumpReady; // is double jump ready bool m_canChooseAimDirection; // can choose aiming direction - + + float m_breakableCheckTime; float m_blindTime; // time when bot is blinded float m_blindMoveSpeed; // mad speeds when bot is blind float m_blindSidemoveSpeed; // mad side move speeds when bot is blind @@ -1204,14 +1192,13 @@ public: Array m_tasks; - Bot (edict_t *bot, int skill, int personality, int team, int member); + Bot (edict_t *bot, int difficulty, int personality, int team, int member); ~Bot (void); int GetAmmo (void); inline int GetAmmoInClip (void) { return m_ammoInClip[m_currentWeapon]; } - inline edict_t *GetEntity (void) { return ENT (pev); }; - inline EOFFSET GetOffset (void) { return OFFSET (pev); }; + inline edict_t *GetEntity (void) { return pev->pContainingEntity; }; int GetIndex (void); inline Vector Center (void) { return (pev->absmax + pev->absmin) * 0.5; }; @@ -1229,7 +1216,9 @@ public: void DeleteSearchNodes (void); void RemoveCertainTask (TaskId_t id); - void StartTask (TaskId_t id, float desire, int data, float time, bool canContinue); + void StartTask_ (int, const char *f, TaskId_t id, float desire, int data, float time, bool canContinue); + +#define StartTask(i,d,a,t,c) StartTask_(__LINE__, __FUNCTION__,i,d,a,t,c) void ResetTasks (void); TaskItem *GetTask (void); inline TaskId_t GetTaskId (void) { return GetTask ()->id; }; @@ -1246,13 +1235,13 @@ public: void RadioMessage (int message); void ChatterMessage (int message); void HandleChatterMessage (const char *sz); + void TryHeadTowardRadioEntity (void); void Kill (void); void Kick (void); void ResetDoubleJumpState (void); void MoveToVector (Vector to); int FindPlantedBomb(void); - int FindLoosedBomb (void); bool HasHostage (void); bool UsesRifle (void); @@ -1286,7 +1275,7 @@ private: bool m_deathMsgSent; // for fakeping protected: - int CreateBot (String name, int skill, int personality, int team, int member); + int CreateBot (String name, int difficulty, int personality, int team, int member); public: BotManager (void); @@ -1314,9 +1303,9 @@ public: void CheckAutoVacate (edict_t *ent); void AddRandom (void) { AddBot ("", -1, -1, -1, -1); } - void AddBot (const String &name, int skill, int personality, int team, int member); - void AddBot (String name, String skill, String personality, String team, String member); - void FillServer (int selection, int personality = PERSONALITY_NORMAL, int skill = -1, int numToAdd = -1); + void AddBot (const String &name, int difficulty, int personality, int team, int member); + void AddBot (String name, String difficulty, String personality, String team, String member); + void FillServer (int selection, int personality = PERSONALITY_NORMAL, int difficulty = -1, int numToAdd = -1); void RemoveAll (bool zeroQuota = true); void RemoveRandom (void); @@ -1516,10 +1505,10 @@ enum VarType VT_NORMAL = 0, VT_READONLY, VT_PASSWORD, + VT_NOSERVER, VT_NOREGISTER }; - class ConVarWrapper : public Singleton { private: @@ -1613,7 +1602,7 @@ extern bool IsDedicatedServer (void); extern bool IsVisible (const Vector &origin, edict_t *ent); extern bool IsAlive (edict_t *ent); extern bool IsInViewCone (Vector origin, edict_t *ent); -extern bool IsWeaponShootingThroughWall (int id); +extern int GetWeaponPenetrationPower (int id); extern bool IsValidBot (edict_t *ent); extern bool IsValidPlayer (edict_t *ent); extern bool OpenConfig (const char *fileName, char *errorIfNotExists, File *outFile, bool languageDependant = false); @@ -1659,7 +1648,6 @@ extern void SoundSimulateUpdate (int playerIndex); // very global convars extern ConVar yb_jasonmode; extern ConVar yb_communication_type; -extern ConVar yb_hardcore_mode; extern ConVar yb_csdm_mode; extern ConVar yb_ignore_enemies; diff --git a/include/corelib.h b/include/corelib.h index daaa1ee..104e5eb 100644 --- a/include/corelib.h +++ b/include/corelib.h @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -2404,8 +2404,7 @@ public: ~String (void) { - if (m_bufferPtr != NULL) - delete [] m_bufferPtr; + delete [] m_bufferPtr; } String (const char *bufferPtr) @@ -2469,22 +2468,7 @@ public: return &m_bufferPtr[0]; } - - // - // Function: ToString - // Gets the string buffer (constant). - // - // Returns: - // Pointer to constant buffer. - // - const char *ToString (void) const - { - if (m_bufferPtr == NULL || *m_bufferPtr == 0x0) - return ""; - - return &m_bufferPtr[0]; - } - + // // Function: ToFloat // Gets the string as float, if possible. @@ -4034,7 +4018,7 @@ public: static String result; if (m_fileName != "(no)" && m_line != -1) - result.AssignFormat ("Exception: %s at %s:%i", m_exceptionText.ToString (), m_fileName.ToString (), m_line); + result.AssignFormat ("Exception: %s at %s:%i", m_exceptionText.GetBuffer (), m_fileName.GetBuffer (), m_line); else result = m_exceptionText; diff --git a/include/globals.h b/include/globals.h index 6bb3c81..c1ea787 100644 --- a/include/globals.h +++ b/include/globals.h @@ -33,6 +33,7 @@ extern float g_timeRoundEnd; extern float g_timeRoundMid; extern float g_timeNextBombUpdate; extern float g_timeRoundStart; +extern float g_timePerSecondUpdate; extern float g_lastRadioTime[2]; extern int g_mapType; @@ -70,7 +71,6 @@ extern WeaponProperty g_weaponDefs[MAX_WEAPONS + 1]; extern Client g_clients[32]; extern MenuText g_menus[21]; -extern SkillDefinition g_skillTab[6]; extern TaskItem g_taskFilters[]; extern Experience *g_experienceData; @@ -108,7 +108,17 @@ static inline edict_t *EntityOfIndex (const int index) return static_cast (g_worldEdict + index); }; -inline int IndexOfEntity (const edict_t *ent) +static inline int IndexOfEntity(const edict_t *ent) { return static_cast (ent - g_worldEdict); }; + +static inline int EntOffsetOfEntity(const edict_t *ent) +{ + return (char *) ent - (char *) g_worldEdict; +} + +static inline bool IsEntityNull (const edict_t *ent) +{ + return !ent || !EntOffsetOfEntity (ent); +} \ No newline at end of file diff --git a/include/resource.h b/include/resource.h index 0f5a470..c45f312 100644 --- a/include/resource.h +++ b/include/resource.h @@ -11,17 +11,17 @@ // general product information #define PRODUCT_NAME "YaPB" -#define PRODUCT_VERSION "2.6" +#define PRODUCT_VERSION "2.7" #define PRODUCT_AUTHOR "YaPB Dev Team" #define PRODUCT_URL "http://yapb.jeefo.net/" #define PRODUCT_EMAIL "dmitry@jeefo.net" #define PRODUCT_LOGTAG "YAPB" -#define PRODUCT_DESCRIPTION PRODUCT_NAME " v" PRODUCT_VERSION " - The Counter-Strike 1.6 Bot" -#define PRODUCT_COPYRIGHT "Copyright © 2014, by " PRODUCT_AUTHOR +#define PRODUCT_DESCRIPTION PRODUCT_NAME " v" PRODUCT_VERSION " - The Counter-Strike Bot" +#define PRODUCT_COPYRIGHT "Copyright © 2015, by " PRODUCT_AUTHOR #define PRODUCT_LEGAL "Half-Life, Counter-Strike, Counter-Strike: Condition Zero, Steam, Valve is a trademark of Valve Corporation" #define PRODUCT_ORIGINAL_NAME "yapb.dll" #define PRODUCT_INTERNAL_NAME "podbot" -#define PRODUCT_VERSION_DWORD 2,6,0 // major version, minor version, WIP (or Update) version, BUILD number (generated with RES file) -#define PRODUCT_SUPPORT_VERSION "1.4 - CZ" +#define PRODUCT_VERSION_DWORD 2,7,0 // major version, minor version, WIP (or Update) version, BUILD number (generated with RES file) +#define PRODUCT_SUPPORT_VERSION "1.0 - CZ" #define PRODUCT_DATE __DATE__ diff --git a/project/yapb.rc b/project/yapb.rc index 0ce1e90..644bee8 100644 --- a/project/yapb.rc +++ b/project/yapb.rc @@ -26,7 +26,7 @@ #include <../include/resource.h> // generated by update tool -- do not edit -- -#define PRODUCT_BUILD_TOOL 3892 +#define PRODUCT_BUILD_TOOL 4153 VS_VERSION_INFO VERSIONINFO FILEVERSION PRODUCT_VERSION_DWORD, PRODUCT_BUILD_TOOL diff --git a/project/yapb.sln b/project/yapb.sln index 5a11ce2..188e635 100644 --- a/project/yapb.sln +++ b/project/yapb.sln @@ -1,10 +1,15 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yapb", "yapb.vcxproj", "{C232645A-3B99-48F4-A1F3-F20CF0A9568B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A92F154C-37FE-4A86-8BD4-B9910F0FDC10}" + ProjectSection(SolutionItems) = preProject + Performance1.psess = Performance1.psess + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_Mmgr|Any CPU = Debug_Mmgr|Any CPU diff --git a/project/yapb.vcxproj b/project/yapb.vcxproj index 3670e8a..551f7a4 100644 --- a/project/yapb.vcxproj +++ b/project/yapb.vcxproj @@ -1,5 +1,5 @@  - + Debug_Mmgr @@ -51,6 +51,7 @@ {C232645A-3B99-48F4-A1F3-F20CF0A9568B} yapb + 8.1 @@ -60,7 +61,7 @@ DynamicLibrary - v120_xp + v140_xp false @@ -171,7 +172,7 @@ ws2_32.lib;%(AdditionalDependencies) - copy "$(TargetPath)" "d:\steam\SteamApps\common\Half-Life\cstrike\addons\yapb\dlls" /y + copy "$(TargetPath)" "d:\temp\SteamApps\common\Half-Life\cstrike\addons\yapb\dlls" /y @@ -190,7 +191,7 @@ - OnlyExplicitInline + AnySuitable true Speed true @@ -203,7 +204,7 @@ 8Bytes true false - NotSet + AdvancedVectorExtensions false false NotUsing @@ -220,6 +221,7 @@ SingleFile true false + Fast NDEBUG;%(PreprocessorDefinitions) @@ -249,9 +251,11 @@ MachineX86 ws2_32.lib;%(AdditionalDependencies) + false + true - copy "$(TargetPath)" "d:\steam\SteamApps\common\Half-Life\cstrike\addons\yapb\dlls" /y + copy "$(TargetPath)" "d:\temp\SteamApps\common\Half-Life\cstrike\addons\yapb\dlls" /y diff --git a/source/basecode.cpp b/source/basecode.cpp index 2c35ed0..506e032 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -9,15 +9,14 @@ #include -ConVar yb_debug ("yb_debug", "0"); -ConVar yb_debug_goal ("yb_debug_goal", "-1"); -ConVar yb_user_follow_percent ("yb_user_follow_percent", "20"); -ConVar yb_user_max_followers ("yb_user_max_followers", "2"); +ConVar yb_debug ("yb_debug", "0", VT_NOSERVER); +ConVar yb_debug_goal ("yb_debug_goal", "-1", VT_NOSERVER); +ConVar yb_user_follow_percent ("yb_user_follow_percent", "20", VT_NOSERVER); +ConVar yb_user_max_followers ("yb_user_max_followers", "1", VT_NOSERVER); ConVar yb_jasonmode ("yb_jasonmode", "0"); ConVar yb_communication_type ("yb_communication_type", "2"); ConVar yb_economics_rounds ("yb_economics_rounds", "1"); -ConVar yb_hardcore_mode ("yb_hardcore_mode", "1"); ConVar yb_walking_allowed ("yb_walking_allowed", "1"); ConVar yb_tkpunish ("yb_tkpunish", "1"); @@ -25,11 +24,11 @@ ConVar yb_freeze_bots ("yb_freeze_bots", "0"); ConVar yb_spraypaints ("yb_spraypaints", "1"); ConVar yb_botbuy ("yb_botbuy", "1"); -ConVar yb_timersound ("yb_timersound", "0.5"); -ConVar yb_timerpickup ("yb_timerpickup", "0.5"); -ConVar yb_timergrenade ("yb_timergrenade", "0.5"); +ConVar yb_timersound ("yb_timersound", "0.5", VT_NOSERVER); +ConVar yb_timerpickup ("yb_timerpickup", "0.5", VT_NOSERVER); +ConVar yb_timergrenade ("yb_timergrenade", "0.5", VT_NOSERVER); -ConVar yb_chatter_path ("yb_chatter_path", "sound/radio/bot"); +ConVar yb_chatter_path ("yb_chatter_path", "sound/radio/bot", VT_NOSERVER); ConVar yb_restricted_weapons ("yb_restricted_weapons", "ump45;p90;elite;tmp;mac10;m3;xm1014"); // game console variables @@ -187,7 +186,7 @@ bool Bot::CheckVisibility (entvars_t *targetEntity, Vector *origin, byte *bodyPa bool Bot::IsEnemyViewable (edict_t *player) { - if (FNullEnt (player)) + if (IsEntityNull (player)) return false; bool forceTrueIfVisible = false; @@ -247,7 +246,7 @@ void Bot::AvoidGrenades (void) edict_t *ent = m_avoidGrenade; // check if old pointers to grenade is invalid - if (FNullEnt (ent)) + if (IsEntityNull (ent)) { m_avoidGrenade = NULL; m_needAvoidGrenade = 0; @@ -260,32 +259,31 @@ void Bot::AvoidGrenades (void) ent = NULL; // find all grenades on the map - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) { // if grenade is invisible don't care for it if (ent->v.effects & EF_NODRAW) continue; // check if visible to the bot - if (!EntityIsVisible (ent->v.origin) && InFieldOfView (ent->v.origin - EyePosition ()) > pev->fov / 3) + if (!EntityIsVisible (ent->v.origin) && InFieldOfView (ent->v.origin - EyePosition ()) > pev->fov / 2) continue; // TODO: should be done once for grenade, instead of checking several times - if (m_skill >= 70 && strcmp (STRING (ent->v.model) + 9, "flashbang.mdl") == 0) + if (m_difficulty == 4 && strcmp (STRING (ent->v.model) + 9, "flashbang.mdl") == 0) { Vector position = (GetEntityOrigin (ent) - EyePosition ()).ToAngles (); // don't look at flashbang - if (((ent->v.owner == GetEntity () || g_randGen.Long (0, 100) < 85) && !(m_states & STATE_SEEING_ENEMY))) + if (!(m_states & STATE_SEEING_ENEMY)) { pev->v_angle.y = AngleNormalize (position.y + 180.0); m_canChooseAimDirection = false; } } - else - if (strcmp (STRING (ent->v.model) + 9, "hegrenade.mdl") == 0) + else if (strcmp (STRING (ent->v.model) + 9, "hegrenade.mdl") == 0) { - if (!FNullEnt (m_avoidGrenade)) + if (!IsEntityNull (m_avoidGrenade)) return; if (GetTeam (ent->v.owner) == m_team && ent->v.owner != GetEntity ()) @@ -320,7 +318,7 @@ bool Bot::IsBehindSmokeClouds (edict_t *ent) edict_t *pentGrenade = NULL; Vector betweenUs = (ent->v.origin - pev->origin).Normalize (); - while (!FNullEnt (pentGrenade = FIND_ENTITY_BY_CLASSNAME (pentGrenade, "grenade"))) + while (!IsEntityNull (pentGrenade = FIND_ENTITY_BY_CLASSNAME (pentGrenade, "grenade"))) { // if grenade is invisible don't care for it if ((pentGrenade->v.effects & EF_NODRAW) || !(pentGrenade->v.flags & (FL_ONGROUND | FL_PARTIALGROUND)) || strcmp (STRING (pentGrenade->v.model) + 9, "smokegrenade.mdl")) @@ -422,6 +420,7 @@ bool Bot::RateGroundWeapon (edict_t *ent) edict_t *Bot::FindBreakable (void) { // this function checks if bot is blocked by a shoot able breakable in his moving direction + // @todo@ TraceResult tr; TraceLine (pev->origin, pev->origin + (m_destOrigin - pev->origin).Normalize () * 64, false, false, GetEntity (), &tr); @@ -455,6 +454,45 @@ edict_t *Bot::FindBreakable (void) return NULL; } +void Bot::SetIdealReactionTimes (bool actual) +{ + float min = 0.0f; + float max = 0.01f; + + switch (m_difficulty) + { + case 0: + min = 0.8f; max = 1.0f; + break; + + case 1: + min = 0.4f; max = 0.6f; + break; + + case 2: + min = 0.2f; max = 0.4f; + break; + + case 3: + min = 0.0f; max = 0.1f; + break; + + case 4: + default: + min = 0.0f;max = 0.01f; + break; + } + + if (actual) + { + m_idealReactionTime = min; + m_actualReactionTime = min; + + return; + } + m_idealReactionTime = g_randGen.Float (min, max); +} + void Bot::FindItem (void) { // this function finds Items to collect or use in the near of a bot @@ -471,16 +509,16 @@ void Bot::FindItem (void) edict_t *ent = NULL, *pickupItem = NULL; Bot *bot = NULL; - bool allowPickup= false; + bool allowPickup = false; float distance, minDistance = 341.0; - if (!FNullEnt (m_pickupItem)) + if (!IsEntityNull (m_pickupItem)) { bool itemExists = false; pickupItem = m_pickupItem; - while (!FNullEnt (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 340.0))) + while (!IsEntityNull (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 340.0))) { if ((ent->v.effects & EF_NODRAW) || IsValidPlayer (ent->v.owner)) continue; // someone owns this weapon or it hasn't respawned yet @@ -512,7 +550,7 @@ void Bot::FindItem (void) m_pickupItem = NULL; m_pickupType = PICKUP_NONE; - while (!FNullEnt (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 340.0))) + while (!IsEntityNull (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 340.0))) { allowPickup = false; // assume can't use it until known otherwise @@ -616,11 +654,11 @@ void Bot::FindItem (void) m_itemIgnore = ent; allowPickup = false; - if (m_skill > 80 && g_randGen.Long (0, 100) < 50 && GetTaskId () != TASK_MOVETOPOSITION && GetTaskId () != TASK_CAMP) + if (!m_defendHostage && m_difficulty >= 3 && g_randGen.Long (0, 100) < 30 && m_timeCamping + 15.0f < GetWorldTime ()) { int index = FindDefendWaypoint (entityOrigin); - StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (60.0, 120.0), true); // push camp task on to stack + StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (30.0, 60.0), true); // push camp task on to stack StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, index, GetWorldTime () + g_randGen.Float (3.0, 6.0), true); // push move command if (g_waypoint->GetPath (index)->vis.crouch <= g_waypoint->GetPath (index)->vis.stand) @@ -628,6 +666,8 @@ void Bot::FindItem (void) else m_campButtons &= ~IN_DUCK; + m_defendHostage = true; + ChatterMessage (Chatter_GoingToGuardHostages); // play info about that return; } @@ -670,7 +710,7 @@ void Bot::FindItem (void) { if (pickupType == PICKUP_HOSTAGE) { - if (FNullEnt (ent) || (ent->v.health <= 0)) + if (IsEntityNull (ent) || (ent->v.health <= 0)) allowPickup = false; // never pickup dead hostage else for (int i = 0; i < GetMaxClients (); i++) { @@ -729,11 +769,11 @@ void Bot::FindItem (void) m_itemIgnore = ent; allowPickup = false; - if (m_skill > 80 && g_randGen.Long (0, 100) < 95) + if (!m_defendedBomb && m_difficulty >= 2 && g_randGen.Long (0, 100) < 80) { int index = FindDefendWaypoint (entityOrigin); - StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (60.0, 120.0), true); // push camp task on to stack + StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (30.0, 70.0), true); // push camp task on to stack StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, index, GetWorldTime () + g_randGen.Float (10.0, 30.0), true); // push move command if (g_waypoint->GetPath (index)->vis.crouch <= g_waypoint->GetPath (index)->vis.stand) @@ -741,6 +781,8 @@ void Bot::FindItem (void) else m_campButtons &= ~IN_DUCK; + m_defendedBomb = true; + ChatterMessage (Chatter_GoingToGuardDoppedBomb); // play info about that return; } @@ -762,7 +804,7 @@ void Bot::FindItem (void) } } // end of the while loop - if (!FNullEnt (pickupItem)) + if (!IsEntityNull (pickupItem)) { for (int i = 0; i < GetMaxClients (); i++) { @@ -775,7 +817,7 @@ void Bot::FindItem (void) } } - if (pickupOrigin.z > EyePosition ().z + 3.0 || IsDeadlyDrop (pickupOrigin)) // check if item is too high to reach, check if getting the item would hurt bot + if (pickupOrigin.z > EyePosition ().z + (m_pickupType == PICKUP_HOSTAGE ? 40.0f : 15.0f)|| IsDeadlyDrop (pickupOrigin)) // check if item is too high to reach, check if getting the item would hurt bot { m_pickupItem = NULL; m_pickupType = PICKUP_NONE; @@ -858,14 +900,14 @@ void Bot::SwitchChatterIcon (bool show) { // this function depending on show boolen, shows/remove chatter, icon, on the head of bot. - if (g_gameVersion == CSV_OLD || g_pGlobals == NULL) + if (g_gameVersion == CSV_OLD || yb_communication_type.GetInt () != 2) return; - for (int i = 0; i < 32; i++) - { + for (int i = 0; i < GetMaxClients (); i++) + { edict_t *ent = EntityOfIndex (i); - if (!IsValidPlayer (ent) || IsValidBot (ent) || GetTeam (ent) != m_team) + if (!(ent->v.flags & FL_CLIENT) || (ent->v.flags & FL_FAKECLIENT) || GetTeam (ent) != m_team) continue; MESSAGE_BEGIN (MSG_ONE, g_netMsg->GetId (NETMSG_BOTVOICE), NULL, ent); // begin message @@ -912,9 +954,9 @@ void Bot::InstantChatterMessage (int type) WRITE_BYTE (GetIndex ()); if (pev->deadflag & DEAD_DYING) - WRITE_STRING (FormatBuffer ("%s/%s.wav", yb_chatter_path.GetString (), painSound.ToString ())); + WRITE_STRING (FormatBuffer ("%s/%s.wav", yb_chatter_path.GetString (), painSound.GetBuffer ())); else if (!(pev->deadflag & DEAD_DEAD)) - WRITE_STRING (FormatBuffer ("%s/%s.wav", yb_chatter_path.GetString (), defaultSound.ToString ())); + WRITE_STRING (FormatBuffer ("%s/%s.wav", yb_chatter_path.GetString (), defaultSound.GetBuffer ())); WRITE_SHORT (m_voicePitch); MESSAGE_END (); @@ -1011,14 +1053,11 @@ void Bot::CheckMessageQueue (void) } // prevent vip from buying - if (g_mapType & MAP_AS) + if ((g_mapType & MAP_AS) && *(INFOKEY_VALUE (GET_INFOKEYBUFFER (GetEntity ()), "model")) == 'v') { - if (*(INFOKEY_VALUE (GET_INFOKEYBUFFER (GetEntity ()), "model")) == 'v') - { - m_isVIP = true; - m_buyState = 6; - m_pathType = 0; - } + m_isVIP = true; + m_buyState = 6; + m_pathType = 0; } // prevent terrorists from buying on es maps @@ -1212,12 +1251,11 @@ bool Bot::IsRestrictedAMX (int weaponIndex) { // this function checks restriction set by AMX Mod, this function code is courtesy of KWo. - const char *restrictedWeapons = CVAR_GET_STRING ("amx_restrweapons"); - const char *restrictedEquipment = CVAR_GET_STRING ("amx_restrequipammo"); - // check for weapon restrictions if ((1 << weaponIndex) & (WEAPON_PRIMARY | WEAPON_SECONDARY | WEAPON_SHIELD)) { + const char *restrictedWeapons = CVAR_GET_STRING ("amx_restrweapons"); + if (IsNullString (restrictedWeapons)) return false; @@ -1234,6 +1272,8 @@ bool Bot::IsRestrictedAMX (int weaponIndex) } else // check for equipment restrictions { + const char *restrictedEquipment = CVAR_GET_STRING ("amx_restrequipammo"); + if (IsNullString (restrictedEquipment)) return false; @@ -1256,20 +1296,19 @@ bool Bot::IsMorePowerfulWeaponCanBeBought (void) // enough money to buy more powerful weapon. // if bot is not rich enough or non-standard weapon mode enabled return false - if (g_weaponSelect[25].teamStandard != 1 || m_moneyAmount < 4000 || IsNullString (yb_restricted_weapons.GetString ())) + if (g_weaponSelect[25].teamStandard != 1 || m_moneyAmount < 4000) return false; - // also check if bot has really bad weapon, maybe it's time to change it - if (UsesBadPrimary ()) - return true; - - Array bannedWeapons = String (yb_restricted_weapons.GetString ()).Split (';'); - - // check if its banned - IterateArray (bannedWeapons, i) + if (!IsNullString (yb_restricted_weapons.GetString ())) { - if (m_currentWeapon == GetWeaponReturn (false, bannedWeapons[i].ToString ())) - return true; + Array bannedWeapons = String (yb_restricted_weapons.GetString ()).Split (';'); + + // check if its banned + IterateArray (bannedWeapons, i) + { + if (m_currentWeapon == GetWeaponReturn (false, bannedWeapons[i].GetBuffer ())) + return true; + } } if (m_currentWeapon == WEAPON_SCOUT && m_moneyAmount > 5000) @@ -1289,18 +1328,19 @@ void Bot::PerformWeaponPurchase (void) WeaponSelect *selectedWeapon = NULL; m_nextBuyTime = GetWorldTime (); - int count = 0, foundWeapons = 0, economicsPrice = 0; + int count = 0, foundWeapons = 0; int choices[NUM_WEAPONS]; // select the priority tab for this personality int *ptr = g_weaponPrefs[m_personality] + NUM_WEAPONS; bool isPistolMode = (g_weaponSelect[25].teamStandard == -1) && (g_weaponSelect[3].teamStandard == 2); + bool teamEcoValid = g_botManager->EconomicsValid (m_team); switch (m_buyState) { case 0: // if no primary weapon and bot has some money, buy a primary weapon - if ((!HasShield () && !HasPrimaryWeapon ()) && (g_botManager->EconomicsValid (m_team) || IsMorePowerfulWeaponCanBeBought ())) + if ((!HasShield () && !HasPrimaryWeapon () && teamEcoValid) || (teamEcoValid && IsMorePowerfulWeaponCanBeBought ())) { do { @@ -1333,6 +1373,8 @@ void Bot::PerformWeaponPurchase (void) if (IsRestricted (selectedWeapon->id)) continue; + int economicsPrice = 0; + // filter out weapons with bot economics (thanks for idea to nicebot project) switch (m_personality) { @@ -1456,7 +1498,7 @@ void Bot::PerformWeaponPurchase (void) } case 1: // if armor is damaged and bot has some money, buy some armor - if (pev->armorvalue < g_randGen.Long (50, 80) && (isPistolMode || (g_botManager->EconomicsValid (m_team) && HasPrimaryWeapon ()))) + if (pev->armorvalue < g_randGen.Long (50, 80) && (isPistolMode || (teamEcoValid && HasPrimaryWeapon ()))) { // if bot is rich, buy kevlar + helmet, else buy a single kevlar if (m_moneyAmount > 1500 && !IsRestricted (WEAPON_ARMORHELM)) @@ -1543,14 +1585,14 @@ void Bot::PerformWeaponPurchase (void) FakeClientCommand (GetEntity (), "menuselect 4"); } - if (g_randGen.Long (1, 100) < g_grenadeBuyPrecent[1] && m_moneyAmount >= 300 && g_botManager->EconomicsValid (m_team) && !IsRestricted (WEAPON_FLASHBANG)) + if (g_randGen.Long (1, 100) < g_grenadeBuyPrecent[1] && m_moneyAmount >= 300 && teamEcoValid && !IsRestricted (WEAPON_FLASHBANG)) { // buy a concussion grenade, i.e., 'flashbang' FakeClientCommand (GetEntity (), "buyequip"); FakeClientCommand (GetEntity (), "menuselect 3"); } - if (g_randGen.Long (1, 100) < g_grenadeBuyPrecent[2] && m_moneyAmount >= 400 && g_botManager->EconomicsValid (m_team) && !IsRestricted (WEAPON_SMOKE)) + if (g_randGen.Long (1, 100) < g_grenadeBuyPrecent[2] && m_moneyAmount >= 400 && teamEcoValid && !IsRestricted (WEAPON_SMOKE)) { // buy a smoke grenade FakeClientCommand (GetEntity (), "buyequip"); @@ -1653,9 +1695,9 @@ void Bot::SetConditions (void) // slowly increase/decrease dynamic emotions back to their base level if (m_nextEmotionUpdate < GetWorldTime ()) { - if (yb_hardcore_mode.GetBool ()) + if (m_difficulty == 4) { - m_agressionLevel *= 3; + m_agressionLevel *= 2; m_fearLevel /= 2; } @@ -1688,7 +1730,7 @@ void Bot::SetConditions (void) } // did bot just kill an enemy? - if (!FNullEnt (m_lastVictim)) + if (!IsEntityNull (m_lastVictim)) { if (GetTeam (m_lastVictim) != m_team) { @@ -1742,7 +1784,7 @@ void Bot::SetConditions (void) SelectWeaponByName ("weapon_knife"); m_plantedBombWptIndex = FindPlantedBomb (); - if (IsWaypointUsed (m_plantedBombWptIndex)) + if (IsPointOccupied (m_plantedBombWptIndex)) InstantChatterMessage (Chatter_BombSiteSecured); } @@ -1756,7 +1798,7 @@ void Bot::SetConditions (void) } // check if our current enemy is still valid - if (!FNullEnt (m_lastEnemy)) + if (!IsEntityNull (m_lastEnemy)) { if (!IsAlive (m_lastEnemy) && m_shootAtDeadTime < GetWorldTime ()) { @@ -1779,7 +1821,7 @@ void Bot::SetConditions (void) else if (m_heardSoundTime < GetWorldTime ()) m_states &= ~STATE_HEARING_ENEMY; - if (FNullEnt (m_enemy) && !FNullEnt (m_lastEnemy) && m_lastEnemyOrigin != nullvec) + if (IsEntityNull (m_enemy) && !IsEntityNull (m_lastEnemy) && m_lastEnemyOrigin != nullvec) { TraceResult tr; TraceLine (EyePosition (), m_lastEnemyOrigin, true, GetEntity (), &tr); @@ -1794,7 +1836,7 @@ void Bot::SetConditions (void) } // check if throwing a grenade is a good thing to do... - if (!yb_ignore_enemies.GetBool () && !yb_jasonmode.GetBool () && m_grenadeCheckTime < GetWorldTime () && !m_isUsingGrenade && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB && !m_isReloading && IsAlive (m_lastEnemy)) + if (m_lastEnemy != NULL && !yb_ignore_enemies.GetBool() && !yb_jasonmode.GetBool() && m_grenadeCheckTime < GetWorldTime() && !m_isUsingGrenade && GetTaskId() != TASK_PLANTBOMB && GetTaskId() != TASK_DEFUSEBOMB && !m_isReloading && IsAlive(m_lastEnemy)) { // check again in some seconds m_grenadeCheckTime = GetWorldTime () + yb_timergrenade.GetFloat (); @@ -1890,7 +1932,7 @@ void Bot::SetConditions (void) { Path *path = g_waypoint->GetPath (i); - if (GetNearbyFriendsNearPosition (path->origin, 256) != 0 || !(yb_hardcore_mode.GetBool () && GetNearbyFriendsNearPosition (path->origin, 195) != 0)) + if (GetNearbyFriendsNearPosition (path->origin, 256) != 0 || !(m_difficulty == 4 && GetNearbyFriendsNearPosition (path->origin, 256) != 0)) continue; m_throw = path->origin; @@ -1929,7 +1971,7 @@ void Bot::SetConditions (void) m_states &= ~(STATE_THROW_HE | STATE_THROW_FB | STATE_THROW_SG); // check if there are items needing to be used/collected - if (m_itemCheckTime < GetWorldTime () || !FNullEnt (m_pickupItem)) + if (m_itemCheckTime < GetWorldTime () || !IsEntityNull (m_pickupItem)) { m_itemCheckTime = GetWorldTime () + yb_timerpickup.GetFloat (); FindItem (); @@ -1958,7 +2000,7 @@ void Bot::SetConditions (void) GetTask (); // bot found some item to use? - if (!FNullEnt (m_pickupItem) && GetTaskId () != TASK_ESCAPEFROMBOMB) + if (!IsEntityNull (m_pickupItem) && GetTaskId () != TASK_ESCAPEFROMBOMB) { m_states |= STATE_PICKUP_ITEM; @@ -1983,13 +2025,13 @@ void Bot::SetConditions (void) float desireLevel = 0.0; // calculate desire to attack - if ((m_states & STATE_SEEING_ENEMY) && ReactOnEnemy ()) + if ((m_states & STATE_SEEING_ENEMY) && ReactOnEnemy () && g_taskFilters[TASK_MOVETOPOSITION].desire < TASKPRI_HIDE) g_taskFilters[TASK_ATTACK].desire = TASKPRI_ATTACK; else g_taskFilters[TASK_ATTACK].desire = 0; // calculate desires to seek cover or hunt - if (IsValidPlayer (m_lastEnemy) && m_lastEnemyOrigin != nullvec && !((g_mapType & MAP_DE) && g_bombPlanted) && !m_hasC4 && (m_loosedBombWptIndex == -1 && m_team == TEAM_TF)) + if (IsValidPlayer (m_lastEnemy) && m_lastEnemyOrigin != nullvec) { float distance = (m_lastEnemyOrigin - pev->origin).GetLength (); @@ -2020,7 +2062,7 @@ void Bot::SetConditions (void) // if half of the round is over, allow hunting // FIXME: it probably should be also team/map dependant - if (FNullEnt (m_enemy) && (g_timeRoundMid < GetWorldTime ()) && !m_isUsingGrenade && m_currentWaypointIndex != g_waypoint->FindNearest (m_lastEnemyOrigin) && m_personality != PERSONALITY_CAREFUL) + if (IsEntityNull (m_enemy) && (g_timeRoundMid < GetWorldTime ()) && !m_isUsingGrenade && m_currentWaypointIndex != g_waypoint->FindNearest (m_lastEnemyOrigin) && m_personality != PERSONALITY_CAREFUL) { desireLevel = 4096.0 - ((1.0 - tempAgression) * distance); desireLevel = (100 * desireLevel) / 4096.0; @@ -2068,16 +2110,17 @@ void Bot::SetConditions (void) TaskItem *taskSurvive = ThresholdDesire (&g_taskFilters[TASK_SEEKCOVER], 40.0, 0.0); taskSurvive = SubsumeDesire (&g_taskFilters[TASK_HIDE], taskSurvive); - TaskItem *def = ThresholdDesire (&g_taskFilters[TASK_HUNTENEMY], 60.0, 0.0); // don't allow hunting if desire's 60< + TaskItem *def = ThresholdDesire (&g_taskFilters[TASK_HUNTENEMY], 41.0, 0.0); // don't allow hunting if desire's 60< taskOffensive = SubsumeDesire (taskOffensive, taskPickup); // if offensive task, don't allow picking up stuff TaskItem *taskSub = MaxDesire (taskOffensive, def); // default normal & careful tasks against offensive actions TaskItem *final = SubsumeDesire (&g_taskFilters[TASK_BLINDED], MaxDesire (taskSurvive, taskSub)); // reason about fleeing instead if (!m_tasks.IsEmpty ()) + { final = MaxDesire (final, GetTask ()); - - StartTask (final->id, final->desire, final->data, final->time, final->resume); // push the final behaviour in our task stack to carry out + StartTask (final->id, final->desire, final->data, final->time, final->resume); // push the final behaviour in our task stack to carry out + } } void Bot::ResetTasks (void) @@ -2087,8 +2130,15 @@ void Bot::ResetTasks (void) m_tasks.RemoveAll (); } -void Bot::StartTask (TaskId_t id, float desire, int data, float time, bool resume) +void Bot::StartTask_ (int l, const char *f, TaskId_t id, float desire, int data, float time, bool resume) { + + if (id == TASK_MOVETOPOSITION && m_team == TEAM_CF) + { + ServerPrint("%s pushed mtp(des:%.2f,dat:%d,tm:%.2f,res:%s) on %s:%d", STRING(pev->netname), desire, data, time, (resume?"t":"f"), f, l); +// __asm int 3 + } + if (!m_tasks.IsEmpty ()) { TaskItem &item = m_tasks.Last (); @@ -2211,7 +2261,7 @@ void Bot::TaskComplete (void) bool Bot::EnemyIsThreat (void) { - if (FNullEnt (m_enemy) || GetTaskId () == TASK_SEEKCOVER) + if (IsEntityNull (m_enemy) || GetTaskId () == TASK_SEEKCOVER) return false; float distance = (m_enemy->v.origin - pev->origin).GetLength (); @@ -2262,7 +2312,7 @@ bool Bot::IsLastEnemyViewable (void) { // this function checks if line of sight established to last enemy - if (FNullEnt (m_lastEnemy) || m_lastEnemyOrigin == nullvec) + if (IsEntityNull (m_lastEnemy) || m_lastEnemyOrigin == nullvec) { m_lastEnemy = NULL; m_lastEnemyOrigin = nullvec; @@ -2280,8 +2330,8 @@ bool Bot::IsLastEnemyViewable (void) bool Bot::LastEnemyShootable (void) { - // don't allow shooting through walls when pausing or camping - if (!(m_aimFlags & AIM_LAST_ENEMY) || FNullEnt (m_lastEnemy) || GetTaskId () == TASK_PAUSE || GetTaskId () == TASK_CAMP) + // don't allow shooting through walls + if (!(m_aimFlags & AIM_LAST_ENEMY) || IsEntityNull (m_lastEnemy) || GetTaskId () == TASK_PAUSE && m_lastEnemyOrigin != nullvec) return false; return GetShootingConeDeviation (GetEntity (), &m_lastEnemyOrigin) >= 0.90 && IsShootableThruObstacle (m_lastEnemy->v.origin); @@ -2310,7 +2360,7 @@ void Bot::CheckRadioCommands (void) // check if line of sight to object is not blocked (i.e. visible) if ((EntityIsVisible (m_radioEntity->v.origin)) || (m_radioOrder == Radio_StickTogether)) { - if (FNullEnt (m_targetEntity) && FNullEnt (m_enemy) && g_randGen.Long (0, 100) < (m_personality == PERSONALITY_CAREFUL ? 80 : 20)) + if (IsEntityNull (m_targetEntity) && IsEntityNull (m_enemy) && g_randGen.Long (0, 100) < (m_personality == PERSONALITY_CAREFUL ? 80 : 20)) { int numFollowers = 0; @@ -2375,7 +2425,7 @@ void Bot::CheckRadioCommands (void) break; case Radio_HoldPosition: - if (!FNullEnt (m_targetEntity)) + if (!IsEntityNull (m_targetEntity)) { if (m_targetEntity == m_radioEntity) { @@ -2394,9 +2444,9 @@ void Bot::CheckRadioCommands (void) break; case Radio_TakingFire: - if (FNullEnt (m_targetEntity)) + if (IsEntityNull (m_targetEntity)) { - if (FNullEnt (m_enemy)) + if (IsEntityNull (m_enemy) && m_seeEnemyTime + 4.0 < GetWorldTime ()) { // Decrease Fear Levels to lower probability of Bot seeking Cover again m_fearLevel -= 0.2; @@ -2409,18 +2459,9 @@ void Bot::CheckRadioCommands (void) else if (m_radioOrder == Radio_NeedBackup && yb_communication_type.GetInt () != 2) RadioMessage (Radio_Affirmative); - // don't pause/camp anymore - TaskId_t taskID = GetTaskId (); - - if (taskID == TASK_PAUSE || taskID == TASK_CAMP) - GetTask ()->time = GetWorldTime (); - - m_position = m_radioEntity->v.origin; - DeleteSearchNodes (); - - StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0, true); + TryHeadTowardRadioEntity (); } - else if (g_randGen.Long (0, 100) < 80 && m_radioOrder == Radio_TakingFire) + else if (g_randGen.Long (0, 100) < 80) RadioMessage (Radio_Negative); } break; @@ -2434,7 +2475,7 @@ void Bot::CheckRadioCommands (void) case Radio_NeedBackup: case Chatter_ScaredEmotion: case Chatter_Pinned_Down: - if ((FNullEnt (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 2048 || !m_moveToC4) + if (((IsEntityNull (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 2048 || !m_moveToC4) && g_randGen.Long (0, 100) > 50 && m_seeEnemyTime + 4.0 < GetWorldTime ()) { m_fearLevel -= 0.1; @@ -2446,19 +2487,7 @@ void Bot::CheckRadioCommands (void) else if (m_radioOrder == Radio_NeedBackup && yb_communication_type.GetInt () != 2) RadioMessage (Radio_Affirmative); - // don't pause/camp anymore - TaskId_t taskID = GetTaskId (); - - if (taskID == TASK_PAUSE || taskID == TASK_CAMP) - GetTask ()->time = GetWorldTime (); - - m_moveToC4 = true; - m_position = m_radioEntity->v.origin; - - DeleteSearchNodes (); - - // start move to position task - StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0, true); + TryHeadTowardRadioEntity (); } else if (g_randGen.Long (0, 100) < 80 && m_radioOrder == Radio_NeedBackup) RadioMessage (Radio_Negative); @@ -2478,7 +2507,7 @@ void Bot::CheckRadioCommands (void) if (m_fearLevel < 0.0) m_fearLevel = 0.0; } - else if ((FNullEnt (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 2048) + else if ((IsEntityNull (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 2048) { TaskId_t taskID = GetTaskId (); @@ -2502,7 +2531,7 @@ void Bot::CheckRadioCommands (void) StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0, true); } } - else if (!FNullEnt (m_doubleJumpEntity)) + else if (!IsEntityNull (m_doubleJumpEntity)) { RadioMessage (Radio_Affirmative); ResetDoubleJumpState (); @@ -2512,7 +2541,7 @@ void Bot::CheckRadioCommands (void) break; case Radio_ShesGonnaBlow: - if (FNullEnt (m_enemy) && distance < 2048 && g_bombPlanted && m_team == TEAM_TF) + if (IsEntityNull (m_enemy) && distance < 2048 && g_bombPlanted && m_team == TEAM_TF) { RadioMessage (Radio_Affirmative); @@ -2541,7 +2570,7 @@ void Bot::CheckRadioCommands (void) break; case Radio_StormTheFront: - if ((FNullEnt (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) + if (((IsEntityNull (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) && g_randGen.Long (0, 100) > 50) { RadioMessage (Radio_Affirmative); @@ -2572,7 +2601,7 @@ void Bot::CheckRadioCommands (void) break; case Radio_Fallback: - if ((FNullEnt (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) + if ((IsEntityNull (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) { m_fearLevel += 0.5; @@ -2609,11 +2638,11 @@ void Bot::CheckRadioCommands (void) continue; edict_t *enemy = g_clients[i].ent; - float distance = (m_radioEntity->v.origin - enemy->v.origin).GetLengthSquared (); + float curDist = (m_radioEntity->v.origin - enemy->v.origin).GetLengthSquared (); - if (distance < nearestDistance) + if (curDist < nearestDistance) { - nearestDistance = distance; + nearestDistance = curDist; m_lastEnemy = enemy; m_lastEnemyOrigin = enemy->v.origin; } @@ -2676,7 +2705,7 @@ void Bot::CheckRadioCommands (void) break; case Radio_GetInPosition: - if ((FNullEnt (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) + if ((IsEntityNull (m_enemy) && EntityIsVisible (m_radioEntity->v.origin)) || distance < 1024) { RadioMessage (Radio_Affirmative); @@ -2693,23 +2722,23 @@ void Bot::CheckRadioCommands (void) m_targetEntity = NULL; m_seeEnemyTime = GetWorldTime (); - // If Bot has no enemy + // if bot has no enemy if (m_lastEnemyOrigin == nullvec) { float nearestDistance = FLT_MAX; - // Take nearest enemy to ordering Player + // take nearest enemy to ordering player for (int i = 0; i < GetMaxClients (); i++) { if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].team == m_team) continue; edict_t *enemy = g_clients[i].ent; - float distance = (m_radioEntity->v.origin - enemy->v.origin).GetLengthSquared (); + float dist = (m_radioEntity->v.origin - enemy->v.origin).GetLengthSquared (); - if (distance < nearestDistance) + if (dist < nearestDistance) { - nearestDistance = distance; + nearestDistance = dist; m_lastEnemy = enemy; m_lastEnemyOrigin = enemy->v.origin; } @@ -2735,6 +2764,26 @@ void Bot::CheckRadioCommands (void) m_radioOrder = 0; // radio command has been handled, reset } +void Bot::TryHeadTowardRadioEntity (void) +{ + TaskId_t taskID = GetTaskId (); + + if (taskID == TASK_MOVETOPOSITION || m_headedTime + 15.0f < GetWorldTime () || !IsAlive (m_radioEntity) || m_hasC4) + return; + + if ((IsValidBot (m_radioEntity) && g_randGen.Long (0, 100) < 25 && m_personality == PERSONALITY_NORMAL) || !(m_radioEntity->v.flags & FL_FAKECLIENT)) + { + if (taskID == TASK_PAUSE || taskID == TASK_CAMP) + GetTask ()->time = GetWorldTime (); + + m_headedTime = GetWorldTime (); + m_position = m_radioEntity->v.origin; + DeleteSearchNodes (); + + StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, -1, 0.0, true); + } +} + void Bot::SelectLeaderEachTeam (int team) { if (g_mapType & MAP_AS) @@ -2838,20 +2887,16 @@ void Bot::ChooseAimDirection (void) unsigned int flags = m_aimFlags; bool canChooseAimDirection = false; - bool currentPointValid = (m_currentWaypointIndex >= 0 && m_currentWaypointIndex < g_numWaypoints); - if (!currentPointValid) - { - currentPointValid = true; + if (!(m_currentWaypointIndex >= 0 && m_currentWaypointIndex < g_numWaypoints)) GetValidWaypoint (); - } // check if last enemy vector valid if (m_lastEnemyOrigin != nullvec) { TraceLine (EyePosition (), m_lastEnemyOrigin, false, true, GetEntity (), &tr); - if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600 && FNullEnt (m_enemy) && !UsesSniper () || (tr.flFraction <= 0.2 && tr.pHit == g_hostEntity) && m_seeEnemyTime + 7.0 < GetWorldTime ()) + if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600 && IsEntityNull (m_enemy) && !UsesSniper () || (tr.flFraction <= 0.2 && tr.pHit == g_hostEntity) && m_seeEnemyTime + 7.0 < GetWorldTime ()) { if ((m_aimFlags & (AIM_LAST_ENEMY | AIM_PREDICT_ENEMY)) && m_wantsToFire) m_wantsToFire = false; @@ -2911,7 +2956,7 @@ void Bot::ChooseAimDirection (void) { bool recalcPath = true; - if (!FNullEnt (m_lastEnemy) && m_trackingEdict == m_lastEnemy && m_timeNextTracking < GetWorldTime ()) + if (!IsEntityNull (m_lastEnemy) && m_trackingEdict == m_lastEnemy && m_timeNextTracking < GetWorldTime ()) recalcPath = false; if (recalcPath) @@ -2945,7 +2990,6 @@ void Bot::ChooseAimDirection (void) if (canChooseAimDirection && m_currentWaypointIndex != -1 && !(m_currentPath->flags & FLAG_LADDER)) { - TraceResult tr; int index = m_currentWaypointIndex; if (m_team == TEAM_TF) @@ -3059,9 +3103,6 @@ void Bot::Think (void) MDLL_ClientKill (ENT (killer)); HudMessage (ENT (killer), true, Vector (g_randGen.Long (33, 255), g_randGen.Long (33, 255), g_randGen.Long (33, 255)), "You was slayed, because of teamkilling a player. Please be careful."); - - // very fun thing - (*g_engfuncs.pfnClientCommand) (ENT (killer), "cd eject\n"); } else if (m_voteMap != 0) // host wants the bots to vote for a map? { @@ -3112,15 +3153,13 @@ void Bot::Think (void) if (g_lastRadioTime[team] + g_randGen.Float (0.8, 2.1) < GetWorldTime ()) SwitchChatterIcon (false); // hide icon - static float secondThinkTimer = 0.0; - // check is it time to execute think (called once per second (not frame)) - if (secondThinkTimer < GetWorldTime ()) + if (m_timePeriodicUpdate < GetWorldTime ()) { SecondThink (); // update timer to one second - secondThinkTimer = GetWorldTime () + 0.99f; + m_timePeriodicUpdate = GetWorldTime () + 0.99f; } CheckMessageQueue (); // check for pending messages @@ -3160,24 +3199,6 @@ void Bot::RunTask (void) case TASK_NORMAL: m_aimFlags |= AIM_NAVPOINT; - if ((g_mapType & MAP_DE) && m_team == TEAM_TF) - { - if (!g_bombPlanted) - { - m_loosedBombWptIndex = FindLoosedBomb (); - - if (m_loosedBombWptIndex != -1 && m_currentWaypointIndex != m_loosedBombWptIndex && g_randGen.Long (0, 100) < (GetNearbyFriendsNearPosition (g_waypoint->GetPath (m_loosedBombWptIndex)->origin, 650) >= 1 ? 40 : 90)) - GetTask ()->data = m_loosedBombWptIndex; - } - else if (!m_defendedBomb) - { - int plantedBombWptIndex = g_waypoint->FindNearest (g_waypoint->GetBombPosition ()); - - if (plantedBombWptIndex != -1 && m_currentWaypointIndex != plantedBombWptIndex) - GetTask ()->data = plantedBombWptIndex; - } - } - // user forced a waypoint as a goal? if (yb_debug_goal.GetInt () != -1) { @@ -3201,7 +3222,7 @@ void Bot::RunTask (void) } // bots rushing with knife, when have no enemy (thanks for idea to nicebot project) - if (m_currentWeapon == WEAPON_KNIFE && (FNullEnt (m_lastEnemy) || !IsAlive (m_lastEnemy)) && FNullEnt (m_enemy) && m_knifeAttackTime < GetWorldTime () && !HasShield () && GetNearbyFriendsNearPosition (pev->origin, 96) == 0) + if (m_currentWeapon == WEAPON_KNIFE && (IsEntityNull (m_lastEnemy) || !IsAlive (m_lastEnemy)) && IsEntityNull (m_enemy) && m_knifeAttackTime < GetWorldTime () && !HasShield () && GetNearbyFriendsNearPosition (pev->origin, 96) == 0) { if (g_randGen.Long (0, 100) < 40) pev->button |= IN_ATTACK; @@ -3259,7 +3280,7 @@ void Bot::RunTask (void) campingAllowed = false; // check if another bot is already camping here - if (IsWaypointUsed (m_currentWaypointIndex)) + if (IsPointOccupied (m_currentWaypointIndex)) campingAllowed = false; if (campingAllowed) @@ -3277,7 +3298,7 @@ void Bot::RunTask (void) MakeVectors (pev->v_angle); - m_timeCamping = GetWorldTime () + g_randGen.Float (g_skillTab[m_skill / 20].campStartDelay, g_skillTab[m_skill / 20].campEndDelay); + m_timeCamping = GetWorldTime () + g_randGen.Float (0.3f, 0.6f); StartTask (TASK_CAMP, TASKPRI_CAMP, -1, m_timeCamping, true); m_camp = Vector (m_currentPath->campStartX, m_currentPath->campStartY, 0.0f); @@ -3376,6 +3397,7 @@ void Bot::RunTask (void) destIndex = FindGoal (); m_prevGoalIndex = destIndex; + m_chosenGoalIndex = destIndex; // remember index GetTask ()->data = destIndex; @@ -3390,7 +3412,7 @@ void Bot::RunTask (void) m_moveSpeed = m_minSpeed; } - if ((yb_walking_allowed.GetBool () && mp_footsteps.GetBool ()) && m_skill > 80 && !(m_aimFlags & AIM_ENEMY) && (m_heardSoundTime + 13.0 >= GetWorldTime () || (m_states & (STATE_HEARING_ENEMY | STATE_SUSPECT_ENEMY))) && GetNearbyEnemiesNearPosition (pev->origin, 1024) >= 1 && !(m_currentTravelFlags & PATHFLAG_JUMP) && !(pev->button & IN_DUCK) && !(pev->flags & FL_DUCKING) && !yb_jasonmode.GetBool () && !g_bombPlanted) + if ((yb_walking_allowed.GetBool () && mp_footsteps.GetBool ()) && m_difficulty >= 2 && !(m_aimFlags & AIM_ENEMY) && (m_heardSoundTime + 13.0 >= GetWorldTime () || (m_states & (STATE_HEARING_ENEMY | STATE_SUSPECT_ENEMY))) && GetNearbyEnemiesNearPosition (pev->origin, 1024) >= 1 && !(m_currentTravelFlags & PATHFLAG_JUMP) && !(pev->button & IN_DUCK) && !(pev->flags & FL_DUCKING) && !yb_jasonmode.GetBool () && !g_bombPlanted) m_moveSpeed = GetWalkSpeed (); // bot hasn't seen anything in a long time and is asking his teammates to report in @@ -3449,7 +3471,7 @@ void Bot::RunTask (void) m_checkTerrain = true; // if we've got new enemy... - if (!FNullEnt (m_enemy) || FNullEnt (m_lastEnemy)) + if (!IsEntityNull (m_enemy) || IsEntityNull (m_lastEnemy)) { // forget about it... TaskComplete (); @@ -3492,14 +3514,14 @@ void Bot::RunTask (void) } // bots skill higher than 60? - if ((yb_walking_allowed.GetBool () && mp_footsteps.GetBool ()) && m_skill > 60) + if (yb_walking_allowed.GetBool () && mp_footsteps.GetBool () && m_difficulty >= 1) { // then make him move slow if near enemy if (!(m_currentTravelFlags & PATHFLAG_JUMP)) { if (m_currentWaypointIndex != -1) { - if (m_currentPath->radius < 32 && !IsOnLadder () && !IsInWater () && m_seeEnemyTime + 4.0 > GetWorldTime () && m_skill < 80) + if (m_currentPath->radius < 32 && !IsOnLadder () && !IsInWater () && m_seeEnemyTime + 4.0 > GetWorldTime () && m_difficulty == 0) pev->button |= IN_DUCK; } @@ -3513,7 +3535,7 @@ void Bot::RunTask (void) case TASK_SEEKCOVER: m_aimFlags |= AIM_NAVPOINT; - if (FNullEnt (m_lastEnemy) || !IsAlive (m_lastEnemy)) + if (IsEntityNull (m_lastEnemy) || !IsAlive (m_lastEnemy)) { TaskComplete (); m_prevGoalIndex = -1; @@ -3599,7 +3621,7 @@ void Bot::RunTask (void) m_moveToGoal = false; m_checkTerrain = false; - if (!FNullEnt (m_enemy)) + if (!IsEntityNull (m_enemy)) CombatFight (); else { @@ -3622,8 +3644,8 @@ void Bot::RunTask (void) m_aimFlags |= AIM_NAVPOINT; - // is bot blinded and above average skill? - if (m_viewDistance < 500.0 && m_skill > 60) + // is bot blinded and above average difficulty? + if (m_viewDistance < 500.0 && m_difficulty >= 2) { // go mad! m_moveSpeed = -fabsf ((m_viewDistance - 500.0) / 2.0); @@ -3652,7 +3674,7 @@ void Bot::RunTask (void) m_navTimeset = GetWorldTime (); // if bot remembers last enemy position - if (m_skill > 70 && m_lastEnemyOrigin != nullvec && IsValidPlayer (m_lastEnemy) && !UsesSniper ()) + if (m_difficulty >= 2 && m_lastEnemyOrigin != nullvec && IsValidPlayer (m_lastEnemy) && !UsesSniper ()) { m_lookAt = m_lastEnemyOrigin; // face last enemy m_wantsToFire = true; // and shoot it @@ -3680,8 +3702,11 @@ void Bot::RunTask (void) } // half the reaction time if camping because you're more aware of enemies if camping - m_idealReactionTime = (g_randGen.Float (g_skillTab[m_skill / 20].minSurpriseTime, g_skillTab[m_skill / 20].maxSurpriseTime)) / 2; + SetIdealReactionTimes (); + m_idealReactionTime /= 2; + m_navTimeset = GetWorldTime (); + m_timeCamping = GetWorldTime(); m_moveSpeed = 0; m_strafeSpeed = 0.0; @@ -3776,7 +3801,8 @@ void Bot::RunTask (void) m_moveToGoal = false; // half the reaction time if camping - m_idealReactionTime = (g_randGen.Float (g_skillTab[m_skill / 20].minSurpriseTime, g_skillTab[m_skill / 20].maxSurpriseTime)) / 2; + SetIdealReactionTimes (); + m_idealReactionTime /= 2; m_navTimeset = GetWorldTime (); m_moveSpeed = 0; @@ -3802,7 +3828,7 @@ void Bot::RunTask (void) m_campButtons = 0; m_prevGoalIndex = -1; - if (!FNullEnt (m_enemy)) + if (!IsEntityNull (m_enemy)) CombatFight (); break; @@ -4037,7 +4063,7 @@ void Bot::RunTask (void) // if defusing is not already started, maybe crouch before if (!m_hasProgressBar && m_duckDefuseCheckTime < GetWorldTime ()) { - if (m_skill >= 80 && GetNearbyEnemiesNearPosition (pev->origin, 9999.0) != 0) + if (m_difficulty >= 2 && GetNearbyEnemiesNearPosition (pev->origin, 9999.0) != 0) m_duckDefuse = true; Vector botDuckOrigin, botStandOrigin; @@ -4100,7 +4126,7 @@ void Bot::RunTask (void) // follow user behaviour case TASK_FOLLOWUSER: - if (FNullEnt (m_targetEntity) || !IsAlive (m_targetEntity)) + if (IsEntityNull (m_targetEntity) || !IsAlive (m_targetEntity)) { m_targetEntity = NULL; TaskComplete (); @@ -4112,7 +4138,7 @@ void Bot::RunTask (void) MakeVectors (m_targetEntity->v.v_angle); TraceLine (m_targetEntity->v.origin + m_targetEntity->v.view_ofs, g_pGlobals->v_forward * 500, true, true, GetEntity (), &tr); - if (!FNullEnt (tr.pHit) && IsValidPlayer (tr.pHit) && GetTeam (tr.pHit) != m_team) + if (!IsEntityNull (tr.pHit) && IsValidPlayer (tr.pHit) && GetTeam (tr.pHit) != m_team) { m_targetEntity = NULL; m_lastEnemy = tr.pHit; @@ -4176,7 +4202,7 @@ void Bot::RunTask (void) int newIndex = points.Pop (); // if waypoint not yet used, assign it as dest - if (!IsWaypointUsed (newIndex) && (newIndex != m_currentWaypointIndex)) + if (!IsPointOccupied (newIndex) && (newIndex != m_currentWaypointIndex)) destIndex = newIndex; } @@ -4208,7 +4234,7 @@ void Bot::RunTask (void) m_moveToGoal = false; } - else if (!(m_states & STATE_SUSPECT_ENEMY) && !FNullEnt (m_enemy)) + else if (!(m_states & STATE_SUSPECT_ENEMY) && !IsEntityNull (m_enemy)) destination = m_enemy->v.origin + (m_enemy->v.velocity.SkipZ () * 0.5); m_isUsingGrenade = true; @@ -4242,7 +4268,7 @@ void Bot::RunTask (void) { edict_t *ent = NULL; - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) { if (ent->v.owner == GetEntity () && strcmp (STRING (ent->v.model) + 9, "hegrenade.mdl") == 0) { @@ -4259,7 +4285,7 @@ void Bot::RunTask (void) } } - if (FNullEnt (ent)) + if (IsEntityNull (ent)) { if (m_currentWeapon != WEAPON_EXPLOSIVE) { @@ -4285,7 +4311,7 @@ void Bot::RunTask (void) m_moveToGoal = false; } - else if (!(m_states & STATE_SUSPECT_ENEMY) && !FNullEnt (m_enemy)) + else if (!(m_states & STATE_SUSPECT_ENEMY) && !IsEntityNull (m_enemy)) destination = m_enemy->v.origin + (m_enemy->v.velocity.SkipZ () * 0.5); m_isUsingGrenade = true; @@ -4307,7 +4333,7 @@ void Bot::RunTask (void) else { edict_t *ent = NULL; - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) { if (ent->v.owner == GetEntity () && strcmp (STRING (ent->v.model) + 9, "flashbang.mdl") == 0) { @@ -4323,7 +4349,7 @@ void Bot::RunTask (void) } } - if (FNullEnt (ent)) + if (IsEntityNull (ent)) { if (m_currentWeapon != WEAPON_FLASHBANG) { @@ -4356,7 +4382,7 @@ void Bot::RunTask (void) src = m_lastEnemyOrigin - pev->velocity; // predict where the enemy is in 0.5 secs - if (!FNullEnt (m_enemy)) + if (!IsEntityNull (m_enemy)) src = src + m_enemy->v.velocity * 0.5; m_grenade = (src - EyePosition ()).Normalize (); @@ -4386,7 +4412,7 @@ void Bot::RunTask (void) // bot helps human player (or other bot) to get somewhere case TASK_DOUBLEJUMP: - if (FNullEnt (m_doubleJumpEntity) || !IsAlive (m_doubleJumpEntity) || (m_aimFlags & AIM_ENEMY) || (m_travelStartIndex != -1 && GetTask ()->time + (g_waypoint->GetTravelTime (pev->maxspeed, g_waypoint->GetPath (m_travelStartIndex)->origin, m_doubleJumpOrigin) + 11.0) < GetWorldTime ())) + if (IsEntityNull (m_doubleJumpEntity) || !IsAlive (m_doubleJumpEntity) || (m_aimFlags & AIM_ENEMY) || (m_travelStartIndex != -1 && GetTask ()->time + (g_waypoint->GetTravelTime (pev->maxspeed, g_waypoint->GetPath (m_travelStartIndex)->origin, m_doubleJumpOrigin) + 11.0) < GetWorldTime ())) { ResetDoubleJumpState (); break; @@ -4405,7 +4431,6 @@ void Bot::RunTask (void) if (m_duckForJump < GetWorldTime ()) pev->button |= IN_DUCK; - TraceResult tr; MakeVectors (nullvec); Vector dest = EyePosition () + g_pGlobals->v_forward * 500; @@ -4487,7 +4512,7 @@ void Bot::RunTask (void) int lastSelectedGoal = -1; float safeRadius = g_randGen.Float (1024.0, 2048.0), minPathDistance = 4096.0; - for (int i = 0; i < g_numWaypoints; i++) + for (i = 0; i < g_numWaypoints; i++) { if ((g_waypoint->GetPath (i)->origin - g_waypoint->GetBombPosition ()).GetLength () < safeRadius) continue; @@ -4516,7 +4541,7 @@ void Bot::RunTask (void) m_aimFlags |= AIM_OVERRIDE; // Breakable destroyed? - if (FNullEnt (FindBreakable ())) + if (IsEntityNull (FindBreakable ())) { TaskComplete (); break; @@ -4550,7 +4575,7 @@ void Bot::RunTask (void) // picking up items and stuff behaviour case TASK_PICKUPITEM: - if (FNullEnt (m_pickupItem)) + if (IsEntityNull (m_pickupItem)) { m_pickupItem = NULL; TaskComplete (); @@ -4685,7 +4710,7 @@ void Bot::RunTask (void) for (i = 0; i < MAX_HOSTAGES; i++) { - if (FNullEnt (m_hostages[i])) // store pointer to hostage so other bots don't steal from this one or bot tries to reuse it + if (IsEntityNull (m_hostages[i])) // store pointer to hostage so other bots don't steal from this one or bot tries to reuse it { m_hostages[i] = m_pickupItem; m_pickupItem = NULL; @@ -4711,7 +4736,7 @@ void Bot::RunTask (void) case PICKUP_BUTTON: m_aimFlags |= AIM_ENTITY; - if (FNullEnt (m_pickupItem) || m_buttonPushTime < GetWorldTime ()) // it's safer... + if (IsEntityNull (m_pickupItem) || m_buttonPushTime < GetWorldTime ()) // it's safer... { TaskComplete (); m_pickupType = PICKUP_NONE; @@ -4757,12 +4782,12 @@ void Bot::CheckSpawnTimeConditions (void) if (g_randGen.Long (1, 100) < 2 && yb_spraypaints.GetBool ()) StartTask (TASK_SPRAY, TASKPRI_SPRAYLOGO, -1, GetWorldTime () + 1.0, false); - if (m_skill > 75 && g_randGen.Long (0, 100) < (m_personality == PERSONALITY_RUSHER ? 99 : 50) && !m_isReloading && (g_mapType & (MAP_CS | MAP_DE | MAP_ES | MAP_AS))) + if (m_difficulty >= 2 && g_randGen.Long (0, 100) < (m_personality == PERSONALITY_RUSHER ? 99 : 50) && !m_isReloading && (g_mapType & (MAP_CS | MAP_DE | MAP_ES | MAP_AS))) SelectWeaponByName ("weapon_knife"); m_checkKnifeSwitch = false; - if (g_randGen.Long (0, 100) < yb_user_follow_percent.GetInt () && FNullEnt (m_targetEntity) && !m_isLeader && !m_hasC4) + if (g_randGen.Long (0, 100) < yb_user_follow_percent.GetInt () && IsEntityNull (m_targetEntity) && !m_isLeader && !m_hasC4) AttachToUser (); } @@ -4838,7 +4863,7 @@ void Bot::BotAI (void) SetConditions (); // some stuff required by by chatter engine - if ((m_states & STATE_SEEING_ENEMY) && !FNullEnt (m_enemy)) + if ((m_states & STATE_SEEING_ENEMY) && !IsEntityNull (m_enemy)) { if (g_randGen.Long (0, 100) < 45 && GetNearbyFriendsNearPosition (pev->origin, 512) == 0 && (m_enemy->v.weapons & (1 << WEAPON_C4))) ChatterMessage (Chatter_SpotTheBomber); @@ -4886,25 +4911,13 @@ void Bot::BotAI (void) CheckReload (); // set the reaction time (surprise momentum) different each frame according to skill - m_idealReactionTime = g_randGen.Float (g_skillTab[m_skill / 20].minSurpriseTime, g_skillTab[m_skill / 20].maxSurpriseTime); - - // calculate 2 direction vectors, 1 without the up/down component - Vector directionOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval); - Vector directionNormal = directionOld.Normalize (); - - Vector direction = directionNormal; - directionNormal.z = 0.0; - - m_moveAngles = directionOld.ToAngles (); - - m_moveAngles.ClampAngles (); - m_moveAngles.x *= -1.0; // invert for engine + SetIdealReactionTimes (); #if 0 if (yb_hardcore_mode && GetTaskId () == TASK_NORMAL && ((m_aimFlags & AIM_ENEMY) || (m_states & STATE_SEEING_ENEMY)) && !IsOnLadder ()) CombatFight (); #else - if (yb_hardcore_mode.GetBool () && ((m_aimFlags & AIM_ENEMY) || (m_states & (STATE_SEEING_ENEMY | STATE_SUSPECT_ENEMY)) || (GetTaskId () == TASK_SEEKCOVER && (m_isReloading || m_isVIP))) && !yb_jasonmode.GetBool () && GetTaskId () != TASK_CAMP && !IsOnLadder ()) + if (m_difficulty == 4 && ((m_aimFlags & AIM_ENEMY) || (m_states & (STATE_SEEING_ENEMY | STATE_SUSPECT_ENEMY)) || (GetTaskId () == TASK_SEEKCOVER && (m_isReloading || m_isVIP))) && !yb_jasonmode.GetBool () && GetTaskId () != TASK_CAMP && !IsOnLadder ()) { m_moveToGoal = false; // don't move to goal m_navTimeset = GetWorldTime (); @@ -4949,329 +4962,7 @@ void Bot::BotAI (void) } if (m_checkTerrain) // are we allowed to check blocking terrain (and react to it)? - { - m_isStuck = false; - edict_t *ent = NULL; - - // Test if there's a shootable breakable in our way - if (!FNullEnt (ent = FindBreakable ())) - { - m_breakableEntity = ent; - m_campButtons = pev->button & IN_DUCK; - - StartTask (TASK_SHOOTBREAKABLE, TASKPRI_SHOOTBREAKABLE, -1, 0.0, false); - } - else - { - ent = NULL; - edict_t *pentNearest = NULL; - - if (FindNearestPlayer (reinterpret_cast (&pentNearest), GetEntity (), pev->maxspeed, true, false, true, true)) // found somebody? - { - MakeVectors (m_moveAngles); // use our movement angles - - // try to predict where we should be next frame - Vector moved = pev->origin + g_pGlobals->v_forward * m_moveSpeed * m_frameInterval; - moved = moved + g_pGlobals->v_right * m_strafeSpeed * m_frameInterval; - moved = moved + pev->velocity * m_frameInterval; - - float nearestDistance = (pentNearest->v.origin - pev->origin).GetLength2D (); - float movedDistance = (pentNearest->v.origin - moved).GetLength2D (); - float nextFrameDistance = ((pentNearest->v.origin + pentNearest->v.velocity * m_frameInterval) - pev->origin).GetLength2D (); - - // is player that near now or in future that we need to steer away? - if (movedDistance <= 48.0 || (nearestDistance <= 56.0 && nextFrameDistance < nearestDistance)) - { - // to start strafing, we have to first figure out if the target is on the left side or right side - Vector dirToPoint = (pev->origin - pentNearest->v.origin).SkipZ (); - - if ((dirToPoint | g_pGlobals->v_right.SkipZ ()) > 0.0) - SetStrafeSpeed (directionNormal, pev->maxspeed); - else - SetStrafeSpeed (directionNormal, -pev->maxspeed); - - ResetCollideState (); - - if (nearestDistance < 56.0 && (dirToPoint | g_pGlobals->v_forward.SkipZ ()) < 0.0) - m_moveSpeed = -pev->maxspeed; - } - } - - // Standing still, no need to check? - // FIXME: doesn't care for ladder movement (handled separately) should be included in some way - if ((m_moveSpeed >= 10 || m_strafeSpeed >= 10) && m_lastCollTime < GetWorldTime ()) - { - if (movedDistance < 2.0 && m_prevSpeed >= 1.0) // didn't we move enough previously? - { - // Then consider being stuck - m_prevTime = GetWorldTime (); - m_isStuck = true; - - if (m_firstCollideTime == 0.0) - m_firstCollideTime = GetWorldTime () + 0.2; - } - else // not stuck yet - { - // test if there's something ahead blocking the way - if (CantMoveForward (directionNormal, &tr) && !IsOnLadder ()) - { - if (m_firstCollideTime == 0.0) - m_firstCollideTime = GetWorldTime () + 0.2; - - else if (m_firstCollideTime <= GetWorldTime ()) - m_isStuck = true; - } - else - m_firstCollideTime = 0.0; - } - - if (!m_isStuck) // not stuck? - { - if (m_probeTime + 0.5 < GetWorldTime ()) - ResetCollideState (); // reset collision memory if not being stuck for 0.5 secs - else - { - // remember to keep pressing duck if it was necessary ago - if (m_collideMoves[m_collStateIndex] == COLLISION_DUCK && IsOnFloor () || IsInWater ()) - pev->button |= IN_DUCK; - } - } - else // bot is stuck! - { - // not yet decided what to do? - if (m_collisionState == COLLISION_NOTDECICED) - { - char bits = 0; - - if (IsOnLadder ()) - bits = PROBE_STRAFE; - else if (IsInWater ()) - bits = (PROBE_JUMP | PROBE_STRAFE); - else - bits = ((g_randGen.Long (0, 10) > 7 ? PROBE_JUMP : 0) | PROBE_STRAFE | PROBE_DUCK); - - // collision check allowed if not flying through the air - if (IsOnFloor () || IsOnLadder () || IsInWater ()) - { - char state[8]; - int i = 0; - - // first 4 entries hold the possible collision states - state[i++] = COLLISION_JUMP; - state[i++] = COLLISION_DUCK; - state[i++] = COLLISION_STRAFELEFT; - state[i++] = COLLISION_STRAFERIGHT; - - // now weight all possible states - if (bits & PROBE_JUMP) - { - state[i] = 0; - - if (CanJumpUp (directionNormal)) - state[i] += 10; - - if (m_destOrigin.z >= pev->origin.z + 18.0) - state[i] += 5; - - if (EntityIsVisible (m_destOrigin)) - { - MakeVectors (m_moveAngles); - - src = EyePosition (); - src = src + (g_pGlobals->v_right * 15); - - TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); - - if (tr.flFraction >= 1.0) - { - src = EyePosition (); - src = src - (g_pGlobals->v_right * 15); - - TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); - - if (tr.flFraction >= 1.0) - state[i] += 5; - } - } - if (pev->flags & FL_DUCKING) - src = pev->origin; - else - src = pev->origin + Vector (0, 0, -17); - - destination = src + directionNormal * 30; - TraceLine (src, destination, true, true, GetEntity (), &tr); - - if (tr.flFraction != 1.0) - state[i] += 10; - } - else - state[i] = 0; - i++; - - if (bits & PROBE_DUCK) - { - state[i] = 0; - - if (CanDuckUnder (directionNormal)) - state[i] += 10; - - if ((m_destOrigin.z + 36.0 <= pev->origin.z) && EntityIsVisible (m_destOrigin)) - state[i] += 5; - } - else - state[i] = 0; - i++; - - if (bits & PROBE_STRAFE) - { - state[i] = 0; - state[i + 1] = 0; - - // to start strafing, we have to first figure out if the target is on the left side or right side - MakeVectors (m_moveAngles); - - Vector dirToPoint = (pev->origin - m_destOrigin).Normalize2D (); - Vector rightSide = g_pGlobals->v_right.Normalize2D (); - - bool dirRight = false; - bool dirLeft = false; - bool blockedLeft = false; - bool blockedRight = false; - - if ((dirToPoint | rightSide) > 0) - dirRight = true; - else - dirLeft = true; - - if (m_moveSpeed > 0) - direction = g_pGlobals->v_forward; - else - direction = -g_pGlobals->v_forward; - - // now check which side is blocked - src = pev->origin + (g_pGlobals->v_right * 32); - destination = src + (direction * 32); - - TraceHull (src, destination, true, head_hull, GetEntity (), &tr); - - if (tr.flFraction != 1.0) - blockedRight = true; - - src = pev->origin - (g_pGlobals->v_right * 32); - destination = src + (direction * 32); - - TraceHull (src, destination, true, head_hull, GetEntity (), &tr); - - if (tr.flFraction != 1.0) - blockedLeft = true; - - if (dirLeft) - state[i] += 5; - else - state[i] -= 5; - - if (blockedLeft) - state[i] -= 5; - - i++; - - if (dirRight) - state[i] += 5; - else - state[i] -= 5; - - if (blockedRight) - state[i] -= 5; - } - else - { - state[i] = 0; - i++; - - state[i] = 0; - } - - // weighted all possible moves, now sort them to start with most probable - int temp = 0; - bool isSorting = false; - - do - { - isSorting = false; - for (i = 0; i < 3; i++) - { - if (state[i + 4] < state[i + 5]) - { - temp = state[i]; - - state[i] = state[i + 1]; - state[i + 1] = temp; - - temp = state[i + 4]; - - state[i + 4] = state[i + 5]; - state[i + 5] = temp; - - isSorting = true; - } - } - } while (isSorting); - - for (i = 0; i < 4; i++) - m_collideMoves[i] = state[i]; - - m_collideTime = GetWorldTime (); - m_probeTime = GetWorldTime () + 0.5; - m_collisionProbeBits = bits; - m_collisionState = COLLISION_PROBING; - m_collStateIndex = 0; - } - } - - if (m_collisionState == COLLISION_PROBING) - { - if (m_probeTime < GetWorldTime ()) - { - m_collStateIndex++; - m_probeTime = GetWorldTime () + 0.5; - - if (m_collStateIndex > 4) - { - m_navTimeset = GetWorldTime () - 5.0; - ResetCollideState (); - } - } - - if (m_collStateIndex <= 4) - { - switch (m_collideMoves[m_collStateIndex]) - { - case COLLISION_JUMP: - if (IsOnFloor () || IsInWater ()) - pev->button |= IN_JUMP; - break; - - case COLLISION_DUCK: - if (IsOnFloor () || IsInWater ()) - pev->button |= IN_DUCK; - break; - - case COLLISION_STRAFELEFT: - pev->button |= IN_MOVELEFT; - SetStrafeSpeed (directionNormal, -pev->maxspeed); - break; - - case COLLISION_STRAFERIGHT: - pev->button |= IN_MOVERIGHT; - SetStrafeSpeed (directionNormal, pev->maxspeed); - break; - } - } - } - } - } - } - } + CheckTerrain (movedDistance); // must avoid a grenade? if (m_needAvoidGrenade != 0) @@ -5284,12 +4975,12 @@ void Bot::BotAI (void) } // time to reach waypoint - if (m_navTimeset + GetEstimatedReachTime () < GetWorldTime () && FNullEnt (m_enemy)) + if (m_navTimeset + GetEstimatedReachTime () < GetWorldTime () && IsEntityNull (m_enemy)) { GetValidWaypoint (); // clear these pointers, bot mingh be stuck getting to them - if (!FNullEnt (m_pickupItem) && !m_hasProgressBar) + if (!IsEntityNull (m_pickupItem) && !m_hasProgressBar) m_itemIgnore = m_pickupItem; m_pickupItem = NULL; @@ -5298,7 +4989,7 @@ void Bot::BotAI (void) m_pickupType = PICKUP_NONE; } - if (m_duckTime > GetWorldTime ()) + if (m_duckTime >= GetWorldTime ()) pev->button |= IN_DUCK; if (pev->button & IN_JUMP) @@ -5328,7 +5019,7 @@ void Bot::BotAI (void) static float timeDebugUpdate = 0.0; - if (!FNullEnt (g_hostEntity) && yb_debug.GetInt () >= 1) + if (!IsEntityNull (g_hostEntity) && yb_debug.GetInt () >= 1) { int specIndex = g_hostEntity->v.iuser2; @@ -5436,9 +5127,9 @@ void Bot::BotAI (void) char enemyName[80], weaponName[80], aimFlags[32], botType[32]; - if (!FNullEnt (m_enemy)) + if (!IsEntityNull (m_enemy)) strcpy (enemyName, STRING (m_enemy->v.netname)); - else if (!FNullEnt (m_lastEnemy)) + else if (!IsEntityNull (m_lastEnemy)) { strcpy (enemyName, " (L)"); strcat (enemyName, STRING (m_lastEnemy->v.netname)); @@ -5449,7 +5140,7 @@ void Bot::BotAI (void) char pickupName[80]; memset (pickupName, 0, sizeof (pickupName)); - if (!FNullEnt (m_pickupItem)) + if (!IsEntityNull (m_pickupItem)) strcpy (pickupName, STRING (m_pickupItem->v.classname)); else strcpy (pickupName, " (null)"); @@ -5552,13 +5243,13 @@ void Bot::BotAI (void) while (node != NULL) { - Vector src = g_waypoint->GetPath (node->index)->origin; + Vector srcPath = g_waypoint->GetPath (node->index)->origin; node = node->next; if (node != NULL) { Vector dest = g_waypoint->GetPath (node->index)->origin; - DrawArrow (g_hostEntity, src, dest, 15, 0, 255, 100, 55, 200, 5, 1); + DrawArrow (g_hostEntity, srcPath, dest, 15, 0, 255, 100, 55, 200, 5, 1); } } } @@ -5577,7 +5268,7 @@ bool Bot::HasHostage (void) { for (int i = 0; i < MAX_HOSTAGES; i++) { - if (!FNullEnt (m_hostages[i])) + if (!IsEntityNull (m_hostages[i])) { // don't care about dead hostages if (m_hostages[i]->v.health <= 0 || (pev->origin - m_hostages[i]->v.origin).GetLength () > 600) @@ -5656,7 +5347,7 @@ void Bot::TakeDamage (edict_t *inflictor, int damage, int armor, int bits) } RemoveCertainTask (TASK_CAMP); - if (FNullEnt (m_enemy) && m_team != GetTeam (inflictor)) + if (IsEntityNull (m_enemy) && m_team != GetTeam (inflictor)) { m_lastEnemy = inflictor; m_lastEnemyOrigin = inflictor->v.origin; @@ -5695,13 +5386,13 @@ void Bot::TakeBlinded (const Vector &fade, int alpha) m_maxViewDistance = g_randGen.Float (10, 20); m_blindTime = GetWorldTime () + static_cast (alpha - 200) / 16; - if (m_skill <= 80) + if (m_difficulty <= 2) { m_blindMoveSpeed = 0.0; m_blindSidemoveSpeed = 0.0; m_blindButton = IN_DUCK; } - else if (m_skill < 99 || m_skill == 100) + else if (m_difficulty > 2) { m_blindMoveSpeed = -pev->maxspeed; m_blindSidemoveSpeed = 0.0; @@ -6054,7 +5745,7 @@ Vector Bot::CheckBombAudible (void) if (!g_bombPlanted || (GetTaskId () == TASK_ESCAPEFROMBOMB)) return nullvec; // reliability check - if (m_skill > 80) + if (m_difficulty >= 3) return g_waypoint->GetBombPosition(); Vector bombOrigin = g_waypoint->GetBombPosition (); @@ -6169,7 +5860,7 @@ void Bot::CheckBurstMode (float distance) void Bot::CheckSilencer (void) { - if (((m_currentWeapon == WEAPON_USP && m_skill <= 80) || m_currentWeapon == WEAPON_M4A1) && !HasShield()) + if (((m_currentWeapon == WEAPON_USP && m_difficulty < 2) || m_currentWeapon == WEAPON_M4A1) && !HasShield()) { int iRandomNum = (m_personality == PERSONALITY_RUSHER ? 35 : 65); @@ -6202,7 +5893,7 @@ float Bot::GetBombTimeleft (void) float Bot::GetEstimatedReachTime (void) { - float estimatedTime = 2.5f; // time to reach next waypoint + float estimatedTime = 3.0f; // time to reach next waypoint // calculate 'real' time that we need to get from one waypoint to another if (m_currentWaypointIndex >= 0 && m_currentWaypointIndex < g_numWaypoints && m_prevWptIndex[0] >= 0 && m_prevWptIndex[0] < g_numWaypoints) @@ -6220,12 +5911,12 @@ float Bot::GetEstimatedReachTime (void) estimatedTime *= 3.0; // check for too low values - if (estimatedTime < 3.0) - estimatedTime = 3.0; + if (estimatedTime < 1.0f) + estimatedTime = 1.0f; // check for too high values - if (estimatedTime > 8.0) - estimatedTime = 8.0; + if (estimatedTime > 8.0f) + estimatedTime = 8.0f; } return estimatedTime; } @@ -6292,7 +5983,7 @@ void Bot::ReactOnSound (void) edict_t *player = NULL; float maxVolume = 0.0, volume = 0.0; - int hearEnemyIndex = -1, hearEnemyDistance = 0; + int hearEnemyIndex = -1; // loop through all enemy clients to check for hearable stuff for (int i = 0; i < GetMaxClients (); i++) @@ -6327,7 +6018,6 @@ void Bot::ReactOnSound (void) continue; hearEnemyIndex = i; - hearEnemyDistance = distance; } if (hearEnemyIndex >= 0) @@ -6337,7 +6027,7 @@ void Bot::ReactOnSound (void) } // did the bot hear someone ? - if (!FNullEnt (player)) + if (!IsEntityNull (player)) { // change to best weapon if heard something if (!(m_states & STATE_SEEING_ENEMY) && m_seeEnemyTime + 2.5 < GetWorldTime () && IsOnFloor () && m_currentWeapon != WEAPON_C4 && m_currentWeapon != WEAPON_EXPLOSIVE && m_currentWeapon != WEAPON_SMOKE && m_currentWeapon != WEAPON_FLASHBANG && !yb_jasonmode.GetBool ()) @@ -6346,10 +6036,10 @@ void Bot::ReactOnSound (void) m_heardSoundTime = GetWorldTime () + 5.0; m_states |= STATE_HEARING_ENEMY; - if ((g_randGen.Long (0, 100) < 25) && FNullEnt (m_enemy) && FNullEnt (m_lastEnemy) && m_seeEnemyTime + 7.0 < GetWorldTime ()) + if ((g_randGen.Long (0, 100) < 25) && IsEntityNull (m_enemy) && IsEntityNull (m_lastEnemy) && m_seeEnemyTime + 7.0 < GetWorldTime ()) ChatterMessage (Chatter_HeardEnemy); - m_aimFlags |= AIM_LAST_ENEMY; + m_aimFlags |= AIM_LAST_ENEMY; // didn't bot already have an enemy ? take this one... if (m_lastEnemyOrigin == nullvec || m_lastEnemy == NULL) @@ -6370,9 +6060,9 @@ void Bot::ReactOnSound (void) else { // if bot had an enemy but the heard one is nearer, take it instead - float distance = (m_lastEnemyOrigin - pev->origin).GetLength (); + float distance = (m_lastEnemyOrigin - pev->origin).GetLengthSquared (); - if (distance > (player->v.origin - pev->origin).GetLength () && m_seeEnemyTime + 2.0 < GetWorldTime ()) + if (distance > (player->v.origin - pev->origin).GetLengthSquared () && m_seeEnemyTime + 2.0 < GetWorldTime ()) { m_lastEnemy = player; m_lastEnemyOrigin = player->v.origin; @@ -6381,6 +6071,9 @@ void Bot::ReactOnSound (void) return; } } + + // useless? +#if 0 extern ConVar yb_shoots_thru_walls; // check if heard enemy can be seen @@ -6393,7 +6086,7 @@ void Bot::ReactOnSound (void) m_states |= STATE_SEEING_ENEMY; m_seeEnemyTime = GetWorldTime (); } - else if (m_lastEnemy == player && m_seeEnemyTime + 1.0 > GetWorldTime () && yb_shoots_thru_walls.GetBool () && (g_randGen.Long (1, 100) < g_skillTab[m_skill / 20].heardShootThruProb) && IsShootableThruObstacle (player->v.origin)) + else if (m_lastEnemy == player && m_seeEnemyTime + 1.0 > GetWorldTime () && yb_shoots_thru_walls.GetBool () && IsShootableThruObstacle (player->v.origin)) { m_enemy = player; m_lastEnemy = player; @@ -6402,6 +6095,7 @@ void Bot::ReactOnSound (void) m_states |= STATE_SEEING_ENEMY; m_seeEnemyTime = GetWorldTime (); } +#endif } } @@ -6415,23 +6109,21 @@ bool Bot::IsShootableBreakable (edict_t *ent) return false; } -void Bot::EquipInBuyzone (int iBuyCount) +void Bot::EquipInBuyzone (int buyCount) { // this function is gets called when bot enters a buyzone, to allow bot to buy some stuff - static float lastEquipTime = 0.0; - // if bot is in buy zone, try to buy ammo for this weapon... - if (lastEquipTime + 15.0 < GetWorldTime () && m_inBuyZone && g_timeRoundStart + g_randGen.Float (10.0, 20.0) + mp_buytime.GetFloat () < GetWorldTime () && !g_bombPlanted && m_moneyAmount > g_botBuyEconomyTable[0]) + if (m_lastEquipTime + 15.0 < GetWorldTime () && m_inBuyZone && g_timeRoundStart + g_randGen.Float (10.0, 20.0) + mp_buytime.GetFloat () < GetWorldTime () && !g_bombPlanted && m_moneyAmount > g_botBuyEconomyTable[0]) { m_buyingFinished = false; - m_buyState = iBuyCount; + m_buyState = buyCount; // push buy message PushMessageQueue (GSM_BUY_STUFF); m_nextBuyTime = GetWorldTime (); - lastEquipTime = GetWorldTime (); + m_lastEquipTime = GetWorldTime (); } } @@ -6452,7 +6144,7 @@ bool Bot::IsBombDefusing (Vector bombOrigin) if (m_team != GetTeam (bot->GetEntity ()) || bot->GetTaskId () == TASK_ESCAPEFROMBOMB) continue; // skip other mess - if ((bot->pev->origin - bombOrigin).GetLength () < 100 && (bot->GetTaskId () == TASK_DEFUSEBOMB || bot->m_hasProgressBar)) + if ((bot->pev->origin - bombOrigin).GetLength () < 140.0f && (bot->GetTaskId () == TASK_DEFUSEBOMB || bot->m_hasProgressBar)) { defusingInProgress = true; break; @@ -6462,7 +6154,7 @@ bool Bot::IsBombDefusing (Vector bombOrigin) if (defusingInProgress || !(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].team != m_team || IsValidBot (g_clients[i].ent)) continue; - if ((g_clients[i].ent->v.origin - bombOrigin).GetLength () < 100) + if ((g_clients[i].ent->v.origin - bombOrigin).GetLength () < 140.0f) { defusingInProgress = true; break; diff --git a/source/chatlib.cpp b/source/chatlib.cpp index ade6c8b..cc3fe97 100644 --- a/source/chatlib.cpp +++ b/source/chatlib.cpp @@ -49,6 +49,8 @@ void StripTags (char *buffer) { strtrim (buffer); // if so, string is just a tag + int tagLength = 0; + // strip just the tag part... for (index = 0; index < ARRAYSIZE_HLSDK(tagOpen); index++) { @@ -58,7 +60,7 @@ void StripTags (char *buffer) if (fieldStart >= 0 && fieldStart < 32) { fieldStop = fieldStart + strlen (tagOpen[index]); // set the tag stop - int tagLength = strlen (tagOpen[index]); + tagLength = strlen (tagOpen[index]); for (i = fieldStart; i < length - tagLength; i++) buffer[i] = buffer[i + tagLength]; // overwrite the buffer with the stripped string @@ -71,7 +73,7 @@ void StripTags (char *buffer) if (fieldStart >= 0 && fieldStart < 32) { fieldStop = fieldStart + strlen (tagClose[index]); // set the tag - int tagLength = strlen (tagClose[index]); + tagLength = strlen (tagClose[index]); for (i = fieldStart; i < length - tagLength; i++) buffer[i] = buffer[i + tagLength]; // overwrite the buffer with the stripped string @@ -198,7 +200,7 @@ void Bot::PrepareChatMessage (char *text) } talkEntity = g_clients[index].ent; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } // mapname? @@ -215,7 +217,7 @@ void Bot::PrepareChatMessage (char *text) { talkEntity = EntityOfIndex (m_sayTextBuffer.entityIndex); - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } // teammate alive? @@ -233,12 +235,12 @@ void Bot::PrepareChatMessage (char *text) if (i < GetMaxClients ()) { - if (!FNullEnt (pev->dmg_inflictor) && (m_team == GetTeam (pev->dmg_inflictor))) + if (!IsEntityNull (pev->dmg_inflictor) && (m_team == GetTeam (pev->dmg_inflictor))) talkEntity = pev->dmg_inflictor; else talkEntity = g_clients[i].ent; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } else // no teammates alive... @@ -255,7 +257,7 @@ void Bot::PrepareChatMessage (char *text) { talkEntity = g_clients[i].ent; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } } @@ -275,7 +277,7 @@ void Bot::PrepareChatMessage (char *text) { talkEntity = g_clients[i].ent; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } else // no teammates alive... @@ -290,7 +292,7 @@ void Bot::PrepareChatMessage (char *text) { talkEntity = g_clients[i].ent; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } } @@ -301,17 +303,13 @@ void Bot::PrepareChatMessage (char *text) { if (g_randGen.Long (1, 100) < 30) strcat (m_tempStrings, "CZ"); - else if (g_randGen.Long (1, 100) < 80) - strcat (m_tempStrings, "KoHTpa K3"); else strcat (m_tempStrings, "Condition Zero"); } - else if ((g_gameVersion == CSV_STEAM) || (g_gameVersion == CSV_OLD)) + else if (g_gameVersion == CSV_STEAM || g_gameVersion == CSV_OLD) { if (g_randGen.Long (1, 100) < 30) strcat (m_tempStrings, "CS"); - else if (g_randGen.Long (1, 100) < 80) - strcat (m_tempStrings, "KoHTpa"); else strcat (m_tempStrings, "Counter-Strike"); } @@ -320,7 +318,7 @@ void Bot::PrepareChatMessage (char *text) { talkEntity = m_lastVictim; - if (!FNullEnt (talkEntity)) + if (!IsEntityNull (talkEntity)) strcat (m_tempStrings, HumanizeName (const_cast (STRING (talkEntity->v.netname)))); } pattern++; diff --git a/source/combat.cpp b/source/combat.cpp index ce057d2..7ba5cb5 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -11,7 +11,7 @@ ConVar yb_shoots_thru_walls ("yb_shoots_thru_walls", "1"); ConVar yb_ignore_enemies ("yb_ignore_enemies", "0"); -ConVar yb_csdm_mode ("yb_csdm_mode", "0"); +ConVar yb_csdm_mode ("yb_csdm_mode", "0", VT_NOSERVER); ConVar mp_friendlyfire ("mp_friendlyfire", NULL, VT_NOREGISTER); @@ -56,16 +56,17 @@ bool Bot::LookupEnemy (void) return false; // do not check for new enemy too fast - if (!FNullEnt (m_enemy) && m_enemyUpdateTime > GetWorldTime () && !(m_states & STATE_SUSPECT_ENEMY)) + if (!IsEntityNull (m_enemy) && m_enemyUpdateTime + 2.5f > GetWorldTime () && !(m_states & STATE_SUSPECT_ENEMY)) { m_aimFlags |= AIM_ENEMY; + m_states |= STATE_SUSPECT_ENEMY; + return true; } edict_t *player, *newEnemy = NULL; float nearestDistance = m_viewDistance; - int i; - + // setup potentially visible set for this bot Vector potentialVisibility = EyePosition (); @@ -78,7 +79,7 @@ bool Bot::LookupEnemy (void) if (m_seeEnemyTime + 4.0 < GetWorldTime ()) m_states &= ~STATE_SUSPECT_ENEMY; - if (!FNullEnt (m_enemy)) + if (!IsEntityNull (m_enemy)) { player = m_enemy; @@ -88,12 +89,12 @@ bool Bot::LookupEnemy (void) } // the old enemy is no longer visible or - if (FNullEnt (newEnemy)) + if (IsEntityNull (newEnemy)) { m_enemyUpdateTime = GetWorldTime () + 0.25; // search the world for players... - for (i = 0; i < GetMaxClients (); i++) + for (int i = 0; i < GetMaxClients (); i++) { if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || (g_clients[i].team == m_team) || (g_clients[i].ent == GetEntity ())) continue; @@ -109,9 +110,9 @@ bool Bot::LookupEnemy (void) continue; // do some blind by smoke grenade - if (IsBehindSmokeClouds (player) && m_blindRecognizeTime < GetWorldTime ()) + if (m_blindRecognizeTime < GetWorldTime () && IsBehindSmokeClouds (player)) { - m_blindRecognizeTime = GetWorldTime () + g_randGen.Float (2.0, 3.0); + m_blindRecognizeTime = GetWorldTime () + g_randGen.Float (1.0, 2.0); if (g_randGen.Long (0, 100) < 50) ChatterMessage (Chatter_BehindSmoke); @@ -160,13 +161,13 @@ bool Bot::LookupEnemy (void) } else { - if (m_seeEnemyTime + 3.0 < GetWorldTime () && (m_hasC4 || HasHostage () || !FNullEnt (m_targetEntity))) + if (m_seeEnemyTime + 3.0 < GetWorldTime () && (m_hasC4 || HasHostage () || !IsEntityNull (m_targetEntity))) RadioMessage (Radio_EnemySpotted); m_targetEntity = NULL; // stop following when we see an enemy... - if (g_randGen.Long (0, 100) < m_skill) - m_enemySurpriseTime = GetWorldTime () + (m_actualReactionTime / 3); + if (g_randGen.Long (0, 100) < m_difficulty * 25) + m_enemySurpriseTime = GetWorldTime () + m_actualReactionTime / 3; else m_enemySurpriseTime = GetWorldTime () + m_actualReactionTime; @@ -190,7 +191,7 @@ bool Bot::LookupEnemy (void) if (friendBot != NULL) { - if (friendBot->m_seeEnemyTime + 2.0 < GetWorldTime () || FNullEnt (friendBot->m_lastEnemy)) + if (friendBot->m_seeEnemyTime + 2.0 < GetWorldTime () || IsEntityNull (friendBot->m_lastEnemy)) { if (IsVisible (pev->origin, ENT (friendBot->pev))) { @@ -204,7 +205,7 @@ bool Bot::LookupEnemy (void) return true; } } - else if (!FNullEnt (m_enemy)) + else if (!IsEntityNull (m_enemy)) { newEnemy = m_enemy; m_lastEnemy = newEnemy; @@ -237,26 +238,23 @@ bool Bot::LookupEnemy (void) } // if no enemy visible check if last one shoot able through wall - if (yb_shoots_thru_walls.GetBool () && g_randGen.Long (1, 100) < g_skillTab[m_skill / 20].seenShootThruProb) + if (yb_shoots_thru_walls.GetBool () && m_difficulty >= 2 && IsShootableThruObstacle (newEnemy->v.origin)) { - if (IsShootableThruObstacle (newEnemy->v.origin)) - { - m_seeEnemyTime = GetWorldTime () - 0.35f; + m_seeEnemyTime = GetWorldTime () - 0.35f; - m_states |= STATE_SUSPECT_ENEMY; - m_aimFlags |= AIM_LAST_ENEMY; + m_states |= STATE_SUSPECT_ENEMY; + m_aimFlags |= AIM_LAST_ENEMY; - m_enemy = newEnemy; - m_lastEnemy = newEnemy; - m_lastEnemyOrigin = newEnemy->v.origin; + m_enemy = newEnemy; + m_lastEnemy = newEnemy; + m_lastEnemyOrigin = newEnemy->v.origin; - return true; - } + return true; } } // check if bots should reload... - if ((m_aimFlags <= AIM_PREDICT_ENEMY && m_seeEnemyTime + 3.0 < GetWorldTime () && !(m_states & (STATE_SEEING_ENEMY | STATE_HEARING_ENEMY)) && FNullEnt (m_lastEnemy) && FNullEnt (m_enemy) && GetTaskId () != TASK_SHOOTBREAKABLE && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) || g_roundEnded) + if ((m_aimFlags <= AIM_PREDICT_ENEMY && m_seeEnemyTime + 3.0 < GetWorldTime () && !(m_states & (STATE_SEEING_ENEMY | STATE_HEARING_ENEMY)) && IsEntityNull (m_lastEnemy) && IsEntityNull (m_enemy) && GetTaskId () != TASK_SHOOTBREAKABLE && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) || g_roundEnded) { if (!m_reloadState) m_reloadState = RELOAD_PRIMARY; @@ -282,54 +280,60 @@ Vector Bot::GetAimPosition (void) // get enemy position initially Vector targetOrigin = m_enemy->v.origin; + Vector randomize = nullvec; + + const Vector &adjust = Vector (g_randGen.Float (m_enemy->v.mins.x * 0.5f, m_enemy->v.maxs.x * 0.5f), g_randGen.Float (m_enemy->v.mins.y * 0.5f, m_enemy->v.maxs.y * 0.5f), g_randGen.Float (m_enemy->v.mins.z * 0.5f, m_enemy->v.maxs.z * 0.5f)); // do not aim at head, at long distance (only if not using sniper weapon) - if ((m_visibility & VISIBLE_BODY) && !UsesSniper () && !UsesPistol () && (distance > (yb_hardcore_mode.GetBool () ? 3400.0 : 2600.0))) + if ((m_visibility & VISIBLE_BODY) && !UsesSniper () && !UsesPistol () && (distance > (m_difficulty == 4 ? 2400.0 : 1200.0))) m_visibility &= ~VISIBLE_HEAD; // if we only suspect an enemy behind a wall take the worst skill if ((m_states & STATE_SUSPECT_ENEMY) && !(m_states & STATE_SEEING_ENEMY)) - targetOrigin = targetOrigin + Vector (g_randGen.Float (m_enemy->v.mins.x * 0.5f, m_enemy->v.maxs.x * 0.5f), g_randGen.Float (m_enemy->v.mins.y * 0.5f, m_enemy->v.maxs.y * 0.5f), g_randGen.Float (m_enemy->v.mins.z * 0.5f, m_enemy->v.maxs.z * 0.5f)); + targetOrigin = targetOrigin + adjust; else { // now take in account different parts of enemy body if (m_visibility & (VISIBLE_HEAD | VISIBLE_BODY)) // visible head & body { + int headshotFreq[5] = { 20, 40, 60, 90, 100 }; + // now check is our skill match to aim at head, else aim at enemy body - if ((g_randGen.Long (1, 100) < g_skillTab[m_skill / 20].headshotFrequency) || UsesPistol ()) + if ((g_randGen.Long (1, 100) < headshotFreq[m_difficulty]) || UsesPistol ()) targetOrigin = targetOrigin + m_enemy->v.view_ofs + Vector (0.0f, 0.0f, GetZOffset (distance)); else - targetOrigin = targetOrigin + Vector (0.0f, 0.0f, 3.52f); + targetOrigin = targetOrigin + Vector (0.0f, 0.0f, GetZOffset (distance)); } - else if (m_visibility & VISIBLE_HEAD) // visible only head - targetOrigin = targetOrigin + m_enemy->v.view_ofs + Vector (0.0f, 0.0f, GetZOffset (distance)); else if (m_visibility & VISIBLE_BODY) // visible only body - targetOrigin = targetOrigin + Vector (0.0f, 0.0f, 3.52f); + targetOrigin = targetOrigin + Vector (0.0f, 0.0f, GetZOffset (distance)); else if (m_visibility & VISIBLE_OTHER) // random part of body is visible targetOrigin = m_enemyOrigin; + else if (m_visibility & VISIBLE_HEAD) // visible only head + targetOrigin = targetOrigin + m_enemy->v.view_ofs + Vector (0.0f, 0.0f, GetZOffset (distance)); else // something goes wrong, use last enemy origin + { targetOrigin = m_lastEnemyOrigin; - + + if (m_difficulty < 3) + randomize = adjust; + } m_lastEnemyOrigin = targetOrigin; } + const Vector &velocity = UsesSniper () ? nullvec : (1.0f * m_frameInterval * m_enemy->v.velocity - 1.0 * m_frameInterval * pev->velocity).SkipZ (); - if (!yb_hardcore_mode.GetBool ()) + if (m_difficulty < 3 && randomize != nullvec) { - float divOffs, distance = (m_enemyOrigin - pev->origin).GetLength (); + float divOffs = (m_enemyOrigin - pev->origin).GetLength (); if (pev->fov < 40) - divOffs = distance / 2000; + divOffs = divOffs / 2000; else if (pev->fov < 90) - divOffs = distance / 1000; + divOffs = divOffs / 1000; else - divOffs = distance / 500; - - targetOrigin.x += divOffs * g_randGen.Float (-g_skillTab[m_skill / 20].aimOffs_X, g_skillTab[m_skill / 20].aimOffs_X); - targetOrigin.y += divOffs * g_randGen.Float (-g_skillTab[m_skill / 20].aimOffs_Y, g_skillTab[m_skill / 20].aimOffs_Y); - targetOrigin.z += divOffs * g_randGen.Float (-g_skillTab[m_skill / 20].aimOffs_Z, g_skillTab[m_skill / 20].aimOffs_Z); + divOffs = divOffs / 500; // randomize the target position - m_enemyOrigin = targetOrigin + ((pev->velocity - m_enemy->v.velocity).SkipZ () * m_frameInterval * 1.2); + m_enemyOrigin = divOffs * randomize + velocity; } else m_enemyOrigin = targetOrigin; @@ -353,7 +357,7 @@ float Bot::GetZOffset (float distance) const float BurstDistance = 300.0f; const float DoubleBurstDistance = BurstDistance * 2; - float result = 3.0f; + float result = 3.5f; if (distance < 2800.0f && distance > DoubleBurstDistance) { @@ -371,7 +375,7 @@ float Bot::GetZOffset (float distance) else if (zoomableRifle) result = 3.5f; else if (pistol) result = 6.5f; else if (submachine) result = 3.5f; - else if (rifle) result = 1.0f; + else if (rifle) result = 1.6f; else if (m249) result = -1.0f; else if (shotgun) result = 10.0f; } @@ -400,7 +404,7 @@ bool Bot::IsFriendInLineOfFire (float distance) TraceLine (EyePosition (), EyePosition () + pev->v_angle.Normalize () * distance, false, false, GetEntity (), &tr); // check if we hit something - if (!FNullEnt (tr.pHit)) + if (!IsEntityNull (tr.pHit)) { int playerIndex = IndexOfEntity (tr.pHit) - 1; @@ -428,41 +432,49 @@ bool Bot::IsFriendInLineOfFire (float distance) bool Bot::IsShootableThruObstacle (Vector dest) { - // this function returns if enemy can be shoot through some obstacle + // this function returns true if enemy can be shoot through some obstacle, false otherwise. + // credits goes to Immortal_BLG - if (m_skill <= 60 || !IsWeaponShootingThroughWall (m_currentWeapon)) + if (m_difficulty < 2) return false; - Vector source = EyePosition (); - Vector direction = (dest - source).Normalize (); // 1 unit long - Vector point = nullvec; + int penetratePower = GetWeaponPenetrationPower (m_currentWeapon); - int thikness = 0; - int numHits = 0; + if (penetratePower == 0) + return false; + + // set conditions.... + Vector source = EyePosition (); + const Vector &direction = (dest - source).Normalize () * 8.0f; // 8 units long TraceResult tr; - TraceLine (source, dest, true, true, GetEntity (), &tr); - while (tr.flFraction != 1.0 && numHits < 3) + do { - numHits++; - thikness++; + // trace from the bot's eyes to destination... + TraceLine (source, dest, true, GetEntity (), &tr); - point = tr.vecEndPos + direction; - - while (POINT_CONTENTS (point) == CONTENTS_SOLID && thikness < 98) + if (tr.fStartSolid) { - point = point + direction; - thikness++; - } - TraceLine (point, dest, true, true, GetEntity (), &tr); - } + if (tr.fAllSolid) + return false; + + // move 8 units closer to the destination.... + source += direction; + } + else + { + // check if line hit anything + if (tr.flFraction == 1.0f) + return true; + + --penetratePower; + + // move 8 units closer to the destination.... + source = tr.vecEndPos + direction; + } + } while (penetratePower > 0); - if (numHits < 3 && thikness < 98) - { - if ((dest - point).GetLengthSquared () < 13143) - return true; - } return false; } @@ -479,21 +491,35 @@ bool Bot::DoFirePause (float distance, FireDelay *fireDelay) if (m_firePause > GetWorldTime ()) return true; + float offset = 0.0f; + + const float BurstDistance = 300.0f; + const float DoubleBurstDistance = BurstDistance * 2; + + if (distance < BurstDistance) // KWo - 09.04.2010 + return false; + else if (distance < 2 * BurstDistance) + offset = 10.0; + else + offset = 5.0; + + float angle = sqrtf ((fabsf (pev->punchangle.y) * Math::MATH_PI / 180.0) * (fabsf (pev->punchangle.y) * Math::MATH_PI / 180.0) + (fabsf (pev->punchangle.x) * Math::MATH_PI / 180.0) * (fabsf (pev->punchangle.x) * Math::MATH_PI / 180.0)); + // check if we need to compensate recoil - if (tanf ((fabsf (pev->punchangle.y) + fabsf (pev->punchangle.x)) * Math::MATH_PI / 360.0) * distance > 20 + m_skillOffset) + if (tanf (angle) * distance > offset + 30.0f + ((100 - (m_difficulty * 25)) / 100.f)) { - if (m_firePause < GetWorldTime () - 0.4) - m_firePause = GetWorldTime () + g_randGen.Float (0.4, 0.4 + 1.2 * m_skillOffset); + if (m_firePause < GetWorldTime () - 0.4f) + m_firePause = GetWorldTime () + g_randGen.Float (0.4f, 0.4f + 0.3f * ((100 - (m_difficulty * 25)) / 100.f)); return true; } - if (!yb_hardcore_mode.GetBool () && fireDelay->maxFireBullets + g_randGen.Long (0, 1) <= m_burstShotsFired) + if (m_difficulty < 3 && fireDelay->maxFireBullets + g_randGen.Long (0, 1) <= m_burstShotsFired) { float delayTime = 0.1 * distance / fireDelay->minBurstPauseFactor; - if (delayTime > (125.0 / (m_skill + 1))) - delayTime = 125.0 / (m_skill + 1); + if (delayTime > (125.0 / (m_difficulty * 25 + 1))) + delayTime = 125.0 / (m_difficulty * 25 + 1); m_firePause = GetWorldTime () + delayTime; m_burstShotsFired = 0; @@ -516,7 +542,7 @@ void Bot::FireWeapon (void) } // or if friend in line of fire, stop this too but do not update shoot time - if (!FNullEnt (m_enemy) && IsFriendInLineOfFire (distance)) + if (!IsEntityNull (m_enemy) && IsFriendInLineOfFire (distance)) return; FireDelay *delay = &g_fireDelay[0]; @@ -531,8 +557,8 @@ void Bot::FireWeapon (void) if (yb_jasonmode.GetBool ()) goto WeaponSelectEnd; - // use knife if near and good skill (l33t dude!) - if (m_skill > 80 && pev->health > 80 && !FNullEnt (enemy) && pev->health >= enemy->v.health && distance < 100.0f && !IsGroupOfEnemies (pev->origin)) + // use knife if near and good difficulty (l33t dude!) + if (m_difficulty >= 3 && pev->health > 80 && !IsEntityNull (enemy) && pev->health >= enemy->v.health && distance < 100.0f && !IsGroupOfEnemies (pev->origin)) goto WeaponSelectEnd; // loop through all the weapons until terminator is found... @@ -585,7 +611,7 @@ void Bot::FireWeapon (void) if (IsEnemyProtectedByShield (m_enemy) && !(m_currentWeapon == WEAPON_KNIFE) && IsEnemyViewable (m_enemy)) { if (!g_bombPlanted && g_randGen.Float (0, 100) < 50) - StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (10, 20), true); + StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (5, 10), true); } @@ -597,7 +623,7 @@ void Bot::FireWeapon (void) if (distance >= 750 || ((m_enemy->v.button & IN_ATTACK) && !IsShieldDrawn())) { - pev->button |= (IN_ATTACK2 | IN_DUCK); // draw the shield + pev->button |= IN_ATTACK2; // draw the shield pev->button &= ~IN_DUCK; if (IsGroupOfEnemies (pev->origin, 3, 550) || (GetNearbyEnemiesNearPosition (pev->origin, 550) >= 3 && IsShieldDrawn ())) @@ -614,9 +640,10 @@ void Bot::FireWeapon (void) StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + g_randGen.Float (10, 20), true); } } - else if (IsShieldDrawn () || (!FNullEnt (m_enemy) && (m_enemy->v.button & IN_RELOAD) || !IsEnemyViewable (m_enemy))) + else if (IsShieldDrawn () || (!IsEntityNull (m_enemy) && (m_enemy->v.button & IN_RELOAD) || !IsEnemyViewable (m_enemy))) { pev->button |= (IN_ATTACK2 | IN_DUCK); // draw out the shield + if (!g_bombPlanted) StartTask (TASK_SEEKCOVER, TASKPRI_SEEKCOVER, -1, GetWorldTime () + g_randGen.Float (10, 25), true); } @@ -668,7 +695,7 @@ WeaponSelectEnd: { if ((distance >= 750) && !IsShieldDrawn ()) pev->button |= IN_ATTACK2; // draw the shield - else if (IsShieldDrawn () || (!FNullEnt (m_enemy) && (m_enemy->v.button & IN_RELOAD) || !IsEnemyViewable(m_enemy))) + else if (IsShieldDrawn () || (!IsEntityNull (m_enemy) && (m_enemy->v.button & IN_RELOAD) || !IsEnemyViewable(m_enemy))) pev->button |= IN_ATTACK2; // draw out the shield m_shieldCheckTime = GetWorldTime () + 1.0; @@ -687,14 +714,14 @@ WeaponSelectEnd: m_zoomCheckTime = GetWorldTime (); - if (!FNullEnt (m_enemy) && (pev->velocity.x != 0 || pev->velocity.y != 0 || pev->velocity.z != 0) && (pev->basevelocity.x != 0 || pev->basevelocity.y != 0 || pev->basevelocity.z != 0)) + if (!IsEntityNull (m_enemy) && (pev->velocity.x != 0 || pev->velocity.y != 0 || pev->velocity.z != 0) && (pev->basevelocity.x != 0 || pev->basevelocity.y != 0 || pev->basevelocity.z != 0)) { m_moveSpeed = 0.0; m_strafeSpeed = 0.0; m_navTimeset = GetWorldTime (); } } - else if (UsesZoomableRifle () && m_zoomCheckTime < GetWorldTime () && m_skill < 90) // else is the bot holding a zoomable rifle? + else if (UsesZoomableRifle () && m_zoomCheckTime < GetWorldTime () && m_difficulty < 3) // else is the bot holding a zoomable rifle? { if (distance > 800 && pev->fov >= 90) // should the bot switch to zoomed mode? pev->button |= IN_ATTACK2; @@ -717,15 +744,16 @@ WeaponSelectEnd: } const float baseDelay = delay[chosenWeaponIndex].primaryBaseDelay; - const float minDelay = delay[chosenWeaponIndex].primaryMinDelay[abs ((m_skill / 20) - 5)]; - const float maxDelay = delay[chosenWeaponIndex].primaryMaxDelay[abs ((m_skill / 20) - 5)]; + + const float minDelay = delay[chosenWeaponIndex].primaryMinDelay[abs (m_difficulty - 4)]; + const float maxDelay = delay[chosenWeaponIndex].primaryMaxDelay[abs (m_difficulty - 4)]; // need to care for burst fire? if (distance < 256.0 || m_blindTime > GetWorldTime ()) { if (selectId == WEAPON_KNIFE) { - if (distance < 64.0) + if (distance < 102.0f) { if (g_randGen.Long (1, 100) < 30) pev->button |= IN_ATTACK; // use primary attack @@ -790,7 +818,7 @@ WeaponSelectEnd: if (!IsEnemyProtectedByShield(m_lastEnemy)) { pev->button &= ~IN_ATTACK; - LookupEnemy();; + LookupEnemy(); } pev->button |= IN_ATTACK; @@ -808,6 +836,9 @@ bool Bot::IsWeaponBadInDistance (int weaponIndex, float distance) int weaponID = g_weaponSelect[weaponIndex].id; + if (weaponID == WEAPON_KNIFE) + return false; + // check is ammo available for secondary weapon if (m_ammoInClip[g_weaponSelect[GetBestSecondaryWeaponCarried ()].id] >= 1) return false; @@ -878,7 +909,7 @@ void Bot::FocusEnemy (void) void Bot::CombatFight (void) { // no enemy? no need to do strafing - if (FNullEnt (m_enemy)) + if (IsEntityNull (m_enemy)) return; Vector enemyOrigin = m_lookAt; @@ -890,7 +921,7 @@ void Bot::CombatFight (void) float distance = enemyOrigin.GetLength (); // how far away is the enemy scum? - if (m_timeWaypointMove + m_frameInterval < GetWorldTime ()) + if (m_timeWaypointMove + m_frameInterval + 0.5f < GetWorldTime ()) { if (m_currentWeapon == WEAPON_KNIFE) return; @@ -916,17 +947,17 @@ void Bot::CombatFight (void) m_fearLevel += 0.5; CheckGrenades(); - CheckThrow(EyePosition(),m_throw); + CheckThrow (EyePosition(), m_throw); - if (m_states & (STATE_SEEING_ENEMY) && !m_hasC4) - StartTask(TASK_SEEKCOVER, TASKPRI_SEEKCOVER,-1, g_randGen.Long (10, 20), true); + if ((m_states & STATE_SEEING_ENEMY) && !m_hasC4) + StartTask (TASK_SEEKCOVER, TASKPRI_SEEKCOVER, -1, g_randGen.Long (10, 20), true); } // If using sniper do not jump around ! if (UsesSniper () && m_states & STATE_SEEING_ENEMY || IsEnemyViewable (m_enemy) && !m_isStuck) pev->button &= ~IN_JUMP; // only take cover when bomb is not planted and enemy can see the bot or the bot is VIP - if (approach < 30 && !g_bombPlanted && (::IsInViewCone (pev->origin, m_enemy) || m_isVIP)) + if (approach < 30 && !g_bombPlanted && (IsInViewCone (m_enemy->v.origin) || m_isVIP)) { m_moveSpeed = -pev->maxspeed; @@ -978,7 +1009,7 @@ void Bot::CombatFight (void) { if (m_lastFightStyleCheck + 3.0 < GetWorldTime ()) { - if (g_randGen.Long (0, 100) < 65) + if (g_randGen.Long (0, 100) < 50) m_fightStyle = 1; else m_fightStyle = 0; @@ -987,7 +1018,7 @@ void Bot::CombatFight (void) } } - if ((m_skill > 50 && m_fightStyle == 0) || ((pev->button & IN_RELOAD) || m_isReloading) || (UsesPistol () && distance < 500.0)) + if ((m_difficulty >= 1 && m_fightStyle == 0) || ((pev->button & IN_RELOAD) || m_isReloading) || (UsesPistol () && distance < 500.0)) { if (m_strafeSetTime < GetWorldTime ()) { @@ -1005,23 +1036,23 @@ void Bot::CombatFight (void) if (g_randGen.Long (1, 100) < 30) m_combatStrafeDir ^= 1; - m_strafeSetTime = GetWorldTime () + g_randGen.Float (0.5, 2.5); + m_strafeSetTime = GetWorldTime () + g_randGen.Float (0.5, 3.0); } if (m_combatStrafeDir == 0) { if (!CheckWallOnLeft ()) - m_strafeSpeed = -160.0; + m_strafeSpeed = -pev->maxspeed; else { m_combatStrafeDir ^= 1; - m_strafeSetTime = GetWorldTime () + 0.7; + m_strafeSetTime = GetWorldTime () + 1.0; } } else { if (!CheckWallOnRight ()) - m_strafeSpeed = 160.0; + m_strafeSpeed = -pev->maxspeed; else { m_combatStrafeDir ^= 1; @@ -1029,10 +1060,10 @@ void Bot::CombatFight (void) } } - if (m_skill > 80 && (m_jumpTime + 5.0 < GetWorldTime () && IsOnFloor () && g_randGen.Long (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.GetLength2D () > 150.0)) + if (m_difficulty >= 3 && (m_jumpTime + 5.0 < GetWorldTime () && IsOnFloor () && g_randGen.Long (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.GetLength2D () > 150.0)) pev->button |= IN_JUMP; - if (m_moveSpeed != 0.0 && distance > 150.0) + if (m_moveSpeed > 0.0 && distance > 150.0) m_moveSpeed = 0.0; } else if (m_fightStyle == 1) @@ -1049,7 +1080,7 @@ void Bot::CombatFight (void) int nearestToEnemyPoint = g_waypoint->FindNearest (m_enemy->v.origin); if (shouldDuck && GetTaskId () != TASK_SEEKCOVER && GetTaskId () != TASK_HUNTENEMY && (m_visibility & VISIBLE_BODY) && !(m_visibility & VISIBLE_OTHER) && g_waypoint->IsDuckVisible (m_currentWaypointIndex, nearestToEnemyPoint)) - m_duckTime = GetWorldTime () + (m_frameInterval * 3.5); + m_duckTime = GetWorldTime () + 1.0f; m_moveSpeed = 0.0; m_strafeSpeed = 0.0; @@ -1063,16 +1094,16 @@ void Bot::CombatFight (void) m_strafeSpeed = 0.0; } - if (m_moveSpeed != 0.0) + if (m_moveSpeed > 0.0f) m_moveSpeed = GetWalkSpeed (); if (m_isReloading) { m_moveSpeed = -pev->maxspeed; - m_duckTime = GetWorldTime () - (m_frameInterval * 4.0); + m_duckTime = GetWorldTime () - 1.0f; } - if (!IsInWater () && !IsOnLadder () && (m_moveSpeed != 0 || m_strafeSpeed != 0.0f)) + if (!IsInWater () && !IsOnLadder () && (m_moveSpeed > 0.0f || m_strafeSpeed >= 0.0f)) { MakeVectors (pev->v_angle); @@ -1121,7 +1152,7 @@ bool Bot::IsEnemyProtectedByShield (edict_t *enemy) { // this function returns true, if enemy protected by the shield - if (FNullEnt (enemy) || (HasShield () && IsShieldDrawn ())) + if (IsEntityNull (enemy) || (HasShield () && IsShieldDrawn ())) return false; // check if enemy has shield and this shield is drawn diff --git a/source/globals.cpp b/source/globals.cpp index 8fb6c42..388a088 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -32,6 +32,7 @@ float g_timeRoundEnd = 0.0; float g_timeRoundMid = 0.0; float g_timeNextBombUpdate = 0.0; float g_timeBombPlanted = 0.0; +float g_timePerSecondUpdate = 0.0; float g_lastRadioTime[2] = {0.0, 0.0}; float g_autoPathDistance = 250.0; @@ -77,8 +78,6 @@ edict_t *g_hostEntity = NULL; globalvars_t *g_pGlobals = NULL; Experience *g_experienceData = NULL; - - // default tables for personality weapon preferences, overridden by weapons.cfg int g_normalWeaponPrefs[NUM_WEAPONS] = {0, 2, 1, 4, 5, 6, 3, 12, 10, 24, 25, 13, 11, 8, 7, 22, 23, 18, 21, 17, 19, 15, 17, 9, 14, 16}; @@ -95,16 +94,6 @@ int g_grenadeBuyPrecent[NUM_WEAPONS - 23] = int g_botBuyEconomyTable[NUM_WEAPONS - 15] = {1900, 2100, 2100, 4000, 6000, 7000, 16000, 1200, 800, 1000, 3000}; -SkillDefinition g_skillTab[6] = -{ - {0.8, 1.0, 45.0, 65.0, 2.0, 3.0, 40.0, 40.0, 50.0, 0, 0, 0, 50}, - {0.6, 0.8, 40.0, 60.0, 3.0, 4.0, 30.0, 30.0, 42.0, 10, 0, 0, 40}, - {0.4, 0.6, 35.0, 55.0, 4.0, 6.0, 20.0, 20.0, 32.0, 30, 0, 50, 35}, - {0.2, 0.3, 30.0, 50.0, 6.0, 8.0, 10.0, 10.0, 18.0, 0, 30, 80, 30}, - {0.1, 0.2, 25.0, 40.0, 8.0, 10.0, 5.0, 5.0, 10.0, 80, 50, 100, 23}, - {0.0, 0.1, 20.0, 30.0, 9.0, 12.0, 0.0, 5.0, 0.0, 100, 100, 100, 20} -}; - int *g_weaponPrefs[] = { g_normalWeaponPrefs, @@ -168,65 +157,65 @@ TaskItem g_taskFilters[] = // weapons and their specifications WeaponSelect g_weaponSelect[NUM_WEAPONS + 1] = { - {WEAPON_KNIFE, "weapon_knife", "knife.mdl", 0, 0, -1, -1, 0, 0, 0, 0, false, true }, - {WEAPON_USP, "weapon_usp", "usp.mdl", 500, 1, -1, -1, 1, 1, 2, 2, false, false}, - {WEAPON_GLOCK, "weapon_glock18", "glock18.mdl", 400, 1, -1, -1, 1, 2, 1, 1, false, false}, - {WEAPON_DEAGLE, "weapon_deagle", "deagle.mdl", 650, 1, 2, 2, 1, 3, 4, 4, true, false}, - {WEAPON_P228, "weapon_p228", "p228.mdl", 600, 1, 2, 2, 1, 4, 3, 3, false, false}, - {WEAPON_ELITE, "weapon_elite", "elite.mdl", 1000, 1, 0, 0, 1, 5, 5, 5, false, false}, - {WEAPON_FIVESEVEN, "weapon_fiveseven", "fiveseven.mdl", 750, 1, 1, 1, 1, 6, 5, 5, false, false}, - {WEAPON_M3, "weapon_m3", "m3.mdl", 1700, 1, 2, -1, 2, 1, 1, 1, false, false}, - {WEAPON_XM1014, "weapon_xm1014", "xm1014.mdl", 3000, 1, 2, -1, 2, 2, 2, 2, false, false}, - {WEAPON_MP5, "weapon_mp5navy", "mp5.mdl", 1500, 1, 2, 1, 3, 1, 2, 2, false, true }, - {WEAPON_TMP, "weapon_tmp", "tmp.mdl", 1250, 1, 1, 1, 3, 2, 1, 1, false, true }, - {WEAPON_P90, "weapon_p90", "p90.mdl", 2350, 1, 2, 1, 3, 3, 4, 4, false, true }, - {WEAPON_MAC10, "weapon_mac10", "mac10.mdl", 1400, 1, 0, 0, 3, 4, 1, 1, false, true }, - {WEAPON_UMP45, "weapon_ump45", "ump45.mdl", 1700, 1, 2, 2, 3, 5, 3, 3, false, true }, - {WEAPON_AK47, "weapon_ak47", "ak47.mdl", 2500, 1, 0, 0, 4, 1, 2, 2, true, true }, - {WEAPON_SG552, "weapon_sg552", "sg552.mdl", 3500, 1, 0, -1, 4, 2, 4, 4, true, true }, - {WEAPON_M4A1, "weapon_m4a1", "m4a1.mdl", 3100, 1, 1, 1, 4, 3, 3, 3, true, true }, - {WEAPON_GALIL, "weapon_galil", "galil.mdl", 2000, 1, 0, 0, 4, -1, 1, 1, true, true }, - {WEAPON_FAMAS, "weapon_famas", "famas.mdl", 2250, 1, 1, 1, 4, -1, 1, 1, true, true }, - {WEAPON_AUG, "weapon_aug", "aug.mdl", 3500, 1, 1, 1, 4, 4, 4, 4, true, true }, - {WEAPON_SCOUT, "weapon_scout", "scout.mdl", 2750, 1, 2, 0, 4, 5, 3, 2, true, false}, - {WEAPON_AWP, "weapon_awp", "awp.mdl", 4750, 1, 2, 0, 4, 6, 5, 6, true, false}, - {WEAPON_G3SG1, "weapon_g3sg1", "g3sg1.mdl", 5000, 1, 0, 2, 4, 7, 6, 6, true, false}, - {WEAPON_SG550, "weapon_sg550", "sg550.mdl", 4200, 1, 1, 1, 4, 8, 5, 5, true, false}, - {WEAPON_M249, "weapon_m249", "m249.mdl", 5750, 1, 2, 1, 5, 1, 1, 1, true, true }, - {WEAPON_SHIELD, "weapon_shield", "shield.mdl", 2200, 0, 1, 1, 8, -1, 8, 8, false, false}, - {0, "", "", 0, 0, 0, 0, 0, 0, 0, 0, false, false} + {WEAPON_KNIFE, "weapon_knife", "knife.mdl", 0, 0, -1, -1, 0, 0, 0, 0, 0, true }, + {WEAPON_USP, "weapon_usp", "usp.mdl", 500, 1, -1, -1, 1, 1, 2, 2, 0, false}, + {WEAPON_GLOCK, "weapon_glock18", "glock18.mdl", 400, 1, -1, -1, 1, 2, 1, 1, 0, false}, + {WEAPON_DEAGLE, "weapon_deagle", "deagle.mdl", 650, 1, 2, 2, 1, 3, 4, 4, 2, false}, + {WEAPON_P228, "weapon_p228", "p228.mdl", 600, 1, 2, 2, 1, 4, 3, 3, 0, false}, + {WEAPON_ELITE, "weapon_elite", "elite.mdl", 1000, 1, 0, 0, 1, 5, 5, 5, 0, false}, + {WEAPON_FIVESEVEN, "weapon_fiveseven", "fiveseven.mdl", 750, 1, 1, 1, 1, 6, 5, 5, 0, false}, + {WEAPON_M3, "weapon_m3", "m3.mdl", 1700, 1, 2, -1, 2, 1, 1, 1, 0, false}, + {WEAPON_XM1014, "weapon_xm1014", "xm1014.mdl", 3000, 1, 2, -1, 2, 2, 2, 2, 0, false}, + {WEAPON_MP5, "weapon_mp5navy", "mp5.mdl", 1500, 1, 2, 1, 3, 1, 2, 2, 0, true }, + {WEAPON_TMP, "weapon_tmp", "tmp.mdl", 1250, 1, 1, 1, 3, 2, 1, 1, 0, true }, + {WEAPON_P90, "weapon_p90", "p90.mdl", 2350, 1, 2, 1, 3, 3, 4, 4, 0, true }, + {WEAPON_MAC10, "weapon_mac10", "mac10.mdl", 1400, 1, 0, 0, 3, 4, 1, 1, 0, true }, + {WEAPON_UMP45, "weapon_ump45", "ump45.mdl", 1700, 1, 2, 2, 3, 5, 3, 3, 0, true }, + {WEAPON_AK47, "weapon_ak47", "ak47.mdl", 2500, 1, 0, 0, 4, 1, 2, 2, 2, true }, + {WEAPON_SG552, "weapon_sg552", "sg552.mdl", 3500, 1, 0, -1, 4, 2, 4, 4, 2, true }, + {WEAPON_M4A1, "weapon_m4a1", "m4a1.mdl", 3100, 1, 1, 1, 4, 3, 3, 3, 2, true }, + {WEAPON_GALIL, "weapon_galil", "galil.mdl", 2000, 1, 0, 0, 4, -1, 1, 1, 2, true }, + {WEAPON_FAMAS, "weapon_famas", "famas.mdl", 2250, 1, 1, 1, 4, -1, 1, 1, 2, true }, + {WEAPON_AUG, "weapon_aug", "aug.mdl", 3500, 1, 1, 1, 4, 4, 4, 4, 2, true }, + {WEAPON_SCOUT, "weapon_scout", "scout.mdl", 2750, 1, 2, 0, 4, 5, 3, 2, 3, false}, + {WEAPON_AWP, "weapon_awp", "awp.mdl", 4750, 1, 2, 0, 4, 6, 5, 6, 3, false}, + {WEAPON_G3SG1, "weapon_g3sg1", "g3sg1.mdl", 5000, 1, 0, 2, 4, 7, 6, 6, 3, false}, + {WEAPON_SG550, "weapon_sg550", "sg550.mdl", 4200, 1, 1, 1, 4, 8, 5, 5, 3, false}, + {WEAPON_M249, "weapon_m249", "m249.mdl", 5750, 1, 2, 1, 5, 1, 1, 1, 2, true }, + {WEAPON_SHIELD, "weapon_shield", "shield.mdl", 2200, 0, 1, 1, 8, -1, 8, 8, 0, false}, + {0, "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, false} }; // weapon firing delay based on skill (min and max delay for each weapon) FireDelay g_fireDelay[NUM_WEAPONS + 1] = { - {WEAPON_KNIFE, 255, 256, 0.10, {0.0, 0.2, 0.3, 0.4, 0.6, 0.8}, {0.1, 0.3, 0.5, 0.7, 1.0, 1.2}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}, - {WEAPON_USP, 3, 853, 0.15, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_GLOCK, 5, 853, 0.15, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_DEAGLE, 2, 640, 0.20, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_P228, 4, 853, 0.14, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_ELITE, 3, 640, 0.20, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_FIVESEVEN, 4, 731, 0.14, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_M3, 8, 365, 0.86, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_XM1014, 7, 512, 0.15, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_MP5, 4, 731, 0.10, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_TMP, 3, 731, 0.05, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_P90, 4, 731, 0.10, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_MAC10, 3, 731, 0.06, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_UMP45, 4, 731, 0.15, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_AK47, 2, 512, 0.09, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_SG552, 3, 512, 0.11, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_M4A1, 3, 512, 0.08, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_GALIL, 4, 512, 0.09, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_FAMAS, 4, 512, 0.10, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_AUG, 3, 512, 0.11, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_SCOUT, 10, 256, 0.18, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_AWP, 10, 170, 0.22, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_G3SG1, 4, 256, 0.25, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_SG550, 4, 256, 0.25, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_M249, 3, 640, 0.10, {0.0, 0.1, 0.2, 0.3, 0.4, 0.6}, {0.1, 0.2, 0.3, 0.4, 0.5, 0.7}, 0.2, {0.0, 0.0, 0.1, 0.1, 0.2}, {0.1, 0.1, 0.2, 0.2, 0.4}}, - {WEAPON_SHIELD, 0, 256, 0.00, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}}, - {0, 0, 256, 0.00, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 0.0, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}} + { WEAPON_KNIFE, 255, 256, 0.10f,{ 0.0f, 0.2f, 0.3f, 0.4f, 0.6f, 0.8f },{ 0.1f, 0.3f, 0.5f, 0.7f, 1.0f, 1.2f }, 0.0f,{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, + { WEAPON_USP, 3, 853, 0.15f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_GLOCK, 5, 853, 0.15f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_DEAGLE, 2, 640, 0.20f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_P228, 4, 853, 0.14f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_ELITE, 3, 640, 0.20f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_FIVESEVEN, 4, 731, 0.14f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_M3, 8, 365, 0.86f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_XM1014, 7, 512, 0.15f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_MP5, 4, 731, 0.10f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_TMP, 3, 731, 0.05f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_P90, 4, 731, 0.10f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_MAC10, 3, 731, 0.06f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_UMP45, 4, 731, 0.15f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_AK47, 2, 512, 0.09f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_SG552, 3, 512, 0.11f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_M4A1, 3, 512, 0.08f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_GALIL, 4, 512, 0.09f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_FAMAS, 4, 512, 0.10f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_AUG, 3, 512, 0.11f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_SCOUT, 10, 256, 0.18f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_AWP, 10, 170, 0.22f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_G3SG1, 4, 256, 0.25f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_SG550, 4, 256, 0.25f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_M249, 3, 640, 0.10f,{ 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.6f },{ 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.7f }, 0.2f,{ 0.0f, 0.0f, 0.1f, 0.1f, 0.2f },{ 0.1f, 0.1f, 0.2f, 0.2f, 0.4f } }, + { WEAPON_SHIELD, 0, 256, 0.00f,{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, 0.0f,{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }, + { 0, 0, 256, 0.00f,{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, 0.0f,{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } } }; @@ -236,8 +225,8 @@ MenuText g_menus[21] = // main menu { 0x2ff, - "\\yYaPB Main Menu\\w\v\v" - "1. YaPB Control\v" + "\\yMain Menu\\w\v\v" + "1. Control Bots\v" "2. Features\v\v" "3. Fill Server\v" "4. End Round\v\v" @@ -247,7 +236,7 @@ MenuText g_menus[21] = // bot features menu { 0x25f, - "\\yYaPB Features\\w\v\v" + "\\yBots Features\\w\v\v" "1. Weapon Mode Menu\v" "2. Waypoint Menu\v" "3. Select Personality\v\v" @@ -259,7 +248,7 @@ MenuText g_menus[21] = // bot control menu { 0x2ff, - "\\yYaPB Control Menu\\w\v\v" + "\\yBots Control Menu\\w\v\v" "1. Add a Bot, Quick\v" "2. Add a Bot, Specified\v\v" "3. Remove Random Bot\v" @@ -271,7 +260,7 @@ MenuText g_menus[21] = // weapon mode select menu { 0x27f, - "\\yYaPB Weapon Mode\\w\v\v" + "\\yBots Weapon Mode\\w\v\v" "1. Knives only\v" "2. Pistols only\v" "3. Shotguns only\v" @@ -285,7 +274,7 @@ MenuText g_menus[21] = // personality select menu { 0x20f, - "\\yYaPB Personality\\w\v\v" + "\\yBots Personality\\w\v\v" "1. Random\v" "2. Normal\v" "3. Aggressive\v" @@ -293,16 +282,15 @@ MenuText g_menus[21] = "0. Exit" }, - // skill select menu + // difficulty select menu { 0x23f, - "\\yYaPB Skill Level\\w\v\v" - "1. Stupid (0-20)\v" - "2. Newbie (20-40)\v" - "3. Average (40-60)\v" - "4. Advanced (60-80)\v" - "5. Professional (80-99)\v" - "6. Godlike (100)\v\v" + "\\yBots Difficulty Level\\w\v\v" + "1. Newbie\v" + "2. Average\v" + "3. Normal\v" + "4. Professional\v" + "4. Godlike\v" "0. Exit" }, diff --git a/source/interface.cpp b/source/interface.cpp index 9c208ca..8126221 100644 --- a/source/interface.cpp +++ b/source/interface.cpp @@ -11,7 +11,7 @@ // console vars ConVar yb_password ("yb_password", "", VT_PASSWORD); -ConVar yb_password_key ("yb_password_key", "_ybwp"); +ConVar yb_password_key ("yb_password_key", "_ybwp", VT_NOSERVER); ConVar yb_language ("yb_language", "en"); ConVar yb_version ("yb_version", PRODUCT_VERSION, VT_READONLY); @@ -24,9 +24,9 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c if (stricmp (arg0, "addbot") == 0 || stricmp (arg0, "add") == 0) g_botManager->AddBot (arg4, arg1, arg2, arg3, arg5); - // adding one bot with high skill parameters to random team + // adding one bot with high difficuluty parameters to random team if (stricmp (arg0, "addbot_hs") == 0 || stricmp (arg0, "addhs") == 0) - g_botManager->AddBot (arg4, "100", "1", arg3, arg5); + g_botManager->AddBot (arg4, "4", "1", arg3, arg5); // adding one bot with random parameters to terrorist team else if (stricmp (arg0, "addbot_t") == 0 || stricmp (arg0, "add_t") == 0) @@ -122,12 +122,12 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c if (IsNullString (arg1)) return 1; - edict_t *ent = EntityOfIndex (atoi (arg1) - 1); + edict_t *target = EntityOfIndex (atoi (arg1) - 1); - if (IsValidBot (ent)) + if (IsValidBot (target)) { - FakeClientCommand (ent, arg2); - ClientPrint (ent, print_withtag, "Bot %s executing command %s", STRING (ent->v.netname), arg2); + FakeClientCommand (target, arg2); + ClientPrint (ent, print_withtag, "Bot %s executing command %s", STRING (target->v.netname), arg2); } else ClientPrint (ent, print_withtag, "Player is not BOT!"); @@ -280,7 +280,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c // waypoint manimupulation (really obsolete, can be edited through menu) (supported only on listen server) else if (stricmp (arg0, "waypoint") == 0 || stricmp (arg0, "wp") == 0 || stricmp (arg0, "wpt") == 0) { - if (IsDedicatedServer () || FNullEnt (g_hostEntity)) + if (IsDedicatedServer () || IsEntityNull (g_hostEntity)) return 2; // enables or disable waypoint displaying @@ -325,11 +325,11 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c if (stricmp (arg2, "on") == 0) { - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_start"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_start"))) spawnEntity->v.effects &= ~EF_NODRAW; - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_deathmatch"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_deathmatch"))) spawnEntity->v.effects &= ~EF_NODRAW; - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_vip_start"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_vip_start"))) spawnEntity->v.effects &= ~EF_NODRAW; ServerCommand ("mp_roundtime 9"); // reset round time to maximum @@ -338,11 +338,11 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c } else if (stricmp (arg2, "off") == 0) { - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_start"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_start"))) spawnEntity->v.effects |= EF_NODRAW; - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_deathmatch"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_player_deathmatch"))) spawnEntity->v.effects |= EF_NODRAW; - while (!FNullEnt (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_vip_start"))) + while (!IsEntityNull (spawnEntity = FIND_ENTITY_BY_CLASSNAME (spawnEntity, "info_vip_start"))) spawnEntity->v.effects |= EF_NODRAW; } } @@ -448,7 +448,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c // path waypoint editing system (supported only on listen server) else if (stricmp (arg0, "pathwaypoint") == 0 || stricmp (arg0, "path") == 0 || stricmp (arg0, "pwp") == 0) { - if (IsDedicatedServer () || FNullEnt (g_hostEntity)) + if (IsDedicatedServer () || IsEntityNull (g_hostEntity)) return 2; // opens path creation menu @@ -479,7 +479,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c // automatic waypoint handling (supported only on listen server) else if (stricmp (arg0, "autowaypoint") == 0 || stricmp (arg0, "autowp") == 0) { - if (IsDedicatedServer () || FNullEnt (g_hostEntity)) + if (IsDedicatedServer () || IsEntityNull (g_hostEntity)) return 2; // enable autowaypointing @@ -500,7 +500,7 @@ int BotCommandHandler (edict_t *ent, const char *arg0, const char *arg1, const c // experience system handling (supported only on listen server) else if (stricmp (arg0, "experience") == 0 || stricmp (arg0, "exp") == 0) { - if (IsDedicatedServer () || FNullEnt (g_hostEntity)) + if (IsDedicatedServer () || IsEntityNull (g_hostEntity)) return 2; // write experience table (and visibility table) to hard disk @@ -557,10 +557,9 @@ void ParseVoiceEvent (const String &base, int type, float timeToRepeat) void InitConfig (void) { File fp; - char command[80], line[256]; + char line[256]; KeywordFactory replyKey; - int chatType = -1; // fixes for crashing if configs couldn't be accessed g_chatFactory.SetSize (CHAT_TOTAL); @@ -593,47 +592,50 @@ void InitConfig (void) // CHAT SYSTEM CONFIG INITIALIZATION if (OpenConfig ("chat.cfg", "Chat file not found.", &fp, true)) { + char section[80]; + int chatType = -1; + while (fp.GetBuffer (line, 255)) { SKIP_COMMENTS (); - strcpy (command, GetField (line, 0, 1)); + strcpy (section, GetField (line, 0, 1)); - if (strcmp (command, "[KILLED]") == 0) + if (strcmp (section, "[KILLED]") == 0) { chatType = 0; continue; } - else if (strcmp (command, "[BOMBPLANT]") == 0) + else if (strcmp (section, "[BOMBPLANT]") == 0) { chatType = 1; continue; } - else if (strcmp (command, "[DEADCHAT]") == 0) + else if (strcmp (section, "[DEADCHAT]") == 0) { chatType = 2; continue; } - else if (strcmp (command, "[REPLIES]") == 0) + else if (strcmp (section, "[REPLIES]") == 0) { chatType = 3; continue; } - else if (strcmp (command, "[UNKNOWN]") == 0) + else if (strcmp (section, "[UNKNOWN]") == 0) { chatType = 4; continue; } - else if (strcmp (command, "[TEAMATTACK]") == 0) + else if (strcmp (section, "[TEAMATTACK]") == 0) { chatType = 5; continue; } - else if (strcmp (command, "[WELCOME]") == 0) + else if (strcmp (section, "[WELCOME]") == 0) { chatType = 6; continue; } - else if (strcmp (command, "[TEAMKILL]") == 0) + else if (strcmp (section, "[TEAMKILL]") == 0) { chatType = 7; continue; @@ -777,64 +779,6 @@ void InitConfig (void) for (int i = 0; i < NUM_WEAPONS; i++) g_carefulWeaponPrefs[i] = splitted[i].ToInt (); } - else if (pair[0].Contains ("Skill")) - { - if (splitted.GetElementNumber () != 8) - AddLogEntry (true, LL_FATAL, "%s entry in general config is not valid.", pair[0].GetBuffer ()); - - int parserState = 0; - - if (pair[0].Contains ("Stupid")) - parserState = 0; - else if (pair[0].Contains ("Newbie")) - parserState = 1; - else if (pair[0].Contains ("Average")) - parserState = 2; - else if (pair[0].Contains ("Advanced")) - parserState = 3; - else if (pair[0].Contains ("Professional")) - parserState = 4; - else if (pair[0].Contains ("Godlike")) - parserState = 5; - - for (int i = 0; i < 8; i++) - { - switch (i) - { - case 0: - g_skillTab[parserState].minSurpriseTime = splitted[i].ToFloat (); - break; - - case 1: - g_skillTab[parserState].maxSurpriseTime = splitted[i].ToFloat (); - break; - - case 2: - g_skillTab[parserState].minTurnSpeed = splitted[i].ToFloat (); - break; - - case 3: - g_skillTab[parserState].maxTurnSpeed = splitted[i].ToFloat (); - break; - - case 4: - g_skillTab[parserState].headshotFrequency = splitted[i].ToInt (); - break; - - case 5: - g_skillTab[parserState].heardShootThruProb = splitted[i].ToInt (); - break; - - case 6: - g_skillTab[parserState].seenShootThruProb = splitted[i].ToInt (); - break; - - case 7: - g_skillTab[parserState].recoilAmount = splitted[i].ToInt (); - break; - } - } - } } fp.Close (); } @@ -1013,6 +957,8 @@ void InitConfig (void) g_weaponPrefs[PERSONALITY_NORMAL] = reinterpret_cast (&g_normalWeaponPrefs); g_weaponPrefs[PERSONALITY_RUSHER] = reinterpret_cast (&g_rusherWeaponPrefs); g_weaponPrefs[PERSONALITY_CAREFUL] = reinterpret_cast (&g_carefulWeaponPrefs); + + g_timePerSecondUpdate = 0.0f; } void CommandHandler_NotMM (void) @@ -1772,27 +1718,23 @@ void ClientCommand (edict_t *ent) switch (selection) { case 1: - g_storeAddbotVars[0] = g_randGen.Long (0, 20); + g_storeAddbotVars[0] = 0; break; case 2: - g_storeAddbotVars[0] = g_randGen.Long (20, 40); + g_storeAddbotVars[0] = 1; break; case 3: - g_storeAddbotVars[0] = g_randGen.Long (40, 60); + g_storeAddbotVars[0] = 2; break; case 4: - g_storeAddbotVars[0] = g_randGen.Long (60, 80); + g_storeAddbotVars[0] = 3; break; case 5: - g_storeAddbotVars[0] = g_randGen.Long (80, 99); - break; - - case 6: - g_storeAddbotVars[0] = 100; + g_storeAddbotVars[0] = 4; break; case 10: @@ -2102,17 +2044,17 @@ void ClientCommand (edict_t *ent) if (!(g_clients[i].flags & CF_USED) || (team != -1 && team != g_clients[i].team) || isAlive != IsAlive (g_clients[i].ent)) continue; - Bot *bot = g_botManager->GetBot (i); + Bot *target = g_botManager->GetBot (i); - if (bot != NULL) + if (target != NULL) { - bot->m_sayTextBuffer.entityIndex = IndexOfEntity (ent); + target->m_sayTextBuffer.entityIndex = IndexOfEntity (ent); if (IsNullString (CMD_ARGS ())) continue; - strcpy (bot->m_sayTextBuffer.sayText, CMD_ARGS ()); - bot->m_sayTextBuffer.timeNextChat = GetWorldTime () + bot->m_sayTextBuffer.chatDelay; + strcpy (target->m_sayTextBuffer.sayText, CMD_ARGS ()); + target->m_sayTextBuffer.timeNextChat = GetWorldTime () + target->m_sayTextBuffer.chatDelay; } } } @@ -2227,7 +2169,7 @@ void StartFrame (void) { edict_t *player = EntityOfIndex (i + 1); - if (!FNullEnt (player) && (player->v.flags & FL_CLIENT)) + if (!IsEntityNull (player) && (player->v.flags & FL_CLIENT)) { g_clients[i].ent = player; g_clients[i].flags |= CF_USED; @@ -2253,13 +2195,12 @@ void StartFrame (void) g_clients[i].ent = NULL; } } - static float secondTimer = 0.0; // **** AI EXECUTION STARTS **** g_botManager->Think (); // **** AI EXECUTION FINISH **** - if (!IsDedicatedServer () && !FNullEnt (g_hostEntity)) + if (!IsDedicatedServer () && !IsEntityNull (g_hostEntity)) { if (g_waypointOn) g_waypoint->Think (); @@ -2268,14 +2209,16 @@ void StartFrame (void) } g_botManager->SetDeathMsgState (false); - if (secondTimer < GetWorldTime ()) + if (g_timePerSecondUpdate <= GetWorldTime ()) { + g_botManager->CalculatePingOffsets (); + for (int i = 0; i < GetMaxClients (); i++) { edict_t *player = EntityOfIndex (i + 1); // code below is executed only on dedicated server - if (IsDedicatedServer () && !FNullEnt (player) && (player->v.flags & FL_CLIENT) && !(player->v.flags & FL_FAKECLIENT)) + if (IsDedicatedServer () && !IsEntityNull (player) && (player->v.flags & FL_CLIENT) && !(player->v.flags & FL_FAKECLIENT)) { if (g_clients[i].flags & CF_ADMIN) { @@ -2305,7 +2248,7 @@ void StartFrame (void) if (csdm_active != NULL && csdm_active->value > 0) yb_csdm_mode.SetInt (mp_freeforall != NULL && mp_freeforall->value > 0 ? 2 : 1); } - g_botManager->CalculatePingOffsets (); + g_timePerSecondUpdate = GetWorldTime () + 1.0f; } extern ConVar yb_danger_factor; @@ -2313,8 +2256,6 @@ void StartFrame (void) if (yb_danger_factor.GetFloat () >= 4096) yb_danger_factor.SetFloat (4096.0); - secondTimer = GetWorldTime () + 1.5; - if (g_bombPlanted) g_waypoint->SetBombPosition (); } @@ -2486,7 +2427,7 @@ void pfnMessageBegin (int msgDest, int msgType, const float *origin, edict_t *ed g_netMsg->HandleMessageIfRequired (msgType, NETMSG_WEAPONLIST); - if (!FNullEnt (ed)) + if (!IsEntityNull (ed)) { int index = g_botManager->GetIndex (ed); @@ -2626,11 +2567,6 @@ void pfnWriteCoord (float value) void pfnWriteString (const char *sz) { - Bot *bot = g_botManager->FindOneValidAliveBot (); - - if (bot != NULL && IsAlive (bot->GetEntity ())) - bot->HandleChatterMessage (sz); - // if this message is for a bot, call the client message function... g_netMsg->Execute ((void *) sz); @@ -2691,16 +2627,16 @@ const char *pfnCmd_Args (void) if (strncmp ("say ", g_fakeArgv, 4) == 0) { if (g_isMetamod) - RETURN_META_VALUE (MRES_SUPERCEDE, g_fakeArgv + 4); + RETURN_META_VALUE (MRES_SUPERCEDE, &g_fakeArgv[4]); - return g_fakeArgv + 4; // skip the "say" bot client command + return &g_fakeArgv[4]; // skip the "say" bot client command } else if (strncmp ("say_team ", g_fakeArgv, 9) == 0) { if (g_isMetamod) - RETURN_META_VALUE (MRES_SUPERCEDE, g_fakeArgv + 9); + RETURN_META_VALUE (MRES_SUPERCEDE, &g_fakeArgv[9]); - return g_fakeArgv + 9; // skip the "say_team" bot client command + return &g_fakeArgv[9]; // skip the "say_team" bot client command } if (g_isMetamod) @@ -3172,7 +3108,6 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t g_convarWrapper->PushRegisteredConVarsToEngine (); ModSupport_t *knownMod = NULL; - char gameDLLName[256]; for (int i = 0; s_supportedMods[i].name; i++) { @@ -3200,6 +3135,7 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t if (g_isMetamod) return; // we should stop the attempt for loading the real gamedll, since metamod handle this for us + char gameDLLName[256]; sprintf (gameDLLName, "%s/dlls/%s", knownMod->name, #if defined (PLATFORM_WIN32) diff --git a/source/manager.cpp b/source/manager.cpp index 91e7d36..c5916d6 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -14,15 +14,13 @@ ConVar yb_autovacate ("yb_autovacate", "-1"); ConVar yb_quota ("yb_quota", "0"); ConVar yb_quota_match ("yb_quota_match", "0"); ConVar yb_quota_match_max ("yb_quota_match_max", "0"); -ConVar yb_join_after_player ("yb_join_after_player", "0"); +ConVar yb_join_after_player ("yb_join_after_player", "0", VT_NOSERVER); ConVar yb_join_team ("yb_join_team", "any"); -ConVar yb_name_prefix ("yb_name_prefix", ""); -ConVar yb_minskill ("yb_minskill", "60"); -ConVar yb_maxskill ("yb_maxskill", "100"); +ConVar yb_name_prefix ("yb_name_prefix", "", VT_NOSERVER); +ConVar yb_difficulty ("yb_difficulty", "4"); -ConVar yb_skill_tags ("yb_skill_tags", "0"); ConVar yb_latency_display ("yb_latency_display", "2"); BotManager::BotManager (void) @@ -66,9 +64,9 @@ void BotManager::CallGameEntity (entvars_t *vars) (*playerFunction) (vars); } -int BotManager::CreateBot (String name, int skill, int personality, int team, int member) +int BotManager::CreateBot (String name, int difficulty, int personality, int team, int member) { - // this function completely prepares bot entity (edict) for creation, creates team, skill, sets name etc, and + // this function completely prepares bot entity (edict) for creation, creates team, difficulty, sets name etc, and // then sends result to bot constructor @@ -86,11 +84,14 @@ int BotManager::CreateBot (String name, int skill, int personality, int team, in return 0; } - if (skill < 0 || skill > 100) - skill = g_randGen.Long (yb_minskill.GetInt (), yb_maxskill.GetInt ()); + if (difficulty < 0 || difficulty > 4) + difficulty = yb_difficulty.GetInt (); - if (skill > 100 || skill < 0) - skill = g_randGen.Long (0, 100); + if (difficulty < 0 || difficulty > 4) + { + difficulty = g_randGen.Long (3, 4); + yb_difficulty.SetInt (difficulty); + } if (personality < 0 || personality > 2) { @@ -117,13 +118,16 @@ int BotManager::CreateBot (String name, int skill, int personality, int team, in if (nameFound) break; - BotName *name = &g_botNames.GetRandomElement (); + BotName *pickedName = &g_botNames.GetRandomElement (); - if (name == NULL || (name != NULL && name->used)) + if (pickedName == NULL) continue; - name->used = nameFound = true; - strcpy (outputName, name->name); + if (pickedName->used) + continue; + + pickedName->used = nameFound = true; + strcpy (outputName, pickedName->name); } } else @@ -132,25 +136,19 @@ int BotManager::CreateBot (String name, int skill, int personality, int team, in else strncpy (outputName, name, 21); - if (!IsNullString (yb_name_prefix.GetString ()) || yb_skill_tags.GetBool ()) + if (!IsNullString (yb_name_prefix.GetString ())) { char prefixedName[33]; // temp buffer for storing modified name if (!IsNullString (yb_name_prefix.GetString ())) sprintf (prefixedName, "%s %s", yb_name_prefix.GetString (), outputName); - else if (yb_skill_tags.GetBool ()) - sprintf (prefixedName, "%s (%d)", outputName, skill); - - else if (!IsNullString (yb_name_prefix.GetString ()) && yb_skill_tags.GetBool ()) - sprintf (prefixedName, "%s %s (%d)", yb_name_prefix.GetString (), outputName, skill); - // buffer has been modified, copy to real name if (!IsNullString (prefixedName)) strcpy (outputName, prefixedName); } - if (FNullEnt ((bot = (*g_engfuncs.pfnCreateFakeClient) (outputName)))) + if (IsEntityNull ((bot = (*g_engfuncs.pfnCreateFakeClient) (outputName)))) { CenterPrint ("Maximum players reached (%d/%d). Unable to create Bot.", GetMaxClients (), GetMaxClients ()); return 2; @@ -161,12 +159,12 @@ int BotManager::CreateBot (String name, int skill, int personality, int team, in InternalAssert (index >= 0 && index <= 32); // check index InternalAssert (m_bots[index] == NULL); // check bot slot - m_bots[index] = new Bot (bot, skill, personality, team, member); + m_bots[index] = new Bot (bot, difficulty, personality, team, member); if (m_bots == NULL) TerminateOnMalloc (); - ServerPrint ("Connecting Bot... (Skill %d)", skill); + ServerPrint ("Connecting Bot..."); return 1; } @@ -174,7 +172,7 @@ int BotManager::CreateBot (String name, int skill, int personality, int team, in int BotManager::GetIndex (edict_t *ent) { // this function returns index of bot (using own bot array) - if (FNullEnt (ent)) + if (IsEntityNull (ent)) return -1; int index = IndexOfEntity (ent) - 1; @@ -257,7 +255,7 @@ void BotManager::Think (void) } } -void BotManager::AddBot (const String &name, int skill, int personality, int team, int member) +void BotManager::AddBot (const String &name, int difficulty, int personality, int team, int member) { // this function putting bot creation process to queue to prevent engine crashes @@ -265,7 +263,7 @@ void BotManager::AddBot (const String &name, int skill, int personality, int tea // fill the holder bot.name = name; - bot.skill = skill; + bot.difficulty = difficulty; bot.personality = personality; bot.team = team; bot.member = member; @@ -278,18 +276,18 @@ void BotManager::AddBot (const String &name, int skill, int personality, int tea yb_quota.SetInt (GetBotsNum () + 1); } -void BotManager::AddBot (String name, String skill, String personality, String team, String member) +void BotManager::AddBot (String name, String difficulty, String personality, String team, String member) { // this function is same as the function above, but accept as parameters string instead of integers CreateQueue bot; const String &any = "*"; - bot.name = (name.IsEmpty () || (name == any)) ? String ("\0") : name; - bot.skill = (skill.IsEmpty () || (skill == any)) ? -1 : skill.ToInt (); - bot.team = (team.IsEmpty () || (team == any)) ? -1 : team.ToInt (); - bot.member = (member.IsEmpty () || (member == any)) ? -1 : member.ToInt (); - bot.personality = (personality.IsEmpty () || (personality == any)) ? -1 : personality.ToInt (); + bot.name = (name.IsEmpty () || name == any) ? String ("\0") : name; + bot.difficulty = (difficulty.IsEmpty () || difficulty == any) ? -1 : difficulty.ToInt (); + bot.team = (team.IsEmpty () || team == any) ? -1 : team.ToInt (); + bot.member = (member.IsEmpty () || member == any) ? -1 : member.ToInt (); + bot.personality = (personality.IsEmpty () || personality == any) ? -1 : personality.ToInt (); m_creationTab.Push (bot); @@ -320,12 +318,12 @@ void BotManager::MaintainBotQuota (void) if (!m_creationTab.IsEmpty () && m_maintainTime < GetWorldTime ()) { CreateQueue last = m_creationTab.Pop (); - int resultOfCall = CreateBot (last.name, last.skill, last.personality, last.team, last.member); + int resultOfCall = CreateBot (last.name, last.difficulty, last.personality, last.team, last.member); // check the result of creation if (resultOfCall == 0) { - m_creationTab.RemoveAll (); // something worng with waypoints, reset tab of creation + m_creationTab.RemoveAll (); // something wrong with waypoints, reset tab of creation yb_quota.SetInt (0); // reset quota } else if (resultOfCall == 2) @@ -392,7 +390,7 @@ void BotManager::InitQuota (void) m_creationTab.RemoveAll (); } -void BotManager::FillServer (int selection, int personality, int skill, int numToAdd) +void BotManager::FillServer (int selection, int personality, int difficulty, int numToAdd) { // this function fill server with bots, with specified team & personality @@ -420,26 +418,7 @@ void BotManager::FillServer (int selection, int personality, int skill, int numT int toAdd = numToAdd == -1 ? GetMaxClients () - (GetHumansNum () + GetBotsNum ()) : numToAdd; for (int i = 0; i <= toAdd; i++) - { - // since we got constant skill from menu (since creation process call automatic), we need to manually - // randomize skill here, on given skill there. - int randomizedSkill = 0; - - if (skill >= 0 && skill <= 20) - randomizedSkill = g_randGen.Long (0, 20); - else if (skill > 20 && skill <= 40) - randomizedSkill = g_randGen.Long (20, 40); - else if (skill > 40 && skill <= 60) - randomizedSkill = g_randGen.Long (40, 60); - else if (skill > 60 && skill <= 80) - randomizedSkill = g_randGen.Long (60, 80); - else if (skill > 80 && skill <= 99) - randomizedSkill = g_randGen.Long (80, 99); - else if (skill == 100) - randomizedSkill = skill; - - AddBot ("", randomizedSkill, personality, selection, -1); - } + AddBot ("", difficulty, personality, selection, -1); yb_quota.SetInt (toAdd); yb_quota_match.SetInt (0); @@ -503,16 +482,16 @@ void BotManager::RemoveMenu (edict_t *ent, int selection) for (int i = ((selection - 1) * 8); i < selection * 8; i++) { - if ((m_bots[i] != NULL) && !FNullEnt (m_bots[i]->GetEntity ())) + if ((m_bots[i] != NULL) && !IsEntityNull (m_bots[i]->GetEntity ())) { validSlots |= 1 << (i - ((selection - 1) * 8)); sprintf (buffer, "%s %1.1d. %s%s\n", buffer, i - ((selection - 1) * 8) + 1, STRING (m_bots[i]->pev->netname), GetTeam (m_bots[i]->GetEntity ()) == TEAM_CF ? " \\y(CT)\\w" : " \\r(T)\\w"); } else - sprintf (buffer, "%s\\d %1.1d. Not a YaPB\\w\n", buffer, i - ((selection - 1) * 8) + 1); + sprintf (buffer, "%s\\d %1.1d. Not a Bot\\w\n", buffer, i - ((selection - 1) * 8) + 1); } - sprintf (tempBuffer, "\\yYaPB Remove Menu (%d/4):\\w\n\n%s\n%s 0. Back", selection, buffer, (selection == 4) ? "" : " 9. More...\n"); + sprintf (tempBuffer, "\\yBots Remove Menu (%d/4):\\w\n\n%s\n%s 0. Back", selection, buffer, (selection == 4) ? "" : " 9. More...\n"); switch (selection) { @@ -633,7 +612,7 @@ void BotManager::ListBots (void) { // this function list's bots currently playing on the server - ServerPrintNoTag ("%-3.5s %-9.13s %-17.18s %-3.4s %-3.4s %-3.4s", "index", "name", "personality", "team", "skill", "frags"); + ServerPrintNoTag ("%-3.5s %-9.13s %-17.18s %-3.4s %-3.4s %-3.4s", "index", "name", "personality", "team", "difficulty", "frags"); for (int i = 0; i < GetMaxClients (); i++) { @@ -645,7 +624,7 @@ void BotManager::ListBots (void) Bot *bot = GetBot (player); if (bot != NULL) - ServerPrintNoTag ("[%-3.1d] %-9.13s %-17.18s %-3.4s %-3.1d %-3.1d", i, STRING (player->v.netname), bot->m_personality == PERSONALITY_RUSHER ? "rusher" : bot->m_personality == PERSONALITY_NORMAL ? "normal" : "careful", GetTeam (player) != 0 ? "CT" : "T", bot->m_skill, static_cast (player->v.frags)); + ServerPrintNoTag ("[%-3.1d] %-9.13s %-17.18s %-3.4s %-3.1d %-3.1d", i, STRING (player->v.netname), bot->m_personality == PERSONALITY_RUSHER ? "rusher" : bot->m_personality == PERSONALITY_NORMAL ? "normal" : "careful", GetTeam (player) != 0 ? "CT" : "T", bot->m_difficulty, static_cast (player->v.frags)); } } } @@ -735,10 +714,7 @@ void BotManager::Free (void) // this function free all bots slots (used on server shutdown) for (int i = 0; i < 32; i++) - { - if (m_bots[i] != NULL) - Free (i); - } + Free (i); } void BotManager::Free (int index) @@ -749,7 +725,7 @@ void BotManager::Free (int index) m_bots[index] = NULL; } -Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) +Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) { // this function does core operation of creating bot, it's called by CreateBot (), // when bot setup completed, (this is a bot class constructor) @@ -759,7 +735,7 @@ Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) memset (this, 0, sizeof (Bot)); - pev = VARS (bot); + pev = &bot->v; if (bot->pvPrivateData != NULL) FREE_PRIVATE (bot); @@ -771,18 +747,7 @@ Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) BotManager::CallGameEntity (&bot->v); // set all info buffer keys for this bot - char *buffer = GET_INFOKEYBUFFER (bot); - - SET_CLIENT_KEYVALUE (clientIndex, buffer, "model", ""); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "rate", "3500.000000"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_updaterate", "20"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_lw", "0"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_lc", "0"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "tracker", "0"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "cl_dlmax", "128"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "friends", "0"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "dm", "0"); - SET_CLIENT_KEYVALUE (clientIndex, buffer, "_ah", "0"); + char *buffer = GET_INFOKEYBUFFER (bot);; SET_CLIENT_KEYVALUE (clientIndex, buffer, "_vgui_menus", "0"); if (g_gameVersion != CSV_OLD && yb_latency_display.GetInt () == 1) @@ -791,6 +756,9 @@ Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) rejectReason[0] = 0; // reset the reject reason template string MDLL_ClientConnect (bot, "BOT", FormatBuffer ("127.0.0.%d", IndexOfEntity (bot) + 100), rejectReason); + memset (&m_pingOffset, 0, sizeof (m_pingOffset)); + memset (&m_ping, 0, sizeof (m_ping)); + if (!IsNullString (rejectReason)) { AddLogEntry (true, LL_WARNING, "Server refused '%s' connection (%s)", STRING (bot->v.netname), rejectReason); @@ -816,17 +784,24 @@ Bot::Bot (edict_t *bot, int skill, int personality, int team, int member) m_sayTextBuffer.chatProbability = g_randGen.Long (1, 100); m_notKilled = false; - m_skill = skill; m_weaponBurstMode = BM_OFF; + m_difficulty = difficulty; + + if (difficulty < 0 || difficulty > 4) + { + difficulty = g_randGen.Long (3, 4); + yb_difficulty.SetInt (difficulty); + } m_lastThinkTime = GetWorldTime () - 0.1f; m_frameInterval = GetWorldTime (); + m_timePeriodicUpdate = 0.0f; bot->v.idealpitch = bot->v.v_angle.x; bot->v.ideal_yaw = bot->v.v_angle.y; - bot->v.yaw_speed = g_randGen.Float (g_skillTab[m_skill / 20].minTurnSpeed, g_skillTab[m_skill / 20].maxTurnSpeed); - bot->v.pitch_speed = g_randGen.Float (g_skillTab[m_skill / 20].minTurnSpeed, g_skillTab[m_skill / 20].maxTurnSpeed); + bot->v.yaw_speed = g_randGen.Float (m_difficulty * 40, m_difficulty * 45); + bot->v.pitch_speed = g_randGen.Float (m_difficulty * 40, m_difficulty * 45); switch (personality) { @@ -1050,8 +1025,7 @@ void Bot::NewRound (void) m_position = nullvec; m_liftTravelPos = nullvec; - m_idealReactionTime = g_skillTab[m_skill / 20].minSurpriseTime; - m_actualReactionTime = g_skillTab[m_skill / 20].minSurpriseTime; + SetIdealReactionTimes (true); m_targetEntity = NULL; m_tasks = NULL; @@ -1075,7 +1049,7 @@ void Bot::NewRound (void) m_grenadeCheckTime = 0.0; m_isUsingGrenade = false; - m_skillOffset = static_cast ((100 - m_skill) / 100.0); + m_breakableCheckTime = 0.0f; m_blindButton = 0; m_blindTime = 0.0; m_jumpTime = 0.0; @@ -1087,6 +1061,7 @@ void Bot::NewRound (void) m_sayTextBuffer.sayText[0] = 0x0; m_buyState = 0; + m_lastEquipTime = 0.0f; if (!m_notKilled) // if bot died, clear all weapon stuff and force buying again { @@ -1117,6 +1092,8 @@ void Bot::NewRound (void) m_radioEntity = NULL; m_radioOrder = 0; m_defendedBomb = false; + m_defendHostage = false; + m_headedTime = 0.0f; m_timeLogoSpray = GetWorldTime () + g_randGen.Float (0.5, 2.0); m_spawnTime = GetWorldTime (); @@ -1153,7 +1130,7 @@ void Bot::Kill (void) edict_t *hurtEntity = (*g_engfuncs.pfnCreateNamedEntity) (MAKE_STRING ("trigger_hurt")); - if (FNullEnt (hurtEntity)) + if (IsEntityNull (hurtEntity)) return; hurtEntity->v.classname = MAKE_STRING (g_weaponDefs[m_currentWeapon].className); @@ -1199,10 +1176,12 @@ void Bot::StartGame (void) if (m_startAction == GSM_TEAM_SELECT) { m_startAction = GSM_IDLE; // switch back to idle + + char teamJoin = yb_join_team.GetString ()[0]; - if (yb_join_team.GetString ()[0] == 'C' || yb_join_team.GetString ()[0] == 'c') + if (teamJoin == 'C' || teamJoin == 'c') m_wantedTeam = 2; - else if (yb_join_team.GetString ()[0] == 'T' || yb_join_team.GetString ()[0] == 't') + else if (teamJoin == 'T' || teamJoin == 't') m_wantedTeam = 1; if (m_wantedTeam != 1 && m_wantedTeam != 2) @@ -1276,7 +1255,7 @@ void BotManager::CalculatePingOffsets (void) if (bot == NULL) continue; - int botPing = g_randGen.Long (averagePing - averagePing * 0.2f, averagePing + averagePing * 0.2f) + g_randGen.Long (bot->m_skill / 100 * 0.5, bot->m_skill / 100); + int botPing = g_randGen.Long (averagePing - averagePing * 0.2f, averagePing + averagePing * 0.2f) + g_randGen.Long (bot->m_difficulty + 3, bot->m_difficulty + 6) + 10; if (botPing <= 5) botPing = g_randGen.Long (10, 23); @@ -1303,14 +1282,13 @@ void BotManager::SendPingDataOffsets (edict_t *to) if (yb_latency_display.GetInt () != 2) return; - if (!IsValidPlayer (to) || IsValidBot (to)) + if (IsEntityNull (to)) return; - if (!((to->v.button & IN_SCORE) || (to->v.oldbuttons & IN_SCORE))) + if (!(to->v.flags & FL_CLIENT) && !(((to->v.button & IN_SCORE) || !(to->v.oldbuttons & IN_SCORE)))) return; static int sending; - sending = 0; // missing from sdk static const int SVC_PINGS = 17; diff --git a/source/navigate.cpp b/source/navigate.cpp index da725a9..1843a89 100644 --- a/source/navigate.cpp +++ b/source/navigate.cpp @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -9,50 +9,51 @@ #include -ConVar yb_danger_factor ("yb_danger_factor", "800"); +ConVar yb_danger_factor ("yb_danger_factor", "900", VT_NOSERVER); -ConVar yb_aim_method ("yb_aim_method", "3"); +ConVar yb_aim_method ("yb_aim_method", "3", VT_NOSERVER); -ConVar yb_aim_damper_coefficient_x ("yb_aim_damper_coefficient_x", "0.22"); -ConVar yb_aim_damper_coefficient_y ("yb_aim_damper_coefficient_y", "0.22"); +ConVar yb_aim_damper_coefficient_x ("yb_aim_damper_coefficient_x", "0.22", VT_NOSERVER); +ConVar yb_aim_damper_coefficient_y ("yb_aim_damper_coefficient_y", "0.22", VT_NOSERVER); -ConVar yb_aim_deviation_x ("yb_aim_deviation_x", "2.0"); -ConVar yb_aim_deviation_y ("yb_aim_deviation_y", "1.0"); +ConVar yb_aim_deviation_x ("yb_aim_deviation_x", "2.0", VT_NOSERVER); +ConVar yb_aim_deviation_y ("yb_aim_deviation_y", "1.0", VT_NOSERVER); -ConVar yb_aim_influence_x_on_y ("yb_aim_influence_x_on_y", "0.25"); -ConVar yb_aim_influence_y_on_x ("yb_aim_influence_y_on_x", "0.17"); +ConVar yb_aim_influence_x_on_y ("yb_aim_influence_x_on_y", "0.26", VT_NOSERVER); +ConVar yb_aim_influence_y_on_x ("yb_aim_influence_y_on_x", "0.18", VT_NOSERVER); -ConVar yb_aim_notarget_slowdown_ratio ("yb_aim_notarget_slowdown_ratio", "0.5"); -ConVar yb_aim_offset_delay ("yb_aim_offset_delay", "1.2"); +ConVar yb_aim_notarget_slowdown_ratio ("yb_aim_notarget_slowdown_ratio", "0.6", VT_NOSERVER); +ConVar yb_aim_offset_delay ("yb_aim_offset_delay", "0.5", VT_NOSERVER); -ConVar yb_aim_spring_stiffness_x ("yb_aim_spring_stiffness_x", "13.0"); -ConVar yb_aim_spring_stiffness_y ("yb_aim_spring_stiffness_y", "13.0"); +ConVar yb_aim_spring_stiffness_x ("yb_aim_spring_stiffness_x", "15.0", VT_NOSERVER); +ConVar yb_aim_spring_stiffness_y ("yb_aim_spring_stiffness_y", "14.0", VT_NOSERVER); -ConVar yb_aim_target_anticipation_ratio ("yb_aim_target_anticipation_ratio", "3.0"); +ConVar yb_aim_target_anticipation_ratio ("yb_aim_target_anticipation_ratio", "5.0", VT_NOSERVER); int Bot::FindGoal (void) { // chooses a destination (goal) waypoint for a bot - if (m_team == TEAM_TF && (g_mapType & MAP_DE)) + if (!g_bombPlanted && m_team == TEAM_TF && (g_mapType & MAP_DE)) { edict_t *pent = NULL; - while (!FNullEnt (pent = FIND_ENTITY_BY_STRING (pent, "classname", "weaponbox"))) + while (!IsEntityNull (pent = FIND_ENTITY_BY_STRING (pent, "classname", "weaponbox"))) { if (strcmp (STRING (pent->v.model), "models/w_backpack.mdl") == 0) { int index = g_waypoint->FindNearest (GetEntityOrigin (pent)); if (index >= 0 && index < g_numWaypoints) - return index; + return m_loosedBombWptIndex = index; break; } } } + int tactic; + // path finding behaviour depending on map type - int tactic; int offensive; int defensive; int goalDesire; @@ -84,7 +85,7 @@ int Bot::FindGoal (void) tactic = 3; goto TacticChoosen; } - else if (HasHostage () && m_team == TEAM_CF) + else if (m_team == TEAM_CF && HasHostage ()) { tactic = 2; offensiveWpts = g_waypoint->m_rescuePoints; @@ -119,7 +120,7 @@ int Bot::FindGoal (void) } return m_chosenGoalIndex = ChooseBombWaypoint (); } - defensive += 40.0f; + defensive += 25.0f; offensive -= 25.0f; } else if ((g_mapType & MAP_DE) && m_team == TEAM_TF && g_timeRoundStart + 10.0f < GetWorldTime ()) @@ -129,7 +130,7 @@ int Bot::FindGoal (void) return m_chosenGoalIndex = FindDefendWaypoint (g_waypoint->GetBombPosition ()); } - goalDesire = g_randGen.Long (0, 100) + offensive; + goalDesire = g_randGen.Long (0, 100 + (offensive * 0.5)) + offensive; forwardDesire = g_randGen.Long (0, 100) + offensive; campDesire = g_randGen.Long (0, 100) + defensive; backoffDesire = g_randGen.Long (0, 100) + defensive; @@ -145,11 +146,13 @@ int Bot::FindGoal (void) tacticChoice = campDesire; tactic = 1; } + if (forwardDesire > tacticChoice) { tacticChoice = forwardDesire; tactic = 2; } + if (goalDesire > tacticChoice) tactic = 3; @@ -172,7 +175,7 @@ TacticChoosen: for (int i = 0; i < 4; i++) { goalChoices[i] = g_waypoint->m_sniperPoints.GetRandomElement (); - InternalAssert ((goalChoices[i] >= 0) && (goalChoices[i] < g_numWaypoints)); + InternalAssert (goalChoices[i] >= 0 && goalChoices[i] < g_numWaypoints); } } else @@ -180,7 +183,7 @@ TacticChoosen: for (int i = 0; i < 4; i++) { goalChoices[i] = g_waypoint->m_campPoints.GetRandomElement (); - InternalAssert ((goalChoices[i] >= 0) && (goalChoices[i] < g_numWaypoints)); + InternalAssert (goalChoices[i] >= 0 && goalChoices[i] < g_numWaypoints); } } } @@ -189,15 +192,21 @@ TacticChoosen: for (int i = 0; i < 4; i++) { goalChoices[i] = offensiveWpts.GetRandomElement (); - InternalAssert ((goalChoices[i] >= 0) && (goalChoices[i] < g_numWaypoints)); + InternalAssert (goalChoices[i] >= 0 && goalChoices[i] < g_numWaypoints); } } else if (tactic == 3 && !g_waypoint->m_goalPoints.IsEmpty ()) // map goal waypoint { - for (int i = 0; i < 4; i++) + if (m_hasC4 && g_timeRoundStart + 20.0f < GetWorldTime ()) { - goalChoices[i] = g_waypoint->m_goalPoints.GetRandomElement (); - InternalAssert ((goalChoices[i] >= 0) && (goalChoices[i] < g_numWaypoints)); + } + else + { + for (int i = 0; i < 4; i++) + { + goalChoices[i] = g_waypoint->m_goalPoints.GetRandomElement (); + InternalAssert (goalChoices[i] >= 0 && goalChoices[i] < g_numWaypoints); + } } } @@ -205,7 +214,7 @@ TacticChoosen: ChangeWptIndex (g_waypoint->FindNearest (pev->origin)); if (goalChoices[0] == -1) - return m_chosenGoalIndex = g_randGen.Long (0, g_numWaypoints - 1); + return m_chosenGoalIndex = g_randGen.Long (0, g_numWaypoints - 1); bool isSorting = false; @@ -270,6 +279,352 @@ bool Bot::GoalIsValid (void) return false; } +void Bot::CheckTerrain (float movedDistance) +{ + edict_t *ent = NULL; + + // Test if there's a shootable breakable in our way + if (m_breakableCheckTime < GetWorldTime () && !IsEntityNull (ent = FindBreakable ())) + { + m_breakableEntity = ent; + m_campButtons = pev->button & IN_DUCK; + + StartTask (TASK_SHOOTBREAKABLE, TASKPRI_SHOOTBREAKABLE, -1, 0.0, false); + m_breakableCheckTime = GetWorldTime () + 0.7f; + + return; + } + + // calculate 2 direction vectors, 1 without the up/down component + Vector directionOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval); + Vector directionNormal = directionOld.Normalize (); + + Vector direction = directionNormal; + directionNormal.z = 0.0; + + m_moveAngles = directionOld.ToAngles (); + + m_moveAngles.ClampAngles (); + m_moveAngles.x *= -1.0; // invert for engine + + m_isStuck = false; + + Vector src = nullvec; + Vector destination = nullvec; + + TraceResult tr; + + // very cpu intensive +#if 0 + ent = NULL; + edict_t *pentNearest = NULL; + + if (FindNearestPlayer (reinterpret_cast (&pentNearest), GetEntity (), pev->maxspeed, true, false, true, true)) // found somebody? + { + MakeVectors (m_moveAngles); // use our movement angles + + // try to predict where we should be next frame + Vector moved = pev->origin + g_pGlobals->v_forward * m_moveSpeed * m_frameInterval; + moved = moved + g_pGlobals->v_right * m_strafeSpeed * m_frameInterval; + moved = moved + pev->velocity * m_frameInterval; + + float nearestDistance = (pentNearest->v.origin - pev->origin).GetLength2D (); + float nextFrameDistance = ((pentNearest->v.origin + pentNearest->v.velocity * m_frameInterval) - pev->origin).GetLength2D (); + + // is player that near now or in future that we need to steer away? + if ((pentNearest->v.origin - moved).GetLength2D () <= 48.0 || (nearestDistance <= 56.0 && nextFrameDistance < nearestDistance)) + { + // to start strafing, we have to first figure out if the target is on the left side or right side + Vector dirToPoint = (pev->origin - pentNearest->v.origin).SkipZ (); + + if ((dirToPoint | g_pGlobals->v_right.SkipZ ()) > 0.0) + SetStrafeSpeed (directionNormal, pev->maxspeed); + else + SetStrafeSpeed (directionNormal, -pev->maxspeed); + + ResetCollideState (); + + if (nearestDistance < 56.0 && (dirToPoint | g_pGlobals->v_forward.SkipZ ()) < 0.0) + m_moveSpeed = -pev->maxspeed; + } + } +#endif + + // Standing still, no need to check? + // FIXME: doesn't care for ladder movement (handled separately) should be included in some way + if ((m_moveSpeed >= 10 || m_strafeSpeed >= 10) && m_lastCollTime < GetWorldTime ()) + { + if (movedDistance < 2.0 && m_prevSpeed >= 1.0) // didn't we move enough previously? + { + // Then consider being stuck + m_prevTime = GetWorldTime (); + m_isStuck = true; + + if (m_firstCollideTime == 0.0) + m_firstCollideTime = GetWorldTime () + 0.2; + } + else // not stuck yet + { + // test if there's something ahead blocking the way + if (CantMoveForward (directionNormal, &tr) && !IsOnLadder ()) + { + if (m_firstCollideTime == 0.0) + m_firstCollideTime = GetWorldTime () + 0.2; + + else if (m_firstCollideTime <= GetWorldTime ()) + m_isStuck = true; + } + else + m_firstCollideTime = 0.0; + } + + if (!m_isStuck) // not stuck? + { + if (m_probeTime + 0.5 < GetWorldTime ()) + ResetCollideState (); // reset collision memory if not being stuck for 0.5 secs + else + { + // remember to keep pressing duck if it was necessary ago + if (m_collideMoves[m_collStateIndex] == COLLISION_DUCK && IsOnFloor () || IsInWater ()) + pev->button |= IN_DUCK; + } + } + else // bot is stuck! + { + // not yet decided what to do? + if (m_collisionState == COLLISION_NOTDECICED) + { + char bits = 0; + + if (IsOnLadder ()) + bits = PROBE_STRAFE; + else if (IsInWater ()) + bits = (PROBE_JUMP | PROBE_STRAFE); + else + bits = ((g_randGen.Long (0, 10) > 7 ? PROBE_JUMP : 0) | PROBE_STRAFE | PROBE_DUCK); + + // collision check allowed if not flying through the air + if (IsOnFloor () || IsOnLadder () || IsInWater ()) + { + char state[8]; + int i = 0; + + // first 4 entries hold the possible collision states + state[i++] = COLLISION_JUMP; + state[i++] = COLLISION_DUCK; + state[i++] = COLLISION_STRAFELEFT; + state[i++] = COLLISION_STRAFERIGHT; + + // now weight all possible states + if (bits & PROBE_JUMP) + { + state[i] = 0; + + if (CanJumpUp (directionNormal)) + state[i] += 10; + + if (m_destOrigin.z >= pev->origin.z + 18.0) + state[i] += 5; + + if (EntityIsVisible (m_destOrigin)) + { + MakeVectors (m_moveAngles); + + src = EyePosition (); + src = src + (g_pGlobals->v_right * 15); + + TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); + + if (tr.flFraction >= 1.0) + { + src = EyePosition (); + src = src - (g_pGlobals->v_right * 15); + + TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); + + if (tr.flFraction >= 1.0) + state[i] += 5; + } + } + if (pev->flags & FL_DUCKING) + src = pev->origin; + else + src = pev->origin + Vector (0, 0, -17); + + destination = src + directionNormal * 30; + TraceLine (src, destination, true, true, GetEntity (), &tr); + + if (tr.flFraction != 1.0) + state[i] += 10; + } + else + state[i] = 0; + i++; + + if (bits & PROBE_DUCK) + { + state[i] = 0; + + if (CanDuckUnder (directionNormal)) + state[i] += 10; + + if ((m_destOrigin.z + 36.0 <= pev->origin.z) && EntityIsVisible (m_destOrigin)) + state[i] += 5; + } + else + state[i] = 0; + i++; + + if (bits & PROBE_STRAFE) + { + state[i] = 0; + state[i + 1] = 0; + + // to start strafing, we have to first figure out if the target is on the left side or right side + MakeVectors (m_moveAngles); + + Vector dirToPoint = (pev->origin - m_destOrigin).Normalize2D (); + Vector rightSide = g_pGlobals->v_right.Normalize2D (); + + bool dirRight = false; + bool dirLeft = false; + bool blockedLeft = false; + bool blockedRight = false; + + if ((dirToPoint | rightSide) > 0) + dirRight = true; + else + dirLeft = true; + + if (m_moveSpeed > 0) + direction = g_pGlobals->v_forward; + else + direction = -g_pGlobals->v_forward; + + // now check which side is blocked + src = pev->origin + (g_pGlobals->v_right * 32); + destination = src + (direction * 32); + + TraceHull (src, destination, true, head_hull, GetEntity (), &tr); + + if (tr.flFraction != 1.0) + blockedRight = true; + + src = pev->origin - (g_pGlobals->v_right * 32); + destination = src + (direction * 32); + + TraceHull (src, destination, true, head_hull, GetEntity (), &tr); + + if (tr.flFraction != 1.0) + blockedLeft = true; + + if (dirLeft) + state[i] += 5; + else + state[i] -= 5; + + if (blockedLeft) + state[i] -= 5; + + i++; + + if (dirRight) + state[i] += 5; + else + state[i] -= 5; + + if (blockedRight) + state[i] -= 5; + } + else + { + state[i] = 0; + i++; + + state[i] = 0; + } + + // weighted all possible moves, now sort them to start with most probable + int temp = 0; + bool isSorting = false; + + do + { + isSorting = false; + for (i = 0; i < 3; i++) + { + if (state[i + 4] < state[i + 5]) + { + temp = state[i]; + + state[i] = state[i + 1]; + state[i + 1] = temp; + + temp = state[i + 4]; + + state[i + 4] = state[i + 5]; + state[i + 5] = temp; + + isSorting = true; + } + } + } while (isSorting); + + for (i = 0; i < 4; i++) + m_collideMoves[i] = state[i]; + + m_collideTime = GetWorldTime (); + m_probeTime = GetWorldTime () + 0.5; + m_collisionProbeBits = bits; + m_collisionState = COLLISION_PROBING; + m_collStateIndex = 0; + } + } + + if (m_collisionState == COLLISION_PROBING) + { + if (m_probeTime < GetWorldTime ()) + { + m_collStateIndex++; + m_probeTime = GetWorldTime () + 0.5; + + if (m_collStateIndex > 4) + { + m_navTimeset = GetWorldTime () - 5.0; + ResetCollideState (); + } + } + + if (m_collStateIndex <= 4) + { + switch (m_collideMoves[m_collStateIndex]) + { + case COLLISION_JUMP: + if (IsOnFloor () || IsInWater ()) + pev->button |= IN_JUMP; + break; + + case COLLISION_DUCK: + if (IsOnFloor () || IsInWater ()) + pev->button |= IN_DUCK; + break; + + case COLLISION_STRAFELEFT: + pev->button |= IN_MOVELEFT; + SetStrafeSpeed (directionNormal, -pev->maxspeed); + break; + + case COLLISION_STRAFERIGHT: + pev->button |= IN_MOVERIGHT; + SetStrafeSpeed (directionNormal, pev->maxspeed); + break; + } + } + } + } + } +} + bool Bot::DoWaypointNav (void) { // this function is a main path navigation @@ -360,7 +715,7 @@ bool Bot::DoWaypointNav (void) TraceLine (m_currentPath->origin, m_currentPath->origin + Vector (0, 0, -50), true, true, GetEntity (), &tr); // if trace result shows us that it is a lift - if (!FNullEnt (tr.pHit) && m_navNode != NULL && (strcmp (STRING (tr.pHit->v.classname), "func_door") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_plat") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_train") == 0) && !liftClosedDoorExists) + if (!IsEntityNull (tr.pHit) && m_navNode != NULL && (strcmp (STRING (tr.pHit->v.classname), "func_door") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_plat") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_train") == 0) && !liftClosedDoorExists) { if ((m_liftState == LIFT_NO_NEARBY || m_liftState == LIFT_WAITING_FOR || m_liftState == LIFT_LOOKING_BUTTON_OUTSIDE) && tr.pHit->v.velocity.z == 0) { @@ -386,7 +741,7 @@ bool Bot::DoWaypointNav (void) { TraceLine (m_currentPath->origin, g_waypoint->GetPath (m_navNode->next->index)->origin, true, true, GetEntity (), &tr); - if (!FNullEnt (tr.pHit) && (strcmp (STRING (tr.pHit->v.classname), "func_door") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_plat") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_train") == 0)) + if (!IsEntityNull (tr.pHit) && (strcmp (STRING (tr.pHit->v.classname), "func_door") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_plat") == 0 || strcmp (STRING (tr.pHit->v.classname), "func_train") == 0)) m_liftEntity = tr.pHit; } m_liftState = LIFT_LOOKING_BUTTON_OUTSIDE; @@ -491,7 +846,7 @@ bool Bot::DoWaypointNav (void) edict_t *button = FindNearestButton (STRING (m_liftEntity->v.targetname)); // got a valid button entity ? - if (!FNullEnt (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0 < GetWorldTime () && m_liftEntity->v.velocity.z == 0.0 && IsOnFloor ()) + if (!IsEntityNull (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0 < GetWorldTime () && m_liftEntity->v.velocity.z == 0.0 && IsOnFloor ()) { m_pickupItem = button; m_pickupType = PICKUP_BUTTON; @@ -503,7 +858,7 @@ bool Bot::DoWaypointNav (void) // is lift activated and bot is standing on it and lift is moving ? if (m_liftState == LIFT_LOOKING_BUTTON_INSIDE || m_liftState == LIFT_ENTERING_IN || m_liftState == LIFT_WAIT_FOR_TEAMMATES || m_liftState == LIFT_WAITING_FOR) { - if (pev->groundentity == m_liftEntity && m_liftEntity->v.velocity.z != 0 && IsOnFloor () && ((g_waypoint->GetPath (m_prevWptIndex[0])->flags & FLAG_LIFT) || !FNullEnt (m_targetEntity))) + if (pev->groundentity == m_liftEntity && m_liftEntity->v.velocity.z != 0 && IsOnFloor () && ((g_waypoint->GetPath (m_prevWptIndex[0])->flags & FLAG_LIFT) || !IsEntityNull (m_targetEntity))) { m_liftState = LIFT_TRAVELING_BY; m_liftUsageTime = GetWorldTime () + 14.0; @@ -553,12 +908,12 @@ bool Bot::DoWaypointNav (void) edict_t *button = FindNearestButton (STRING (m_liftEntity->v.targetname)); // if we got a valid button entity - if (!FNullEnt (button)) + if (!IsEntityNull (button)) { // iterate though clients, and find if lift already used for (int i = 0; i < GetMaxClients (); i++) { - if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].team != m_team || g_clients[i].ent == GetEntity () || FNullEnt (g_clients[i].ent->v.groundentity)) + if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].team != m_team || g_clients[i].ent == GetEntity () || IsEntityNull (g_clients[i].ent->v.groundentity)) continue; if (g_clients[i].ent->v.groundentity == m_liftEntity) @@ -642,7 +997,7 @@ bool Bot::DoWaypointNav (void) } } - if (!FNullEnt (m_liftEntity) && !(m_currentPath->flags & FLAG_LIFT)) + if (!IsEntityNull (m_liftEntity) && !(m_currentPath->flags & FLAG_LIFT)) { if (m_liftState == LIFT_TRAVELING_BY) { @@ -682,7 +1037,7 @@ bool Bot::DoWaypointNav (void) // check if we are going through a door... TraceLine (pev->origin, m_waypointOrigin, true, GetEntity (), &tr); - if (!FNullEnt (tr.pHit) && FNullEnt (m_liftEntity) && strncmp (STRING (tr.pHit->v.classname), "func_door", 9) == 0) + if (!IsEntityNull (tr.pHit) && IsEntityNull (m_liftEntity) && strncmp (STRING (tr.pHit->v.classname), "func_door", 9) == 0) { // if the door is near enough... if ((GetEntityOrigin (tr.pHit) - pev->origin).GetLengthSquared () < 2500) @@ -699,7 +1054,7 @@ bool Bot::DoWaypointNav (void) edict_t *button = FindNearestButton (STRING (tr.pHit->v.targetname)); // check if we got valid button - if (!FNullEnt (button)) + if (!IsEntityNull (button)) { m_pickupItem = button; m_pickupType = PICKUP_BUTTON; @@ -717,9 +1072,9 @@ bool Bot::DoWaypointNav (void) edict_t *ent = NULL; - if (m_doorOpenAttempt > 2 && !FNullEnt (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 100))) + if (m_doorOpenAttempt > 2 && !IsEntityNull (ent = FIND_ENTITY_IN_SPHERE (ent, pev->origin, 100))) { - if (IsValidPlayer (ent) && IsAlive (ent) && m_team != GetTeam (ent) && IsWeaponShootingThroughWall (m_currentWeapon)) + if (IsValidPlayer (ent) && IsAlive (ent) && m_team != GetTeam (ent) && GetWeaponPenetrationPower (m_currentWeapon) > 0) { m_seeEnemyTime = GetWorldTime (); @@ -1063,7 +1418,7 @@ int gfunctionKillsDistCTWithHostage (int currentIndex, int parentIndex) return 65355; else if (current->flags & (FLAG_CROUCH | FLAG_LADDER)) - return gfunctionKillsDistCT (currentIndex, parentIndex) * 500; + return gfunctionKillsDistCT (currentIndex, parentIndex) * 5000; return gfunctionKillsDistCT (currentIndex, parentIndex); } @@ -1122,7 +1477,7 @@ int gfunctionKillsCTWithHostage (int currentIndex, int parentIndex) return 65355; else if (current->flags & (FLAG_CROUCH | FLAG_LADDER)) - return gfunctionKillsDistCT (currentIndex, parentIndex) * 500; + return gfunctionKillsDistCT (currentIndex, parentIndex) * 5000; return gfunctionKillsCT (currentIndex, parentIndex); } @@ -1156,7 +1511,7 @@ int gfunctionPathDistWithHostage (int currentIndex, int parentIndex) if (current->flags & FLAG_NOHOSTAGE) return 65355; else if (current->flags & (FLAG_CROUCH | FLAG_LADDER)) - return gfunctionPathDist (currentIndex, parentIndex) * 500; + return gfunctionPathDist (currentIndex, parentIndex) * 5000; return gfunctionPathDist (currentIndex, parentIndex); } @@ -1439,14 +1794,14 @@ bool Bot::FindWaypoint (void) float reachDistances[3]; // nullify all waypoint search stuff - for (int i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { waypointIndeces[i] = -1; reachDistances[i] = 9999.0; } // do main search loop - for (int i = 0; i < g_numWaypoints; i++) + for (i = 0; i < g_numWaypoints; i++) { // ignore current waypoint and previous recent waypoints... if (i == m_currentWaypointIndex || i == m_prevWptIndex[0] || i == m_prevWptIndex[1] || i == m_prevWptIndex[2] || i == m_prevWptIndex[3] || i == m_prevWptIndex[4]) @@ -1457,7 +1812,7 @@ bool Bot::FindWaypoint (void) continue; // check if waypoint is already used by another bot... - if (IsWaypointUsed (i)) + if (IsPointOccupied (i)) { coveredWaypoint = i; continue; @@ -1521,7 +1876,7 @@ void Bot::GetValidWaypoint (void) // FIXME: Do some error checks if we got a waypoint } - else if ((m_navTimeset + GetEstimatedReachTime () < GetWorldTime ()) && FNullEnt (m_enemy)) + else if (m_navTimeset + GetEstimatedReachTime () < GetWorldTime () && IsEntityNull (m_enemy)) { if (m_team == TEAM_TF) { @@ -1585,7 +1940,7 @@ void Bot::ChangeWptIndex (int waypointIndex) m_prevWptIndex[4] = m_prevWptIndex[3]; m_prevWptIndex[3] = m_prevWptIndex[2]; m_prevWptIndex[2] = m_prevWptIndex[1]; - m_prevWptIndex[0] = waypointIndex; + m_prevWptIndex[0] = m_currentWaypointIndex; m_currentWaypointIndex = waypointIndex; m_navTimeset = GetWorldTime (); @@ -1626,7 +1981,7 @@ int Bot::ChooseBombWaypoint (void) if (distance < lastDistance) { goal = goals[i]; - lastDistance = distance;; + lastDistance = distance; } } @@ -1666,7 +2021,7 @@ int Bot::FindDefendWaypoint (Vector origin) for (int i = 0; i < g_numWaypoints; i++) // find the best waypoint now { // exclude ladder & current waypoints - if ((g_waypoint->GetPath (i)->flags & FLAG_LADDER) || i == srcIndex || !g_waypoint->IsVisible (i, posIndex) || IsWaypointUsed (i)) + if ((g_waypoint->GetPath (i)->flags & FLAG_LADDER) || i == srcIndex || !g_waypoint->IsVisible (i, posIndex) || IsPointOccupied (i)) continue; // use the 'real' pathfinding distances @@ -1904,7 +2259,7 @@ bool Bot::GetBestNextWaypoint (void) InternalAssert (m_navNode != NULL); InternalAssert (m_navNode->next != NULL); - if (!IsWaypointUsed (m_navNode->index)) + if (!IsPointOccupied (m_navNode->index)) return false; for (int i = 0; i < MAX_PATH_INDEX; i++) @@ -1916,7 +2271,7 @@ bool Bot::GetBestNextWaypoint (void) if (g_waypoint->GetPath (id)->flags & FLAG_LADDER) // don't use ladder waypoints as alternative continue; - if (!IsWaypointUsed (id)) + if (!IsPointOccupied (id)) { m_navNode->index = id; return true; @@ -1948,8 +2303,8 @@ bool Bot::HeadTowardWaypoint (void) if (m_navNode != m_navNodeStart && m_navNode->next != NULL) { GetBestNextWaypoint (); - int taskID= GetTaskId (); + int taskID = GetTaskId (); m_minSpeed = pev->maxspeed; // only if we in normal task and bomb is not planted @@ -1965,38 +2320,35 @@ bool Bot::HeadTowardWaypoint (void) else kills = (g_experienceData + (waypoint * g_numWaypoints) + waypoint)->team1Damage / g_highestDamageCT; + switch (m_personality) + { + case PERSONALITY_NORMAL: + kills *= 0.33f; + break; + + default: + kills *= 0.5f; + break; + } + // if damage done higher than one - if (kills > 0.15f && g_timeRoundMid + 30.0f > GetWorldTime ()) + if (kills > 0.15f && g_timeRoundMid + 30.0f > GetWorldTime () && m_timeCamping + 10.0 < GetWorldTime()) { - switch (m_personality) - { - case PERSONALITY_NORMAL: - kills *= 0.33f; - break; - - default: - kills *= 0.5f; - break; - } - if (m_baseAgressionLevel < kills && GetTaskId () != TASK_MOVETOPOSITION && HasPrimaryWeapon ()) { StartTask (TASK_CAMP, TASKPRI_CAMP, -1, GetWorldTime () + (m_fearLevel * (g_timeRoundMid - GetWorldTime ()) * 0.5), true); // push camp task on to stack - StartTask (TASK_MOVETOPOSITION, TASKPRI_MOVETOPOSITION, FindDefendWaypoint (g_waypoint->GetPath (waypoint)->origin), 0.0, true); - if (m_skill > 95) + if (m_difficulty >= 2) pev->button |= IN_DUCK; } } - else - if (g_botsCanPause && !IsOnLadder () && !IsInWater () && !m_currentTravelFlags && IsOnFloor ()) { if (static_cast (kills) == m_baseAgressionLevel) m_campButtons |= IN_DUCK; - else if (g_randGen.Long (1, 100) > (m_skill + g_randGen.Long (1, 20))) + else if (g_randGen.Long (1, 100) < m_difficulty * 25) m_minSpeed = GetWalkSpeed (); } } @@ -2050,9 +2402,10 @@ bool Bot::HeadTowardWaypoint (void) } // is there a jump waypoint right ahead and do we need to draw out the light weapon ? - if (willJump && (jumpDistance > 210 || (destination.z + 32.0 > src.z && jumpDistance > 150) || ((destination - src).GetLength2D () < 50 && jumpDistance > 60)) && !(m_states & STATE_SEEING_ENEMY) && m_currentWeapon != WEAPON_KNIFE && !m_isReloading) + if (willJump && m_currentWeapon != WEAPON_KNIFE && m_currentWeapon != WEAPON_SCOUT && !m_isReloading && !UsesPistol () && (jumpDistance > 210 || (destination.z + 32.0f > src.z && jumpDistance > 150.0f) || ((destination - src).GetLength2D () < 60 && jumpDistance > 60)) && IsEntityNull (m_enemy)) SelectWeaponByName ("weapon_knife"); // draw out the knife if we needed + // bot not already on ladder but will be soon? if ((g_waypoint->GetPath (destIndex)->flags & FLAG_LADDER) && !IsOnLadder ()) { @@ -2697,9 +3050,10 @@ int Bot::GetAimingWaypoint (void) void Bot::FacePosition (void) { + // adjust all body and view angles to face an absolute vector Vector direction = (m_lookAt - EyePosition ()).ToAngles (); - direction = direction + pev->punchangle * m_skill / 100.0; + direction = direction + pev->punchangle * (m_difficulty * 25) / 100.0; direction.x *= -1.0; // invert for engine Vector deviation = (direction - pev->v_angle); @@ -2707,16 +3061,16 @@ void Bot::FacePosition (void) direction.ClampAngles (); deviation.ClampAngles (); - int forcedTurnMethod = yb_aim_method.GetInt (); + int aimMethod = yb_aim_method.GetInt (); - if ((forcedTurnMethod < 1) || (forcedTurnMethod > 3)) - forcedTurnMethod = 3; + if (aimMethod < 1 || aimMethod > 3) + aimMethod = 3; - if (forcedTurnMethod == 1) + if (aimMethod == 1) pev->v_angle = direction; - else if (forcedTurnMethod == 2) + else if (aimMethod == 2) { - float turnSkill = static_cast (0.05 * m_skill) + 0.5; + float turnSkill = static_cast (0.05 * (m_difficulty * 25)) + 0.5; float aimSpeed = 0.17 + turnSkill * 0.06; float frameCompensation = g_pGlobals->frametime * 1000 * 0.01; @@ -2728,7 +3082,7 @@ void Bot::FacePosition (void) pev->pitch_speed = ((pev->pitch_speed * momentum) + aimSpeed * deviation.x * (1.0 - momentum)) * frameCompensation; pev->yaw_speed = ((pev->yaw_speed * momentum) + aimSpeed * deviation.y * (1.0 - momentum)) * frameCompensation; - if (m_skill < 100) + if (m_difficulty <= 2) { // influence of y movement on x axis, based on skill (less influence than x on y since it's // easier and more natural for the bot to "move its mouse" horizontally than vertically) @@ -2739,7 +3093,7 @@ void Bot::FacePosition (void) pev->v_angle.x += pev->pitch_speed; // change pitch angles pev->v_angle.y += pev->yaw_speed; // change yaw angles } - else if (forcedTurnMethod == 3) + else if (aimMethod == 3) { Vector springStiffness (yb_aim_spring_stiffness_x.GetFloat (), yb_aim_spring_stiffness_y.GetFloat (), 0); Vector damperCoefficient (yb_aim_damper_coefficient_x.GetFloat (), yb_aim_damper_coefficient_y.GetFloat (), 0); @@ -2753,10 +3107,10 @@ void Bot::FacePosition (void) m_targetOriginAngularSpeed.ClampAngles (); m_idealAngles.ClampAngles (); - if (yb_hardcore_mode.GetBool ()) + if (m_difficulty == 4) { - influence = influence * m_skillOffset; - randomization = randomization * m_skillOffset; + influence = influence * ((100 - (m_difficulty * 25)) / 100.f); + randomization = randomization * ((100 - (m_difficulty * 25)) / 100.f); } if (m_aimFlags & (AIM_ENEMY | AIM_ENTITY | AIM_GRENADE | AIM_LAST_ENEMY) || GetTaskId () == TASK_SHOOTBREAKABLE) @@ -2766,10 +3120,10 @@ void Bot::FacePosition (void) if (IsValidPlayer (m_enemy)) { - m_targetOriginAngularSpeed = ((m_enemyOrigin - pev->origin + 1.5 * m_frameInterval * (1.0 * m_enemy->v.velocity) - 0.0 * g_pGlobals->frametime * pev->velocity).ToAngles () - (m_enemyOrigin - pev->origin).ToAngles ()) * 0.45 * yb_aim_target_anticipation_ratio.GetFloat () * static_cast (m_skill / 100); + m_targetOriginAngularSpeed = ((m_enemyOrigin - pev->origin + 1.5 * m_frameInterval * (1.0 * m_enemy->v.velocity) - 0.0 * g_pGlobals->frametime * pev->velocity).ToAngles () - (m_enemyOrigin - pev->origin).ToAngles ()) * 0.45 * yb_aim_target_anticipation_ratio.GetFloat () * static_cast ((m_difficulty * 25) / 100); if (m_angularDeviation.GetLength () < 5.0) - springStiffness = (5.0 - m_angularDeviation.GetLength ()) * 0.25 * static_cast (m_skill / 100) * springStiffness + springStiffness; + springStiffness = (5.0 - m_angularDeviation.GetLength ()) * 0.25 * static_cast ((m_difficulty * 25) / 100) * springStiffness + springStiffness; m_targetOriginAngularSpeed.x = -m_targetOriginAngularSpeed.x; @@ -2782,10 +3136,10 @@ void Bot::FacePosition (void) m_targetOriginAngularSpeed = nullvec; - if (m_skill >= 80) + if (m_difficulty >= 3) stiffness = springStiffness; else - stiffness = springStiffness * (0.2 + m_skill / 125.0); + stiffness = springStiffness * (0.2 + (m_difficulty * 25) / 125.0); } else { @@ -2816,12 +3170,12 @@ void Bot::FacePosition (void) stiffnessMultiplier = 0.5; } - // also take in account the remaining deviation (slow down the aiming in the last 10°) - if (!yb_hardcore_mode.GetBool () && (m_angularDeviation.GetLength () < 10.0)) + // also take in account the remaining deviation (slow down the aiming in the last 10°) + if (m_difficulty < 3 && (m_angularDeviation.GetLength () < 10.0)) stiffnessMultiplier *= m_angularDeviation.GetLength () * 0.1; // slow down even more if we are not moving - if (!yb_hardcore_mode.GetBool () && pev->velocity.GetLength () < 1.0 && GetTaskId () != TASK_CAMP && GetTaskId () != TASK_ATTACK) + if (m_difficulty < 3 && pev->velocity.GetLength () < 1.0 && GetTaskId () != TASK_CAMP && GetTaskId () != TASK_ATTACK) stiffnessMultiplier *= 0.5; // but don't allow getting below a certain value @@ -2874,31 +3228,6 @@ void Bot::SetStrafeSpeed (Vector moveDir, float strafeSpeed) m_strafeSpeed = -strafeSpeed; } -int Bot::FindLoosedBomb (void) -{ - // this function tries to find droped c4 on the defuse scenario map and returns nearest to it waypoint - - if ((m_team != TEAM_TF) || !(g_mapType & MAP_DE)) - return -1; // don't search for bomb if the player is CT, or it's not defusing bomb - - edict_t *bombEntity = NULL; // temporaly pointer to bomb - - // search the bomb on the map - while (!FNullEnt (bombEntity = FIND_ENTITY_BY_CLASSNAME (bombEntity, "weaponbox"))) - { - if (strcmp (STRING (bombEntity->v.model) + 9, "backpack.mdl") == 0) - { - int nearestIndex = g_waypoint->FindNearest (GetEntityOrigin (bombEntity)); - - if ((nearestIndex >= 0) && (nearestIndex < g_numWaypoints)) - return nearestIndex; - - break; - } - } - return -1; -} - int Bot::FindPlantedBomb (void) { // this function tries to find planted c4 on the defuse scenario map and returns nearest to it waypoint @@ -2909,7 +3238,7 @@ int Bot::FindPlantedBomb (void) edict_t *bombEntity = NULL; // temporaly pointer to bomb // search the bomb on the map - while (!FNullEnt (bombEntity = FIND_ENTITY_BY_CLASSNAME (bombEntity, "grenade"))) + while (!IsEntityNull (bombEntity = FIND_ENTITY_BY_CLASSNAME (bombEntity, "grenade"))) { if (strcmp (STRING (bombEntity->v.model) + 9, "c4.mdl") == 0) { @@ -2924,7 +3253,7 @@ int Bot::FindPlantedBomb (void) return -1; } -bool Bot::IsWaypointUsed (int index) +bool Bot::IsPointOccupied (int index) { if (index < 0 || index >= g_numWaypoints) return true; @@ -2938,17 +3267,7 @@ bool Bot::IsWaypointUsed (int index) continue; // check if this waypoint is already used - if (IsAlive (bot->GetEntity ()) && (bot->m_currentWaypointIndex == index || bot->GetTask ()->data == index || (g_waypoint->GetPath (index)->origin - bot->pev->origin).GetLength2D () < 80.0)) - return true; - } - - // secondary check waypoint radius for any player - edict_t *ent = NULL; - - // search player entities in waypoint radius - while (!FNullEnt (ent = FIND_ENTITY_IN_SPHERE (ent, g_waypoint->GetPath (index)->origin, 80.0))) - { - if (ent != GetEntity () && IsValidBot (ent) && IsAlive (ent)) + if (IsAlive (bot->GetEntity ()) && (bot->m_currentWaypointIndex == index || bot->GetTask ()->data == index || (g_waypoint->GetPath (index)->origin - bot->pev->origin).GetLength2D () < 180.0)) return true; } return false; @@ -2966,7 +3285,7 @@ edict_t *Bot::FindNearestButton (const char *targetName) edict_t *searchEntity = NULL, *foundEntity = NULL; // find the nearest button which can open our target - while (!FNullEnt(searchEntity = FIND_ENTITY_BY_TARGET(searchEntity, targetName))) + while (!IsEntityNull(searchEntity = FIND_ENTITY_BY_TARGET(searchEntity, targetName))) { Vector entityOrign = GetEntityOrigin (searchEntity); diff --git a/source/netmsg.cpp b/source/netmsg.cpp index 452f317..c315171 100644 --- a/source/netmsg.cpp +++ b/source/netmsg.cpp @@ -267,7 +267,7 @@ void NetworkMsg::Execute (void *p) edict_t *killer = EntityOfIndex (killerIndex); edict_t *victim = EntityOfIndex (victimIndex); - if (FNullEnt (killer) || FNullEnt (victim)) + if (IsEntityNull (killer) || IsEntityNull (victim)) break; // need to send congrats on well placed shot @@ -291,7 +291,7 @@ void NetworkMsg::Execute (void *p) { Bot *bot = g_botManager->GetBot (i); - if (bot != NULL && IsAlive (bot->GetEntity ()) && GetTeam (bot->GetEntity ()) == GetTeam (victim) && IsVisible (killer->v.origin, bot->GetEntity ()) && FNullEnt (bot->m_enemy) && GetTeam (killer) != GetTeam (victim)) + if (bot != NULL && IsAlive (bot->GetEntity ()) && GetTeam (bot->GetEntity ()) == GetTeam (victim) && IsVisible (killer->v.origin, bot->GetEntity ()) && IsEntityNull (bot->m_enemy) && GetTeam (killer) != GetTeam (victim)) { bot->m_actualReactionTime = 0.0; bot->m_seeEnemyTime = GetWorldTime (); @@ -309,14 +309,14 @@ void NetworkMsg::Execute (void *p) else // did a human kill a bot on his team? { - Bot *bot = g_botManager->GetBot (victim); + Bot *target = g_botManager->GetBot (victim); - if (bot != NULL) + if (target != NULL) { if (GetTeam (killer) == GetTeam (victim)) - bot->m_voteKickIndex = killerIndex; + target->m_voteKickIndex = killerIndex; - bot->m_notKilled = false; + target->m_notKilled = false; } } } @@ -406,25 +406,36 @@ void NetworkMsg::Execute (void *p) g_bombPlanted = g_bombSayString = true; g_timeBombPlanted = GetWorldTime (); - for (int i = 0; i < GetMaxClients (); i++) - { - Bot *bot = g_botManager->GetBot (i); + if (yb_communication_type.GetInt() == 2) + { + for (int i = 0; i < GetMaxClients(); i++) + { + Bot *bot = g_botManager->GetBot(i); - if (bot != NULL && IsAlive (bot->GetEntity ())) - { - bot->DeleteSearchNodes (); - bot->ResetTasks (); + if (bot != NULL && IsAlive(bot->GetEntity())) + { + bot->DeleteSearchNodes(); + bot->ResetTasks(); - if (g_randGen.Long (0, 100) < 85 && GetTeam (bot->GetEntity ()) == TEAM_CF) - bot->ChatterMessage (Chatter_WhereIsTheBomb); - } - } + if (g_randGen.Long(0, 100) < 75 && GetTeam(bot->GetEntity()) == TEAM_CF) + bot->ChatterMessage(Chatter_WhereIsTheBomb); + } + } + } g_waypoint->SetBombPosition (); } else if (m_bot != NULL && FStrEq (PTR_TO_STR (p), "#Switch_To_BurstFire")) m_bot->m_weaponBurstMode = BM_ON; else if (m_bot != NULL && FStrEq (PTR_TO_STR (p), "#Switch_To_SemiAuto")) m_bot->m_weaponBurstMode = BM_OFF; + + if (yb_communication_type.GetInt() == 2) + { + Bot *bot = g_botManager->FindOneValidAliveBot(); + + if (bot != NULL && IsAlive(bot->GetEntity())) + bot->HandleChatterMessage(PTR_TO_STR(p)); + } } break; diff --git a/source/support.cpp b/source/support.cpp index eae4e66..a25cd48 100644 --- a/source/support.cpp +++ b/source/support.cpp @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -9,7 +9,7 @@ #include -ConVar yb_listenserver_welcome ("yb_listenserver_welcome", "1"); +ConVar yb_listenserver_welcome ("yb_listenserver_welcome", "1", VT_NOSERVER); ConVar mp_roundtime ("mp_roundtime", NULL, VT_NOREGISTER); ConVar mp_freezetime ("mp_freezetime", NULL, VT_NOREGISTER); @@ -97,10 +97,10 @@ char *FormatBuffer (char *format, ...) bool IsAlive (edict_t *ent) { - if (FNullEnt (ent)) - return false; // reliability check + if (IsEntityNull (ent)) + return false; - return (ent->v.deadflag == DEAD_NO) && (ent->v.health > 0) && (ent->v.movetype != MOVETYPE_NOCLIP); + return ent->v.deadflag == DEAD_NO && ent->v.health > 0 && ent->v.movetype != MOVETYPE_NOCLIP; } float GetShootingConeDeviation (edict_t *ent, Vector *position) @@ -124,7 +124,7 @@ bool IsInViewCone (Vector origin, edict_t *ent) bool IsVisible (const Vector &origin, edict_t *ent) { - if (FNullEnt (ent)) + if (IsEntityNull (ent)) return false; TraceResult tr; @@ -141,7 +141,7 @@ Vector GetEntityOrigin (edict_t *ent) // this expanded function returns the vector origin of a bounded entity, assuming that any // entity that has a bounding box has its center at the center of the bounding box itself. - if (FNullEnt (ent)) + if (IsEntityNull (ent)) return nullvec; if (ent->v.origin == nullvec) @@ -162,14 +162,14 @@ void DisplayMenuToClient (edict_t *ent, MenuText *menu) String tempText = String (menu->menuText); tempText.Replace ("\v", "\n"); - char *text = g_localizer->TranslateInput (tempText.ToString ()); + char *text = g_localizer->TranslateInput (tempText.GetBuffer ()); tempText = String (text); // make menu looks best for (int i = 0; i <= 9; i++) tempText.Replace (FormatBuffer ("%d.", i), FormatBuffer ("\\r%d.\\w", i)); - text = (char *) tempText.ToString (); + text = (char *) tempText.GetBuffer (); while (strlen (text) >= 64) { @@ -219,7 +219,7 @@ void DecalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex) logotypes = String ("{biohaz;{graf004;{graf005;{lambda06;{target;{hand1").Split (";"); int entityIndex = -1, message = TE_DECAL; - int decalIndex = (*g_engfuncs.pfnDecalIndex) (logotypes[logotypeIndex].ToString ()); + int decalIndex = (*g_engfuncs.pfnDecalIndex) (logotypes[logotypeIndex].GetBuffer ()); if (decalIndex < 0) decalIndex = (*g_engfuncs.pfnDecalIndex) ("{lambda06"); @@ -227,7 +227,7 @@ void DecalTrace (entvars_t *pev, TraceResult *trace, int logotypeIndex) if (trace->flFraction == 1.0) return; - if (!FNullEnt (trace->pHit)) + if (!IsEntityNull (trace->pHit)) { if (trace->pHit->v.solid == SOLID_BSP || trace->pHit->v.movetype == MOVETYPE_PUSHSTEP) entityIndex = IndexOfEntity (trace->pHit); @@ -289,9 +289,7 @@ void FreeLibraryMemory (void) // this function free's all allocated memory g_waypoint->Init (); // frees waypoint data - if (g_experienceData != NULL) - delete [] g_experienceData; - + delete [] g_experienceData; g_experienceData = NULL; } @@ -305,9 +303,9 @@ void FakeClientCommand (edict_t *fakeClient, const char *format, ...) va_list ap; static char command[256]; - int start, stop, i, index, stringIndex = 0; + int stop, i, stringIndex = 0; - if (FNullEnt (fakeClient)) + if (IsEntityNull (fakeClient)) return; // reliability check // concatenate all the arguments in one string @@ -324,7 +322,7 @@ void FakeClientCommand (edict_t *fakeClient, const char *format, ...) // process all individual commands (separated by a semicolon) one each a time while (stringIndex < length) { - start = stringIndex; // save field start position (first character) + int start = stringIndex; // save field start position (first character) while (stringIndex < length && command[stringIndex] != ';') stringIndex++; // reach end of field @@ -340,7 +338,7 @@ void FakeClientCommand (edict_t *fakeClient, const char *format, ...) g_fakeArgv[i - start] = 0; // terminate the string stringIndex++; // move the overall string index one step further to bypass the semicolon - index = 0; + int index = 0; g_fakeArgc = 0; // let's now parse that command and count the different arguments // count the number of arguments @@ -764,6 +762,9 @@ void RoundInit (void) g_lastRadioTime[1] = 0.0; g_botsCanPause = false; + for (int i = 0; i < TASK_MAX; i++) + g_taskFilters[i].time = 0.0f; + UpdateGlobalExperienceData (); // update experience data on round start // calculate the round mid/end in world time @@ -772,7 +773,7 @@ void RoundInit (void) g_timeRoundEnd = g_timeRoundStart + mp_roundtime.GetFloat () * 60; } -bool IsWeaponShootingThroughWall (int id) +int GetWeaponPenetrationPower (int id) { // returns if weapon can pierce through a wall @@ -781,15 +782,11 @@ bool IsWeaponShootingThroughWall (int id) while (g_weaponSelect[i].id) { if (g_weaponSelect[i].id == id) - { - if (g_weaponSelect[i].shootsThru) - return true; + return g_weaponSelect[i].penetratePower; - return false; - } i++; } - return false; + return 0; } int GetTeam (edict_t *ent) @@ -799,7 +796,7 @@ int GetTeam (edict_t *ent) bool IsValidPlayer (edict_t *ent) { - if (FNullEnt (ent)) + if (IsEntityNull (ent)) return false; if (ent->v.flags & FL_PROXY) @@ -813,7 +810,7 @@ bool IsValidPlayer (edict_t *ent) bool IsValidBot (edict_t *ent) { - if (g_botManager->GetBot (ent) != NULL || (!FNullEnt (ent) && (ent->v.flags & FL_FAKECLIENT))) + if (g_botManager->GetBot (ent) != NULL || (!IsEntityNull (ent) && (ent->v.flags & FL_FAKECLIENT))) return true; return false; @@ -884,7 +881,7 @@ void ServerPrint (const char *format, ...) vsprintf (string, g_localizer->TranslateInput (format), ap); va_end (ap); - SERVER_PRINT (FormatBuffer ("[%s] %s\n", PRODUCT_LOGTAG, string)); + SERVER_PRINT (FormatBuffer ("%s\n", string)); } void ServerPrintNoTag (const char *format, ...) @@ -952,7 +949,7 @@ void ClientPrint (edict_t *ent, int dest, const char *format, ...) vsprintf (string, g_localizer->TranslateInput (format), ap); va_end (ap); - if (FNullEnt (ent) || ent == g_hostEntity) + if (IsEntityNull (ent) || ent == g_hostEntity) { if (dest & 0x3ff) ServerPrint (string); @@ -1079,9 +1076,9 @@ void CheckWelcomeMessage (void) if (receiveTime > 0.0 && receiveTime < GetWorldTime () && !isReceived && (g_numWaypoints > 0 ? g_isCommencing : true)) { - ServerCommand ("speak \"%s\"", const_cast (sentences.GetRandomElement ().ToString ())); + ServerCommand ("speak \"%s\"", const_cast (sentences.GetRandomElement ().GetBuffer ())); - ChartPrint ("----- YaPB v%s (Build: %u), {%s}, (c) 2014, by %s -----", PRODUCT_VERSION, GenerateBuildNumber (), PRODUCT_DATE, PRODUCT_AUTHOR); + ChartPrint ("----- YaPB v%s (Build: %u), {%s}, (c) 2015, by %s -----", PRODUCT_VERSION, GenerateBuildNumber (), PRODUCT_DATE, PRODUCT_AUTHOR); HudMessage (g_hostEntity, true, Vector (g_randGen.Long (33, 255), g_randGen.Long (33, 255), g_randGen.Long (33, 255)), "\nServer is running YaPB v%s (Build: %u)\nDeveloped by %s\n\n%s", PRODUCT_VERSION, GenerateBuildNumber (), PRODUCT_AUTHOR, g_waypoint->GetInfo ()); receiveTime = 0.0; @@ -1402,15 +1399,15 @@ bool FindNearestPlayer (void **pvHolder, edict_t *to, float searchDistance, bool edict_t *ent = NULL, *survive = NULL; // pointer to temporaly & survive entity float nearestPlayer = 4096.0; // nearest player - while (!FNullEnt (ent = FIND_ENTITY_IN_SPHERE (ent, to->v.origin, searchDistance))) + while (!IsEntityNull (ent = FIND_ENTITY_IN_SPHERE (ent, to->v.origin, searchDistance))) { - if (FNullEnt (ent) || !IsValidPlayer (ent) || to == ent) + if (IsEntityNull (ent) || !IsValidPlayer (ent) || to == ent) continue; // skip invalid players if ((sameTeam && GetTeam (ent) != GetTeam (to)) || (isAlive && !IsAlive (ent)) || (needBot && !IsValidBot (ent)) || (needDrawn && (ent->v.effects & EF_NODRAW))) continue; // filter players with parameters - float distance = (ent->v.origin - to->v.origin).GetLength (); + float distance = (ent->v.origin - to->v.origin).GetLengthSquared (); if (distance < nearestPlayer) { @@ -1419,7 +1416,7 @@ bool FindNearestPlayer (void **pvHolder, edict_t *to, float searchDistance, bool } } - if (FNullEnt (survive)) + if (IsEntityNull (survive)) return false; // nothing found // fill the holder @@ -1436,7 +1433,7 @@ void SoundAttachToThreat (edict_t *ent, const char *sample, float volume) // this function called by the sound hooking code (in emit_sound) enters the played sound into // the array associated with the entity - if (FNullEnt (ent) || IsNullString (sample)) + if (IsEntityNull (ent) || IsNullString (sample)) return; // reliability check Vector origin = GetEntityOrigin (ent); diff --git a/source/waypoint.cpp b/source/waypoint.cpp index f12f0ee..ad7f8dd 100644 --- a/source/waypoint.cpp +++ b/source/waypoint.cpp @@ -1,4 +1,4 @@ -// +// // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Copyright (c) YaPB Development Team. // @@ -9,10 +9,10 @@ #include -ConVar yb_wptsubfolder ("yb_wptsubfolder", ""); +ConVar yb_wptsubfolder ("yb_wptsubfolder", "", VT_NOSERVER); -ConVar yb_waypoint_autodl_host ("yb_waypoint_autodl_host", "yapb.jeefo.net"); -ConVar yb_waypoint_autodl_enable ("yb_waypoint_autodl_enable", "1"); +ConVar yb_waypoint_autodl_host ("yb_waypoint_autodl_host", "yapb.jeefo.net", VT_NOSERVER); +ConVar yb_waypoint_autodl_enable ("yb_waypoint_autodl_enable", "1", VT_NOSERVER); void Waypoint::Init (void) { @@ -104,7 +104,7 @@ int Waypoint::FindFarest (Vector origin, float maxDistance) int Waypoint::FindNearest (Vector origin, float minDistance, int flags) { - // find the nearest waypoint to that Origin and return the index + // find the nearest waypoint to that origin and return the index int index = -1; @@ -156,7 +156,7 @@ void Waypoint::FindInRadius (Array &queueID, float radius, Vector origin) void Waypoint::Add (int flags, const Vector &waypointOrigin) { - if (FNullEnt (g_hostEntity)) + if (IsEntityNull (g_hostEntity)) return; int index = -1, i; @@ -234,7 +234,7 @@ void Waypoint::Add (int flags, const Vector &waypointOrigin) placeNew = false; path = m_paths[index]; - int flags = 0; + flags = 0; for (i = 0; i < MAX_PATH_INDEX; i++) flags += path->connectionFlags[i]; @@ -581,11 +581,11 @@ int Waypoint::GetFacingIndex (void) // get the current view cone viewCone[0] = GetShootingConeDeviation (g_hostEntity, &m_paths[i]->origin); - Vector bound = m_paths[i]->origin - Vector (0, 0, m_paths[i]->flags & FLAG_CROUCH ? 8 : 15); + Vector bound = m_paths[i]->origin - Vector (0, 0, (m_paths[i]->flags & FLAG_CROUCH) ? 8 : 15); // get the current view cone viewCone[1] = GetShootingConeDeviation (g_hostEntity, &bound); - bound = m_paths[i]->origin + Vector (0, 0, m_paths[i]->flags & FLAG_CROUCH ? 8 : 15); + bound = m_paths[i]->origin + Vector (0, 0, (m_paths[i]->flags & FLAG_CROUCH) ? 8 : 15); // get the current view cone viewCone[2] = GetShootingConeDeviation (g_hostEntity, &bound); @@ -1252,7 +1252,6 @@ bool Waypoint::Reachable (Bot *bot, int index) Vector dest = GetPath (index)->origin; float distance = (dest - src).GetLength (); - float distance2D = (dest - src).GetLength2D (); // check is destination is close to us enoguh if (distance >= 201) // Default: 201 @@ -1260,6 +1259,8 @@ bool Waypoint::Reachable (Bot *bot, int index) if (bot->pev->waterlevel == 2 || bot->pev->waterlevel == 3) { + float distance2D = (dest - src).GetLength2D (); + // is destination waypoint higher that source (45 is max jump height), or destination waypoint higher that source if ((dest.z > src.z + 40.0 || dest.z < src.z - 75.0) && (!(GetPath (index)->flags & FLAG_LADDER) || distance2D >= 16.0)) return false; // unable to reach this one @@ -1289,7 +1290,7 @@ bool Waypoint::IsNodeReachable (Vector src, Vector destination) // check if we go through a func_illusionary, in which case return false TraceHull (src, destination, ignore_monsters, head_hull, g_hostEntity, &tr); - if (!FNullEnt (tr.pHit) && strcmp ("func_illusionary", STRING (tr.pHit->v.classname)) == 0) + if (!IsEntityNull (tr.pHit) && strcmp ("func_illusionary", STRING (tr.pHit->v.classname)) == 0) return false; // don't add pathwaypoints through func_illusionaries // check if this waypoint is "visible"... @@ -1467,7 +1468,7 @@ char *Waypoint::GetWaypointInfo (int id) } static char messageBuffer[1024]; - sprintf (messageBuffer, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (path->flags == 0 && !jumpPoint) ? " (none)" : "", path->flags & FLAG_LIFT ? " LIFT" : "", path->flags & FLAG_CROUCH ? " CROUCH" : "", path->flags & FLAG_CROSSING ? " CROSSING" : "", path->flags & FLAG_CAMP ? " CAMP" : "", path->flags & FLAG_TF_ONLY ? " TERRORIST" : "", path->flags & FLAG_CF_ONLY ? " CT" : "", path->flags & FLAG_SNIPER ? " SNIPER" : "", path->flags & FLAG_GOAL ? " GOAL" : "", path->flags & FLAG_LADDER ? " LADDER" : "", path->flags & FLAG_RESCUE ? " RESCUE" : "", path->flags & FLAG_DOUBLEJUMP ? " JUMPHELP" : "", path->flags & FLAG_NOHOSTAGE ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : ""); + sprintf (messageBuffer, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (path->flags == 0 && !jumpPoint) ? " (none)" : "", (path->flags & FLAG_LIFT) ? " LIFT" : "", (path->flags & FLAG_CROUCH) ? " CROUCH" : "", (path->flags & FLAG_CROSSING) ? " CROSSING" : "", (path->flags & FLAG_CAMP) ? " CAMP" : "", (path->flags & FLAG_TF_ONLY) ? " TERRORIST" : "", (path->flags & FLAG_CF_ONLY) ? " CT" : "", (path->flags & FLAG_SNIPER) ? " SNIPER" : "", (path->flags & FLAG_GOAL) ? " GOAL" : "", (path->flags & FLAG_LADDER) ? " LADDER" : "", (path->flags & FLAG_RESCUE) ? " RESCUE" : "", (path->flags & FLAG_DOUBLEJUMP) ? " JUMPHELP" : "", (path->flags & FLAG_NOHOSTAGE) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : ""); // return the message buffer return messageBuffer; @@ -1477,7 +1478,7 @@ void Waypoint::Think (void) { // this function executes frame of waypoint operation code. - if (FNullEnt (g_hostEntity)) + if (IsEntityNull (g_hostEntity)) return; // this function is only valid on listenserver, and in waypoint enabled mode. float nearestDistance = FLT_MAX; @@ -1644,7 +1645,7 @@ void Waypoint::Think (void) // draw the camplines if (path->flags & FLAG_CAMP) { - Vector campSourceOrigin = campSourceOrigin = path->origin + Vector (0, 0, 36); + Vector campSourceOrigin = path->origin + Vector (0, 0, 36); // check if it's a source if (path->flags & FLAG_CROUCH) @@ -1807,7 +1808,7 @@ bool Waypoint::NodesValid (void) { connections = 0; - for (int j = 0; j < MAX_PATH_INDEX; j++) + for (j = 0; j < MAX_PATH_INDEX; j++) { if (m_paths[i]->index[j] != -1) { @@ -1987,15 +1988,15 @@ bool Waypoint::NodesValid (void) visited[current->index] = true; - IterateArray (outgoingPaths[current->index], j) + IterateArray (outgoingPaths[current->index], p) { - if (visited[outgoingPaths[current->index][j]]) + if (visited[outgoingPaths[current->index][p]]) continue; // skip this waypoint as it's already visited PathNode *pNewNode = new PathNode; pNewNode->next = stack; - pNewNode->index = outgoingPaths[current->index][j]; + pNewNode->index = outgoingPaths[current->index][p]; stack = pNewNode; } delete current; @@ -2006,7 +2007,7 @@ bool Waypoint::NodesValid (void) if (!visited[i]) { AddLogEntry (true, LL_WARNING, "Path broken from Waypoint #%d to Waypoint #0!", i); - (*g_engfuncs.pfnSetOrigin) (g_hostEntity, m_paths[i]->origin); + SET_ORIGIN (g_hostEntity, m_paths[i]->origin); g_waypointOn = true; g_editNoclip = true; @@ -2180,7 +2181,7 @@ void Waypoint::CreateBasic (void) edict_t *ent = NULL; // first of all, if map contains ladder points, create it - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_ladder"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_ladder"))) { Vector ladderLeft = ent->v.absmin; Vector ladderRight = ent->v.absmax; @@ -2229,7 +2230,7 @@ void Waypoint::CreateBasic (void) } // then terrortist spawnpoints - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_player_deathmatch"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_player_deathmatch"))) { Vector origin = GetEntityOrigin (ent); @@ -2238,7 +2239,7 @@ void Waypoint::CreateBasic (void) } // then add ct spawnpoints - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_player_start"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_player_start"))) { Vector origin = GetEntityOrigin (ent); @@ -2247,7 +2248,7 @@ void Waypoint::CreateBasic (void) } // then vip spawnpoint - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_vip_start"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_vip_start"))) { Vector origin = GetEntityOrigin (ent); @@ -2256,7 +2257,7 @@ void Waypoint::CreateBasic (void) } // hostage rescue zone - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_hostage_rescue"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_hostage_rescue"))) { Vector origin = GetEntityOrigin (ent); @@ -2265,7 +2266,7 @@ void Waypoint::CreateBasic (void) } // hostage rescue zone (same as above) - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_hostage_rescue"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_hostage_rescue"))) { Vector origin = GetEntityOrigin (ent); @@ -2274,7 +2275,7 @@ void Waypoint::CreateBasic (void) } // bombspot zone - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_bomb_target"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_bomb_target"))) { Vector origin = GetEntityOrigin (ent); @@ -2283,7 +2284,7 @@ void Waypoint::CreateBasic (void) } // bombspot zone (same as above) - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_bomb_target"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "info_bomb_target"))) { Vector origin = GetEntityOrigin (ent); @@ -2292,7 +2293,7 @@ void Waypoint::CreateBasic (void) } // hostage entities - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "hostage_entity"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "hostage_entity"))) { // if already saved || moving skip it if ((ent->v.effects & EF_NODRAW) && (ent->v.speed > 0)) @@ -2305,7 +2306,7 @@ void Waypoint::CreateBasic (void) } // vip rescue (safety) zone - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_vip_safetyzone"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_vip_safetyzone"))) { Vector origin = GetEntityOrigin (ent); @@ -2314,7 +2315,7 @@ void Waypoint::CreateBasic (void) } // terrorist escape zone - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_escapezone"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "func_escapezone"))) { Vector origin = GetEntityOrigin (ent); @@ -2323,7 +2324,7 @@ void Waypoint::CreateBasic (void) } // weapons on the map ? - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "armoury_entity"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "armoury_entity"))) { Vector origin = GetEntityOrigin (ent); @@ -2382,7 +2383,7 @@ void Waypoint::SetBombPosition (bool shouldReset) edict_t *ent = NULL; - while (!FNullEnt (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) + while (!IsEntityNull (ent = FIND_ENTITY_BY_CLASSNAME (ent, "grenade"))) { if (strcmp (STRING (ent->v.model) + 9, "c4.mdl") == 0) {