Bots are now able to destroy random breakables around him, without touching them.

Added cvars descriptions and yapb.cfg generation.
Finally fixed bomb-defuse problems.
Fixed unaligned access in bot compression/decompression.
Fixed low-fps aim code falure.
This commit is contained in:
jeefo 2019-08-24 12:43:42 +03:00
commit 91c4d9ce1f
21 changed files with 523 additions and 293 deletions

View file

@ -73,6 +73,7 @@ private:
int cmdNodeMenu ();
int cmdMenu ();
int cmdList ();
int cmdCvars ();
int cmdNode ();
int cmdNodeOn ();
int cmdNodeOff ();

View file

@ -66,6 +66,9 @@ namespace detail {
// basic dictionary
template <class K, class V, class H = StringHash <K>, size_t HashSize = 36> class Dictionary final : public DenyCopying {
private:
using DictBucket = detail::DictionaryBucket <K, V>;
public:
enum : size_t {
InvalidIndex = static_cast <size_t> (-1)
@ -73,7 +76,7 @@ public:
private:
Array <detail::DictionaryList *> m_table;
Array <detail::DictionaryBucket <K, V>> m_buckets;
Array <DictBucket> m_buckets;
H m_hasher;
private:
@ -226,19 +229,19 @@ public:
// for range-based loops
public:
detail::DictionaryBucket <K, V> *begin () {
DictBucket *begin () {
return m_buckets.begin ();
}
detail::DictionaryBucket <K, V> *begin () const {
DictBucket *begin () const {
return m_buckets.begin ();
}
detail::DictionaryBucket <K, V> *end () {
DictBucket *end () {
return m_buckets.end ();
}
detail::DictionaryBucket <K, V> *end () const {
DictBucket *end () const {
return m_buckets.end ();
}
};

View file

@ -90,11 +90,11 @@ public:
return fprintf (m_handle, fmt, cr::forward <Args> (args)...);
}
bool puts (const String &buffer) {
bool puts (const char *buffer) {
if (!*this) {
return 0;
}
if (fputs (buffer.chars (), m_handle) < 0) {
if (fputs (buffer, m_handle) < 0) {
return false;
}
return true;

View file

@ -74,6 +74,9 @@ public:
public:
bool patch (void *address, void *replacement) {
if (plat.isArm) {
return false;
}
uint8 *ptr = reinterpret_cast <uint8 *> (address);
while (*reinterpret_cast <uint16 *> (ptr) == 0x25ff) {

View file

@ -51,6 +51,13 @@ CR_NAMESPACE_BEGIN
# define CR_ARCH_X86
#endif
#if defined(__arm__)
# define CR_ARCH_ARM
# if defined(__aarch64__)
# define CR_ARCH_ARM64
# endif
#endif
#if (defined(CR_ARCH_X86) || defined(CR_ARCH_X64)) && !defined(CR_DEBUG)
# define CR_HAS_SSE2
#endif
@ -85,6 +92,7 @@ struct Platform : public Singleton <Platform> {
bool isAndroid = false;
bool isAndroidHardFP = false;
bool isX64 = false;
bool isArm = false;
Platform () {
#if defined(CR_WINDOWS)
@ -94,22 +102,27 @@ struct Platform : public Singleton <Platform> {
#if defined(CR_ANDROID)
isAndroid = true;
# if defined (CR_ANDROID_HARD_FP)
# if defined (CR_ANDROID_HARD_FP)
isAndroidHardFP = true;
# endif
# endif
#endif
#if defined(CR_LINUX)
isLinux = true;
#endif
#if defined (CR_OSX)
#if defined(CR_OSX)
isOSX = true;
#endif
#if defined (CR_ARCH_X64)
#if defined(CR_ARCH_X64) || defined(CR_ARCH_ARM64)
isX64 = true;
#endif
#if defined(CR_ARCH_ARM)
isArm = true;
isAndroid = true;
#endif
}
// helper platform-dependant functions

View file

@ -52,7 +52,7 @@ public:
for (auto &htb : m_hashTable) {
htb = EmptyHash;
}
uint8 *op = out;
auto op = out;
int32 anchor = 0;
int32 cur = 0;
@ -99,9 +99,9 @@ public:
}
if (bestLength >= MinMatch && bestLength < maxMatch && (cur - anchor) != 6) {
const int32 next = cur + 1;
const int32 target = bestLength + 1;
const int32 limit = cr::max <int32> (next - WindowSize, EmptyHash);
const auto next = cur + 1;
const auto target = bestLength + 1;
const auto limit = cr::max <int32> (next - WindowSize, EmptyHash);
int32 chainLength = MaxChain;
int32 lookup = m_hashTable[hash32 (&in[next])];
@ -128,11 +128,11 @@ public:
}
if (bestLength >= MinMatch) {
const int32 length = bestLength - MinMatch;
const int32 token = ((dist >> 12) & 16) + cr::min <int32> (length, 15);
const auto length = bestLength - MinMatch;
const auto token = ((dist >> 12) & 16) + cr::min <int32> (length, 15);
if (anchor != cur) {
const int32 run = cur - anchor;
const auto run = cur - anchor;
if (run >= 7) {
add (op, (7 << 5) + token);
@ -155,7 +155,7 @@ public:
op += 2;
while (bestLength-- != 0) {
const uint32 hash = hash32 (&in[cur]);
const auto hash = hash32 (&in[cur]);
m_prevTable[cur & WindowMask] = m_hashTable[hash];
m_hashTable[hash] = cur++;
@ -163,7 +163,7 @@ public:
anchor = cur;
}
else {
const uint32 hash = hash32 (&in[cur]);
const auto hash = hash32 (&in[cur]);
m_prevTable[cur & WindowMask] = m_hashTable[hash];
m_hashTable[hash] = cur++;
@ -171,7 +171,7 @@ public:
}
if (anchor != cur) {
const int32 run = cur - anchor;
const auto run = cur - anchor;
if (run >= 7) {
add (op, 7 << 5);
@ -187,17 +187,17 @@ public:
}
int32 uncompress (uint8 *in, int32 inputLength, uint8 *out, int32 outLength) {
uint8 *op = out;
uint8 *ip = in;
auto op = out;
auto ip = in;
const uint8 *opEnd = op + outLength;
const uint8 *ipEnd = ip + inputLength;
const auto opEnd = op + outLength;
const auto ipEnd = ip + inputLength;
while (ip < ipEnd) {
const int32 token = *ip++;
const auto token = *ip++;
if (token >= 32) {
int32 run = token >> 5;
auto run = token >> 5;
if (run == 7) {
run += decode (ip);
@ -215,7 +215,7 @@ public:
break;
}
}
int32 length = (token & 15) + MinMatch;
auto length = (token & 15) + MinMatch;
if (length == (15 + MinMatch)) {
length += decode (ip);
@ -224,10 +224,10 @@ public:
if ((opEnd - op) < length) {
return UncompressFailure;
}
const int32 dist = ((token & 16) << 12) + load16 (ip);
const auto dist = ((token & 16) << 12) + load16 (ip);
ip += 2;
uint8 *cp = op - dist;
auto cp = op - dist;
if ((op - out) < dist) {
return UncompressFailure;
@ -237,8 +237,7 @@ public:
copy (op, cp, length);
op += length;
}
else
{
else {
for (int32 i = 0; i < 4; ++i) {
*op++ = *cp++;
}
@ -252,27 +251,33 @@ public:
}
private:
inline uint16 load16 (void *ptr) {
return *reinterpret_cast <const uint16 *> (ptr);
uint16 load16 (void *ptr) {
uint16 ret;
memcpy (&ret, ptr, sizeof (uint16));
return ret;
}
inline uint32 load32 (void *ptr) {
return *reinterpret_cast <const uint32 *> (ptr);
uint32 load32 (void *ptr) {
uint32 ret;
memcpy (&ret, ptr, sizeof (uint32));
return ret;
}
inline void store16 (void *ptr, int32 val) {
*reinterpret_cast <uint16 *> (ptr) = static_cast <uint16> (val);
void store16 (void *ptr, int32 val) {
memcpy (ptr, &val, sizeof (uint16));
}
inline void copy64 (void *dst, void *src) {
*reinterpret_cast <uint64 *> (dst) = *reinterpret_cast <const uint64 *> (src);
void copy64 (void *dst, void *src) {
memcpy (dst, src, sizeof (uint64));
}
inline uint32 hash32 (void *ptr) {
return (load32 (ptr) * 0x9E3779B9) >> (32 - HashBits);
uint32 hash32 (void *ptr) {
return (load32 (ptr) * 0x9e3779b9) >> (32 - HashBits);
}
inline void copy (uint8 *dst, uint8 *src, int32 count) {
void copy (uint8 *dst, uint8 *src, int32 count) {
copy64 (dst, src);
for (int32 i = 8; i < count; i += 8) {
@ -280,11 +285,11 @@ private:
}
}
inline void add (uint8 *&dst, int32 val) {
void add (uint8 *&dst, int32 val) {
*dst++ = static_cast <uint8> (val);
}
inline void encode (uint8 *&ptr, uint32 val) {
void encode (uint8 *&ptr, uint32 val) {
while (val >= 128) {
val -= 128;
@ -294,7 +299,7 @@ private:
*ptr++ = static_cast <uint8> (val);
}
inline uint32 decode (uint8 *&ptr) {
uint32 decode (uint8 *&ptr) {
uint32 val = 0;
for (int32 i = 0; i <= 21; i += 7) {
@ -309,6 +314,4 @@ private:
}
};
CR_NAMESPACE_END

View file

@ -74,6 +74,9 @@ struct VarPair {
bool missing;
const char *regval;
class ConVar *self;
String info;
float initial, min, max;
bool bounded;
};
// entity prototype
@ -95,6 +98,7 @@ private:
edict_t *m_startEntity;
edict_t *m_localEntity;
Array <edict_t *> m_breakables;
SmallArray <VarPair> m_cvars;
SharedLibrary m_gameLib;
@ -137,10 +141,10 @@ public:
const char *getMapName ();
// get the "any" entity origin
Vector getAbsPos (edict_t *ent);
Vector getEntityWorldOrigin (edict_t *ent);
// registers a server command
void registerEngineCommand (const char *command, void func_ ());
void registerEngineCommand (const char *command, void func ());
// play's sound to client
void playSound (edict_t *ent, const char *sound);
@ -149,7 +153,10 @@ public:
void prepareBotArgs (edict_t *ent, String str);
// adds cvar to registration stack
void addNewCvar (const char *variable, const char *value, Var varType, bool regMissing, const char *regVal, class ConVar *self);
void addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, class ConVar *self);
// check the cvar bounds
void checkCvarsBounds ();
// sends local registration stack for engine registration
void registerCvars (bool gameVars = false);
@ -175,6 +182,9 @@ public:
// search entities in sphere
void searchEntities (const Vector &position, const float radius, EntitySearch functor);
// this function is checking that pointed by ent pointer obstacle, can be destroyed
bool isShootableBreakable (edict_t *ent);
// public inlines
public:
// get the current time on server
@ -294,6 +304,21 @@ public:
return m_gameLib;
}
// get registered cvars list
const SmallArray <VarPair> &getCvars () {
return m_cvars;
}
// check if map has breakables
const Array <edict_t *> &getBreakables () {
return m_breakables;
}
// map has breakables ?
bool hasBreakables () const {
return !m_breakables.empty ();
}
// helper to sending the client message
void sendClientMessage (bool console, edict_t *ent, const char *message);
@ -332,33 +357,41 @@ public:
};
// simplify access for console variables
class ConVar final {
class ConVar final : public DenyCopying {
public:
cvar_t *eptr;
cvar_t *ptr;
public:
ConVar (const char *name, const char *initval, Var type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : eptr (nullptr) {
Game::get ().addNewCvar (name, initval, type, regMissing, regVal, this);
ConVar () = delete;
~ConVar () = default;
public:
ConVar (const char *name, const char *initval, Var type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
Game::get ().addNewCvar (name, initval, "", false, 0.0f, 0.0f, type, regMissing, regVal, this);
}
ConVar (const char *name, const char *initval, const char *info, bool bounded = true, float min = 0.0f, float max = 1.0f, Var type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
Game::get ().addNewCvar (name, initval, info, bounded, min, max, type, regMissing, regVal, this);
}
bool bool_ () const {
return eptr->value > 0.0f;
return ptr->value > 0.0f;
}
int int_ () const {
return static_cast <int> (eptr->value);
return static_cast <int> (ptr->value);
}
float float_ () const {
return eptr->value;
return ptr->value;
}
const char *str () const {
return eptr->string;
return ptr->string;
}
void set (float val) {
engfuncs.pfnCVarSetFloat (eptr->name, val);
engfuncs.pfnCVarSetFloat (ptr->name, val);
}
void set (int val) {
@ -366,7 +399,7 @@ public:
}
void set (const char *val) {
engfuncs.pfnCvar_DirectSet (eptr, const_cast <char *> (val));
engfuncs.pfnCvar_DirectSet (ptr, const_cast <char *> (val));
}
};
@ -541,7 +574,7 @@ public:
};
// for android
#if defined (CR_ANDROID)
#if defined (CR_ANDROID) && defined(CR_ARCH_ARM)
extern "C" void player (entvars_t *pev);
#endif
@ -588,7 +621,7 @@ public:
public:
void initialize () {
if (plat.isAndroid) {
if (plat.isArm) {
return;
}
m_dlsym.patch (reinterpret_cast <void *> (&LookupSymbol), reinterpret_cast <void *> (&DynamicEntityLink::replacement));
@ -596,7 +629,7 @@ public:
}
EntityFunction getPlayerFunction () {
#if defined (CR_ANDROID)
#if defined (CR_ANDROID) && defined(CR_ARCH_ARM)
return player;
#else
return reinterpret_cast <EntityFunction> (search (Game::get ().lib ().handle (), "player"));

View file

@ -259,7 +259,7 @@ private:
Vector m_learnVelocity;
Vector m_learnPosition;
Vector m_bombPos;
Vector m_bombOrigin;
Vector m_lastNode;
IntArray m_terrorPoints;
@ -344,7 +344,7 @@ public:
void initBuckets ();
void addToBucket (const Vector &pos, int index);
void eraseFromBucket (const Vector &pos, int index);
void setBombPos (bool reset = false, const Vector &pos = nullptr);
void setBombOrigin (bool reset = false, const Vector &pos = nullptr);
void updateGlobalPractice ();
void unassignPath (int from, int to);
void setDangerValue (int team, int start, int goal, int value);
@ -393,8 +393,8 @@ public:
m_autoPathDistance = distance;
}
const Vector &getBombPos () const {
return m_bombPos;
const Vector &getBombOrigin () const {
return m_bombOrigin;
}
// access paths

View file

@ -118,11 +118,11 @@ public:
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);
public:
Array <edict_t *> &searchActiveGrenades () {
const Array <edict_t *> &searchActiveGrenades () {
return m_activeGrenades;
}
Array <edict_t *> &searchIntrestingEntities () {
const Array <edict_t *> &searchIntrestingEntities () {
return m_intrestingEntities;
}

View file

@ -268,13 +268,13 @@ CR_DECLARE_SCOPED_ENUM (Weapon,
// buy counts
CR_DECLARE_SCOPED_ENUM (BuyState,
PrimaryWeapon = 0,
ArmorVestHelm ,
SecondaryWeapon,
Grenades,
DefusalKit,
Ammo,
NightVision,
Done
ArmorVestHelm,
SecondaryWeapon,
Grenades,
DefusalKit,
Ammo,
NightVision,
Done
)
// economics limits
@ -284,7 +284,7 @@ CR_DECLARE_SCOPED_ENUM (EcoLimit,
SmgTEGreater,
ShotgunGreater,
ShotgunLess,
HeavyGreater ,
HeavyGreater,
HeavyLess,
ProstockNormal,
ProstockRusher,
@ -513,11 +513,17 @@ public:
{ }
};
// clients noise
struct ClientNoise {
Vector pos;
float dist;
float last;
};
// array of clients struct
struct Client {
edict_t *ent; // pointer to actual edict
Vector origin; // position in the world
Vector sound; // position sound was played
int team; // bot team
int team2; // real bot team in free for all mode (csdm)
int flags; // client flags
@ -526,9 +532,8 @@ struct Client {
int ping; // when bot latency is enabled, client ping stored here
int iconFlags[kGameMaxPlayers]; // flag holding chatter icons
float iconTimestamp[kGameMaxPlayers]; // timers for chatter icons
float hearingDistance; // distance this sound is heared
float timeSoundLasting; // time sound is played/heared
bool pingUpdate; // update ping ?
ClientNoise noise;
};
// define chatting collection structure
@ -733,7 +738,6 @@ private:
bool isOccupiedNode (int index);
bool seesItem (const Vector &dest, const char *itemName);
bool lastEnemyShootable ();
bool isShootableBreakable (edict_t *ent);
bool rateGroundWeapon (edict_t *ent);
bool reactOnEnemy ();
bool selectBestNextNode ();
@ -975,6 +979,7 @@ public:
void showChaterIcon (bool show);
void clearSearchNodes ();
void checkBreakable (edict_t *touch);
void checkBreablesAround ();
void startTask (Task id, float desire, int data, float time, bool resume);
void clearTask (Task id);
void filterTasks ();