Fixed crash in message dispatcher after 'meta unload'.
Various cosmetic changes.
This commit is contained in:
parent
9720a63401
commit
ff6c56aeac
37 changed files with 949 additions and 602 deletions
|
|
@ -207,7 +207,7 @@ template <typename ...Args> inline void BotControl::msg (const char *fmt, Args .
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_isFromConsole || strlen (result) > 48) {
|
if (m_isFromConsole || strlen (result) > 56) {
|
||||||
game.clientPrint (m_ent, result);
|
game.clientPrint (m_ent, result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,12 @@
|
||||||
#define CR_NAMESPACE_BEGIN namespace cr {
|
#define CR_NAMESPACE_BEGIN namespace cr {
|
||||||
#define CR_NAMESPACE_END }
|
#define CR_NAMESPACE_END }
|
||||||
|
|
||||||
// undef base max
|
// disable microsoft deprecation warning
|
||||||
#if defined (max)
|
#if defined (_MSC_VER)
|
||||||
# undef max
|
# if !defined (_CRT_SECURE_NO_DEPRECATE)
|
||||||
|
# define _CRT_SECURE_NO_DEPRECATE
|
||||||
|
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// undef base min
|
|
||||||
#if defined (min)
|
|
||||||
# undef min
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ CR_NAMESPACE_BEGIN
|
||||||
// template for hashing our string
|
// template for hashing our string
|
||||||
template <typename K> struct StringHash {
|
template <typename K> struct StringHash {
|
||||||
uint32 operator () (const K &key) const {
|
uint32 operator () (const K &key) const {
|
||||||
char *str = const_cast <char *> (key.chars ());
|
auto str = const_cast <char *> (key.chars ());
|
||||||
uint32 hash = 0;
|
uint32 hash = 0;
|
||||||
|
|
||||||
while (*str++) {
|
while (*str++) {
|
||||||
|
|
@ -68,6 +68,7 @@ namespace detail {
|
||||||
template <class K, class V, class H = StringHash <K>, size_t HashSize = 36> class Dictionary final : public DenyCopying {
|
template <class K, class V, class H = StringHash <K>, size_t HashSize = 36> class Dictionary final : public DenyCopying {
|
||||||
private:
|
private:
|
||||||
using DictBucket = detail::DictionaryBucket <K, V>;
|
using DictBucket = detail::DictionaryBucket <K, V>;
|
||||||
|
using DictList = detail::DictionaryList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
|
|
@ -75,7 +76,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Array <detail::DictionaryList *> m_table;
|
Array <DictList *> m_table;
|
||||||
Array <DictBucket> m_buckets;
|
Array <DictBucket> m_buckets;
|
||||||
H m_hasher;
|
H m_hasher;
|
||||||
|
|
||||||
|
|
@ -98,7 +99,7 @@ private:
|
||||||
size_t created = m_buckets.length ();
|
size_t created = m_buckets.length ();
|
||||||
m_buckets.resize (created + 1);
|
m_buckets.resize (created + 1);
|
||||||
|
|
||||||
auto allocated = alloc.allocate <detail::DictionaryList> ();
|
auto allocated = alloc.allocate <DictList> ();
|
||||||
|
|
||||||
allocated->index = created;
|
allocated->index = created;
|
||||||
allocated->next = m_table[pos];
|
allocated->next = m_table[pos];
|
||||||
|
|
@ -163,7 +164,7 @@ public:
|
||||||
auto pos = hashed % m_table.length ();
|
auto pos = hashed % m_table.length ();
|
||||||
auto *bucket = m_table[pos];
|
auto *bucket = m_table[pos];
|
||||||
|
|
||||||
detail::DictionaryList *next = nullptr;
|
DictList *next = nullptr;
|
||||||
|
|
||||||
while (bucket != nullptr) {
|
while (bucket != nullptr) {
|
||||||
if (m_buckets[bucket->index].hash == hashed) {
|
if (m_buckets[bucket->index].hash == hashed) {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ public:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool open (const String &file, const String &mode) {
|
bool open (const String &file, const String &mode) {
|
||||||
|
if (*this) {
|
||||||
|
close ();
|
||||||
|
}
|
||||||
|
|
||||||
if ((m_handle = fopen (file.chars (), mode.chars ())) == nullptr) {
|
if ((m_handle = fopen (file.chars (), mode.chars ())) == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,25 @@ CR_NAMESPACE_BEGIN
|
||||||
class SimpleHook : DenyCopying {
|
class SimpleHook : DenyCopying {
|
||||||
private:
|
private:
|
||||||
enum : uint32 {
|
enum : uint32 {
|
||||||
CodeLength = 12
|
#if defined (CR_ARCH_X64)
|
||||||
|
CodeLength = 14
|
||||||
|
#else
|
||||||
|
CodeLength = 6
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined (CR_ARCH_X64)
|
||||||
|
using uint = uint64;
|
||||||
|
#else
|
||||||
|
using uint = uint32;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_patched;
|
bool m_patched;
|
||||||
|
|
||||||
uint32 m_pageSize;
|
uint m_pageSize;
|
||||||
uint32 m_origFunc;
|
uint m_origFunc;
|
||||||
uint32 m_hookFunc;
|
uint m_hookFunc;
|
||||||
|
|
||||||
uint8 m_origBytes[CodeLength] {};
|
uint8 m_origBytes[CodeLength] {};
|
||||||
uint8 m_hookBytes[CodeLength] {};
|
uint8 m_hookBytes[CodeLength] {};
|
||||||
|
|
@ -45,9 +55,11 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void *align (void *address) {
|
#if !defined (CR_WINDOWS)
|
||||||
|
void *align (void *address) {
|
||||||
return reinterpret_cast <void *> ((reinterpret_cast <long> (address) & ~(m_pageSize - 1)));
|
return reinterpret_cast <void *> ((reinterpret_cast <long> (address) & ~(m_pageSize - 1)));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool unprotect () {
|
bool unprotect () {
|
||||||
auto orig = reinterpret_cast <void *> (m_origFunc);
|
auto orig = reinterpret_cast <void *> (m_origFunc);
|
||||||
|
|
@ -74,25 +86,36 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool patch (void *address, void *replacement) {
|
bool patch (void *address, void *replacement) {
|
||||||
if (plat.isArm) {
|
const uint16 jmp = 0x25ff;
|
||||||
|
|
||||||
|
if (plat.arm) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint8 *ptr = reinterpret_cast <uint8 *> (address);
|
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||||
|
|
||||||
while (*reinterpret_cast <uint16 *> (ptr) == 0x25ff) {
|
while (*reinterpret_cast <uint16 *> (ptr) == jmp) {
|
||||||
ptr = **reinterpret_cast <uint8 * **> ((ptr + 2));
|
ptr = **reinterpret_cast <uint8 * **> (ptr + 2);
|
||||||
}
|
}
|
||||||
m_origFunc = reinterpret_cast <uint32> (ptr);
|
m_origFunc = reinterpret_cast <uint> (address);
|
||||||
|
|
||||||
if (!m_origFunc) {
|
if (!m_origFunc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_hookFunc = reinterpret_cast <uint32> (replacement);
|
m_hookFunc = reinterpret_cast <uint> (replacement);
|
||||||
|
|
||||||
|
if (plat.x64) {
|
||||||
|
const uint16 nop = 0x00000000;
|
||||||
|
|
||||||
|
memcpy (&m_hookBytes[0], &jmp, sizeof (uint16));
|
||||||
|
memcpy (&m_hookBytes[2], &nop, sizeof (uint16));
|
||||||
|
memcpy (&m_hookBytes[6], &replacement, sizeof (uint));
|
||||||
|
}
|
||||||
|
else {
|
||||||
m_hookBytes[0] = 0x68;
|
m_hookBytes[0] = 0x68;
|
||||||
m_hookBytes[5] = 0xc3;
|
m_hookBytes[5] = 0xc3;
|
||||||
|
|
||||||
*reinterpret_cast <uint32 *> (&m_hookBytes[1]) = m_hookFunc;
|
memcpy (&m_hookBytes[1], &m_hookFunc, sizeof (uint));
|
||||||
|
}
|
||||||
|
|
||||||
if (unprotect ()) {
|
if (unprotect ()) {
|
||||||
memcpy (m_origBytes, reinterpret_cast <void *> (m_origFunc), CodeLength);
|
memcpy (m_origBytes, reinterpret_cast <void *> (m_origFunc), CodeLength);
|
||||||
|
|
|
||||||
|
|
@ -374,19 +374,19 @@ public:
|
||||||
if (boundarySlash != String::InvalidIndex) {
|
if (boundarySlash != String::InvalidIndex) {
|
||||||
boundaryName = localPath.substr (boundarySlash + 1);
|
boundaryName = localPath.substr (boundarySlash + 1);
|
||||||
}
|
}
|
||||||
const String &kBoundary = "---crlib_upload_boundary_1337";
|
const String &boundaryLine = "---crlib_upload_boundary_1337";
|
||||||
|
|
||||||
String request, start, end;
|
String request, start, end;
|
||||||
start.appendf ("--%s\r\n", kBoundary.chars ());
|
start.appendf ("--%s\r\n", boundaryLine.chars ());
|
||||||
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName.chars ());
|
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName.chars ());
|
||||||
start.append ("Content-Type: application/octet-stream\r\n\r\n");
|
start.append ("Content-Type: application/octet-stream\r\n\r\n");
|
||||||
|
|
||||||
end.appendf ("\r\n--%s--\r\n\r\n", kBoundary.chars ());
|
end.appendf ("\r\n--%s--\r\n\r\n", boundaryLine.chars ());
|
||||||
|
|
||||||
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path.chars ());
|
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path.chars ());
|
||||||
request.appendf ("Host: %s\r\n", uri.host.chars ());
|
request.appendf ("Host: %s\r\n", uri.host.chars ());
|
||||||
request.appendf ("User-Agent: %s\r\n", m_userAgent.chars ());
|
request.appendf ("User-Agent: %s\r\n", m_userAgent.chars ());
|
||||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", kBoundary.chars ());
|
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", boundaryLine.chars ());
|
||||||
request.appendf ("Content-Length: %d\r\n\r\n", file.length () + start.length () + end.length ());
|
request.appendf ("Content-Length: %d\r\n\r\n", file.length () + start.length () + end.length ());
|
||||||
|
|
||||||
// send the main request
|
// send the main request
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||||
return createUniqueBase <LambdaFunctor <T>, LambdaFunctorWrapper> (m_callable);
|
return makeUnique <LambdaFunctor <T>> (m_callable);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Lambda () noexcept : Lambda (nullptr)
|
explicit Lambda () noexcept : Lambda (nullptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Lambda (decltype (nullptr)) noexcept : m_functor (nullptr), m_smallObject (false)
|
Lambda (decltype (nullptr)) noexcept : m_functor (nullptr), m_smallObject (false)
|
||||||
|
|
@ -124,7 +124,7 @@ public:
|
||||||
template <typename F> Lambda (F function) {
|
template <typename F> Lambda (F function) {
|
||||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||||
m_smallObject = false;
|
m_smallObject = false;
|
||||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (createUniqueBase <LambdaFunctor <F>, LambdaFunctorWrapper> (cr::move (function)));
|
new (m_small) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_smallObject = true;
|
m_smallObject = true;
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,8 @@
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#elif defined (CR_WINDOWS)
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CR_NAMESPACE_BEGIN
|
CR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// handling dynamic library loading
|
// handling dynamic library loading
|
||||||
|
|
@ -47,6 +43,10 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool load (const String &file) noexcept {
|
bool load (const String &file) noexcept {
|
||||||
|
if (*this) {
|
||||||
|
unload ();
|
||||||
|
}
|
||||||
|
|
||||||
#if defined (CR_WINDOWS)
|
#if defined (CR_WINDOWS)
|
||||||
m_handle = LoadLibraryA (file.chars ());
|
m_handle = LoadLibraryA (file.chars ());
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,6 @@
|
||||||
#include <crlib/cr-files.h>
|
#include <crlib/cr-files.h>
|
||||||
#include <crlib/cr-lambda.h>
|
#include <crlib/cr-lambda.h>
|
||||||
|
|
||||||
#if defined (CR_WINDOWS)
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CR_NAMESPACE_BEGIN
|
CR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class SimpleLogger final : public Singleton <SimpleLogger> {
|
class SimpleLogger final : public Singleton <SimpleLogger> {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,15 @@ CR_NAMESPACE_END
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
|
|
||||||
|
# if defined (max)
|
||||||
|
# undef max
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined (min)
|
||||||
|
# undef min
|
||||||
|
# endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <strings.h>
|
# include <strings.h>
|
||||||
|
|
@ -77,8 +86,10 @@ CR_NAMESPACE_END
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#if defined (CR_ANDROID)
|
#if defined (CR_ANDROID)
|
||||||
# include <android/log.h>
|
# include <android/log.h>
|
||||||
|
|
@ -88,42 +99,42 @@ CR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// helper struct for platform detection
|
// helper struct for platform detection
|
||||||
struct Platform : public Singleton <Platform> {
|
struct Platform : public Singleton <Platform> {
|
||||||
bool isWindows = false;
|
bool win32 = false;
|
||||||
bool isLinux = false;
|
bool linux = false;
|
||||||
bool isOSX = false;
|
bool osx = false;
|
||||||
bool isAndroid = false;
|
bool android = false;
|
||||||
bool isAndroidHardFP = false;
|
bool hfp = false;
|
||||||
bool isX64 = false;
|
bool x64 = false;
|
||||||
bool isArm = false;
|
bool arm = false;
|
||||||
|
|
||||||
Platform () {
|
Platform () {
|
||||||
#if defined(CR_WINDOWS)
|
#if defined(CR_WINDOWS)
|
||||||
isWindows = true;
|
win32 = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CR_ANDROID)
|
#if defined(CR_ANDROID)
|
||||||
isAndroid = true;
|
android = true;
|
||||||
|
|
||||||
# if defined (CR_ANDROID_HARD_FP)
|
# if defined (CR_ANDROID_HARD_FP)
|
||||||
isAndroidHardFP = true;
|
hfp = true;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CR_LINUX)
|
#if defined(CR_LINUX)
|
||||||
isLinux = true;
|
linux = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CR_OSX)
|
#if defined(CR_OSX)
|
||||||
isOSX = true;
|
osx = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CR_ARCH_X64) || defined(CR_ARCH_ARM64)
|
#if defined(CR_ARCH_X64) || defined(CR_ARCH_ARM64)
|
||||||
isX64 = true;
|
x64 = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CR_ARCH_ARM)
|
#if defined(CR_ARCH_ARM)
|
||||||
isArm = true;
|
arm = true;
|
||||||
isAndroid = true;
|
android = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,38 @@
|
||||||
|
|
||||||
CR_NAMESPACE_BEGIN
|
CR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T> uint8 &getMostSignificantByte (T &object) {
|
||||||
|
return *(reinterpret_cast <uint8 *> (&object) + sizeof (object) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N> bool getLeastSignificantBit (uint8 byte) {
|
||||||
|
return byte & cr::bit (N);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N> bool getMostSignificantBit (uint8 byte) {
|
||||||
|
return byte & cr::bit (CHAR_BIT - N - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N> void setLeastSignificantBit (uint8 &byte, bool bit) {
|
||||||
|
if (bit) {
|
||||||
|
byte |= cr::bit (N);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte &= ~cr::bit (N);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t N> void setMostSignificantBit (uint8 &byte, bool bit) {
|
||||||
|
if (bit) {
|
||||||
|
byte |= cr::bit (CHAR_BIT - N - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte &= ~cr::bit (CHAR_BIT - N - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// small-string optimized string class, sso stuff based on: https://github.com/elliotgoodrich/SSO-23/
|
// small-string optimized string class, sso stuff based on: https://github.com/elliotgoodrich/SSO-23/
|
||||||
class String final {
|
class String final {
|
||||||
public:
|
public:
|
||||||
|
|
@ -30,7 +62,6 @@ public:
|
||||||
private:
|
private:
|
||||||
enum : size_t {
|
enum : size_t {
|
||||||
ExcessSpace = 32,
|
ExcessSpace = 32,
|
||||||
CharBit = CHAR_BIT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -77,8 +108,7 @@ public:
|
||||||
assign (ch);
|
assign (ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
String (String &&rhs) noexcept {
|
String (String &&rhs) noexcept : m_data (rhs.m_data) {
|
||||||
m_data = rhs.m_data;
|
|
||||||
rhs.setMoved ();
|
rhs.setMoved ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,35 +117,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T> static uint8 &getMostSignificantByte (T &object) {
|
|
||||||
return *(reinterpret_cast <uint8 *> (&object) + sizeof (object) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N> static bool getLeastSignificantBit (uint8 byte) {
|
|
||||||
return byte & cr::bit (N);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N> static bool getMostSignificantBit (uint8 byte) {
|
|
||||||
return byte & cr::bit (CharBit - N - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N> static void setLeastSignificantBit (uint8 &byte, bool bit) {
|
|
||||||
if (bit) {
|
|
||||||
byte |= cr::bit (N);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
byte &= ~cr::bit (N);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N> static void setMostSignificantBit (uint8 &byte, bool bit) {
|
|
||||||
if (bit) {
|
|
||||||
byte |= cr::bit (CharBit - N - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
byte &= ~cr::bit (CharBit - N - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy () {
|
void destroy () {
|
||||||
if (!isSmall ()) {
|
if (!isSmall ()) {
|
||||||
|
|
@ -162,7 +163,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSmall () const {
|
bool isSmall () const {
|
||||||
return !getLeastSignificantBit <0> (m_data.small.length) && !getLeastSignificantBit <1> (m_data.small.length);
|
return !detail::getLeastSignificantBit <0> (m_data.small.length) && !detail::getLeastSignificantBit <1> (m_data.small.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSmallLength (uint8 length) {
|
void setSmallLength (uint8 length) {
|
||||||
|
|
@ -174,18 +175,18 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDataNonSmall (size_t length, size_t capacity) {
|
void setDataNonSmall (size_t length, size_t capacity) {
|
||||||
uint8 &lengthHighByte = getMostSignificantByte (length);
|
uint8 &lengthHighByte = detail::getMostSignificantByte (length);
|
||||||
uint8 &capacityHighByte = getMostSignificantByte (capacity);
|
uint8 &capacityHighByte = detail::getMostSignificantByte (capacity);
|
||||||
|
|
||||||
const bool lengthHasHighBit = getMostSignificantBit <0> (lengthHighByte);
|
const bool lengthHasHighBit = detail::getMostSignificantBit <0> (lengthHighByte);
|
||||||
const bool capacityHasHighBit = getMostSignificantBit <0> (capacityHighByte);
|
const bool capacityHasHighBit = detail::getMostSignificantBit <0> (capacityHighByte);
|
||||||
const bool capacityHasSecHighBit = getMostSignificantBit <1> (capacityHighByte);
|
const bool capacityHasSecHighBit = detail::getMostSignificantBit <1> (capacityHighByte);
|
||||||
|
|
||||||
setMostSignificantBit <0> (lengthHighByte, capacityHasSecHighBit);
|
detail::setMostSignificantBit <0> (lengthHighByte, capacityHasSecHighBit);
|
||||||
|
|
||||||
capacityHighByte <<= 2;
|
capacityHighByte <<= 2;
|
||||||
setLeastSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
detail::setLeastSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||||
setLeastSignificantBit <1> (capacityHighByte, !lengthHasHighBit);
|
detail::setLeastSignificantBit <1> (capacityHighByte, !lengthHasHighBit);
|
||||||
|
|
||||||
m_data.big.length = length;
|
m_data.big.length = length;
|
||||||
m_data.big.capacity = capacity;
|
m_data.big.capacity = capacity;
|
||||||
|
|
@ -195,18 +196,18 @@ private:
|
||||||
size_t length = m_data.big.length;
|
size_t length = m_data.big.length;
|
||||||
size_t capacity = m_data.big.capacity;
|
size_t capacity = m_data.big.capacity;
|
||||||
|
|
||||||
uint8 &lengthHighByte = getMostSignificantByte (length);
|
uint8 &lengthHighByte = detail::getMostSignificantByte (length);
|
||||||
uint8 &capacityHighByte = getMostSignificantByte (capacity);
|
uint8 &capacityHighByte = detail::getMostSignificantByte (capacity);
|
||||||
|
|
||||||
const bool capacityHasHighBit = getLeastSignificantBit <0> (capacityHighByte);
|
const bool capacityHasHighBit = detail::getLeastSignificantBit <0> (capacityHighByte);
|
||||||
const bool lengthHasHighBit = !getLeastSignificantBit <1> (capacityHighByte);
|
const bool lengthHasHighBit = !detail::getLeastSignificantBit <1> (capacityHighByte);
|
||||||
const bool capacityHasSecHighBit = getMostSignificantBit <0> (lengthHighByte);
|
const bool capacityHasSecHighBit = detail::getMostSignificantBit <0> (lengthHighByte);
|
||||||
|
|
||||||
setMostSignificantBit <0> (lengthHighByte, lengthHasHighBit);
|
detail::setMostSignificantBit <0> (lengthHighByte, lengthHasHighBit);
|
||||||
|
|
||||||
capacityHighByte >>= 2;
|
capacityHighByte >>= 2;
|
||||||
setMostSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
detail::setMostSignificantBit <0> (capacityHighByte, capacityHasHighBit);
|
||||||
setMostSignificantBit <1> (capacityHighByte, capacityHasSecHighBit);
|
detail::setMostSignificantBit <1> (capacityHighByte, capacityHasSecHighBit);
|
||||||
|
|
||||||
return { length, capacity };
|
return { length, capacity };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
CR_NAMESPACE_BEGIN
|
CR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
// simple pair (twin)
|
// simple pair (twin)
|
||||||
template <typename A, typename B> class Twin {
|
template <typename A, typename B> class Twin final {
|
||||||
public:
|
public:
|
||||||
A first;
|
A first;
|
||||||
B second;
|
B second;
|
||||||
|
|
@ -55,13 +55,4 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// creating pairs
|
|
||||||
template <typename A, typename B> constexpr Twin <A, B> makeTwin (A &&a, B &&b) {
|
|
||||||
return Twin <A, B> (cr::forward <A> (a), cr::forward <B> (b));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename A, typename B> constexpr Twin <A, B> makeTwin (const A &a, const B &b) {
|
|
||||||
return Twin <A, B> (a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
CR_NAMESPACE_END
|
CR_NAMESPACE_END
|
||||||
|
|
@ -41,10 +41,11 @@ private:
|
||||||
SmallArray <int32> m_prevTable;
|
SmallArray <int32> m_prevTable;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ULZ () {
|
explicit ULZ () {
|
||||||
m_hashTable.resize (HashLength);
|
m_hashTable.resize (HashLength);
|
||||||
m_prevTable.resize (WindowSize);
|
m_prevTable.resize (WindowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ULZ () = default;
|
~ULZ () = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,15 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UniquePtr () = default;
|
UniquePtr () = default;
|
||||||
|
|
||||||
explicit UniquePtr (T *ptr) : m_ptr (ptr)
|
explicit UniquePtr (T *ptr) : m_ptr (ptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
UniquePtr (UniquePtr &&rhs) noexcept : m_ptr (rhs.m_ptr) {
|
UniquePtr (UniquePtr &&rhs) noexcept : m_ptr (rhs.release ())
|
||||||
rhs.m_ptr = nullptr;
|
{ }
|
||||||
}
|
|
||||||
|
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : m_ptr (rhs.release ())
|
||||||
|
{ }
|
||||||
|
|
||||||
~UniquePtr () {
|
~UniquePtr () {
|
||||||
destroy ();
|
destroy ();
|
||||||
|
|
@ -60,10 +63,14 @@ private:
|
||||||
public:
|
public:
|
||||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
destroy ();
|
reset (rhs.release ());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
m_ptr = rhs.m_ptr;
|
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||||
rhs.m_ptr = nullptr;
|
if (this != &rhs) {
|
||||||
|
reset (rhs.release ());
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -87,13 +94,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// create unique
|
// create unique
|
||||||
template <typename T, typename... Args> UniquePtr <T> createUnique (Args &&... args) {
|
template <typename T, typename... Args> UniquePtr <T> makeUnique (Args &&... args) {
|
||||||
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create unique (base class)
|
|
||||||
template <typename D, typename B, typename... Args> UniquePtr <B> createUniqueBase (Args &&... args) {
|
|
||||||
return UniquePtr <B> (alloc.create <D> (cr::forward <Args> (args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
CR_NAMESPACE_END
|
CR_NAMESPACE_END
|
||||||
|
|
@ -65,7 +65,7 @@ CR_DECLARE_SCOPED_ENUM (MapFlags,
|
||||||
CR_DECLARE_SCOPED_ENUM (EntitySearchResult,
|
CR_DECLARE_SCOPED_ENUM (EntitySearchResult,
|
||||||
Continue,
|
Continue,
|
||||||
Break
|
Break
|
||||||
);
|
)
|
||||||
|
|
||||||
// variable reg pair
|
// variable reg pair
|
||||||
struct VarPair {
|
struct VarPair {
|
||||||
|
|
@ -82,6 +82,31 @@ struct VarPair {
|
||||||
// entity prototype
|
// entity prototype
|
||||||
using EntityFunction = void (*) (entvars_t *);
|
using EntityFunction = void (*) (entvars_t *);
|
||||||
|
|
||||||
|
// rehlds has this fixed, but original hlds doesn't allocate string space passed to precache* argument, so game will crash when unloading module using metamod
|
||||||
|
class EngineWrap final : public DenyCopying {
|
||||||
|
public:
|
||||||
|
EngineWrap () = default;
|
||||||
|
~EngineWrap () = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *allocStr (const char *str) const {
|
||||||
|
return STRING (engfuncs.pfnAllocString (str));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32 precacheModel (const char *model) const {
|
||||||
|
return engfuncs.pfnPrecacheModel (allocStr (model));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 precacheSound (const char *sound) const {
|
||||||
|
return engfuncs.pfnPrecacheSound (allocStr (sound));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setModel (edict_t *ent, const char *model) {
|
||||||
|
engfuncs.pfnSetModel (ent, allocStr (model));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// provides utility functions to not call original engine (less call-cost)
|
// provides utility functions to not call original engine (less call-cost)
|
||||||
class Game final : public Singleton <Game> {
|
class Game final : public Singleton <Game> {
|
||||||
public:
|
public:
|
||||||
|
|
@ -101,6 +126,7 @@ private:
|
||||||
Array <edict_t *> m_breakables;
|
Array <edict_t *> m_breakables;
|
||||||
SmallArray <VarPair> m_cvars;
|
SmallArray <VarPair> m_cvars;
|
||||||
SharedLibrary m_gameLib;
|
SharedLibrary m_gameLib;
|
||||||
|
EngineWrap m_engineWrap;
|
||||||
|
|
||||||
bool m_precached;
|
bool m_precached;
|
||||||
int m_gameFlags;
|
int m_gameFlags;
|
||||||
|
|
@ -621,7 +647,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void initialize () {
|
void initialize () {
|
||||||
if (plat.isArm) {
|
if (plat.arm) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_dlsym.patch (reinterpret_cast <void *> (&LookupSymbol), reinterpret_cast <void *> (&DynamicEntityLink::replacement));
|
m_dlsym.patch (reinterpret_cast <void *> (&LookupSymbol), reinterpret_cast <void *> (&DynamicEntityLink::replacement));
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,24 @@
|
||||||
// This header file included by engine files and DLL files.
|
// This header file included by engine files and DLL files.
|
||||||
// Most came from server.h
|
// Most came from server.h
|
||||||
|
|
||||||
|
#define INTERFACE_VERSION 140
|
||||||
|
|
||||||
|
// Dot products for view cone checking
|
||||||
|
#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees
|
||||||
|
#define VIEW_FIELD_WIDE (float)-0.7 // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks
|
||||||
|
#define VIEW_FIELD_NARROW (float)0.7 // +-45 degrees, more narrow check used to set up ranged attacks
|
||||||
|
#define VIEW_FIELD_ULTRA_NARROW (float)0.9 // +-25 degrees, more narrow check used to set up ranged attacks
|
||||||
|
|
||||||
|
#define FCVAR_ARCHIVE (1 << 0) // set to cause it to be saved to vars.rc
|
||||||
|
#define FCVAR_USERINFO (1 << 1) // changes the client's info string
|
||||||
|
#define FCVAR_SERVER (1 << 2) // notifies players when changed
|
||||||
|
#define FCVAR_EXTDLL (1 << 3) // defined by external DLL
|
||||||
|
#define FCVAR_CLIENTDLL (1 << 4) // defined by the client dll
|
||||||
|
#define FCVAR_PROTECTED (1 << 5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
||||||
|
#define FCVAR_SPONLY (1 << 6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
||||||
|
#define FCVAR_PRINTABLEONLY (1 << 7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
||||||
|
#define FCVAR_UNLOGGED (1 << 8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
||||||
|
|
||||||
// edict->flags
|
// edict->flags
|
||||||
#define FL_FLY (1 << 0) // Changes the SV_Movestep() behavior to not need to be on ground
|
#define FL_FLY (1 << 0) // Changes the SV_Movestep() behavior to not need to be on ground
|
||||||
#define FL_SWIM (1 << 1) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
|
#define FL_SWIM (1 << 1) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
|
||||||
|
|
@ -667,6 +685,122 @@
|
||||||
#define TE_BOUNCE_SHELL 1
|
#define TE_BOUNCE_SHELL 1
|
||||||
#define TE_BOUNCE_SHOTSHELL 2
|
#define TE_BOUNCE_SHOTSHELL 2
|
||||||
|
|
||||||
|
#define MAX_ENT_LEAFS 48
|
||||||
|
|
||||||
|
#define MAX_WEAPON_SLOTS 5 // hud item selection slots
|
||||||
|
#define MAX_ITEM_TYPES 6 // hud item selection slots
|
||||||
|
|
||||||
|
#define MAX_ITEMS 5 // hard coded item types
|
||||||
|
|
||||||
|
#define HIDEHUD_WEAPONS (1 << 0)
|
||||||
|
#define HIDEHUD_FLASHLIGHT (1 << 1)
|
||||||
|
#define HIDEHUD_ALL (1 << 2)
|
||||||
|
#define HIDEHUD_HEALTH (1 << 3)
|
||||||
|
|
||||||
|
#define MAX_AMMO_TYPES 32 // ???
|
||||||
|
#define MAX_AMMO_SLOTS 32 // not really slots
|
||||||
|
|
||||||
|
#define HUD_PRINTNOTIFY 1
|
||||||
|
#define HUD_PRINTCONSOLE 2
|
||||||
|
#define HUD_PRINTTALK 3
|
||||||
|
#define HUD_PRINTCENTER 4
|
||||||
|
|
||||||
|
#define WEAPON_SUIT 31
|
||||||
|
|
||||||
|
#define VERTEXSIZE 7
|
||||||
|
#define MAXLIGHTMAPS 4
|
||||||
|
#define NUM_AMBIENTS 4
|
||||||
|
#define MAX_MAP_HULLS 4
|
||||||
|
#define MAX_PHYSINFO_STRING 256
|
||||||
|
#define MAX_PHYSENTS 600
|
||||||
|
#define MAX_MOVEENTS 64
|
||||||
|
#define MAX_LIGHTSTYLES 64
|
||||||
|
#define MAX_LIGHTSTYLEVALUE 256
|
||||||
|
#define SURF_DRAWTILED 0x20
|
||||||
|
|
||||||
|
|
||||||
|
#define AMBIENT_SOUND_STATIC 0 // medium radius attenuation
|
||||||
|
#define AMBIENT_SOUND_EVERYWHERE 1
|
||||||
|
#define AMBIENT_SOUND_SMALLRADIUS 2
|
||||||
|
#define AMBIENT_SOUND_MEDIUMRADIUS 4
|
||||||
|
#define AMBIENT_SOUND_LARGERADIUS 8
|
||||||
|
#define AMBIENT_SOUND_START_SILENT 16
|
||||||
|
#define AMBIENT_SOUND_NOT_LOOPING 32
|
||||||
|
|
||||||
|
#define SPEAKER_START_SILENT 1 // wait for trigger 'on' to start announcements
|
||||||
|
|
||||||
|
#define SND_SPAWNING (1 << 8) // duplicated in protocol.h we're spawing, used in some cases for ambients
|
||||||
|
#define SND_STOP (1 << 5) // duplicated in protocol.h stop sound
|
||||||
|
#define SND_CHANGE_VOL (1 << 6) // duplicated in protocol.h change sound vol
|
||||||
|
#define SND_CHANGE_PITCH (1 << 7) // duplicated in protocol.h change sound pitch
|
||||||
|
|
||||||
|
#define LFO_SQUARE 1
|
||||||
|
#define LFO_TRIANGLE 2
|
||||||
|
#define LFO_RANDOM 3
|
||||||
|
|
||||||
|
// func_rotating
|
||||||
|
#define SF_BRUSH_ROTATE_Y_AXIS 0
|
||||||
|
#define SF_BRUSH_ROTATE_INSTANT 1
|
||||||
|
#define SF_BRUSH_ROTATE_BACKWARDS 2
|
||||||
|
#define SF_BRUSH_ROTATE_Z_AXIS 4
|
||||||
|
#define SF_BRUSH_ROTATE_X_AXIS 8
|
||||||
|
#define SF_PENDULUM_AUTO_RETURN 16
|
||||||
|
#define SF_PENDULUM_PASSABLE 32
|
||||||
|
|
||||||
|
#define SF_BRUSH_ROTATE_SMALLRADIUS 128
|
||||||
|
#define SF_BRUSH_ROTATE_MEDIUMRADIUS 256
|
||||||
|
#define SF_BRUSH_ROTATE_LARGERADIUS 512
|
||||||
|
|
||||||
|
#define PUSH_BLOCK_ONLY_X 1
|
||||||
|
#define PUSH_BLOCK_ONLY_Y 2
|
||||||
|
|
||||||
|
#define VEC_HULL_MIN Vector(-16, -16, -36)
|
||||||
|
#define VEC_HULL_MAX Vector(16, 16, 36)
|
||||||
|
#define VEC_HUMAN_HULL_MIN Vector(-16, -16, 0)
|
||||||
|
#define VEC_HUMAN_HULL_MAX Vector(16, 16, 72)
|
||||||
|
#define VEC_HUMAN_HULL_DUCK Vector(16, 16, 36)
|
||||||
|
|
||||||
|
#define VEC_VIEW Vector(0, 0, 28)
|
||||||
|
|
||||||
|
#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18)
|
||||||
|
#define VEC_DUCK_HULL_MAX Vector(16, 16, 18)
|
||||||
|
#define VEC_DUCK_VIEW Vector(0, 0, 12)
|
||||||
|
|
||||||
|
#define SVC_TEMPENTITY 23
|
||||||
|
#define SVC_CENTERPRINT 26
|
||||||
|
#define SVC_INTERMISSION 30
|
||||||
|
#define SVC_CDTRACK 32
|
||||||
|
#define SVC_WEAPONANIM 35
|
||||||
|
#define SVC_ROOMTYPE 37
|
||||||
|
#define SVC_DIRECTOR 51
|
||||||
|
|
||||||
|
// triggers
|
||||||
|
#define SF_TRIGGER_ALLOWMONSTERS 1 // monsters allowed to fire this trigger
|
||||||
|
#define SF_TRIGGER_NOCLIENTS 2 // players not allowed to fire this trigger
|
||||||
|
#define SF_TRIGGER_PUSHABLES 4 // only pushables can fire this trigger
|
||||||
|
|
||||||
|
// func breakable
|
||||||
|
#define SF_BREAK_TRIGGER_ONLY 1 // may only be broken by trigger
|
||||||
|
#define SF_BREAK_TOUCH 2 // can be 'crashed through' by running player (plate glass)
|
||||||
|
#define SF_BREAK_PRESSURE 4 // can be broken by a player standing on it
|
||||||
|
#define SF_BREAK_CROWBAR 256 // instant break if hit with crowbar
|
||||||
|
|
||||||
|
// func_pushable (it's also func_breakable, so don't collide with those flags)
|
||||||
|
#define SF_PUSH_BREAKABLE 128
|
||||||
|
|
||||||
|
#define SF_LIGHT_START_OFF 1
|
||||||
|
|
||||||
|
#define SPAWNFLAG_NOMESSAGE 1
|
||||||
|
#define SPAWNFLAG_NOTOUCH 1
|
||||||
|
#define SPAWNFLAG_DROIDONLY 4
|
||||||
|
|
||||||
|
#define SPAWNFLAG_USEONLY 1 // can't be touched, must be used (buttons)
|
||||||
|
|
||||||
|
#define TELE_PLAYER_ONLY 1
|
||||||
|
#define TELE_SILENT 2
|
||||||
|
|
||||||
|
#define SF_TRIG_PUSH_ONCE 1
|
||||||
|
|
||||||
// Rendering constants
|
// Rendering constants
|
||||||
enum {
|
enum {
|
||||||
kRenderNormal, // src
|
kRenderNormal, // src
|
||||||
|
|
@ -701,29 +835,46 @@ enum {
|
||||||
kRenderFxClampMinScale // Keep this sprite from getting very small (SPRITES only!)
|
kRenderFxClampMinScale // Keep this sprite from getting very small (SPRITES only!)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int func_t;
|
typedef enum {
|
||||||
typedef int string_t;
|
ignore_monsters = 1,
|
||||||
|
dont_ignore_monsters = 0,
|
||||||
|
missile = 2
|
||||||
|
} IGNORE_MONSTERS;
|
||||||
|
|
||||||
typedef struct link_s {
|
typedef enum {
|
||||||
struct link_s *prev, *next;
|
ignore_glass = 1,
|
||||||
} link_t;
|
dont_ignore_glass = 0
|
||||||
|
} IGNORE_GLASS;
|
||||||
|
|
||||||
typedef struct edict_s edict_t;
|
typedef enum {
|
||||||
|
point_hull = 0,
|
||||||
|
human_hull = 1,
|
||||||
|
large_hull = 2,
|
||||||
|
head_hull = 3
|
||||||
|
} HULL;
|
||||||
|
|
||||||
typedef struct {
|
typedef enum {
|
||||||
vec3_t normal;
|
at_notice,
|
||||||
float dist;
|
at_console, // same as at_notice, but forces a ConPrintf, not a message box
|
||||||
} plane_t;
|
at_aiconsole, // same as at_console, but only shown if developer level is 2!
|
||||||
|
at_warning,
|
||||||
|
at_error,
|
||||||
|
at_logged // Server print to console ( only in multiplayer games ).
|
||||||
|
} ALERT_TYPE;
|
||||||
|
|
||||||
|
// 4-22-98 JOHN: added for use in pfnClientPrintf
|
||||||
|
typedef enum {
|
||||||
|
print_console,
|
||||||
|
print_center,
|
||||||
|
print_chat
|
||||||
|
} PRINT_TYPE;
|
||||||
|
|
||||||
|
// For integrity checking of content on clients
|
||||||
|
typedef enum {
|
||||||
|
force_exactfile, // File on client must exactly match server's file
|
||||||
|
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
|
||||||
|
force_model_specifybounds // For model files only, the geometry must fit in the specified bbox
|
||||||
|
} FORCE_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int allsolid; // if true, plane is not valid
|
|
||||||
int startsolid; // if true, the initial point was in a solid area
|
|
||||||
int inopen, inwater;
|
|
||||||
float fraction; // time completed, 1.0 = didn't hit anything
|
|
||||||
vec3_t endpos; // final position
|
|
||||||
plane_t plane; // surface normal at impact
|
|
||||||
edict_t *ent; // entity the surface is on
|
|
||||||
int hitgroup; // 0 == generic, non zero is specific body part
|
|
||||||
} trace_t;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -12,22 +12,7 @@
|
||||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
#ifndef EIFACE_H
|
#pragma once
|
||||||
#define EIFACE_H
|
|
||||||
|
|
||||||
#define INTERFACE_VERSION 140
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define FCVAR_ARCHIVE (1 << 0) // set to cause it to be saved to vars.rc
|
|
||||||
#define FCVAR_USERINFO (1 << 1) // changes the client's info string
|
|
||||||
#define FCVAR_SERVER (1 << 2) // notifies players when changed
|
|
||||||
#define FCVAR_EXTDLL (1 << 3) // defined by external DLL
|
|
||||||
#define FCVAR_CLIENTDLL (1 << 4) // defined by the client dll
|
|
||||||
#define FCVAR_PROTECTED (1 << 5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
|
||||||
#define FCVAR_SPONLY (1 << 6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
|
||||||
#define FCVAR_PRINTABLEONLY (1 << 7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
|
||||||
#define FCVAR_UNLOGGED (1 << 8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
|
||||||
|
|
||||||
struct cvar_t {
|
struct cvar_t {
|
||||||
char *name;
|
char *name;
|
||||||
|
|
@ -37,39 +22,18 @@ struct cvar_t {
|
||||||
cvar_t *next;
|
cvar_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
typedef struct hudtextparms_s {
|
||||||
// Defines entity interface between engine and DLLs.
|
float x;
|
||||||
// This header file included by engine files and DLL files.
|
float y;
|
||||||
//
|
int effect;
|
||||||
// Before including this header, DLLs must:
|
uint8 r1, g1, b1, a1;
|
||||||
// include progdefs.h
|
uint8 r2, g2, b2, a2;
|
||||||
// This is conveniently done for them in extdll.h
|
float fadeinTime;
|
||||||
//
|
float fadeoutTime;
|
||||||
|
float holdTime;
|
||||||
#ifdef _WIN32
|
float fxTime;
|
||||||
#define DLLEXPORT __stdcall
|
int channel;
|
||||||
#else
|
} hudtextparms_t;
|
||||||
#define DLLEXPORT /* */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
at_notice,
|
|
||||||
at_console, // same as at_notice, but forces a ConPrintf, not a message box
|
|
||||||
at_aiconsole, // same as at_console, but only shown if developer level is 2!
|
|
||||||
at_warning,
|
|
||||||
at_error,
|
|
||||||
at_logged // Server print to console ( only in multiplayer games ).
|
|
||||||
} ALERT_TYPE;
|
|
||||||
|
|
||||||
// 4-22-98 JOHN: added for use in pfnClientPrintf
|
|
||||||
typedef enum { print_console, print_center, print_chat } PRINT_TYPE;
|
|
||||||
|
|
||||||
// For integrity checking of content on clients
|
|
||||||
typedef enum {
|
|
||||||
force_exactfile, // File on client must exactly match server's file
|
|
||||||
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
|
|
||||||
force_model_specifybounds // For model files only, the geometry must fit in the specified bbox
|
|
||||||
} FORCE_TYPE;
|
|
||||||
|
|
||||||
// Returned by TraceLine
|
// Returned by TraceLine
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -109,8 +73,8 @@ typedef uint32 CRC32_t;
|
||||||
// Engine hands this to DLLs for functionality callbacks
|
// Engine hands this to DLLs for functionality callbacks
|
||||||
|
|
||||||
typedef struct enginefuncs_s {
|
typedef struct enginefuncs_s {
|
||||||
int (*pfnPrecacheModel) (char *s);
|
int (*pfnPrecacheModel) (const char *s);
|
||||||
int (*pfnPrecacheSound) (char *s);
|
int (*pfnPrecacheSound) (const char *s);
|
||||||
void (*pfnSetModel) (edict_t *e, const char *m);
|
void (*pfnSetModel) (edict_t *e, const char *m);
|
||||||
int (*pfnModelIndex) (const char *m);
|
int (*pfnModelIndex) (const char *m);
|
||||||
int (*pfnModelFrames) (int modelIndex);
|
int (*pfnModelFrames) (int modelIndex);
|
||||||
|
|
@ -375,9 +339,6 @@ typedef struct {
|
||||||
int (*pfnAllowLagCompensation) ();
|
int (*pfnAllowLagCompensation) ();
|
||||||
} gamefuncs_t;
|
} gamefuncs_t;
|
||||||
|
|
||||||
// Current version.
|
|
||||||
#define NEWGAMEDLLFUNCS_VERSION 1
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// Called right before the object's memory is freed.
|
// Called right before the object's memory is freed.
|
||||||
// Calls its destructor.
|
// Calls its destructor.
|
||||||
|
|
@ -388,5 +349,3 @@ typedef struct {
|
||||||
void (*pfnCvarValue) (const edict_t *pEnt, const char *value);
|
void (*pfnCvarValue) (const edict_t *pEnt, const char *value);
|
||||||
void (*pfnCvarValue2) (const edict_t *pEnt, int requestID, const char *cvarName, const char *value);
|
void (*pfnCvarValue2) (const edict_t *pEnt, int requestID, const char *cvarName, const char *value);
|
||||||
} newgamefuncs_t;
|
} newgamefuncs_t;
|
||||||
|
|
||||||
#endif /* EIFACE_H */
|
|
||||||
|
|
|
||||||
|
|
@ -16,54 +16,58 @@
|
||||||
#ifndef EXTDLL_H
|
#ifndef EXTDLL_H
|
||||||
#define EXTDLL_H
|
#define EXTDLL_H
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
/* disable deprecation warnings concerning unsafe CRT functions */
|
|
||||||
#if !defined _CRT_SECURE_NO_DEPRECATE
|
|
||||||
#define _CRT_SECURE_NO_DEPRECATE
|
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#define NOWINRES
|
|
||||||
#define NOSERVICE
|
|
||||||
#define NOMCX
|
|
||||||
#define NOIME
|
|
||||||
#include "windows.h"
|
|
||||||
#include "winsock2.h"
|
|
||||||
#else // _WIN32
|
|
||||||
#define FALSE 0
|
|
||||||
#define TRUE (!FALSE)
|
|
||||||
#define MAX_PATH PATH_MAX
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#ifndef min
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef max
|
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define _vsnprintf(a, b, c, d) vsnprintf (a, b, c, d)
|
|
||||||
#endif
|
|
||||||
#endif //_WIN32
|
|
||||||
|
|
||||||
#include "stdio.h"
|
|
||||||
#include "stdlib.h"
|
|
||||||
|
|
||||||
typedef int func_t; //
|
typedef int func_t; //
|
||||||
typedef int string_t; // from engine's pr_comp.h;
|
|
||||||
typedef float vec_t; // needed before including progdefs.h
|
typedef float vec_t; // needed before including progdefs.h
|
||||||
|
typedef vec_t vec2_t[2];
|
||||||
|
typedef vec_t vec4_t[4];
|
||||||
|
typedef int qboolean;
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
#include <crlib/cr-vector.h>
|
#include <crlib/cr-vector.h>
|
||||||
|
|
||||||
|
// idea from regamedll
|
||||||
|
class string_t final {
|
||||||
|
private:
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit string_t () : offset (0) { }
|
||||||
|
string_t (int offset) : offset (offset) { }
|
||||||
|
|
||||||
|
~string_t () = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const char *chars () const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
operator int () const {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_t &operator = (const string_t &rhs) {
|
||||||
|
offset = rhs.offset;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef cr::Vector vec3_t;
|
typedef cr::Vector vec3_t;
|
||||||
using namespace cr::types;
|
using namespace cr::types;
|
||||||
|
|
||||||
|
typedef struct edict_s edict_t;
|
||||||
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "progdefs.h"
|
#include "progdefs.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
#define MAX_ENT_LEAFS 48
|
typedef struct link_s {
|
||||||
|
struct link_s *prev, *next;
|
||||||
|
} link_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3_t normal;
|
||||||
|
float dist;
|
||||||
|
} plane_t;
|
||||||
|
|
||||||
struct edict_s {
|
struct edict_s {
|
||||||
int free;
|
int free;
|
||||||
|
|
@ -79,24 +83,29 @@ struct edict_s {
|
||||||
|
|
||||||
#include "eiface.h"
|
#include "eiface.h"
|
||||||
|
|
||||||
#define MAX_WEAPON_SLOTS 5 // hud item selection slots
|
extern globalvars_t *globals;
|
||||||
#define MAX_ITEM_TYPES 6 // hud item selection slots
|
extern enginefuncs_t engfuncs;
|
||||||
|
extern gamefuncs_t dllapi;
|
||||||
|
|
||||||
#define MAX_ITEMS 5 // hard coded item types
|
// Use this instead of ALLOC_STRING on constant strings
|
||||||
|
#define STRING(offset) (const char *)(globals->pStringBase + (int)offset)
|
||||||
|
|
||||||
#define HIDEHUD_WEAPONS (1 << 0)
|
// form fwgs-hlsdk
|
||||||
#define HIDEHUD_FLASHLIGHT (1 << 1)
|
#if defined (CR_ARCH_X64)
|
||||||
#define HIDEHUD_ALL (1 << 2)
|
static inline int MAKE_STRING (const char *val) {
|
||||||
#define HIDEHUD_HEALTH (1 << 3)
|
long long ptrdiff = val - STRING (0);
|
||||||
|
|
||||||
#define MAX_AMMO_TYPES 32 // ???
|
if (ptrdiff > INT_MAX || ptrdiff < INT_MIN) {
|
||||||
#define MAX_AMMO_SLOTS 32 // not really slots
|
return engfuncs.pfnAllocString (val);
|
||||||
|
}
|
||||||
|
return static_cast <int> (ptrdiff);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0)))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HUD_PRINTNOTIFY 1
|
inline const char *string_t::chars () const {
|
||||||
#define HUD_PRINTCONSOLE 2
|
return STRING (offset);
|
||||||
#define HUD_PRINTTALK 3
|
}
|
||||||
#define HUD_PRINTCENTER 4
|
|
||||||
|
|
||||||
#define WEAPON_SUIT 31
|
|
||||||
|
|
||||||
#endif // EXTDLL_H
|
#endif // EXTDLL_H
|
||||||
|
|
|
||||||
203
include/engine/metamod.h
Normal file
203
include/engine/metamod.h
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||||
|
* See the file "dllapi.h" in this folder for full information
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Simplified version by Wei Mingzhi
|
||||||
|
|
||||||
|
#ifndef METAMOD_H
|
||||||
|
#define METAMOD_H
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PNL_NULL = 0,
|
||||||
|
PNL_INI_DELETED,
|
||||||
|
PNL_FILE_NEWER,
|
||||||
|
PNL_COMMAND,
|
||||||
|
PNL_CMD_FORCED,
|
||||||
|
PNL_DELAYED,
|
||||||
|
PNL_PLUGIN,
|
||||||
|
PNL_PLG_FORCED,
|
||||||
|
PNL_RELOAD
|
||||||
|
} PL_UNLOAD_REASON;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MRES_UNSET = 0,
|
||||||
|
MRES_IGNORED,
|
||||||
|
MRES_HANDLED,
|
||||||
|
MRES_OVERRIDE,
|
||||||
|
MRES_SUPERCEDE
|
||||||
|
} META_RES;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PT_NEVER = 0,
|
||||||
|
PT_STARTUP,
|
||||||
|
PT_CHANGELEVEL,
|
||||||
|
PT_ANYTIME,
|
||||||
|
PT_ANYPAUSE
|
||||||
|
} PLUG_LOADTIME;
|
||||||
|
|
||||||
|
// for getgameinfo:
|
||||||
|
typedef enum {
|
||||||
|
GINFO_NAME = 0,
|
||||||
|
GINFO_DESC,
|
||||||
|
GINFO_GAMEDIR,
|
||||||
|
GINFO_DLL_FULLPATH,
|
||||||
|
GINFO_DLL_FILENAME,
|
||||||
|
GINFO_REALDLL_FULLPATH
|
||||||
|
} ginfo_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*GETENTITYAPI_FN) (gamefuncs_t *pFunctionTable, int interfaceVersion);
|
||||||
|
typedef int (*GETENTITYAPI2_FN) (gamefuncs_t *pFunctionTable, int *interfaceVersion);
|
||||||
|
typedef int (*GETNEWDLLFUNCTIONS_FN) (newgamefuncs_t *pFunctionTable, int *interfaceVersion);
|
||||||
|
typedef int (*GET_ENGINE_FUNCTIONS_FN) (enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);
|
||||||
|
|
||||||
|
#define META_INTERFACE_VERSION "5:13"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char const *ifvers;
|
||||||
|
char const *name;
|
||||||
|
char const *version;
|
||||||
|
char const *date;
|
||||||
|
char const *author;
|
||||||
|
char const *url;
|
||||||
|
char const *logtag;
|
||||||
|
PLUG_LOADTIME loadable;
|
||||||
|
PLUG_LOADTIME unloadable;
|
||||||
|
} plugin_info_t;
|
||||||
|
|
||||||
|
extern plugin_info_t Plugin_info;
|
||||||
|
typedef plugin_info_t *plid_t;
|
||||||
|
|
||||||
|
#define PLID &Plugin_info
|
||||||
|
|
||||||
|
typedef struct meta_globals_s {
|
||||||
|
META_RES mres;
|
||||||
|
META_RES prev_mres;
|
||||||
|
META_RES status;
|
||||||
|
void *orig_ret;
|
||||||
|
void *override_ret;
|
||||||
|
} meta_globals_t;
|
||||||
|
|
||||||
|
extern meta_globals_t *gpMetaGlobals;
|
||||||
|
|
||||||
|
#define RETURN_META(result) \
|
||||||
|
{ \
|
||||||
|
gpMetaGlobals->mres = result; \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RETURN_META_VALUE(result, value) \
|
||||||
|
{ \
|
||||||
|
gpMetaGlobals->mres = result; \
|
||||||
|
return (value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define META_RESULT_STATUS gpMetaGlobals->status
|
||||||
|
#define META_RESULT_PREVIOUS gpMetaGlobals->prev_mres
|
||||||
|
#define META_RESULT_ORIG_RET(type) *(type *)gpMetaGlobals->orig_ret
|
||||||
|
#define META_RESULT_OVERRIDE_RET(type) *(type *)gpMetaGlobals->override_ret
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GETENTITYAPI_FN pfnGetEntityAPI;
|
||||||
|
GETENTITYAPI_FN pfnGetEntityAPI_Post;
|
||||||
|
GETENTITYAPI2_FN pfnGetEntityAPI2;
|
||||||
|
GETENTITYAPI2_FN pfnGetEntityAPI2_Post;
|
||||||
|
GETNEWDLLFUNCTIONS_FN pfnGetNewDLLFunctions;
|
||||||
|
GETNEWDLLFUNCTIONS_FN pfnGetNewDLLFunctions_Post;
|
||||||
|
GET_ENGINE_FUNCTIONS_FN pfnGetEngineFunctions;
|
||||||
|
GET_ENGINE_FUNCTIONS_FN pfnGetEngineFunctions_Post;
|
||||||
|
} metamod_funcs_t;
|
||||||
|
|
||||||
|
// max buffer size for printed messages
|
||||||
|
#define MAX_LOGMSG_LEN 1024
|
||||||
|
|
||||||
|
|
||||||
|
// Meta Utility Function table type.
|
||||||
|
typedef struct meta_util_funcs_s {
|
||||||
|
void (*pfnLogConsole) (plid_t plid, const char *szFormat, ...);
|
||||||
|
void (*pfnLogMessage) (plid_t plid, const char *szFormat, ...);
|
||||||
|
void (*pfnLogError) (plid_t plid, const char *szFormat, ...);
|
||||||
|
void (*pfnLogDeveloper) (plid_t plid, const char *szFormat, ...);
|
||||||
|
void (*pfnCenterSay) (plid_t plid, const char *szFormat, ...);
|
||||||
|
void (*pfnCenterSayParms) (plid_t plid, hudtextparms_t tparms, const char *szFormat, ...);
|
||||||
|
void (*pfnCenterSayVarargs) (plid_t plid, hudtextparms_t tparms, const char *szFormat, va_list ap);
|
||||||
|
int (*pfnCallGameEntity) (plid_t plid, const char *entStr, entvars_t *pev);
|
||||||
|
int (*pfnGetUserMsgID) (plid_t plid, const char *msgname, int *size);
|
||||||
|
const char *(*pfnGetUserMsgName) (plid_t plid, int msgid, int *size);
|
||||||
|
const char *(*pfnGetPluginPath) (plid_t plid);
|
||||||
|
const char *(*pfnGetGameInfo) (plid_t plid, ginfo_t tag);
|
||||||
|
int (*pfnLoadPlugin) (plid_t plid, const char *cmdline, PLUG_LOADTIME now, void **plugin_handle);
|
||||||
|
int (*pfnUnloadPlugin) (plid_t plid, const char *cmdline, PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
|
||||||
|
int (*pfnUnloadPluginByHandle) (plid_t plid, void *plugin_handle, PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
|
||||||
|
const char *(*pfnIsQueryingClienCVar_t) (plid_t plid, const edict_t *player);
|
||||||
|
int (*pfnMakeRequestID) (plid_t plid);
|
||||||
|
void (*pfnGetHookTables) (plid_t plid, enginefuncs_t **peng, gamefuncs_t **pdll, newgamefuncs_t **pnewdll);
|
||||||
|
} mutil_funcs_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gamefuncs_t *dllapi_table;
|
||||||
|
newgamefuncs_t *newapi_table;
|
||||||
|
} gamedll_funcs_t;
|
||||||
|
|
||||||
|
extern gamedll_funcs_t *gpGamedllFuncs;
|
||||||
|
extern mutil_funcs_t *gpMetaUtilFuncs;
|
||||||
|
extern metamod_funcs_t gMetaFunctionTable;
|
||||||
|
|
||||||
|
#define MDLL_FUNC gpGamedllFuncs->dllapi_table
|
||||||
|
|
||||||
|
#define MDLL_GameDLLInit MDLL_FUNC->pfnGameInit
|
||||||
|
#define MDLL_Spawn MDLL_FUNC->pfnSpawn
|
||||||
|
#define MDLL_Think MDLL_FUNC->pfnThink
|
||||||
|
#define MDLL_Use MDLL_FUNC->pfnUse
|
||||||
|
#define MDLL_Touch MDLL_FUNC->pfnTouch
|
||||||
|
#define MDLL_Blocked MDLL_FUNC->pfnBlocked
|
||||||
|
#define MDLL_KeyValue MDLL_FUNC->pfnKeyValue
|
||||||
|
#define MDLL_Save MDLL_FUNC->pfnSave
|
||||||
|
#define MDLL_Restore MDLL_FUNC->pfnRestore
|
||||||
|
#define MDLL_ObjectCollsionBox MDLL_FUNC->pfnAbsBox
|
||||||
|
#define MDLL_SaveWriteFields MDLL_FUNC->pfnSaveWriteFields
|
||||||
|
#define MDLL_SaveReadFields MDLL_FUNC->pfnSaveReadFields
|
||||||
|
#define MDLL_SaveGlobalState MDLL_FUNC->pfnSaveGlobalState
|
||||||
|
#define MDLL_RestoreGlobalState MDLL_FUNC->pfnRestoreGlobalState
|
||||||
|
#define MDLL_ResetGlobalState MDLL_FUNC->pfnResetGlobalState
|
||||||
|
#define MDLL_ClientConnect MDLL_FUNC->pfnClientConnect
|
||||||
|
#define MDLL_ClientDisconnect MDLL_FUNC->pfnClientDisconnect
|
||||||
|
#define MDLL_ClientKill MDLL_FUNC->pfnClientKill
|
||||||
|
#define MDLL_ClientPutInServer MDLL_FUNC->pfnClientPutInServer
|
||||||
|
#define MDLL_ClientCommand MDLL_FUNC->pfnClientCommand
|
||||||
|
#define MDLL_ClientUserInfoChanged MDLL_FUNC->pfnClientUserInfoChanged
|
||||||
|
#define MDLL_ServerActivate MDLL_FUNC->pfnServerActivate
|
||||||
|
#define MDLL_ServerDeactivate MDLL_FUNC->pfnServerDeactivate
|
||||||
|
#define MDLL_PlayerPreThink MDLL_FUNC->pfnPlayerPreThink
|
||||||
|
#define MDLL_PlayerPostThink MDLL_FUNC->pfnPlayerPostThink
|
||||||
|
#define MDLL_StartFrame MDLL_FUNC->pfnStartFrame
|
||||||
|
#define MDLL_ParmsNewLevel MDLL_FUNC->pfnParmsNewLevel
|
||||||
|
#define MDLL_ParmsChangeLevel MDLL_FUNC->pfnParmsChangeLevel
|
||||||
|
#define MDLL_GetGameDescription MDLL_FUNC->pfnGetGameDescription
|
||||||
|
#define MDLL_PlayerCustomization MDLL_FUNC->pfnPlayerCustomization
|
||||||
|
#define MDLL_SpectatorConnect MDLL_FUNC->pfnSpectatorConnect
|
||||||
|
#define MDLL_SpectatorDisconnect MDLL_FUNC->pfnSpectatorDisconnect
|
||||||
|
#define MDLL_SpectatorThink MDLL_FUNC->pfnSpectatorThink
|
||||||
|
#define MDLL_Sys_Error MDLL_FUNC->pfnSys_Error
|
||||||
|
#define MDLL_PM_Move MDLL_FUNC->pfnPM_Move
|
||||||
|
#define MDLL_PM_Init MDLL_FUNC->pfnPM_Init
|
||||||
|
#define MDLL_PM_FindTextureType MDLL_FUNC->pfnPM_FindTextureType
|
||||||
|
#define MDLL_SetupVisibility MDLL_FUNC->pfnSetupVisibility
|
||||||
|
#define MDLL_UpdateClientData MDLL_FUNC->pfnUpdateClientData
|
||||||
|
#define MDLL_AddToFullPack MDLL_FUNC->pfnAddToFullPack
|
||||||
|
#define MDLL_CreateBaseline MDLL_FUNC->pfnCreateBaseline
|
||||||
|
#define MDLL_RegisterEncoders MDLL_FUNC->pfnRegisterEncoders
|
||||||
|
#define MDLL_GetWeaponData MDLL_FUNC->pfnGetWeaponData
|
||||||
|
#define MDLL_CmdStart MDLL_FUNC->pfnCmdStart
|
||||||
|
#define MDLL_CmdEnd MDLL_FUNC->pfnCmdEnd
|
||||||
|
#define MDLL_ConnectionlessPacket MDLL_FUNC->pfnConnectionlessPacket
|
||||||
|
#define MDLL_GetHullBounds MDLL_FUNC->pfnGetHullBounds
|
||||||
|
#define MDLL_CreateInstancedBaselines MDLL_FUNC->pfnCreateInstancedBaselines
|
||||||
|
#define MDLL_InconsistentFile MDLL_FUNC->pfnInconsistentFile
|
||||||
|
#define MDLL_AllowLagCompensation MDLL_FUNC->pfnAllowLagCompensation
|
||||||
|
|
||||||
|
#define CALL_GAME_ENTITY (*gpMetaUtilFuncs->pfnCallGameEntity)
|
||||||
|
#define GET_USER_MSG_ID (*gpMetaUtilFuncs->pfnGetUserMsgID)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -18,23 +18,6 @@
|
||||||
#ifndef MODEL_H
|
#ifndef MODEL_H
|
||||||
#define MODEL_H
|
#define MODEL_H
|
||||||
|
|
||||||
typedef vec_t vec2_t[2];
|
|
||||||
typedef vec_t vec4_t[4];
|
|
||||||
|
|
||||||
typedef int qboolean;
|
|
||||||
typedef unsigned char byte;
|
|
||||||
|
|
||||||
#define VERTEXSIZE 7
|
|
||||||
#define MAXLIGHTMAPS 4
|
|
||||||
#define NUM_AMBIENTS 4
|
|
||||||
#define MAX_MAP_HULLS 4
|
|
||||||
#define MAX_PHYSINFO_STRING 256
|
|
||||||
#define MAX_PHYSENTS 600
|
|
||||||
#define MAX_MOVEENTS 64
|
|
||||||
#define MAX_LIGHTSTYLES 64
|
|
||||||
#define MAX_LIGHTSTYLEVALUE 256
|
|
||||||
#define SURF_DRAWTILED 0x20
|
|
||||||
|
|
||||||
typedef struct mplane_s {
|
typedef struct mplane_s {
|
||||||
vec3_t normal;
|
vec3_t normal;
|
||||||
float dist;
|
float dist;
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,7 @@
|
||||||
* use or distribution of this code by or to any unlicensed person is illegal.
|
* use or distribution of this code by or to any unlicensed person is illegal.
|
||||||
*
|
*
|
||||||
****/
|
****/
|
||||||
#ifndef PROGDEFS_H
|
|
||||||
#define PROGDEFS_H
|
|
||||||
#ifdef _WIN32
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float time;
|
float time;
|
||||||
|
|
@ -84,8 +80,8 @@ typedef struct entvars_s {
|
||||||
int modelindex;
|
int modelindex;
|
||||||
string_t model;
|
string_t model;
|
||||||
|
|
||||||
int viewmodel; // player's viewmodel
|
string_t viewmodel; // player's viewmodel
|
||||||
int weaponmodel; // what other players see
|
string_t weaponmodel; // what other players see
|
||||||
|
|
||||||
vec3_t absmin; // BB max translated to world coord
|
vec3_t absmin; // BB max translated to world coord
|
||||||
vec3_t absmax; // BB max translated to world coord
|
vec3_t absmax; // BB max translated to world coord
|
||||||
|
|
@ -216,4 +212,3 @@ typedef struct entvars_s {
|
||||||
edict_t *euser4;
|
edict_t *euser4;
|
||||||
} entvars_t;
|
} entvars_t;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,11 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int32 add (const String &name, int32 id);
|
int32 add (const String &name, int32 id);
|
||||||
|
int32 id (NetMsg msg);
|
||||||
|
|
||||||
void start (edict_t *ent, int32 type);
|
void start (edict_t *ent, int32 type);
|
||||||
void stop ();
|
void stop ();
|
||||||
|
void ensureMessages ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T> void collect (const T &value) {
|
template <typename T> void collect (const T &value) {
|
||||||
|
|
@ -137,10 +140,6 @@ public:
|
||||||
m_current = NetMsg::None;
|
m_current = NetMsg::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 id (NetMsg msg) const {
|
|
||||||
return m_maps[msg];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset () {
|
void reset () {
|
||||||
m_current = NetMsg::None;
|
m_current = NetMsg::None;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ private:
|
||||||
SmallArray <Client> m_clients;
|
SmallArray <Client> m_clients;
|
||||||
SmallArray <Twin <String, String>> m_tags;
|
SmallArray <Twin <String, String>> m_tags;
|
||||||
|
|
||||||
|
Dictionary <int32, String, IntNoHash <int32>> m_weaponAlias;
|
||||||
Dictionary <String, int32> m_noiseCache;
|
Dictionary <String, int32> m_noiseCache;
|
||||||
SimpleHook m_sendToHook;
|
SimpleHook m_sendToHook;
|
||||||
|
|
||||||
|
|
@ -41,8 +42,8 @@ public:
|
||||||
// need to send welcome message ?
|
// need to send welcome message ?
|
||||||
void checkWelcome ();
|
void checkWelcome ();
|
||||||
|
|
||||||
// gets the weapon alias as hlsting, maybe move to config...
|
// converts weapon id to alias name
|
||||||
int getWeaponAlias (bool needString, const char *weaponAlias, int weaponIndex = -1);
|
const String &weaponIdToAlias (const int32 id);
|
||||||
|
|
||||||
// gets the build number of bot
|
// gets the build number of bot
|
||||||
int buildNumber ();
|
int buildNumber ();
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <engine/extdll.h>
|
#include <engine/extdll.h>
|
||||||
#include <engine/meta_api.h>
|
#include <engine/metamod.h>
|
||||||
|
|
||||||
#include <crlib/cr-complete.h>
|
#include <crlib/cr-complete.h>
|
||||||
|
|
||||||
|
|
@ -790,7 +790,7 @@ private:
|
||||||
void findShortestPath (int srcIndex, int destIndex);
|
void findShortestPath (int srcIndex, int destIndex);
|
||||||
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
|
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
|
||||||
void clearRoute ();
|
void clearRoute ();
|
||||||
void sayDebug (const char *format, ...);
|
void debugMsgInternal (const char *str);
|
||||||
void frame ();
|
void frame ();
|
||||||
void resetCollision ();
|
void resetCollision ();
|
||||||
void ignoreCollision ();
|
void ignoreCollision ();
|
||||||
|
|
@ -1039,13 +1039,23 @@ public:
|
||||||
return pev->pContainingEntity;
|
return pev->pContainingEntity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// bots array index
|
||||||
int index () const {
|
int index () const {
|
||||||
return m_index;
|
return m_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// entity index with worldspawn shift
|
||||||
int entindex () const {
|
int entindex () const {
|
||||||
return m_index + 1;
|
return m_index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prints debug message
|
||||||
|
template <typename ...Args> void debugMsg (const char *fmt, Args ...args) {
|
||||||
|
debugMsgInternal (strings.format (fmt, cr::forward <Args> (args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute client command helper
|
||||||
|
template <typename ...Args> void issueCommand (const char *fmt, Args ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
@ -1063,3 +1073,8 @@ extern ConVar yb_chat;
|
||||||
extern ConVar yb_language;
|
extern ConVar yb_language;
|
||||||
extern ConVar yb_show_latency;
|
extern ConVar yb_show_latency;
|
||||||
extern ConVar yb_enable_query_hook;
|
extern ConVar yb_enable_query_hook;
|
||||||
|
|
||||||
|
// execute client command helper
|
||||||
|
template <typename ...Args> void Bot::issueCommand (const char * fmt, Args ...args) {
|
||||||
|
game.botCommand (ent (), strings.format (fmt, cr::forward <Args> (args)...));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ ifeq "$(DEBUG)" "true"
|
||||||
COMPILER_FLAGS += -g3 -DCR_DEBUG
|
COMPILER_FLAGS += -g3 -DCR_DEBUG
|
||||||
BINARY_DIR = debug
|
BINARY_DIR = debug
|
||||||
else
|
else
|
||||||
COMPILER_FLAGS += -pipe -O3 -march=core2 -msse2 -mfpmath=sse -ffast-math -fno-builtin -fno-threadsafe-statics -funroll-loops -fomit-frame-pointer -fno-stack-protector -fvisibility=hidden -fvisibility-inlines-hidden
|
COMPILER_FLAGS += -pipe -O2 -march=core2 -msse2 -mfpmath=sse -ffast-math -fno-builtin -fno-threadsafe-statics -funroll-loops -fomit-frame-pointer -fno-stack-protector -fvisibility=hidden -fvisibility-inlines-hidden
|
||||||
BINARY_DIR = release
|
BINARY_DIR = release
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ CR_EXPORT int Server_GetBlendingInterface (int version, struct sv_blending_inter
|
||||||
|
|
||||||
if (!api_GetBlendingInterface) {
|
if (!api_GetBlendingInterface) {
|
||||||
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
return api_GetBlendingInterface (version, ppinterface, pstudio, rotationmatrix, bonetransform);
|
return api_GetBlendingInterface (version, ppinterface, pstudio, rotationmatrix, bonetransform);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ bool Bot::seesItem (const Vector &destination, const char *itemName) {
|
||||||
|
|
||||||
// check if line of sight to object is not blocked (i.e. visible)
|
// check if line of sight to object is not blocked (i.e. visible)
|
||||||
if (tr.flFraction != 1.0f) {
|
if (tr.flFraction != 1.0f) {
|
||||||
return strcmp (STRING (tr.pHit->v.classname), itemName) == 0;
|
return strcmp (tr.pHit->v.classname.chars (), itemName) == 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +330,7 @@ void Bot::avoidGrenades () {
|
||||||
if (!seesEntity (pent->v.origin) && isInFOV (pent->v.origin - getEyesPos ()) > pev->fov * 0.5f) {
|
if (!seesEntity (pent->v.origin) && isInFOV (pent->v.origin - getEyesPos ()) > pev->fov * 0.5f) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto model = STRING (pent->v.model) + 9;
|
auto model = pent->v.model.chars () + 9;
|
||||||
|
|
||||||
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == 4 && strcmp (model, "flashbang.mdl") == 0) {
|
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == 4 && strcmp (model, "flashbang.mdl") == 0) {
|
||||||
// don't look at flash bang
|
// don't look at flash bang
|
||||||
|
|
@ -500,7 +500,7 @@ void Bot::updatePickups () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent == pickupItem) {
|
if (ent == pickupItem) {
|
||||||
if (seesItem (origin, STRING (ent->v.classname))) {
|
if (seesItem (origin, ent->v.classname.chars ())) {
|
||||||
itemExists = true;
|
itemExists = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,8 +538,8 @@ void Bot::updatePickups () {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto classname = STRING (ent->v.classname);
|
auto classname = ent->v.classname.chars ();
|
||||||
auto model = STRING (ent->v.model) + 9;
|
auto model = ent->v.model.chars () + 9;
|
||||||
|
|
||||||
// check if line of sight to object is not blocked (i.e. visible)
|
// check if line of sight to object is not blocked (i.e. visible)
|
||||||
if (seesItem (origin, classname)) {
|
if (seesItem (origin, classname)) {
|
||||||
|
|
@ -1089,19 +1089,19 @@ void Bot::checkMsgQueue () {
|
||||||
if (m_radioSelect != -1) {
|
if (m_radioSelect != -1) {
|
||||||
if ((m_radioSelect != Radio::ReportingIn && m_forceRadio) || yb_radio_mode.int_ () != 2 || !conf.hasChatterBank (m_radioSelect) || !game.is (GameFlags::HasBotVoice)) {
|
if ((m_radioSelect != Radio::ReportingIn && m_forceRadio) || yb_radio_mode.int_ () != 2 || !conf.hasChatterBank (m_radioSelect) || !game.is (GameFlags::HasBotVoice)) {
|
||||||
if (m_radioSelect < Radio::GoGoGo) {
|
if (m_radioSelect < Radio::GoGoGo) {
|
||||||
game.botCommand (ent (), "radio1");
|
issueCommand ("radio1");
|
||||||
}
|
}
|
||||||
else if (m_radioSelect < Radio::RogerThat) {
|
else if (m_radioSelect < Radio::RogerThat) {
|
||||||
m_radioSelect -= Radio::GoGoGo - 1;
|
m_radioSelect -= Radio::GoGoGo - 1;
|
||||||
game.botCommand (ent (), "radio2");
|
issueCommand ("radio2");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_radioSelect -= Radio::RogerThat - 1;
|
m_radioSelect -= Radio::RogerThat - 1;
|
||||||
game.botCommand (ent (), "radio3");
|
issueCommand ("radio3");
|
||||||
}
|
}
|
||||||
|
|
||||||
// select correct menu item for this radio message
|
// select correct menu item for this radio message
|
||||||
game.botCommand (ent (), "menuselect %d", m_radioSelect);
|
issueCommand ("menuselect %d", m_radioSelect);
|
||||||
}
|
}
|
||||||
else if (m_radioSelect != Radio::ReportingIn) {
|
else if (m_radioSelect != Radio::ReportingIn) {
|
||||||
instantChatter (m_radioSelect);
|
instantChatter (m_radioSelect);
|
||||||
|
|
@ -1136,13 +1136,12 @@ bool Bot::isWeaponRestricted (int weaponIndex) {
|
||||||
if (strings.isEmpty (yb_restricted_weapons.str ())) {
|
if (strings.isEmpty (yb_restricted_weapons.str ())) {
|
||||||
return isWeaponRestrictedAMX (weaponIndex); // no banned weapons
|
return isWeaponRestrictedAMX (weaponIndex); // no banned weapons
|
||||||
}
|
}
|
||||||
auto bannedWeapons = String (yb_restricted_weapons.str ()).split (";");
|
const auto &bannedWeapons = String (yb_restricted_weapons.str ()).split (";");
|
||||||
|
const auto &alias = util.weaponIdToAlias (weaponIndex);
|
||||||
for (auto &ban : bannedWeapons) {
|
|
||||||
const char *banned = STRING (util.getWeaponAlias (true, nullptr, weaponIndex));
|
|
||||||
|
|
||||||
|
for (const auto &ban : bannedWeapons) {
|
||||||
// check is this weapon is banned
|
// check is this weapon is banned
|
||||||
if (strncmp (ban.chars (), banned, ban.length ()) == 0) {
|
if (ban == alias) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1154,7 +1153,7 @@ bool Bot::isWeaponRestrictedAMX (int weaponIndex) {
|
||||||
|
|
||||||
// check for weapon restrictions
|
// check for weapon restrictions
|
||||||
if (cr::bit (weaponIndex) & (kPrimaryWeaponMask | kSecondaryWeaponMask | Weapon::Shield)) {
|
if (cr::bit (weaponIndex) & (kPrimaryWeaponMask | kSecondaryWeaponMask | Weapon::Shield)) {
|
||||||
const char *restrictedWeapons = engfuncs.pfnCVarGetString ("amx_restrweapons");
|
auto restrictedWeapons = engfuncs.pfnCVarGetString ("amx_restrweapons");
|
||||||
|
|
||||||
if (strings.isEmpty (restrictedWeapons)) {
|
if (strings.isEmpty (restrictedWeapons)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1173,7 +1172,7 @@ bool Bot::isWeaponRestrictedAMX (int weaponIndex) {
|
||||||
|
|
||||||
// check for equipment restrictions
|
// check for equipment restrictions
|
||||||
else {
|
else {
|
||||||
const char *restrictedEquipment = engfuncs.pfnCVarGetString ("amx_restrequipammo");
|
auto restrictedEquipment = engfuncs.pfnCVarGetString ("amx_restrequipammo");
|
||||||
|
|
||||||
if (strings.isEmpty (restrictedEquipment)) {
|
if (strings.isEmpty (restrictedEquipment)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1202,17 +1201,6 @@ bool Bot::canReplaceWeapon () {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strings.isEmpty (yb_restricted_weapons.str ())) {
|
|
||||||
auto bannedWeapons = String (yb_restricted_weapons.str ()).split (";");
|
|
||||||
|
|
||||||
// check if its banned
|
|
||||||
for (auto &ban : bannedWeapons) {
|
|
||||||
if (m_currentWeapon == util.getWeaponAlias (false, ban.chars ())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_currentWeapon == Weapon::Scout && m_moneyAmount > 5000) {
|
if (m_currentWeapon == Weapon::Scout && m_moneyAmount > 5000) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1222,7 +1210,7 @@ bool Bot::canReplaceWeapon () {
|
||||||
else if ((m_currentWeapon == Weapon::M3 || m_currentWeapon == Weapon::XM1014) && m_moneyAmount > 4000) {
|
else if ((m_currentWeapon == Weapon::M3 || m_currentWeapon == Weapon::XM1014) && m_moneyAmount > 4000) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return isWeaponRestricted (m_currentWeapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bot::pickBestWeapon (int *vec, int count, int moneySave) {
|
int Bot::pickBestWeapon (int *vec, int count, int moneySave) {
|
||||||
|
|
@ -1458,17 +1446,17 @@ void Bot::buyStuff () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedWeapon != nullptr) {
|
if (selectedWeapon != nullptr) {
|
||||||
game.botCommand (ent (), "buy;menuselect %d", selectedWeapon->buyGroup);
|
issueCommand ("buy;menuselect %d", selectedWeapon->buyGroup);
|
||||||
|
|
||||||
if (isOldGame) {
|
if (isOldGame) {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelect);
|
issueCommand ("menuselect %d", selectedWeapon->buySelect);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_team == Team::Terrorist) {
|
if (m_team == Team::Terrorist) {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelectT);
|
issueCommand ("menuselect %d", selectedWeapon->buySelectT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelectCT);
|
issueCommand ("menuselect %d", selectedWeapon->buySelectCT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1487,10 +1475,10 @@ void Bot::buyStuff () {
|
||||||
if (pev->armorvalue < rg.int_ (50, 80) && (isPistolMode || (teamEcoValid && hasPrimaryWeapon ()))) {
|
if (pev->armorvalue < rg.int_ (50, 80) && (isPistolMode || (teamEcoValid && hasPrimaryWeapon ()))) {
|
||||||
// if bot is rich, buy kevlar + helmet, else buy a single kevlar
|
// if bot is rich, buy kevlar + helmet, else buy a single kevlar
|
||||||
if (m_moneyAmount > 1500 && !isWeaponRestricted (Weapon::ArmorHelm)) {
|
if (m_moneyAmount > 1500 && !isWeaponRestricted (Weapon::ArmorHelm)) {
|
||||||
game.botCommand (ent (), "buyequip;menuselect 2");
|
issueCommand ("buyequip;menuselect 2");
|
||||||
}
|
}
|
||||||
else if (!isWeaponRestricted (Weapon::Armor)) {
|
else if (!isWeaponRestricted (Weapon::Armor)) {
|
||||||
game.botCommand (ent (), "buyequip;menuselect 1");
|
issueCommand ("buyequip;menuselect 1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1552,17 +1540,17 @@ void Bot::buyStuff () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedWeapon != nullptr) {
|
if (selectedWeapon != nullptr) {
|
||||||
game.botCommand (ent (), "buy;menuselect %d", selectedWeapon->buyGroup);
|
issueCommand ("buy;menuselect %d", selectedWeapon->buyGroup);
|
||||||
|
|
||||||
if (isOldGame) {
|
if (isOldGame) {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelect);
|
issueCommand ("menuselect %d", selectedWeapon->buySelect);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_team == Team::Terrorist) {
|
if (m_team == Team::Terrorist) {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelectT);
|
issueCommand ("menuselect %d", selectedWeapon->buySelectT);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.botCommand (ent (), "menuselect %d", selectedWeapon->buySelectCT);
|
issueCommand ("menuselect %d", selectedWeapon->buySelectCT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1573,30 +1561,30 @@ void Bot::buyStuff () {
|
||||||
|
|
||||||
// buy a he grenade
|
// buy a he grenade
|
||||||
if (conf.chanceToBuyGrenade (0) && m_moneyAmount >= 400 && !isWeaponRestricted (Weapon::Explosive)) {
|
if (conf.chanceToBuyGrenade (0) && m_moneyAmount >= 400 && !isWeaponRestricted (Weapon::Explosive)) {
|
||||||
game.botCommand (ent (), "buyequip");
|
issueCommand ("buyequip");
|
||||||
game.botCommand (ent (), "menuselect 4");
|
issueCommand ("menuselect 4");
|
||||||
}
|
}
|
||||||
|
|
||||||
// buy a concussion grenade, i.e., 'flashbang'
|
// buy a concussion grenade, i.e., 'flashbang'
|
||||||
if (conf.chanceToBuyGrenade (1) && m_moneyAmount >= 300 && teamEcoValid && !isWeaponRestricted (Weapon::Flashbang)) {
|
if (conf.chanceToBuyGrenade (1) && m_moneyAmount >= 300 && teamEcoValid && !isWeaponRestricted (Weapon::Flashbang)) {
|
||||||
game.botCommand (ent (), "buyequip");
|
issueCommand ("buyequip");
|
||||||
game.botCommand (ent (), "menuselect 3");
|
issueCommand ("menuselect 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
// buy a smoke grenade
|
// buy a smoke grenade
|
||||||
if (conf.chanceToBuyGrenade (2) && m_moneyAmount >= 400 && teamEcoValid && !isWeaponRestricted (Weapon::Smoke)) {
|
if (conf.chanceToBuyGrenade (2) && m_moneyAmount >= 400 && teamEcoValid && !isWeaponRestricted (Weapon::Smoke)) {
|
||||||
game.botCommand (ent (), "buyequip");
|
issueCommand ("buyequip");
|
||||||
game.botCommand (ent (), "menuselect 5");
|
issueCommand ("menuselect 5");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BuyState::DefusalKit: // if bot is CT and we're on a bomb map, randomly buy the defuse kit
|
case BuyState::DefusalKit: // if bot is CT and we're on a bomb map, randomly buy the defuse kit
|
||||||
if (game.mapIs (MapFlags::Demolition) && m_team == Team::CT && rg.chance (80) && m_moneyAmount > 200 && !isWeaponRestricted (Weapon::Defuser)) {
|
if (game.mapIs (MapFlags::Demolition) && m_team == Team::CT && rg.chance (80) && m_moneyAmount > 200 && !isWeaponRestricted (Weapon::Defuser)) {
|
||||||
if (isOldGame) {
|
if (isOldGame) {
|
||||||
game.botCommand (ent (), "buyequip;menuselect 6");
|
issueCommand ("buyequip;menuselect 6");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.botCommand (ent (), "defuser"); // use alias in steamcs
|
issueCommand ("defuser"); // use alias in steamcs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1609,10 +1597,10 @@ void Bot::buyStuff () {
|
||||||
// if it's somewhat darkm do buy nightvision goggles
|
// if it's somewhat darkm do buy nightvision goggles
|
||||||
if ((skyColor >= 50.0f && lightLevel <= 15.0f) || (skyColor < 50.0f && lightLevel < 40.0f)) {
|
if ((skyColor >= 50.0f && lightLevel <= 15.0f) || (skyColor < 50.0f && lightLevel < 40.0f)) {
|
||||||
if (isOldGame) {
|
if (isOldGame) {
|
||||||
game.botCommand (ent (), "buyequip;menuselect 7");
|
issueCommand ("buyequip;menuselect 7");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.botCommand (ent (), "nvgs"); // use alias in steamcs
|
issueCommand ("nvgs"); // use alias in steamcs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1620,16 +1608,16 @@ void Bot::buyStuff () {
|
||||||
|
|
||||||
case BuyState::Ammo: // buy enough primary & secondary ammo (do not check for money here)
|
case BuyState::Ammo: // buy enough primary & secondary ammo (do not check for money here)
|
||||||
for (int i = 0; i <= 5; ++i) {
|
for (int i = 0; i <= 5; ++i) {
|
||||||
game.botCommand (ent (), "buyammo%d", rg.int_ (1, 2)); // simulate human
|
issueCommand ("buyammo%d", rg.int_ (1, 2)); // simulate human
|
||||||
}
|
}
|
||||||
|
|
||||||
// buy enough secondary ammo
|
// buy enough secondary ammo
|
||||||
if (hasPrimaryWeapon ()) {
|
if (hasPrimaryWeapon ()) {
|
||||||
game.botCommand (ent (), "buy;menuselect 7");
|
issueCommand ("buy;menuselect 7");
|
||||||
}
|
}
|
||||||
|
|
||||||
// buy enough primary ammo
|
// buy enough primary ammo
|
||||||
game.botCommand (ent (), "buy;menuselect 6");
|
issueCommand ("buy;menuselect 6");
|
||||||
|
|
||||||
// try to reload secondary weapon
|
// try to reload secondary weapon
|
||||||
if (m_reloadState != Reload::Primary) {
|
if (m_reloadState != Reload::Primary) {
|
||||||
|
|
@ -2827,10 +2815,10 @@ void Bot::checkDarkness () {
|
||||||
pev->impulse = 100;
|
pev->impulse = 100;
|
||||||
}
|
}
|
||||||
else if (!m_usesNVG && ((skyColor > 50.0f && m_path->light < 15.0f) || (skyColor <= 50.0f && m_path->light < 40.0f))) {
|
else if (!m_usesNVG && ((skyColor > 50.0f && m_path->light < 15.0f) || (skyColor <= 50.0f && m_path->light < 40.0f))) {
|
||||||
game.botCommand (ent (), "nightvision");
|
issueCommand ("nightvision");
|
||||||
}
|
}
|
||||||
else if (m_usesNVG && ((m_path->light > 20.0f && skyColor > 50.0f) || (m_path->light > 45.0f && skyColor <= 50.0f))) {
|
else if (m_usesNVG && ((m_path->light > 20.0f && skyColor > 50.0f) || (m_path->light > 45.0f && skyColor <= 50.0f))) {
|
||||||
game.botCommand (ent (), "nightvision");
|
issueCommand ("nightvision");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_checkDarkTime = game.time ();
|
m_checkDarkTime = game.time ();
|
||||||
|
|
@ -2926,7 +2914,7 @@ void Bot::update () {
|
||||||
else if (!m_notKilled) {
|
else if (!m_notKilled) {
|
||||||
// we got a teamkiller? vote him away...
|
// we got a teamkiller? vote him away...
|
||||||
if (m_voteKickIndex != m_lastVoteKick && yb_tkpunish.bool_ ()) {
|
if (m_voteKickIndex != m_lastVoteKick && yb_tkpunish.bool_ ()) {
|
||||||
game.botCommand (ent (), "vote %d", m_voteKickIndex);
|
issueCommand ("vote %d", m_voteKickIndex);
|
||||||
m_lastVoteKick = m_voteKickIndex;
|
m_lastVoteKick = m_voteKickIndex;
|
||||||
|
|
||||||
// if bot tk punishment is enabled slay the tk
|
// if bot tk punishment is enabled slay the tk
|
||||||
|
|
@ -2941,7 +2929,7 @@ void Bot::update () {
|
||||||
|
|
||||||
// host wants us to kick someone
|
// host wants us to kick someone
|
||||||
else if (m_voteMap != 0) {
|
else if (m_voteMap != 0) {
|
||||||
game.botCommand (ent (), "votemap %d", m_voteMap);
|
issueCommand ("votemap %d", m_voteMap);
|
||||||
m_voteMap = 0;
|
m_voteMap = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4386,7 +4374,7 @@ void Bot::pickupItem_ () {
|
||||||
auto &info = conf.getWeapons ();
|
auto &info = conf.getWeapons ();
|
||||||
|
|
||||||
for (index = 0; index < 7; ++index) {
|
for (index = 0; index < 7; ++index) {
|
||||||
if (strcmp (info[index].model, STRING (m_pickupItem->v.model) + 9) == 0) {
|
if (strcmp (info[index].model, m_pickupItem->v.model.chars () + 9) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4403,10 +4391,10 @@ void Bot::pickupItem_ () {
|
||||||
|
|
||||||
if (wid > 0) {
|
if (wid > 0) {
|
||||||
selectWeaponById (wid);
|
selectWeaponById (wid);
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
|
|
||||||
if (hasShield ()) {
|
if (hasShield ()) {
|
||||||
game.botCommand (ent (), "drop"); // discard both shield and pistol
|
issueCommand ("drop"); // discard both shield and pistol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enteredBuyZone (BuyState::PrimaryWeapon);
|
enteredBuyZone (BuyState::PrimaryWeapon);
|
||||||
|
|
@ -4417,7 +4405,7 @@ void Bot::pickupItem_ () {
|
||||||
|
|
||||||
if (wid == Weapon::Shield || wid > 6 || hasShield ()) {
|
if (wid == Weapon::Shield || wid > 6 || hasShield ()) {
|
||||||
selectWeaponById (wid);
|
selectWeaponById (wid);
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wid) {
|
if (!wid) {
|
||||||
|
|
@ -4448,7 +4436,7 @@ void Bot::pickupItem_ () {
|
||||||
|
|
||||||
if (wid > 6) {
|
if (wid > 6) {
|
||||||
selectWeaponById (wid);
|
selectWeaponById (wid);
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -4666,7 +4654,7 @@ void Bot::checkSpawnConditions () {
|
||||||
if (m_difficulty >= 2 && rg.chance (m_personality == Personality::Rusher ? 99 : 50) && !m_isReloading && game.mapIs (MapFlags::HostageRescue | MapFlags::Demolition | MapFlags::Escape | MapFlags::Assassination)) {
|
if (m_difficulty >= 2 && rg.chance (m_personality == Personality::Rusher ? 99 : 50) && !m_isReloading && game.mapIs (MapFlags::HostageRescue | MapFlags::Demolition | MapFlags::Escape | MapFlags::Assassination)) {
|
||||||
if (yb_jasonmode.bool_ ()) {
|
if (yb_jasonmode.bool_ ()) {
|
||||||
selectSecondary ();
|
selectSecondary ();
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
selectWeaponByName ("weapon_knife");
|
selectWeaponByName ("weapon_knife");
|
||||||
|
|
@ -4944,9 +4932,9 @@ void Bot::showDebugOverlay () {
|
||||||
static float timeDebugUpdate = 0.0f;
|
static float timeDebugUpdate = 0.0f;
|
||||||
static int index, goal, taskID;
|
static int index, goal, taskID;
|
||||||
|
|
||||||
static Dictionary <int, String, IntHash <int>> tasks;
|
static Dictionary <int32, String, IntHash <int32>> tasks;
|
||||||
static Dictionary <int, String, IntHash <int>> personalities;
|
static Dictionary <int32, String, IntHash <int32>> personalities;
|
||||||
static Dictionary <int, String, IntHash <int>> flags;
|
static Dictionary <int32, String, IntHash <int32>> flags;
|
||||||
|
|
||||||
if (tasks.empty ()) {
|
if (tasks.empty ()) {
|
||||||
tasks.push (Task::Normal, "Normal");
|
tasks.push (Task::Normal, "Normal");
|
||||||
|
|
@ -4993,15 +4981,15 @@ void Bot::showDebugOverlay () {
|
||||||
String enemy = "(none)";
|
String enemy = "(none)";
|
||||||
|
|
||||||
if (!game.isNullEntity (m_enemy)) {
|
if (!game.isNullEntity (m_enemy)) {
|
||||||
enemy = STRING (m_enemy->v.netname);
|
enemy = m_enemy->v.netname.chars ();
|
||||||
}
|
}
|
||||||
else if (!game.isNullEntity (m_lastEnemy)) {
|
else if (!game.isNullEntity (m_lastEnemy)) {
|
||||||
enemy.assignf ("%s (L)", STRING (m_lastEnemy->v.netname));
|
enemy.assignf ("%s (L)", m_lastEnemy->v.netname.chars ());
|
||||||
}
|
}
|
||||||
String pickup = "(none)";
|
String pickup = "(none)";
|
||||||
|
|
||||||
if (!game.isNullEntity (m_pickupItem)) {
|
if (!game.isNullEntity (m_pickupItem)) {
|
||||||
pickup = STRING (m_pickupItem->v.netname);
|
pickup = m_pickupItem->v.netname.chars ();
|
||||||
}
|
}
|
||||||
String aimFlags;
|
String aimFlags;
|
||||||
|
|
||||||
|
|
@ -5012,10 +5000,10 @@ void Bot::showDebugOverlay () {
|
||||||
aimFlags.appendf (" %s", flags[cr::bit (i)].chars ());
|
aimFlags.appendf (" %s", flags[cr::bit (i)].chars ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String weapon = STRING (util.getWeaponAlias (true, nullptr, m_currentWeapon));
|
const String &weapon = util.weaponIdToAlias (m_currentWeapon);
|
||||||
|
|
||||||
String debugData;
|
String debugData;
|
||||||
debugData.assignf ("\n\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%s Pickup=%s Type=%s\n", STRING (pev->netname), pev->health, pev->armorvalue, taskID, tasks[taskID].chars (), getTask ()->desire, weapon.chars (), getAmmoInClip (), getAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags.trim ().chars (), m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - game.time (), pev->movetype, enemy.chars (), pickup.chars (), personalities[m_personality].chars ());
|
debugData.assignf ("\n\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%s Pickup=%s Type=%s\n", pev->netname.chars (), pev->health, pev->armorvalue, taskID, tasks[taskID].chars (), getTask ()->desire, weapon.chars (), getAmmoInClip (), getAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags.trim ().chars (), m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - game.time (), pev->movetype, enemy.chars (), pickup.chars (), personalities[m_personality].chars ());
|
||||||
|
|
||||||
MessageWriter (MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, nullptr, game.getLocalEntity ())
|
MessageWriter (MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, nullptr, game.getLocalEntity ())
|
||||||
.writeByte (TE_TEXTMESSAGE)
|
.writeByte (TE_TEXTMESSAGE)
|
||||||
|
|
@ -5288,11 +5276,11 @@ void Bot::dropWeaponForUser (edict_t *user, bool discardC4) {
|
||||||
|
|
||||||
if (discardC4) {
|
if (discardC4) {
|
||||||
selectWeaponByName ("weapon_c4");
|
selectWeaponByName ("weapon_c4");
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
selectBestWeapon ();
|
selectBestWeapon ();
|
||||||
game.botCommand (ent (), "drop");
|
issueCommand ("drop");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pickupItem = nullptr;
|
m_pickupItem = nullptr;
|
||||||
|
|
@ -5317,7 +5305,7 @@ void Bot::startDoubleJump (edict_t *ent) {
|
||||||
m_doubleJumpEntity = ent;
|
m_doubleJumpEntity = ent;
|
||||||
|
|
||||||
startTask (Task::DoubleJump, TaskPri::DoubleJump, kInvalidNodeIndex, game.time (), true);
|
startTask (Task::DoubleJump, TaskPri::DoubleJump, kInvalidNodeIndex, game.time (), true);
|
||||||
sayTeam (strings.format ("Ok %s, i will help you!", STRING (ent->v.netname)));
|
sayTeam (strings.format ("Ok %s, i will help you!", ent->v.netname.chars ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::resetDoubleJump () {
|
void Bot::resetDoubleJump () {
|
||||||
|
|
@ -5330,7 +5318,7 @@ void Bot::resetDoubleJump () {
|
||||||
m_jumpReady = false;
|
m_jumpReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::sayDebug (const char *format, ...) {
|
void Bot::debugMsgInternal (const char *str) {
|
||||||
if (game.isDedicated ()) {
|
if (game.isDedicated ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -5339,15 +5327,8 @@ void Bot::sayDebug (const char *format, ...) {
|
||||||
if (level <= 2) {
|
if (level <= 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
va_list ap;
|
|
||||||
auto result = strings.chars ();
|
|
||||||
|
|
||||||
va_start (ap, format);
|
|
||||||
vsnprintf (result, StringBuffer::StaticBufferSize, format, ap);
|
|
||||||
va_end (ap);
|
|
||||||
|
|
||||||
String printBuf;
|
String printBuf;
|
||||||
printBuf.assignf ("%s: %s", STRING (pev->netname), result);
|
printBuf.assignf ("%s: %s", pev->netname.chars (), str);
|
||||||
|
|
||||||
bool playMessage = false;
|
bool playMessage = false;
|
||||||
|
|
||||||
|
|
@ -5462,7 +5443,7 @@ edict_t *Bot::correctGrenadeVelocity (const char *model) {
|
||||||
edict_t *result = nullptr;
|
edict_t *result = nullptr;
|
||||||
|
|
||||||
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
||||||
if (ent->v.owner == this->ent () && strcmp (STRING (ent->v.model) + 9, model) == 0) {
|
if (ent->v.owner == this->ent () && strcmp (ent->v.model.chars () + 9, model) == 0) {
|
||||||
result = ent;
|
result = ent;
|
||||||
|
|
||||||
// set the correct velocity for the grenade
|
// set the correct velocity for the grenade
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ void Bot::prepareChatMessage (const String &message) {
|
||||||
if (!util.isPlayer (ent)) {
|
if (!util.isPlayer (ent)) {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
String playerName = STRING (ent->v.netname);
|
String playerName = ent->v.netname.chars ();
|
||||||
util.humanizePlayerName (playerName);
|
util.humanizePlayerName (playerName);
|
||||||
|
|
||||||
return playerName;
|
return playerName;
|
||||||
|
|
@ -361,7 +361,7 @@ void Bot::say (const char *text) {
|
||||||
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
game.botCommand (ent (), "say \"%s\"", text);
|
issueCommand ("say \"%s\"", text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::sayTeam (const char *text) {
|
void Bot::sayTeam (const char *text) {
|
||||||
|
|
@ -370,5 +370,5 @@ void Bot::sayTeam (const char *text) {
|
||||||
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
game.botCommand (ent (), "say_team \"%s\"", text);
|
issueCommand ("say_team \"%s\"", text);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1196,7 +1196,7 @@ bool Bot::hasSecondaryWeapon () {
|
||||||
bool Bot::hasShield () {
|
bool Bot::hasShield () {
|
||||||
// this function returns true, if bot has a tactical shield
|
// this function returns true, if bot has a tactical shield
|
||||||
|
|
||||||
return strncmp (STRING (pev->viewmodel), "models/shield/v_shield_", 23) == 0;
|
return strncmp (pev->viewmodel.chars (), "models/shield/v_shield_", 23) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::isShieldDrawn () {
|
bool Bot::isShieldDrawn () {
|
||||||
|
|
@ -1216,7 +1216,7 @@ bool Bot::isEnemyBehindShield (edict_t *enemy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if enemy has shield and this shield is drawn
|
// check if enemy has shield and this shield is drawn
|
||||||
if ((enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7) && strncmp (STRING (enemy->v.viewmodel), "models/shield/v_shield_", 23) == 0) {
|
if ((enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7) && strncmp (enemy->v.viewmodel.chars (), "models/shield/v_shield_", 23) == 0) {
|
||||||
if (util.isInViewCone (pev->origin, enemy)) {
|
if (util.isInViewCone (pev->origin, enemy)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1355,7 +1355,7 @@ bool Bot::rateGroundWeapon (edict_t *ent) {
|
||||||
auto tab = conf.getRawWeapons ();
|
auto tab = conf.getRawWeapons ();
|
||||||
|
|
||||||
for (int i = 0; i < kNumWeapons; ++i) {
|
for (int i = 0; i < kNumWeapons; ++i) {
|
||||||
if (strcmp (tab[*pref].model, STRING (ent->v.model) + 9) == 0) {
|
if (strcmp (tab[*pref].model, ent->v.model.chars () + 9) == 0) {
|
||||||
groundIndex = i;
|
groundIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1464,13 +1464,13 @@ int Bot::bestWeaponCarried () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::selectWeaponByName (const char *name) {
|
void Bot::selectWeaponByName (const char *name) {
|
||||||
game.botCommand (ent (), name);
|
issueCommand (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::selectWeaponById (int num) {
|
void Bot::selectWeaponById (int num) {
|
||||||
auto tab = conf.getRawWeapons ();
|
auto tab = conf.getRawWeapons ();
|
||||||
|
|
||||||
game.botCommand (ent (), tab[num].name);
|
issueCommand (tab[num].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::decideFollowUser () {
|
void Bot::decideFollowUser () {
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,7 @@ int BotControl::cmdNodeAcquireEditor () {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graph.hasEditor ()) {
|
if (graph.hasEditor ()) {
|
||||||
msg ("Sorry, players \"%s\" already acquired rights to edit graph on this server.", STRING (graph.getEditor ()->v.netname));
|
msg ("Sorry, players \"%s\" already acquired rights to edit graph on this server.", graph.getEditor ()->v.netname.chars ());
|
||||||
return BotCommandResult::Handled;
|
return BotCommandResult::Handled;
|
||||||
}
|
}
|
||||||
graph.setEditor (m_ent);
|
graph.setEditor (m_ent);
|
||||||
|
|
@ -1854,7 +1854,7 @@ void BotControl::kickBotByMenu (int page) {
|
||||||
// check for fakeclient bit, since we're clear it upon kick, but actual bot struct destroyed after client disconnected
|
// check for fakeclient bit, since we're clear it upon kick, but actual bot struct destroyed after client disconnected
|
||||||
if (bot != nullptr && (bot->pev->flags & FL_FAKECLIENT)) {
|
if (bot != nullptr && (bot->pev->flags & FL_FAKECLIENT)) {
|
||||||
menuKeys |= cr::bit (cr::abs (i - menuKey));
|
menuKeys |= cr::bit (cr::abs (i - menuKey));
|
||||||
menus.appendf ("%1.1d. %s%s\n", i - menuKey + 1, STRING (bot->pev->netname), bot->m_team == Team::CT ? " \\y(CT)\\w" : " \\r(T)\\w");
|
menus.appendf ("%1.1d. %s%s\n", i - menuKey + 1, bot->pev->netname.chars (), bot->m_team == Team::CT ? " \\y(CT)\\w" : " \\r(T)\\w");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
menus.appendf ("\\d %1.1d. Not a Bot\\w\n", i - menuKey + 1);
|
menus.appendf ("\\d %1.1d. Not a Bot\\w\n", i - menuKey + 1);
|
||||||
|
|
@ -1915,13 +1915,13 @@ void BotControl::maintainAdminRights () {
|
||||||
}
|
}
|
||||||
else if (!!strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ())))) {
|
else if (!!strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ())))) {
|
||||||
client.flags &= ~ClientFlags::Admin;
|
client.flags &= ~ClientFlags::Admin;
|
||||||
game.print ("Player %s had lost remote access to %s.", STRING (player->v.netname), PRODUCT_SHORT_NAME);
|
game.print ("Player %s had lost remote access to %s.", player->v.netname.chars (), PRODUCT_SHORT_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(client.flags & ClientFlags::Admin) && !strings.isEmpty (yb_password_key.str ()) && !strings.isEmpty (yb_password.str ())) {
|
else if (!(client.flags & ClientFlags::Admin) && !strings.isEmpty (yb_password_key.str ()) && !strings.isEmpty (yb_password.str ())) {
|
||||||
if (strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ()))) == 0) {
|
if (strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ()))) == 0) {
|
||||||
client.flags |= ClientFlags::Admin;
|
client.flags |= ClientFlags::Admin;
|
||||||
game.print ("Player %s had gained full remote access to %s.", STRING (player->v.netname), PRODUCT_SHORT_NAME);
|
game.print ("Player %s had gained full remote access to %s.", player->v.netname.chars (), PRODUCT_SHORT_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,17 @@ void Game::precache () {
|
||||||
}
|
}
|
||||||
m_precached = true;
|
m_precached = true;
|
||||||
|
|
||||||
m_drawModels[DrawLine::Simple] = engfuncs.pfnPrecacheModel (ENGINE_STR ("sprites/laserbeam.spr"));
|
|
||||||
m_drawModels[DrawLine::Arrow] = engfuncs.pfnPrecacheModel (ENGINE_STR ("sprites/arrow1.spr"));
|
|
||||||
|
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("weapons/xbow_hit1.wav")); // waypoint add
|
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("weapons/mine_activate.wav")); // waypoint delete
|
m_drawModels[DrawLine::Simple] = m_engineWrap.precacheModel ("sprites/laserbeam.spr");
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("common/wpn_hudoff.wav")); // path add/delete start
|
m_drawModels[DrawLine::Arrow] = m_engineWrap.precacheModel ("sprites/arrow1.spr");
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("common/wpn_hudon.wav")); // path add/delete done
|
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("common/wpn_moveselect.wav")); // path add/delete cancel
|
m_engineWrap.precacheSound ("weapons/xbow_hit1.wav"); // waypoint add
|
||||||
engfuncs.pfnPrecacheSound (ENGINE_STR ("common/wpn_denyselect.wav")); // path add/delete error
|
m_engineWrap.precacheSound ("weapons/mine_activate.wav"); // waypoint delete
|
||||||
|
m_engineWrap.precacheSound ("common/wpn_hudoff.wav"); // path add/delete start
|
||||||
|
m_engineWrap.precacheSound ("common/wpn_hudon.wav"); // path add/delete done
|
||||||
|
m_engineWrap.precacheSound ("common/wpn_moveselect.wav"); // path add/delete cancel
|
||||||
|
m_engineWrap.precacheSound ("common/wpn_denyselect.wav"); // path add/delete error
|
||||||
|
|
||||||
m_mapFlags = 0; // reset map type as worldspawn is the first entity spawned
|
m_mapFlags = 0; // reset map type as worldspawn is the first entity spawned
|
||||||
|
|
||||||
|
|
@ -74,7 +76,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
if (!ent || ent->free || ent->v.classname == 0) {
|
if (!ent || ent->free || ent->v.classname == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto classname = STRING (ent->v.classname);
|
auto classname = ent->v.classname.chars ();
|
||||||
|
|
||||||
if (strcmp (classname, "worldspawn") == 0) {
|
if (strcmp (classname, "worldspawn") == 0) {
|
||||||
m_startEntity = ent;
|
m_startEntity = ent;
|
||||||
|
|
@ -86,7 +88,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
util.installSendTo ();
|
util.installSendTo ();
|
||||||
}
|
}
|
||||||
else if (strcmp (classname, "player_weaponstrip") == 0) {
|
else if (strcmp (classname, "player_weaponstrip") == 0) {
|
||||||
if ((is (GameFlags::Legacy)) && (STRING (ent->v.target))[0] == '\0') {
|
if (is (GameFlags::Legacy) && ent->v.target.chars ()[0] == '\0') {
|
||||||
ent->v.target = ent->v.targetname = engfuncs.pfnAllocString ("fake");
|
ent->v.target = ent->v.targetname = engfuncs.pfnAllocString ("fake");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -94,7 +96,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp (classname, "info_player_start") == 0) {
|
else if (strcmp (classname, "info_player_start") == 0) {
|
||||||
engfuncs.pfnSetModel (ent, ENGINE_STR ("models/player/urban/urban.mdl"));
|
m_engineWrap.setModel (ent, "models/player/urban/urban.mdl");
|
||||||
|
|
||||||
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
||||||
ent->v.renderamt = 127; // set its transparency amount
|
ent->v.renderamt = 127; // set its transparency amount
|
||||||
|
|
@ -103,7 +105,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
++m_spawnCount[Team::CT];
|
++m_spawnCount[Team::CT];
|
||||||
}
|
}
|
||||||
else if (strcmp (classname, "info_player_deathmatch") == 0) {
|
else if (strcmp (classname, "info_player_deathmatch") == 0) {
|
||||||
engfuncs.pfnSetModel (ent, ENGINE_STR ("models/player/terror/terror.mdl"));
|
m_engineWrap.setModel (ent, "models/player/terror/terror.mdl");
|
||||||
|
|
||||||
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
||||||
ent->v.renderamt = 127; // set its transparency amount
|
ent->v.renderamt = 127; // set its transparency amount
|
||||||
|
|
@ -113,7 +115,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp (classname, "info_vip_start") == 0) {
|
else if (strcmp (classname, "info_vip_start") == 0) {
|
||||||
engfuncs.pfnSetModel (ent, ENGINE_STR ("models/player/vip/vip.mdl"));
|
m_engineWrap.setModel (ent, "models/player/vip/vip.mdl");
|
||||||
|
|
||||||
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
ent->v.rendermode = kRenderTransAlpha; // set its render mode to transparency
|
||||||
ent->v.renderamt = 127; // set its transparency amount
|
ent->v.renderamt = 127; // set its transparency amount
|
||||||
|
|
@ -306,7 +308,7 @@ const char *Game::getModName () {
|
||||||
const char *Game::getMapName () {
|
const char *Game::getMapName () {
|
||||||
// this function gets the map name and store it in the map_name global string variable.
|
// this function gets the map name and store it in the map_name global string variable.
|
||||||
|
|
||||||
return strings.format ("%s", STRING (globals->mapname));
|
return strings.format ("%s", globals->mapname.chars ());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector Game::getEntityWorldOrigin (edict_t *ent) {
|
Vector Game::getEntityWorldOrigin (edict_t *ent) {
|
||||||
|
|
@ -465,7 +467,7 @@ bool Game::isSoftwareRenderer () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// and on only windows version you can use software-render game. Linux, OSX always defaults to OpenGL
|
// and on only windows version you can use software-render game. Linux, OSX always defaults to OpenGL
|
||||||
if (plat.isWindows) {
|
if (plat.win32) {
|
||||||
return plat.hasModule ("sw");
|
return plat.hasModule ("sw");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -577,15 +579,15 @@ bool Game::loadCSBinary () {
|
||||||
}
|
}
|
||||||
StringArray libs;
|
StringArray libs;
|
||||||
|
|
||||||
if (plat.isWindows) {
|
if (plat.win32) {
|
||||||
libs.push ("mp.dll");
|
libs.push ("mp.dll");
|
||||||
libs.push ("cs.dll");
|
libs.push ("cs.dll");
|
||||||
}
|
}
|
||||||
else if (plat.isLinux) {
|
else if (plat.linux) {
|
||||||
libs.push ("cs.so");
|
libs.push ("cs.so");
|
||||||
libs.push ("cs_i386.so");
|
libs.push ("cs_i386.so");
|
||||||
}
|
}
|
||||||
else if (plat.isOSX) {
|
else if (plat.osx) {
|
||||||
libs.push ("cs.dylib");
|
libs.push ("cs.dylib");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,13 +741,13 @@ bool Game::postload () {
|
||||||
print ("%s v%s.0.%d successfully loaded for game: Counter-Strike %s (%s).\n", PRODUCT_SHORT_NAME, PRODUCT_VERSION, util.buildNumber (), gameVersionStr.chars (), String::join (gameVersionFlags, ", ").chars ());
|
print ("%s v%s.0.%d successfully loaded for game: Counter-Strike %s (%s).\n", PRODUCT_SHORT_NAME, PRODUCT_VERSION, util.buildNumber (), gameVersionStr.chars (), String::join (gameVersionFlags, ", ").chars ());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (plat.isAndroid) {
|
if (plat.android) {
|
||||||
m_gameFlags |= (GameFlags::Xash3D | GameFlags::Mobility | GameFlags::HasBotVoice | GameFlags::ReGameDLL);
|
m_gameFlags |= (GameFlags::Xash3D | GameFlags::Mobility | GameFlags::HasBotVoice | GameFlags::ReGameDLL);
|
||||||
|
|
||||||
if (is (GameFlags::Metamod)) {
|
if (is (GameFlags::Metamod)) {
|
||||||
return true; // we should stop the attempt for loading the real gamedll, since metamod handle this for us
|
return true; // we should stop the attempt for loading the real gamedll, since metamod handle this for us
|
||||||
}
|
}
|
||||||
auto gamedll = strings.format ("%s/%s", getenv ("XASH3D_GAMELIBDIR"), plat.isAndroidHardFP ? "libserver_hardfp.so" : "libserver.so");
|
auto gamedll = strings.format ("%s/%s", getenv ("XASH3D_GAMELIBDIR"), plat.hfp ? "libserver_hardfp.so" : "libserver.so");
|
||||||
|
|
||||||
if (!m_gameLib.load (gamedll)) {
|
if (!m_gameLib.load (gamedll)) {
|
||||||
logger.fatal ("Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", gamedll, getModName ());
|
logger.fatal ("Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", gamedll, getModName ());
|
||||||
|
|
@ -879,9 +881,8 @@ bool Game::isShootableBreakable (edict_t *ent) {
|
||||||
if (isNullEntity (ent)) {
|
if (isNullEntity (ent)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto classname = STRING (ent->v.classname);
|
|
||||||
|
|
||||||
if (strcmp (classname, "func_breakable") == 0 || (strcmp (classname, "func_pushable") == 0 && (ent->v.spawnflags & SF_PUSH_BREAKABLE))) {
|
if (strcmp (ent->v.classname.chars (), "func_breakable") == 0 || (strcmp (ent->v.classname.chars (), "func_pushable") == 0 && (ent->v.spawnflags & SF_PUSH_BREAKABLE))) {
|
||||||
return ent->v.takedamage != DAMAGE_NO && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY) && ent->v.health < 500.0f;
|
return ent->v.takedamage != DAMAGE_NO && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY) && ent->v.health < 500.0f;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1098,7 +1098,7 @@ void BotGraph::calculatePathRadius (int index) {
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
game.testLine (radiusStart, radiusEnd, TraceIgnore::Monsters, nullptr, &tr);
|
game.testLine (radiusStart, radiusEnd, TraceIgnore::Monsters, nullptr, &tr);
|
||||||
|
|
||||||
if (strncmp ("func_door", STRING (tr.pHit->v.classname), 9) == 0) {
|
if (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
|
||||||
path.radius = 0.0f;
|
path.radius = 0.0f;
|
||||||
wayBlocked = true;
|
wayBlocked = true;
|
||||||
|
|
||||||
|
|
@ -1676,7 +1676,7 @@ bool BotGraph::saveGraphData () {
|
||||||
options |= StorageOption::Recovered;
|
options |= StorageOption::Recovered;
|
||||||
}
|
}
|
||||||
else if (!game.isNullEntity (m_editor)) {
|
else if (!game.isNullEntity (m_editor)) {
|
||||||
author = STRING (m_editor->v.netname);
|
author = m_editor->v.netname.chars ();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
author = "YAPB";
|
author = "YAPB";
|
||||||
|
|
@ -1691,9 +1691,10 @@ bool BotGraph::saveGraphData () {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::saveOldFormat () {
|
void BotGraph::saveOldFormat () {
|
||||||
PODGraphHeader header;
|
PODGraphHeader header {};
|
||||||
|
|
||||||
strcpy (header.header, kPodbotMagic);
|
strcpy (header.header, kPodbotMagic);
|
||||||
strncpy (header.author, STRING (m_editor->v.netname), cr::bufsize (header.author));
|
strncpy (header.author, m_editor->v.netname.chars (), cr::bufsize (header.author));
|
||||||
strncpy (header.mapName, game.getMapName (), cr::bufsize (header.mapName));
|
strncpy (header.mapName, game.getMapName (), cr::bufsize (header.mapName));
|
||||||
|
|
||||||
header.mapName[31] = 0;
|
header.mapName[31] = 0;
|
||||||
|
|
@ -1750,7 +1751,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
||||||
// check if we go through a func_illusionary, in which case return false
|
// check if we go through a func_illusionary, in which case return false
|
||||||
game.testHull (src, destination, TraceIgnore::Monsters, head_hull, m_editor, &tr);
|
game.testHull (src, destination, TraceIgnore::Monsters, head_hull, m_editor, &tr);
|
||||||
|
|
||||||
if (!game.isNullEntity (tr.pHit) && strcmp ("func_illusionary", STRING (tr.pHit->v.classname)) == 0) {
|
if (!game.isNullEntity (tr.pHit) && strcmp ("func_illusionary", tr.pHit->v.classname.chars ()) == 0) {
|
||||||
return false; // don't add pathnodes through func_illusionaries
|
return false; // don't add pathnodes through func_illusionaries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1758,9 +1759,9 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
||||||
game.testLine (src, destination, TraceIgnore::Monsters, m_editor, &tr);
|
game.testLine (src, destination, TraceIgnore::Monsters, m_editor, &tr);
|
||||||
|
|
||||||
// if node is visible from current position (even behind head)...
|
// if node is visible from current position (even behind head)...
|
||||||
if (tr.flFraction >= 1.0f || strncmp ("func_door", STRING (tr.pHit->v.classname), 9) == 0) {
|
if (tr.flFraction >= 1.0f || strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
|
||||||
// if it's a door check if nothing blocks behind
|
// if it's a door check if nothing blocks behind
|
||||||
if (strncmp ("func_door", STRING (tr.pHit->v.classname), 9) == 0) {
|
if (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
|
||||||
game.testLine (tr.vecEndPos, destination, TraceIgnore::Monsters, tr.pHit, &tr);
|
game.testLine (tr.vecEndPos, destination, TraceIgnore::Monsters, tr.pHit, &tr);
|
||||||
|
|
||||||
if (tr.flFraction < 1.0f) {
|
if (tr.flFraction < 1.0f) {
|
||||||
|
|
@ -2649,7 +2650,7 @@ void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
||||||
if (strcmp (STRING (ent->v.model) + 9, "c4.mdl") == 0) {
|
if (strcmp (ent->v.model.chars () + 9, "c4.mdl") == 0) {
|
||||||
m_bombOrigin = game.getEntityWorldOrigin (ent);
|
m_bombOrigin = game.getEntityWorldOrigin (ent);
|
||||||
return EntitySearchResult::Break;
|
return EntitySearchResult::Break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,14 @@ namespace variadic {
|
||||||
auto buffer = strings.chars ();
|
auto buffer = strings.chars ();
|
||||||
|
|
||||||
va_start (ap, format);
|
va_start (ap, format);
|
||||||
_vsnprintf (buffer, StringBuffer::StaticBufferSize, format, ap);
|
vsnprintf (buffer, StringBuffer::StaticBufferSize, format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
if (ent && (ent->v.flags & (FL_FAKECLIENT | FL_DORMANT))) {
|
if (ent && (ent->v.flags & (FL_FAKECLIENT | FL_DORMANT))) {
|
||||||
if (bots[ent]) {
|
auto bot = bots[ent];
|
||||||
game.botCommand (ent, buffer);
|
|
||||||
|
if (bot) {
|
||||||
|
bot->issueCommand (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.is (GameFlags::Metamod)) {
|
if (game.is (GameFlags::Metamod)) {
|
||||||
|
|
@ -441,7 +443,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
||||||
}
|
}
|
||||||
dllapi.pfnPM_Move (playerMove, server);
|
dllapi.pfnPM_Move (playerMove, server);
|
||||||
};
|
};
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
|
CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
|
||||||
|
|
@ -498,7 +500,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
|
||||||
RETURN_META (MRES_IGNORED);
|
RETURN_META (MRES_IGNORED);
|
||||||
};
|
};
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
||||||
|
|
@ -787,7 +789,7 @@ CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
||||||
|
|
||||||
table->pfnClientCommand = variadic::clientCommand;
|
table->pfnClientCommand = variadic::clientCommand;
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion) {
|
CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion) {
|
||||||
|
|
@ -801,11 +803,11 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
|
||||||
|
|
||||||
if (!api_GetNewDLLFunctions || !api_GetNewDLLFunctions (table, interfaceVersion)) {
|
if (!api_GetNewDLLFunctions || !api_GetNewDLLFunctions (table, interfaceVersion)) {
|
||||||
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dllfuncs.newapi_table = table;
|
dllfuncs.newapi_table = table;
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
|
CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
|
||||||
|
|
@ -834,7 +836,7 @@ CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
|
||||||
RETURN_META_VALUE (MRES_IGNORED, 0);
|
RETURN_META_VALUE (MRES_IGNORED, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_EXPORT int Meta_Query (char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs) {
|
CR_EXPORT int Meta_Query (char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs) {
|
||||||
|
|
@ -845,7 +847,7 @@ CR_EXPORT int Meta_Query (char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMet
|
||||||
gpMetaUtilFuncs = pMetaUtilFuncs;
|
gpMetaUtilFuncs = pMetaUtilFuncs;
|
||||||
*pPlugInfo = &Plugin_info;
|
*pPlugInfo = &Plugin_info;
|
||||||
|
|
||||||
return TRUE; // tell metamod this plugin looks safe
|
return true; // tell metamod this plugin looks safe
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) {
|
CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) {
|
||||||
|
|
@ -867,7 +869,7 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
||||||
|
|
||||||
if (now > Plugin_info.loadable) {
|
if (now > Plugin_info.loadable) {
|
||||||
logger.error ("%s: plugin NOT attaching (can't load plugin right now)", Plugin_info.name);
|
logger.error ("%s: plugin NOT attaching (can't load plugin right now)", Plugin_info.name);
|
||||||
return FALSE; // returning FALSE prevents metamod from attaching this plugin
|
return false; // returning FALSE prevents metamod from attaching this plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep track of the pointers to engine function tables metamod gives us
|
// keep track of the pointers to engine function tables metamod gives us
|
||||||
|
|
@ -875,7 +877,7 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
||||||
memcpy (functionTable, &metamodFunctionTable, sizeof (metamod_funcs_t));
|
memcpy (functionTable, &metamodFunctionTable, sizeof (metamod_funcs_t));
|
||||||
gpGamedllFuncs = pGamedllFuncs;
|
gpGamedllFuncs = pGamedllFuncs;
|
||||||
|
|
||||||
return TRUE; // returning true enables metamod to attach this plugin
|
return true; // returning true enables metamod to attach this plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
||||||
|
|
@ -884,7 +886,7 @@ CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
||||||
|
|
||||||
if (now > Plugin_info.unloadable && reason != PNL_CMD_FORCED) {
|
if (now > Plugin_info.unloadable && reason != PNL_CMD_FORCED) {
|
||||||
logger.error ("%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name);
|
logger.error ("%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name);
|
||||||
return FALSE; // returning FALSE prevents metamod from unloading this plugin
|
return false; // returning FALSE prevents metamod from unloading this plugin
|
||||||
}
|
}
|
||||||
bots.kickEveryone (true); // kick all bots off this server
|
bots.kickEveryone (true); // kick all bots off this server
|
||||||
|
|
||||||
|
|
@ -892,7 +894,7 @@ CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
||||||
graph.savePractice ();
|
graph.savePractice ();
|
||||||
util.disableSendTo ();
|
util.disableSendTo ();
|
||||||
|
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CR_EXPORT void Meta_Init () {
|
CR_EXPORT void Meta_Init () {
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,16 @@ BotManager::BotManager () {
|
||||||
|
|
||||||
m_bombPlanted = false;
|
m_bombPlanted = false;
|
||||||
m_botsCanPause = false;
|
m_botsCanPause = false;
|
||||||
|
m_roundEnded = false;
|
||||||
|
|
||||||
m_bombSayStatus = BombPlantedSay::ChatSay | BombPlantedSay::Chatter;
|
m_bombSayStatus = BombPlantedSay::ChatSay | BombPlantedSay::Chatter;
|
||||||
|
|
||||||
for (int i = 0; i < kGameTeamNum; ++i) {
|
for (int i = 0; i < kGameTeamNum; ++i) {
|
||||||
m_leaderChoosen[i] = false;
|
m_leaderChoosen[i] = false;
|
||||||
m_economicsGood[i] = true;
|
m_economicsGood[i] = true;
|
||||||
|
|
||||||
|
m_lastRadioTime[i] = 0.0f;
|
||||||
|
m_lastRadio[i] = -1;
|
||||||
}
|
}
|
||||||
reset ();
|
reset ();
|
||||||
|
|
||||||
|
|
@ -106,7 +110,7 @@ void BotManager::touchKillerEntity (Bot *bot) {
|
||||||
kv.szClassName = const_cast <char *> (prop.classname.chars ());
|
kv.szClassName = const_cast <char *> (prop.classname.chars ());
|
||||||
kv.szKeyName = "damagetype";
|
kv.szKeyName = "damagetype";
|
||||||
kv.szValue = const_cast <char *> (strings.format ("%d", cr::bit (4)));
|
kv.szValue = const_cast <char *> (strings.format ("%d", cr::bit (4)));
|
||||||
kv.fHandled = FALSE;
|
kv.fHandled = false;
|
||||||
|
|
||||||
MDLL_KeyValue (m_killerEntity, &kv);
|
MDLL_KeyValue (m_killerEntity, &kv);
|
||||||
MDLL_Touch (m_killerEntity, bot->ent ());
|
MDLL_Touch (m_killerEntity, bot->ent ());
|
||||||
|
|
@ -205,7 +209,7 @@ BotCreateResult BotManager::create (const String &name, int difficulty, int pers
|
||||||
ctrl.msg ("Maximum players reached (%d/%d). Unable to create Bot.", game.maxClients (), game.maxClients ());
|
ctrl.msg ("Maximum players reached (%d/%d). Unable to create Bot.", game.maxClients (), game.maxClients ());
|
||||||
return BotCreateResult::MaxPlayersReached;
|
return BotCreateResult::MaxPlayersReached;
|
||||||
}
|
}
|
||||||
auto object = cr::createUnique <Bot> (bot, difficulty, personality, team, member);
|
auto object = cr::makeUnique <Bot> (bot, difficulty, personality, team, member);
|
||||||
auto index = object->index ();
|
auto index = object->index ();
|
||||||
|
|
||||||
// assign owner of bot name
|
// assign owner of bot name
|
||||||
|
|
@ -660,7 +664,7 @@ void BotManager::listBots () {
|
||||||
ctrl.msg ("%-3.5s\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.4s\t%-3.4s\t%-3.5s", "index", "name", "personality", "team", "difficulty", "frags", "alive");
|
ctrl.msg ("%-3.5s\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.4s\t%-3.4s\t%-3.5s", "index", "name", "personality", "team", "difficulty", "frags", "alive");
|
||||||
|
|
||||||
for (const auto &bot : bots) {;
|
for (const auto &bot : bots) {;
|
||||||
ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s", bot->index (), STRING (bot->pev->netname), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", bot->m_team == Team::CT ? "CT" : "T", bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_notKilled ? "yes" : "no");
|
ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", bot->m_team == Team::CT ? "CT" : "T", bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_notKilled ? "yes" : "no");
|
||||||
}
|
}
|
||||||
ctrl.msg ("%d bots", m_bots.length ());
|
ctrl.msg ("%d bots", m_bots.length ());
|
||||||
}
|
}
|
||||||
|
|
@ -816,11 +820,11 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char reject[256] = {0, };
|
char reject[256] = {0, };
|
||||||
MDLL_ClientConnect (bot, STRING (bot->v.netname), strings.format ("127.0.0.%d", clientIndex + 100), reject);
|
MDLL_ClientConnect (bot, bot->v.netname.chars (), strings.format ("127.0.0.%d", clientIndex + 100), reject);
|
||||||
|
|
||||||
if (!strings.isEmpty (reject)) {
|
if (!strings.isEmpty (reject)) {
|
||||||
logger.error ("Server refused '%s' connection (%s)", STRING (bot->v.netname), reject);
|
logger.error ("Server refused '%s' connection (%s)", bot->v.netname.chars (), reject);
|
||||||
game.serverCommand ("kick \"%s\"", STRING (bot->v.netname)); // kick the bot player if the server refused it
|
game.serverCommand ("kick \"%s\"", bot->v.netname.chars ()); // kick the bot player if the server refused it
|
||||||
|
|
||||||
bot->v.flags |= FL_KILLME;
|
bot->v.flags |= FL_KILLME;
|
||||||
return;
|
return;
|
||||||
|
|
@ -1246,7 +1250,7 @@ void Bot::kill () {
|
||||||
|
|
||||||
void Bot::kick () {
|
void Bot::kick () {
|
||||||
// this function kick off one bot from the server.
|
// this function kick off one bot from the server.
|
||||||
auto username = STRING (pev->netname);
|
auto username = pev->netname.chars ();
|
||||||
|
|
||||||
if (!(pev->flags & FL_FAKECLIENT) || strings.isEmpty (username)) {
|
if (!(pev->flags & FL_FAKECLIENT) || strings.isEmpty (username)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1304,7 +1308,7 @@ void Bot::updateTeamJoin () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// select the team the bot wishes to join...
|
// select the team the bot wishes to join...
|
||||||
game.botCommand (ent (), "menuselect %d", m_wantedTeam);
|
issueCommand ("menuselect %d", m_wantedTeam);
|
||||||
}
|
}
|
||||||
else if (m_startAction == BotMsg::ClassSelect) {
|
else if (m_startAction == BotMsg::ClassSelect) {
|
||||||
m_startAction = BotMsg::None; // switch back to idle
|
m_startAction = BotMsg::None; // switch back to idle
|
||||||
|
|
@ -1317,7 +1321,7 @@ void Bot::updateTeamJoin () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// select the class the bot wishes to use...
|
// select the class the bot wishes to use...
|
||||||
game.botCommand (ent (), "menuselect %d", m_wantedClass);
|
issueCommand ("menuselect %d", m_wantedClass);
|
||||||
|
|
||||||
// bot has now joined the game (doesn't need to be started)
|
// bot has now joined the game (doesn't need to be started)
|
||||||
m_notStarted = false;
|
m_notStarted = false;
|
||||||
|
|
@ -1409,7 +1413,7 @@ void BotManager::updateActiveGrenade () {
|
||||||
// search the map for any type of grenade
|
// search the map for any type of grenade
|
||||||
game.searchEntities ("classname", "grenade", [&] (edict_t *e) {
|
game.searchEntities ("classname", "grenade", [&] (edict_t *e) {
|
||||||
// do not count c4 as a grenade
|
// do not count c4 as a grenade
|
||||||
if (strcmp (STRING (e->v.model) + 9, "c4.mdl") == 0) {
|
if (strcmp (e->v.model.chars () + 9, "c4.mdl") == 0) {
|
||||||
return EntitySearchResult::Continue;
|
return EntitySearchResult::Continue;
|
||||||
}
|
}
|
||||||
m_activeGrenades.push (e);
|
m_activeGrenades.push (e);
|
||||||
|
|
@ -1430,7 +1434,7 @@ void BotManager::updateIntrestingEntities () {
|
||||||
|
|
||||||
// search the map for any type of grenade
|
// search the map for any type of grenade
|
||||||
game.searchEntities (nullptr, kInfiniteDistance, [&] (edict_t *e) {
|
game.searchEntities (nullptr, kInfiniteDistance, [&] (edict_t *e) {
|
||||||
auto classname = STRING (e->v.classname);
|
auto classname = e->v.classname.chars ();
|
||||||
|
|
||||||
// search for grenades, weaponboxes, weapons, items and armoury entities
|
// search for grenades, weaponboxes, weapons, items and armoury entities
|
||||||
if (strncmp ("weapon", classname, 6) == 0 || strncmp ("grenade", classname, 7) == 0 || strncmp ("item", classname, 4) == 0 || strncmp ("armoury", classname, 7) == 0) {
|
if (strncmp ("weapon", classname, 6) == 0 || strncmp ("grenade", classname, 7) == 0 || strncmp ("item", classname, 4) == 0 || strncmp ("armoury", classname, 7) == 0) {
|
||||||
|
|
@ -1689,7 +1693,7 @@ void BotConfig::loadMainConfig () {
|
||||||
firstLoad = false;
|
firstLoad = false;
|
||||||
|
|
||||||
// android is abit hard to play, lower the difficulty by default
|
// android is abit hard to play, lower the difficulty by default
|
||||||
if (plat.isAndroid && yb_difficulty.int_ () > 3) {
|
if (plat.android && yb_difficulty.int_ () > 3) {
|
||||||
yb_difficulty.set (3);
|
yb_difficulty.set (3);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -507,3 +507,25 @@ void MessageDispatcher::stop () {
|
||||||
(this->*m_handlers[m_current]) ();
|
(this->*m_handlers[m_current]) ();
|
||||||
m_current = NetMsg::None;
|
m_current = NetMsg::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageDispatcher::ensureMessages () {
|
||||||
|
// we're getting messages ids in regusermsg for metamod, but when we're unloaded, we're lost our ids on next 'meta load'.
|
||||||
|
// this function tries to associate appropriate message ids.
|
||||||
|
|
||||||
|
// check if we're have one
|
||||||
|
if (m_maps.exists (NetMsg::Money)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-register our message
|
||||||
|
for (const auto &msg : m_wanted) {
|
||||||
|
add (msg.key, GET_USER_MSG_ID (PLID, msg.key.chars (), nullptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 MessageDispatcher::id (NetMsg msg) {
|
||||||
|
if (game.is (GameFlags::Metamod)) {
|
||||||
|
ensureMessages ();
|
||||||
|
}
|
||||||
|
return m_maps[msg];
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ int Bot::findBestGoal () {
|
||||||
int result = kInvalidNodeIndex;
|
int result = kInvalidNodeIndex;
|
||||||
|
|
||||||
game.searchEntities ("classname", "weaponbox", [&] (edict_t *ent) {
|
game.searchEntities ("classname", "weaponbox", [&] (edict_t *ent) {
|
||||||
if (strcmp (STRING (ent->v.model), "models/w_backpack.mdl") == 0) {
|
if (strcmp (ent->v.model.chars () + 9, "backpack.mdl") == 0) {
|
||||||
result = graph.getNearest (game.getEntityWorldOrigin (ent));
|
result = graph.getNearest (game.getEntityWorldOrigin (ent));
|
||||||
|
|
||||||
if (graph.exists (result)) {
|
if (graph.exists (result)) {
|
||||||
|
|
@ -708,7 +708,7 @@ bool Bot::updateNavigation () {
|
||||||
if (game.mapIs (MapFlags::HasDoors)) {
|
if (game.mapIs (MapFlags::HasDoors)) {
|
||||||
game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (pev->origin, m_pathOrigin, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
||||||
if (!game.isNullEntity (tr.pHit) && game.isNullEntity (m_liftEntity) && strncmp (STRING (tr.pHit->v.classname), "func_door", 9) == 0) {
|
if (!game.isNullEntity (tr.pHit) && game.isNullEntity (m_liftEntity) && strncmp (tr.pHit->v.classname.chars (), "func_door", 9) == 0) {
|
||||||
// if the door is near enough...
|
// if the door is near enough...
|
||||||
if ((game.getEntityWorldOrigin (tr.pHit) - pev->origin).lengthSq () < 2500.0f) {
|
if ((game.getEntityWorldOrigin (tr.pHit) - pev->origin).lengthSq () < 2500.0f) {
|
||||||
ignoreCollision (); // don't consider being stuck
|
ignoreCollision (); // don't consider being stuck
|
||||||
|
|
@ -728,7 +728,7 @@ bool Bot::updateNavigation () {
|
||||||
m_aimFlags &= ~(AimFlags::LastEnemy | AimFlags::PredictPath);
|
m_aimFlags &= ~(AimFlags::LastEnemy | AimFlags::PredictPath);
|
||||||
m_canChooseAimDirection = false;
|
m_canChooseAimDirection = false;
|
||||||
|
|
||||||
auto button = lookupButton (STRING (tr.pHit->v.targetname));
|
auto button = lookupButton (tr.pHit->v.targetname.chars ());
|
||||||
|
|
||||||
// check if we got valid button
|
// check if we got valid button
|
||||||
if (!game.isNullEntity (button)) {
|
if (!game.isNullEntity (button)) {
|
||||||
|
|
@ -849,7 +849,7 @@ bool Bot::updateLiftHandling () {
|
||||||
// update node time set
|
// update node time set
|
||||||
m_navTimeset = game.time ();
|
m_navTimeset = game.time ();
|
||||||
|
|
||||||
TraceResult tr, tr2;
|
TraceResult tr;
|
||||||
|
|
||||||
// wait for something about for lift
|
// wait for something about for lift
|
||||||
auto wait = [&] () {
|
auto wait = [&] () {
|
||||||
|
|
@ -865,9 +865,9 @@ bool Bot::updateLiftHandling () {
|
||||||
};
|
};
|
||||||
|
|
||||||
// trace line to door
|
// trace line to door
|
||||||
game.testLine (pev->origin, m_path->origin, TraceIgnore::Everything, ent (), &tr2);
|
game.testLine (pev->origin, m_path->origin, TraceIgnore::Everything, ent (), &tr);
|
||||||
|
|
||||||
if (tr2.flFraction < 1.0f && strcmp (STRING (tr2.pHit->v.classname), "func_door") == 0 && (m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) && pev->groundentity != tr2.pHit) {
|
if (tr.flFraction < 1.0f && strcmp (tr.pHit->v.classname.chars (), "func_door") == 0 && (m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) && pev->groundentity != tr.pHit) {
|
||||||
if (m_liftState == LiftState::None) {
|
if (m_liftState == LiftState::None) {
|
||||||
m_liftState = LiftState::LookingButtonOutside;
|
m_liftState = LiftState::LookingButtonOutside;
|
||||||
m_liftUsageTime = game.time () + 7.0f;
|
m_liftUsageTime = game.time () + 7.0f;
|
||||||
|
|
@ -879,8 +879,8 @@ bool Bot::updateLiftHandling () {
|
||||||
game.testLine (m_path->origin, m_path->origin + Vector (0.0f, 0.0f, -50.0f), TraceIgnore::Everything, ent (), &tr);
|
game.testLine (m_path->origin, m_path->origin + Vector (0.0f, 0.0f, -50.0f), TraceIgnore::Everything, ent (), &tr);
|
||||||
|
|
||||||
// if trace result shows us that it is a lift
|
// if trace result shows us that it is a lift
|
||||||
if (!game.isNullEntity (tr.pHit) && !m_pathWalk.empty () && (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 (!game.isNullEntity (tr.pHit) && !m_pathWalk.empty () && (strcmp (tr.pHit->v.classname.chars (), "func_door") == 0 || strcmp (tr.pHit->v.classname.chars (), "func_plat") == 0 || strcmp (tr.pHit->v.classname.chars (), "func_train") == 0) && !liftClosedDoorExists) {
|
||||||
if ((m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) && tr.pHit->v.velocity.z == 0.0f) {
|
if ((m_liftState == LiftState::None || m_liftState == LiftState::WaitingFor || m_liftState == LiftState::LookingButtonOutside) && cr::fzero (tr.pHit->v.velocity.z)) {
|
||||||
if (cr::abs (pev->origin.z - tr.vecEndPos.z) < 70.0f) {
|
if (cr::abs (pev->origin.z - tr.vecEndPos.z) < 70.0f) {
|
||||||
m_liftEntity = tr.pHit;
|
m_liftEntity = tr.pHit;
|
||||||
m_liftState = LiftState::EnteringIn;
|
m_liftState = LiftState::EnteringIn;
|
||||||
|
|
@ -901,7 +901,7 @@ bool Bot::updateLiftHandling () {
|
||||||
if (graph.exists (nextNode) && (graph[nextNode].flags & NodeFlag::Lift)) {
|
if (graph.exists (nextNode) && (graph[nextNode].flags & NodeFlag::Lift)) {
|
||||||
game.testLine (m_path->origin, graph[nextNode].origin, TraceIgnore::Everything, ent (), &tr);
|
game.testLine (m_path->origin, graph[nextNode].origin, TraceIgnore::Everything, ent (), &tr);
|
||||||
|
|
||||||
if (!game.isNullEntity (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 (!game.isNullEntity (tr.pHit) && (strcmp (tr.pHit->v.classname.chars (), "func_door") == 0 || strcmp (tr.pHit->v.classname.chars (), "func_plat") == 0 || strcmp (tr.pHit->v.classname.chars (), "func_train") == 0)) {
|
||||||
m_liftEntity = tr.pHit;
|
m_liftEntity = tr.pHit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -983,7 +983,7 @@ bool Bot::updateLiftHandling () {
|
||||||
|
|
||||||
// bot is trying to find button inside a lift
|
// bot is trying to find button inside a lift
|
||||||
if (m_liftState == LiftState::LookingButtonInside) {
|
if (m_liftState == LiftState::LookingButtonInside) {
|
||||||
auto button = lookupButton (STRING (m_liftEntity->v.targetname));
|
auto button = lookupButton (m_liftEntity->v.targetname.chars ());
|
||||||
|
|
||||||
// got a valid button entity ?
|
// got a valid button entity ?
|
||||||
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && m_liftEntity->v.velocity.z == 0.0f && isOnFloor ()) {
|
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && m_liftEntity->v.velocity.z == 0.0f && isOnFloor ()) {
|
||||||
|
|
@ -1032,7 +1032,7 @@ bool Bot::updateLiftHandling () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!game.isNullEntity (m_liftEntity)) {
|
else if (!game.isNullEntity (m_liftEntity)) {
|
||||||
auto button = lookupButton (STRING (m_liftEntity->v.targetname));
|
auto button = lookupButton (m_liftEntity->v.targetname.chars ());
|
||||||
|
|
||||||
// if we got a valid button entity
|
// if we got a valid button entity
|
||||||
if (!game.isNullEntity (button)) {
|
if (!game.isNullEntity (button)) {
|
||||||
|
|
@ -1331,63 +1331,40 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
return hfunctionPathDist (index, startIndex, goalIndex) / 128.0f * 10.0f;
|
return hfunctionPathDist (index, startIndex, goalIndex) / 128.0f * 10.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// holders for heuristic functions
|
||||||
|
Lambda <float (int, int, int)> gcalc, hcalc;
|
||||||
|
|
||||||
// get correct calculation for heuristic
|
// get correct calculation for heuristic
|
||||||
auto calculate = [&] (bool hfun, int a, int b, int c) -> float {
|
|
||||||
if (pathType == FindPath::Optimal) {
|
if (pathType == FindPath::Optimal) {
|
||||||
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
||||||
if (hfun) {
|
hcalc = hfunctionPathDistWithHostage;
|
||||||
return hfunctionPathDistWithHostage (a, b, c);
|
gcalc = gfunctionKillsDistCTWithHostage;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return gfunctionKillsDistCTWithHostage (a, b, c);
|
hcalc = hfunctionPathDist;
|
||||||
}
|
gcalc = gfunctionKillsDist;
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (hfun) {
|
|
||||||
return hfunctionPathDist (a, b, c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return gfunctionKillsDist (a, b, c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pathType == FindPath::Safe) {
|
else if (pathType == FindPath::Safe) {
|
||||||
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
||||||
if (hfun) {
|
hcalc = hfunctionNone;
|
||||||
return hfunctionNone (a, b, c);
|
gcalc = gfunctionKillsCTWithHostage;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return gfunctionKillsCTWithHostage (a, b, c);
|
hcalc = hfunctionNone;
|
||||||
}
|
gcalc = gfunctionKills;
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (hfun) {
|
|
||||||
return hfunctionNone (a, b, c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return gfunctionKills (a, b, c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
if (game.mapIs (MapFlags::HostageRescue) && hasHostage ()) {
|
||||||
if (hfun) {
|
hcalc = hfunctionPathDistWithHostage;
|
||||||
return hfunctionPathDistWithHostage (a, b, c);
|
gcalc = gfunctionPathDistWithHostage;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return gfunctionPathDistWithHostage (a, b, c);
|
hcalc = hfunctionPathDist;
|
||||||
|
gcalc = gfunctionPathDist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (hfun) {
|
|
||||||
return hfunctionPathDist (a, b, c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return gfunctionPathDist (a, b, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!graph.exists (srcIndex)) {
|
if (!graph.exists (srcIndex)) {
|
||||||
logger.error ("Pathfinder source path index not valid (%d)", srcIndex);
|
logger.error ("Pathfinder source path index not valid (%d)", srcIndex);
|
||||||
|
|
@ -1406,8 +1383,8 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
auto srcRoute = &m_routes[srcIndex];
|
auto srcRoute = &m_routes[srcIndex];
|
||||||
|
|
||||||
// put start node into open list
|
// put start node into open list
|
||||||
srcRoute->g = calculate (false, m_team, srcIndex, kInvalidNodeIndex);
|
srcRoute->g = gcalc (m_team, srcIndex, kInvalidNodeIndex);
|
||||||
srcRoute->f = srcRoute->g + calculate (true, srcIndex, srcIndex, destIndex);
|
srcRoute->f = srcRoute->g + hcalc (srcIndex, srcIndex, destIndex);
|
||||||
srcRoute->state = RouteState::Open;
|
srcRoute->state = RouteState::Open;
|
||||||
|
|
||||||
m_routeQue.clear ();
|
m_routeQue.clear ();
|
||||||
|
|
@ -1419,7 +1396,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
|
|
||||||
// safes us from bad graph...
|
// safes us from bad graph...
|
||||||
if (m_routeQue.length () >= kMaxRouteLength - 1) {
|
if (m_routeQue.length () >= kMaxRouteLength - 1) {
|
||||||
logger.error ("A* Search for bots \"%s\" has tried to build path with at least %d nodes. Seems to be graph is broken.", STRING (pev->netname), m_routeQue.length ());
|
logger.error ("A* Search for bot \"%s\" has tried to build path with at least %d nodes. Seems to be graph is broken.", pev->netname.chars (), m_routeQue.length ());
|
||||||
|
|
||||||
// bail out to shortest path
|
// bail out to shortest path
|
||||||
findShortestPath (srcIndex, destIndex);
|
findShortestPath (srcIndex, destIndex);
|
||||||
|
|
@ -1458,8 +1435,8 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
auto childRoute = &m_routes[child.index];
|
auto childRoute = &m_routes[child.index];
|
||||||
|
|
||||||
// calculate the F value as F = G + H
|
// calculate the F value as F = G + H
|
||||||
float g = curRoute->g + calculate (false, m_team, child.index, currentIndex);
|
float g = curRoute->g + gcalc (m_team, child.index, currentIndex);
|
||||||
float h = calculate (true, child.index, srcIndex, destIndex);
|
float h = hcalc (child.index, srcIndex, destIndex);
|
||||||
float f = g + h;
|
float f = g + h;
|
||||||
|
|
||||||
if (childRoute->state == RouteState::New || childRoute->f > f) {
|
if (childRoute->state == RouteState::New || childRoute->f > f) {
|
||||||
|
|
@ -1474,6 +1451,9 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
logger.error ("A* Search for bot \"%s\" has failed. Falling back to shortest-path algorithm. Seems to be graph is broken.", pev->netname.chars ());
|
||||||
|
|
||||||
|
// fallback to shortest path
|
||||||
findShortestPath (srcIndex, destIndex); // A* found no path, try floyd pathfinder instead
|
findShortestPath (srcIndex, destIndex); // A* found no path, try floyd pathfinder instead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2098,6 +2078,22 @@ bool Bot::advanceMovement () {
|
||||||
m_pathWalk.shift (); // advance in list
|
m_pathWalk.shift (); // advance in list
|
||||||
m_currentTravelFlags = 0; // reset travel flags (jumping etc)
|
m_currentTravelFlags = 0; // reset travel flags (jumping etc)
|
||||||
|
|
||||||
|
// helper to change bot's goal
|
||||||
|
auto changeNextGoal = [&] {
|
||||||
|
int newGoal = findBestGoal ();
|
||||||
|
|
||||||
|
m_prevGoalIndex = newGoal;
|
||||||
|
m_chosenGoalIndex = newGoal;
|
||||||
|
|
||||||
|
// remember index
|
||||||
|
getTask ()->data = newGoal;
|
||||||
|
|
||||||
|
// do path finding if it's not the current node
|
||||||
|
if (newGoal != m_currentNodeIndex) {
|
||||||
|
findPath (m_currentNodeIndex, newGoal, m_pathType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// we're not at the end of the list?
|
// we're not at the end of the list?
|
||||||
if (!m_pathWalk.empty ()) {
|
if (!m_pathWalk.empty ()) {
|
||||||
// if in between a route, postprocess the node (find better alternatives)...
|
// if in between a route, postprocess the node (find better alternatives)...
|
||||||
|
|
@ -2142,22 +2138,15 @@ bool Bot::advanceMovement () {
|
||||||
|
|
||||||
// force terrorist bot to plant bomb
|
// force terrorist bot to plant bomb
|
||||||
if (m_inBombZone && !m_hasProgressBar && m_hasC4) {
|
if (m_inBombZone && !m_hasProgressBar && m_hasC4) {
|
||||||
int newGoal = findBestGoal ();
|
changeNextGoal ();
|
||||||
|
|
||||||
m_prevGoalIndex = newGoal;
|
|
||||||
m_chosenGoalIndex = newGoal;
|
|
||||||
|
|
||||||
// remember index
|
|
||||||
getTask ()->data = newGoal;
|
|
||||||
|
|
||||||
// do path finding if it's not the current node
|
|
||||||
if (newGoal != m_currentNodeIndex) {
|
|
||||||
findPath (m_currentNodeIndex, newGoal, m_pathType);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (m_pathWalk.hasNext () && m_pathWalk.next () == m_pathWalk.last () && isOccupiedNode (m_pathWalk.last ())) {
|
||||||
|
changeNextGoal ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_pathWalk.empty ()) {
|
if (!m_pathWalk.empty ()) {
|
||||||
const int destIndex = m_pathWalk.first ();
|
const int destIndex = m_pathWalk.first ();
|
||||||
|
|
@ -2192,7 +2181,7 @@ bool Bot::advanceMovement () {
|
||||||
src = path.origin;
|
src = path.origin;
|
||||||
dst = next.origin;
|
dst = next.origin;
|
||||||
|
|
||||||
jumpDistance = (src - dst).length ();
|
jumpDistance = (path.origin - next.origin).length ();
|
||||||
willJump = true;
|
willJump = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -2255,7 +2244,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
||||||
if (!game.mapIs (MapFlags::HasDoors)) {
|
if (!game.mapIs (MapFlags::HasDoors)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return tr->flFraction < 1.0f && strncmp ("func_door", STRING (tr->pHit->v.classname), 9) != 0;
|
return tr->flFraction < 1.0f && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) != 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// trace from the bot's eyes straight forward...
|
// trace from the bot's eyes straight forward...
|
||||||
|
|
@ -2263,7 +2252,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
||||||
|
|
||||||
// check if the trace hit something...
|
// check if the trace hit something...
|
||||||
if (tr->flFraction < 1.0f) {
|
if (tr->flFraction < 1.0f) {
|
||||||
if (game.mapIs (MapFlags::HasDoors) && strncmp ("func_door", STRING (tr->pHit->v.classname), 9) == 0) {
|
if (game.mapIs (MapFlags::HasDoors) && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true; // bot's head will hit something
|
return true; // bot's head will hit something
|
||||||
|
|
@ -2614,7 +2603,7 @@ bool Bot::isBlockedLeft () {
|
||||||
game.testLine (pev->origin, forward * direction - right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (pev->origin, forward * direction - right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
||||||
// check if the trace hit something...
|
// check if the trace hit something...
|
||||||
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && strncmp ("func_door", STRING (tr.pHit->v.classname), 9) != 0) {
|
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0) {
|
||||||
return true; // bot's body will hit something
|
return true; // bot's body will hit something
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2634,7 +2623,7 @@ bool Bot::isBlockedRight () {
|
||||||
game.testLine (pev->origin, pev->origin + forward * direction + right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
game.testLine (pev->origin, pev->origin + forward * direction + right * 48.0f, TraceIgnore::Monsters, ent (), &tr);
|
||||||
|
|
||||||
// check if the trace hit something...
|
// check if the trace hit something...
|
||||||
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && (strncmp ("func_door", STRING (tr.pHit->v.classname), 9) != 0)) {
|
if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) != 0)) {
|
||||||
return true; // bot's body will hit something
|
return true; // bot's body will hit something
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2995,7 +2984,7 @@ int Bot::getNearestToPlantedBomb () {
|
||||||
|
|
||||||
// search the bomb on the map
|
// search the bomb on the map
|
||||||
game.searchEntities ("classname", "grenade", [&result] (edict_t *ent) {
|
game.searchEntities ("classname", "grenade", [&result] (edict_t *ent) {
|
||||||
if (strcmp (STRING (ent->v.model) + 9, "c4.mdl") == 0) {
|
if (strcmp (ent->v.model.chars () + 9, "c4.mdl") == 0) {
|
||||||
result = graph.getNearest (game.getEntityWorldOrigin (ent));
|
result = graph.getNearest (game.getEntityWorldOrigin (ent));
|
||||||
|
|
||||||
if (graph.exists (result)) {
|
if (graph.exists (result)) {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,40 @@ BotUtils::BotUtils () {
|
||||||
m_noiseCache["debris/bust"] = Noise::NeedHandle | Noise::Broke;
|
m_noiseCache["debris/bust"] = Noise::NeedHandle | Noise::Broke;
|
||||||
m_noiseCache["doors/doorm"] = Noise::NeedHandle | Noise::Door;
|
m_noiseCache["doors/doorm"] = Noise::NeedHandle | Noise::Door;
|
||||||
|
|
||||||
|
// register weapon aliases
|
||||||
|
m_weaponAlias.push (Weapon::USP, "usp"); // HK USP .45 Tactical
|
||||||
|
m_weaponAlias.push (Weapon::Glock18, "glock"); // Glock18 Select Fire
|
||||||
|
m_weaponAlias.push (Weapon::Deagle, "deagle"); // Desert Eagle .50AE
|
||||||
|
m_weaponAlias.push (Weapon::P228, "p228"); // SIG P228
|
||||||
|
m_weaponAlias.push (Weapon::Elite, "elite"); // Dual Beretta 96G Elite
|
||||||
|
m_weaponAlias.push (Weapon::FiveSeven, "fn57"); // FN Five-Seven
|
||||||
|
m_weaponAlias.push (Weapon::M3, "m3"); // Benelli M3 Super90
|
||||||
|
m_weaponAlias.push (Weapon::XM1014, "xm1014"); // Benelli XM1014
|
||||||
|
m_weaponAlias.push (Weapon::MP5, "mp5"); // HK MP5-Navy
|
||||||
|
m_weaponAlias.push (Weapon::TMP, "tmp"); // Steyr Tactical Machine Pistol
|
||||||
|
m_weaponAlias.push (Weapon::P90, "p90"); // FN P90
|
||||||
|
m_weaponAlias.push (Weapon::MAC10, "mac10"); // Ingram MAC-10
|
||||||
|
m_weaponAlias.push (Weapon::UMP45, "ump45"); // HK UMP45
|
||||||
|
m_weaponAlias.push (Weapon::AK47, "ak47"); // Automat Kalashnikov AK-47
|
||||||
|
m_weaponAlias.push (Weapon::Galil, "galil"); // IMI Galil
|
||||||
|
m_weaponAlias.push (Weapon::Famas, "famas"); // GIAT FAMAS
|
||||||
|
m_weaponAlias.push (Weapon::SG552, "sg552"); // Sig SG-552 Commando
|
||||||
|
m_weaponAlias.push (Weapon::M4A1, "m4a1"); // Colt M4A1 Carbine
|
||||||
|
m_weaponAlias.push (Weapon::AUG, "aug"); // Steyr Aug
|
||||||
|
m_weaponAlias.push (Weapon::Scout, "scout"); // Steyr Scout
|
||||||
|
m_weaponAlias.push (Weapon::AWP, "awp"); // AI Arctic Warfare/Magnum
|
||||||
|
m_weaponAlias.push (Weapon::G3SG1, "g3sg1"); // HK G3/SG-1 Sniper Rifle
|
||||||
|
m_weaponAlias.push (Weapon::SG550, "sg550"); // Sig SG-550 Sniper
|
||||||
|
m_weaponAlias.push (Weapon::M249, "m249"); // FN M249 Para
|
||||||
|
m_weaponAlias.push (Weapon::Flashbang, "flash"); // Concussion Grenade
|
||||||
|
m_weaponAlias.push (Weapon::Explosive, "hegren"); // High-Explosive Grenade
|
||||||
|
m_weaponAlias.push (Weapon::Smoke, "sgren"); // Smoke Grenade
|
||||||
|
m_weaponAlias.push (Weapon::Armor, "vest"); // Kevlar Vest
|
||||||
|
m_weaponAlias.push (Weapon::ArmorHelm, "vesthelm"); // Kevlar Vest and Helmet
|
||||||
|
m_weaponAlias.push (Weapon::Defuser, "defuser"); // Defuser Kit
|
||||||
|
m_weaponAlias.push (Weapon::Shield, "shield"); // Tactical Shield
|
||||||
|
m_weaponAlias.push (Weapon::Knife, "knife"); // Knife
|
||||||
|
|
||||||
m_clients.resize (kGameMaxPlayers + 1);
|
m_clients.resize (kGameMaxPlayers + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,7 +203,7 @@ bool BotUtils::isPlayer (edict_t *ent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ent->v.flags & (FL_CLIENT | FL_FAKECLIENT)) || bots[ent] != nullptr) {
|
if ((ent->v.flags & (FL_CLIENT | FL_FAKECLIENT)) || bots[ent] != nullptr) {
|
||||||
return !strings.isEmpty (STRING (ent->v.netname));
|
return !strings.isEmpty (ent->v.netname.chars ());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -609,7 +643,7 @@ void BotUtils::installSendTo () {
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable only on modern games
|
// enable only on modern games
|
||||||
if (game.is (GameFlags::Modern) && (plat.isLinux || plat.isWindows) && !plat.isArm && !m_sendToHook.enabled ()) {
|
if (game.is (GameFlags::Modern) && (plat.linux || plat.win32) && !plat.arm && !m_sendToHook.enabled ()) {
|
||||||
m_sendToHook.patch (reinterpret_cast <void *> (&sendto), reinterpret_cast <void *> (&BotUtils::sendTo));
|
m_sendToHook.patch (reinterpret_cast <void *> (&sendto), reinterpret_cast <void *> (&BotUtils::sendTo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -709,66 +743,11 @@ int BotUtils::buildNumber () {
|
||||||
return buildNumber;
|
return buildNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BotUtils::getWeaponAlias (bool needString, const char *weaponAlias, int weaponIndex) {
|
const String &BotUtils::weaponIdToAlias (const int32 id) {
|
||||||
// this function returning weapon id from the weapon alias and vice versa.
|
static const String &none = "none";
|
||||||
|
|
||||||
// structure definition for weapon tab
|
if (m_weaponAlias.exists (id)) {
|
||||||
struct WeaponTab_t {
|
return m_weaponAlias[id];
|
||||||
Weapon weaponIndex; // weapon id
|
|
||||||
const char *alias; // weapon alias
|
|
||||||
};
|
|
||||||
|
|
||||||
// weapon enumeration
|
|
||||||
WeaponTab_t weaponTab[] = {
|
|
||||||
{Weapon::USP, "usp"}, // HK USP .45 Tactical
|
|
||||||
{Weapon::Glock18, "glock"}, // Glock18 Select Fire
|
|
||||||
{Weapon::Deagle, "deagle"}, // Desert Eagle .50AE
|
|
||||||
{Weapon::P228, "p228"}, // SIG P228
|
|
||||||
{Weapon::Elite, "elite"}, // Dual Beretta 96G Elite
|
|
||||||
{Weapon::FiveSeven, "fn57"}, // FN Five-Seven
|
|
||||||
{Weapon::M3, "m3"}, // Benelli M3 Super90
|
|
||||||
{Weapon::XM1014, "xm1014"}, // Benelli XM1014
|
|
||||||
{Weapon::MP5, "mp5"}, // HK MP5-Navy
|
|
||||||
{Weapon::TMP, "tmp"}, // Steyr Tactical Machine Pistol
|
|
||||||
{Weapon::P90, "p90"}, // FN P90
|
|
||||||
{Weapon::MAC10, "mac10"}, // Ingram MAC-10
|
|
||||||
{Weapon::UMP45, "ump45"}, // HK UMP45
|
|
||||||
{Weapon::AK47, "ak47"}, // Automat Kalashnikov AK-47
|
|
||||||
{Weapon::Galil, "galil"}, // IMI Galil
|
|
||||||
{Weapon::Famas, "famas"}, // GIAT FAMAS
|
|
||||||
{Weapon::SG552, "sg552"}, // Sig SG-552 Commando
|
|
||||||
{Weapon::M4A1, "m4a1"}, // Colt M4A1 Carbine
|
|
||||||
{Weapon::AUG, "aug"}, // Steyr Aug
|
|
||||||
{Weapon::Scout, "scout"}, // Steyr Scout
|
|
||||||
{Weapon::AWP, "awp"}, // AI Arctic Warfare/Magnum
|
|
||||||
{Weapon::G3SG1, "g3sg1"}, // HK G3/SG-1 Sniper Rifle
|
|
||||||
{Weapon::SG550, "sg550"}, // Sig SG-550 Sniper
|
|
||||||
{Weapon::M249, "m249"}, // FN M249 Para
|
|
||||||
{Weapon::Flashbang, "flash"}, // Concussion Grenade
|
|
||||||
{Weapon::Explosive, "hegren"}, // High-Explosive Grenade
|
|
||||||
{Weapon::Smoke, "sgren"}, // Smoke Grenade
|
|
||||||
{Weapon::Armor, "vest"}, // Kevlar Vest
|
|
||||||
{Weapon::ArmorHelm, "vesthelm"}, // Kevlar Vest and Helmet
|
|
||||||
{Weapon::Defuser, "defuser"}, // Defuser Kit
|
|
||||||
{Weapon::Shield, "shield"}, // Tactical Shield
|
|
||||||
{Weapon::Knife, "knife"} // Knife
|
|
||||||
};
|
|
||||||
|
|
||||||
// if we need to return the string, find by weapon id
|
|
||||||
if (needString && weaponIndex != -1) {
|
|
||||||
for (auto &tab : weaponTab) {
|
|
||||||
if (tab.weaponIndex == weaponIndex) { // is weapon id found?
|
|
||||||
return MAKE_STRING (tab.alias);
|
|
||||||
}
|
}
|
||||||
}
|
return none;
|
||||||
return MAKE_STRING ("(none)"); // return none
|
|
||||||
}
|
|
||||||
|
|
||||||
// else search weapon by name and return weapon id
|
|
||||||
for (auto &tab : weaponTab) {
|
|
||||||
if (strncmp (tab.alias, weaponAlias, strlen (tab.alias)) == 0) {
|
|
||||||
return tab.weaponIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1; // no weapon was found return -1
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue