From a186f33ffb3343663db720374949c002f0fea30b Mon Sep 17 00:00:00 2001 From: jeefo Date: Sun, 4 Aug 2019 18:22:01 +0300 Subject: [PATCH] More fixes to optiomal node search. Support for replying to UTF-8 chat messages. Minor refactoring. --- include/crlib/cr-array.h | 6 +- include/crlib/cr-files.h | 2 +- include/crlib/cr-http.h | 4 +- include/crlib/cr-platform.h | 8 +- include/crlib/cr-string.h | 233 +++++++++++++++++++++++++++++++++++- include/crlib/cr-ulz.h | 4 +- include/engine.h | 57 +++------ include/yapb.h | 42 +++++-- source/basecode.cpp | 47 ++++---- source/chatlib.cpp | 12 +- source/combat.cpp | 51 ++++---- source/control.cpp | 16 +-- source/engine.cpp | 77 ++++++++---- source/graph.cpp | 19 ++- source/interface.cpp | 8 +- source/manager.cpp | 56 +++++---- source/navigate.cpp | 27 +++-- source/support.cpp | 8 +- 18 files changed, 488 insertions(+), 189 deletions(-) diff --git a/include/crlib/cr-array.h b/include/crlib/cr-array.h index 0ca5de7..ad602c5 100644 --- a/include/crlib/cr-array.h +++ b/include/crlib/cr-array.h @@ -205,7 +205,7 @@ public: if (index + count > m_capacity) { return false; } - for (size_t i = index; i < index + count; i++) { + for (size_t i = index; i < index + count; ++i) { alloc.destruct (&m_data[i]); } m_length -= count; @@ -233,7 +233,7 @@ public: return false; } alloc.construct (&m_data[m_length], cr::forward (object)); - m_length++; + ++m_length; return true; } @@ -243,7 +243,7 @@ public: return false; } alloc.construct (&m_data[m_length], cr::forward (args)...); - m_length++; + ++m_length; return true; } diff --git a/include/crlib/cr-files.h b/include/crlib/cr-files.h index 3eb8732..9bf1d61 100644 --- a/include/crlib/cr-files.h +++ b/include/crlib/cr-files.h @@ -234,7 +234,7 @@ public: return kEOF; } auto ch = m_data[m_pos]; - m_pos++; + ++m_pos; return static_cast (ch); } diff --git a/include/crlib/cr-http.h b/include/crlib/cr-http.h index 27ec16d..f7a3bff 100644 --- a/include/crlib/cr-http.h +++ b/include/crlib/cr-http.h @@ -236,10 +236,10 @@ private: break; default: - symbols++; + ++symbols; break; } - pos++; + ++pos; } String response (reinterpret_cast (buffer)); size_t responseCodeStart = response.find ("HTTP/1.1"); diff --git a/include/crlib/cr-platform.h b/include/crlib/cr-platform.h index 9ca67a7..36cfd49 100644 --- a/include/crlib/cr-platform.h +++ b/include/crlib/cr-platform.h @@ -69,6 +69,7 @@ CR_NAMESPACE_END #endif #include +#include #if defined (CR_ANDROID) # include @@ -78,6 +79,12 @@ CR_NAMESPACE_BEGIN // helper struct for platform detection struct Platform : public Singleton { +#if defined (CR_WINDOWS) + using LocaleHandle = _locale_t; +#else + using LocaleHandle = locale_t; +#endif + bool isWindows = false; bool isLinux = false; bool isOSX = false; @@ -193,7 +200,6 @@ struct Platform : public Singleton { #endif ::abort (); } - }; // expose platform singleton diff --git a/include/crlib/cr-string.h b/include/crlib/cr-string.h index 9fbaf4f..cc125a3 100644 --- a/include/crlib/cr-string.h +++ b/include/crlib/cr-string.h @@ -558,7 +558,7 @@ public: insert (pos, to); pos += to.length (); - replaced++; + ++replaced; } return replaced; } @@ -867,4 +867,235 @@ public: // expose global string pool static auto &strings = StringBuffer::get (); +// some limited utf8 stuff +class Utf8Tools : public Singleton { +private: + enum : int32 { + Utf8MaxChars = 706 + }; + +private: + // sample implementation from unicode home page: https://web.archive.org/web/19970105220809/http://www.stonehand.com/unicode/standard/fss-utf.html + struct Utf8Table { + int32 cmask, cval, shift; + long lmask, lval; + + Utf8Table (int32 cmask, int32 cval, int32 shift, long lmask, long lval) : + cmask (cmask), cval (cval), shift (shift), lmask (lmask), lval (lval) { + + } + }; + + struct Utf8CaseTable { + int32 from, to; + }; + +private: + Utf8CaseTable m_toUpperTable[Utf8MaxChars] = { + { 0x0061, 0x0041 }, { 0x0062, 0x0042 }, { 0x0063, 0x0043 }, { 0x0064, 0x0044 }, { 0x0065, 0x0045 }, { 0x0066, 0x0046 }, { 0x0067, 0x0047 }, { 0x0068, 0x0048 }, + { 0x0069, 0x0049 }, { 0x006a, 0x004a }, { 0x006b, 0x004b }, { 0x006c, 0x004c }, { 0x006d, 0x004d }, { 0x006e, 0x004e }, { 0x006f, 0x004f }, { 0x0070, 0x0050 }, + { 0x0071, 0x0051 }, { 0x0072, 0x0052 }, { 0x0073, 0x0053 }, { 0x0074, 0x0054 }, { 0x0075, 0x0055 }, { 0x0076, 0x0056 }, { 0x0077, 0x0057 }, { 0x0078, 0x0058 }, + { 0x0079, 0x0059 }, { 0x007a, 0x005a }, { 0x00e0, 0x00c0 }, { 0x00e1, 0x00c1 }, { 0x00e2, 0x00c2 }, { 0x00e3, 0x00c3 }, { 0x00e4, 0x00c4 }, { 0x00e5, 0x00c5 }, + { 0x00e6, 0x00c6 }, { 0x00e7, 0x00c7 }, { 0x00e8, 0x00c8 }, { 0x00e9, 0x00c9 }, { 0x00ea, 0x00ca }, { 0x00eb, 0x00cb }, { 0x00ec, 0x00cc }, { 0x00ed, 0x00cd }, + { 0x00ee, 0x00ce }, { 0x00ef, 0x00cf }, { 0x00f0, 0x00d0 }, { 0x00f1, 0x00d1 }, { 0x00f2, 0x00d2 }, { 0x00f3, 0x00d3 }, { 0x00f4, 0x00d4 }, { 0x00f5, 0x00d5 }, + { 0x00f6, 0x00d6 }, { 0x00f8, 0x00d8 }, { 0x00f9, 0x00d9 }, { 0x00fa, 0x00da }, { 0x00fb, 0x00db }, { 0x00fc, 0x00dc }, { 0x00fd, 0x00dd }, { 0x00fe, 0x00de }, + { 0x00ff, 0x0178 }, { 0x0101, 0x0100 }, { 0x0103, 0x0102 }, { 0x0105, 0x0104 }, { 0x0107, 0x0106 }, { 0x0109, 0x0108 }, { 0x010b, 0x010a }, { 0x010d, 0x010c }, + { 0x010f, 0x010e }, { 0x0111, 0x0110 }, { 0x0113, 0x0112 }, { 0x0115, 0x0114 }, { 0x0117, 0x0116 }, { 0x0119, 0x0118 }, { 0x011b, 0x011a }, { 0x011d, 0x011c }, + { 0x011f, 0x011e }, { 0x0121, 0x0120 }, { 0x0123, 0x0122 }, { 0x0125, 0x0124 }, { 0x0127, 0x0126 }, { 0x0129, 0x0128 }, { 0x012b, 0x012a }, { 0x012d, 0x012c }, + { 0x012f, 0x012e }, { 0x0131, 0x0049 }, { 0x0133, 0x0132 }, { 0x0135, 0x0134 }, { 0x0137, 0x0136 }, { 0x013a, 0x0139 }, { 0x013c, 0x013b }, { 0x013e, 0x013d }, + { 0x0140, 0x013f }, { 0x0142, 0x0141 }, { 0x0144, 0x0143 }, { 0x0146, 0x0145 }, { 0x0148, 0x0147 }, { 0x014b, 0x014a }, { 0x014d, 0x014c }, { 0x014f, 0x014e }, + { 0x0151, 0x0150 }, { 0x0153, 0x0152 }, { 0x0155, 0x0154 }, { 0x0157, 0x0156 }, { 0x0159, 0x0158 }, { 0x015b, 0x015a }, { 0x015d, 0x015c }, { 0x015f, 0x015e }, + { 0x0161, 0x0160 }, { 0x0163, 0x0162 }, { 0x0165, 0x0164 }, { 0x0167, 0x0166 }, { 0x0169, 0x0168 }, { 0x016b, 0x016a }, { 0x016d, 0x016c }, { 0x016f, 0x016e }, + { 0x0171, 0x0170 }, { 0x0173, 0x0172 }, { 0x0175, 0x0174 }, { 0x0177, 0x0176 }, { 0x017a, 0x0179 }, { 0x017c, 0x017b }, { 0x017e, 0x017d }, { 0x0183, 0x0182 }, + { 0x0185, 0x0184 }, { 0x0188, 0x0187 }, { 0x018c, 0x018b }, { 0x0192, 0x0191 }, { 0x0195, 0x01f6 }, { 0x0199, 0x0198 }, { 0x019e, 0x0220 }, { 0x01a1, 0x01a0 }, + { 0x01a3, 0x01a2 }, { 0x01a5, 0x01a4 }, { 0x01a8, 0x01a7 }, { 0x01ad, 0x01ac }, { 0x01b0, 0x01af }, { 0x01b4, 0x01b3 }, { 0x01b6, 0x01b5 }, { 0x01b9, 0x01b8 }, + { 0x01bd, 0x01bc }, { 0x01bf, 0x01f7 }, { 0x01c6, 0x01c4 }, { 0x01c9, 0x01c7 }, { 0x01cc, 0x01ca }, { 0x01ce, 0x01cd }, { 0x01d0, 0x01cf }, { 0x01d2, 0x01d1 }, + { 0x01d4, 0x01d3 }, { 0x01d6, 0x01d5 }, { 0x01d8, 0x01d7 }, { 0x01da, 0x01d9 }, { 0x01dc, 0x01db }, { 0x01dd, 0x018e }, { 0x01df, 0x01de }, { 0x01e1, 0x01e0 }, + { 0x01e3, 0x01e2 }, { 0x01e5, 0x01e4 }, { 0x01e7, 0x01e6 }, { 0x01e9, 0x01e8 }, { 0x01eb, 0x01ea }, { 0x01ed, 0x01ec }, { 0x01ef, 0x01ee }, { 0x01f3, 0x01f1 }, + { 0x01f5, 0x01f4 }, { 0x01f9, 0x01f8 }, { 0x01fb, 0x01fa }, { 0x01fd, 0x01fc }, { 0x01ff, 0x01fe }, { 0x0201, 0x0200 }, { 0x0203, 0x0202 }, { 0x0205, 0x0204 }, + { 0x0207, 0x0206 }, { 0x0209, 0x0208 }, { 0x020b, 0x020a }, { 0x020d, 0x020c }, { 0x020f, 0x020e }, { 0x0211, 0x0210 }, { 0x0213, 0x0212 }, { 0x0215, 0x0214 }, + { 0x0217, 0x0216 }, { 0x0219, 0x0218 }, { 0x021b, 0x021a }, { 0x021d, 0x021c }, { 0x021f, 0x021e }, { 0x0223, 0x0222 }, { 0x0225, 0x0224 }, { 0x0227, 0x0226 }, + { 0x0229, 0x0228 }, { 0x022b, 0x022a }, { 0x022d, 0x022c }, { 0x022f, 0x022e }, { 0x0231, 0x0230 }, { 0x0233, 0x0232 }, { 0x0253, 0x0181 }, { 0x0254, 0x0186 }, + { 0x0256, 0x0189 }, { 0x0257, 0x018a }, { 0x0259, 0x018f }, { 0x025b, 0x0190 }, { 0x0260, 0x0193 }, { 0x0263, 0x0194 }, { 0x0268, 0x0197 }, { 0x0269, 0x0196 }, + { 0x026f, 0x019c }, { 0x0272, 0x019d }, { 0x0275, 0x019f }, { 0x0280, 0x01a6 }, { 0x0283, 0x01a9 }, { 0x0288, 0x01ae }, { 0x028a, 0x01b1 }, { 0x028b, 0x01b2 }, + { 0x0292, 0x01b7 }, { 0x03ac, 0x0386 }, { 0x03ad, 0x0388 }, { 0x03ae, 0x0389 }, { 0x03af, 0x038a }, { 0x03b1, 0x0391 }, { 0x03b2, 0x0392 }, { 0x03b3, 0x0393 }, + { 0x03b4, 0x0394 }, { 0x03b5, 0x0395 }, { 0x03b6, 0x0396 }, { 0x03b7, 0x0397 }, { 0x03b8, 0x0398 }, { 0x03b9, 0x0345 }, { 0x03ba, 0x039a }, { 0x03bb, 0x039b }, + { 0x03bc, 0x00b5 }, { 0x03bd, 0x039d }, { 0x03be, 0x039e }, { 0x03bf, 0x039f }, { 0x03c0, 0x03a0 }, { 0x03c1, 0x03a1 }, { 0x03c3, 0x03a3 }, { 0x03c4, 0x03a4 }, + { 0x03c5, 0x03a5 }, { 0x03c6, 0x03a6 }, { 0x03c7, 0x03a7 }, { 0x03c8, 0x03a8 }, { 0x03c9, 0x03a9 }, { 0x03ca, 0x03aa }, { 0x03cb, 0x03ab }, { 0x03cc, 0x038c }, + { 0x03cd, 0x038e }, { 0x03ce, 0x038f }, { 0x03d9, 0x03d8 }, { 0x03db, 0x03da }, { 0x03dd, 0x03dc }, { 0x03df, 0x03de }, { 0x03e1, 0x03e0 }, { 0x03e3, 0x03e2 }, + { 0x03e5, 0x03e4 }, { 0x03e7, 0x03e6 }, { 0x03e9, 0x03e8 }, { 0x03eb, 0x03ea }, { 0x03ed, 0x03ec }, { 0x03ef, 0x03ee }, { 0x03f2, 0x03f9 }, { 0x03f8, 0x03f7 }, + { 0x03fb, 0x03fa }, { 0x0430, 0x0410 }, { 0x0431, 0x0411 }, { 0x0432, 0x0412 }, { 0x0433, 0x0413 }, { 0x0434, 0x0414 }, { 0x0435, 0x0415 }, { 0x0436, 0x0416 }, + { 0x0437, 0x0417 }, { 0x0438, 0x0418 }, { 0x0439, 0x0419 }, { 0x043a, 0x041a }, { 0x043b, 0x041b }, { 0x043c, 0x041c }, { 0x043d, 0x041d }, { 0x043e, 0x041e }, + { 0x043f, 0x041f }, { 0x0440, 0x0420 }, { 0x0441, 0x0421 }, { 0x0442, 0x0422 }, { 0x0443, 0x0423 }, { 0x0444, 0x0424 }, { 0x0445, 0x0425 }, { 0x0446, 0x0426 }, + { 0x0447, 0x0427 }, { 0x0448, 0x0428 }, { 0x0449, 0x0429 }, { 0x044a, 0x042a }, { 0x044b, 0x042b }, { 0x044c, 0x042c }, { 0x044d, 0x042d }, { 0x044e, 0x042e }, + { 0x044f, 0x042f }, { 0x0450, 0x0400 }, { 0x0451, 0x0401 }, { 0x0452, 0x0402 }, { 0x0453, 0x0403 }, { 0x0454, 0x0404 }, { 0x0455, 0x0405 }, { 0x0456, 0x0406 }, + { 0x0457, 0x0407 }, { 0x0458, 0x0408 }, { 0x0459, 0x0409 }, { 0x045a, 0x040a }, { 0x045b, 0x040b }, { 0x045c, 0x040c }, { 0x045d, 0x040d }, { 0x045e, 0x040e }, + { 0x045f, 0x040f }, { 0x0461, 0x0460 }, { 0x0463, 0x0462 }, { 0x0465, 0x0464 }, { 0x0467, 0x0466 }, { 0x0469, 0x0468 }, { 0x046b, 0x046a }, { 0x046d, 0x046c }, + { 0x046f, 0x046e }, { 0x0471, 0x0470 }, { 0x0473, 0x0472 }, { 0x0475, 0x0474 }, { 0x0477, 0x0476 }, { 0x0479, 0x0478 }, { 0x047b, 0x047a }, { 0x047d, 0x047c }, + { 0x047f, 0x047e }, { 0x0481, 0x0480 }, { 0x048b, 0x048a }, { 0x048d, 0x048c }, { 0x048f, 0x048e }, { 0x0491, 0x0490 }, { 0x0493, 0x0492 }, { 0x0495, 0x0494 }, + { 0x0497, 0x0496 }, { 0x0499, 0x0498 }, { 0x049b, 0x049a }, { 0x049d, 0x049c }, { 0x049f, 0x049e }, { 0x04a1, 0x04a0 }, { 0x04a3, 0x04a2 }, { 0x04a5, 0x04a4 }, + { 0x04a7, 0x04a6 }, { 0x04a9, 0x04a8 }, { 0x04ab, 0x04aa }, { 0x04ad, 0x04ac }, { 0x04af, 0x04ae }, { 0x04b1, 0x04b0 }, { 0x04b3, 0x04b2 }, { 0x04b5, 0x04b4 }, + { 0x04b7, 0x04b6 }, { 0x04b9, 0x04b8 }, { 0x04bb, 0x04ba }, { 0x04bd, 0x04bc }, { 0x04bf, 0x04be }, { 0x04c2, 0x04c1 }, { 0x04c4, 0x04c3 }, { 0x04c6, 0x04c5 }, + { 0x04c8, 0x04c7 }, { 0x04ca, 0x04c9 }, { 0x04cc, 0x04cb }, { 0x04ce, 0x04cd }, { 0x04d1, 0x04d0 }, { 0x04d3, 0x04d2 }, { 0x04d5, 0x04d4 }, { 0x04d7, 0x04d6 }, + { 0x04d9, 0x04d8 }, { 0x04db, 0x04da }, { 0x04dd, 0x04dc }, { 0x04df, 0x04de }, { 0x04e1, 0x04e0 }, { 0x04e3, 0x04e2 }, { 0x04e5, 0x04e4 }, { 0x04e7, 0x04e6 }, + { 0x04e9, 0x04e8 }, { 0x04eb, 0x04ea }, { 0x04ed, 0x04ec }, { 0x04ef, 0x04ee }, { 0x04f1, 0x04f0 }, { 0x04f3, 0x04f2 }, { 0x04f5, 0x04f4 }, { 0x04f9, 0x04f8 }, + { 0x0501, 0x0500 }, { 0x0503, 0x0502 }, { 0x0505, 0x0504 }, { 0x0507, 0x0506 }, { 0x0509, 0x0508 }, { 0x050b, 0x050a }, { 0x050d, 0x050c }, { 0x050f, 0x050e }, + { 0x0561, 0x0531 }, { 0x0562, 0x0532 }, { 0x0563, 0x0533 }, { 0x0564, 0x0534 }, { 0x0565, 0x0535 }, { 0x0566, 0x0536 }, { 0x0567, 0x0537 }, { 0x0568, 0x0538 }, + { 0x0569, 0x0539 }, { 0x056a, 0x053a }, { 0x056b, 0x053b }, { 0x056c, 0x053c }, { 0x056d, 0x053d }, { 0x056e, 0x053e }, { 0x056f, 0x053f }, { 0x0570, 0x0540 }, + { 0x0571, 0x0541 }, { 0x0572, 0x0542 }, { 0x0573, 0x0543 }, { 0x0574, 0x0544 }, { 0x0575, 0x0545 }, { 0x0576, 0x0546 }, { 0x0577, 0x0547 }, { 0x0578, 0x0548 }, + { 0x0579, 0x0549 }, { 0x057a, 0x054a }, { 0x057b, 0x054b }, { 0x057c, 0x054c }, { 0x057d, 0x054d }, { 0x057e, 0x054e }, { 0x057f, 0x054f }, { 0x0580, 0x0550 }, + { 0x0581, 0x0551 }, { 0x0582, 0x0552 }, { 0x0583, 0x0553 }, { 0x0584, 0x0554 }, { 0x0585, 0x0555 }, { 0x0586, 0x0556 }, { 0x1e01, 0x1e00 }, { 0x1e03, 0x1e02 }, + { 0x1e05, 0x1e04 }, { 0x1e07, 0x1e06 }, { 0x1e09, 0x1e08 }, { 0x1e0b, 0x1e0a }, { 0x1e0d, 0x1e0c }, { 0x1e0f, 0x1e0e }, { 0x1e11, 0x1e10 }, { 0x1e13, 0x1e12 }, + { 0x1e15, 0x1e14 }, { 0x1e17, 0x1e16 }, { 0x1e19, 0x1e18 }, { 0x1e1b, 0x1e1a }, { 0x1e1d, 0x1e1c }, { 0x1e1f, 0x1e1e }, { 0x1e21, 0x1e20 }, { 0x1e23, 0x1e22 }, + { 0x1e25, 0x1e24 }, { 0x1e27, 0x1e26 }, { 0x1e29, 0x1e28 }, { 0x1e2b, 0x1e2a }, { 0x1e2d, 0x1e2c }, { 0x1e2f, 0x1e2e }, { 0x1e31, 0x1e30 }, { 0x1e33, 0x1e32 }, + { 0x1e35, 0x1e34 }, { 0x1e37, 0x1e36 }, { 0x1e39, 0x1e38 }, { 0x1e3b, 0x1e3a }, { 0x1e3d, 0x1e3c }, { 0x1e3f, 0x1e3e }, { 0x1e41, 0x1e40 }, { 0x1e43, 0x1e42 }, + { 0x1e45, 0x1e44 }, { 0x1e47, 0x1e46 }, { 0x1e49, 0x1e48 }, { 0x1e4b, 0x1e4a }, { 0x1e4d, 0x1e4c }, { 0x1e4f, 0x1e4e }, { 0x1e51, 0x1e50 }, { 0x1e53, 0x1e52 }, + { 0x1e55, 0x1e54 }, { 0x1e57, 0x1e56 }, { 0x1e59, 0x1e58 }, { 0x1e5b, 0x1e5a }, { 0x1e5d, 0x1e5c }, { 0x1e5f, 0x1e5e }, { 0x1e61, 0x1e60 }, { 0x1e63, 0x1e62 }, + { 0x1e65, 0x1e64 }, { 0x1e67, 0x1e66 }, { 0x1e69, 0x1e68 }, { 0x1e6b, 0x1e6a }, { 0x1e6d, 0x1e6c }, { 0x1e6f, 0x1e6e }, { 0x1e71, 0x1e70 }, { 0x1e73, 0x1e72 }, + { 0x1e75, 0x1e74 }, { 0x1e77, 0x1e76 }, { 0x1e79, 0x1e78 }, { 0x1e7b, 0x1e7a }, { 0x1e7d, 0x1e7c }, { 0x1e7f, 0x1e7e }, { 0x1e81, 0x1e80 }, { 0x1e83, 0x1e82 }, + { 0x1e85, 0x1e84 }, { 0x1e87, 0x1e86 }, { 0x1e89, 0x1e88 }, { 0x1e8b, 0x1e8a }, { 0x1e8d, 0x1e8c }, { 0x1e8f, 0x1e8e }, { 0x1e91, 0x1e90 }, { 0x1e93, 0x1e92 }, + { 0x1e95, 0x1e94 }, { 0x1ea1, 0x1ea0 }, { 0x1ea3, 0x1ea2 }, { 0x1ea5, 0x1ea4 }, { 0x1ea7, 0x1ea6 }, { 0x1ea9, 0x1ea8 }, { 0x1eab, 0x1eaa }, { 0x1ead, 0x1eac }, + { 0x1eaf, 0x1eae }, { 0x1eb1, 0x1eb0 }, { 0x1eb3, 0x1eb2 }, { 0x1eb5, 0x1eb4 }, { 0x1eb7, 0x1eb6 }, { 0x1eb9, 0x1eb8 }, { 0x1ebb, 0x1eba }, { 0x1ebd, 0x1ebc }, + { 0x1ebf, 0x1ebe }, { 0x1ec1, 0x1ec0 }, { 0x1ec3, 0x1ec2 }, { 0x1ec5, 0x1ec4 }, { 0x1ec7, 0x1ec6 }, { 0x1ec9, 0x1ec8 }, { 0x1ecb, 0x1eca }, { 0x1ecd, 0x1ecc }, + { 0x1ecf, 0x1ece }, { 0x1ed1, 0x1ed0 }, { 0x1ed3, 0x1ed2 }, { 0x1ed5, 0x1ed4 }, { 0x1ed7, 0x1ed6 }, { 0x1ed9, 0x1ed8 }, { 0x1edb, 0x1eda }, { 0x1edd, 0x1edc }, + { 0x1edf, 0x1ede }, { 0x1ee1, 0x1ee0 }, { 0x1ee3, 0x1ee2 }, { 0x1ee5, 0x1ee4 }, { 0x1ee7, 0x1ee6 }, { 0x1ee9, 0x1ee8 }, { 0x1eeb, 0x1eea }, { 0x1eed, 0x1eec }, + { 0x1eef, 0x1eee }, { 0x1ef1, 0x1ef0 }, { 0x1ef3, 0x1ef2 }, { 0x1ef5, 0x1ef4 }, { 0x1ef7, 0x1ef6 }, { 0x1ef9, 0x1ef8 }, { 0x1f00, 0x1f08 }, { 0x1f01, 0x1f09 }, + { 0x1f02, 0x1f0a }, { 0x1f03, 0x1f0b }, { 0x1f04, 0x1f0c }, { 0x1f05, 0x1f0d }, { 0x1f06, 0x1f0e }, { 0x1f07, 0x1f0f }, { 0x1f10, 0x1f18 }, { 0x1f11, 0x1f19 }, + { 0x1f12, 0x1f1a }, { 0x1f13, 0x1f1b }, { 0x1f14, 0x1f1c }, { 0x1f15, 0x1f1d }, { 0x1f20, 0x1f28 }, { 0x1f21, 0x1f29 }, { 0x1f22, 0x1f2a }, { 0x1f23, 0x1f2b }, + { 0x1f24, 0x1f2c }, { 0x1f25, 0x1f2d }, { 0x1f26, 0x1f2e }, { 0x1f27, 0x1f2f }, { 0x1f30, 0x1f38 }, { 0x1f31, 0x1f39 }, { 0x1f32, 0x1f3a }, { 0x1f33, 0x1f3b }, + { 0x1f34, 0x1f3c }, { 0x1f35, 0x1f3d }, { 0x1f36, 0x1f3e }, { 0x1f37, 0x1f3f }, { 0x1f40, 0x1f48 }, { 0x1f41, 0x1f49 }, { 0x1f42, 0x1f4a }, { 0x1f43, 0x1f4b }, + { 0x1f44, 0x1f4c }, { 0x1f45, 0x1f4d }, { 0x1f51, 0x1f59 }, { 0x1f53, 0x1f5b }, { 0x1f55, 0x1f5d }, { 0x1f57, 0x1f5f }, { 0x1f60, 0x1f68 }, { 0x1f61, 0x1f69 }, + { 0x1f62, 0x1f6a }, { 0x1f63, 0x1f6b }, { 0x1f64, 0x1f6c }, { 0x1f65, 0x1f6d }, { 0x1f66, 0x1f6e }, { 0x1f67, 0x1f6f }, { 0x1f70, 0x1fba }, { 0x1f71, 0x1fbb }, + { 0x1f72, 0x1fc8 }, { 0x1f73, 0x1fc9 }, { 0x1f74, 0x1fca }, { 0x1f75, 0x1fcb }, { 0x1f76, 0x1fda }, { 0x1f77, 0x1fdb }, { 0x1f78, 0x1ff8 }, { 0x1f79, 0x1ff9 }, + { 0x1f7a, 0x1fea }, { 0x1f7b, 0x1feb }, { 0x1f7c, 0x1ffa }, { 0x1f7d, 0x1ffb }, { 0x1f80, 0x1f88 }, { 0x1f81, 0x1f89 }, { 0x1f82, 0x1f8a }, { 0x1f83, 0x1f8b }, + { 0x1f84, 0x1f8c }, { 0x1f85, 0x1f8d }, { 0x1f86, 0x1f8e }, { 0x1f87, 0x1f8f }, { 0x1f90, 0x1f98 }, { 0x1f91, 0x1f99 }, { 0x1f92, 0x1f9a }, { 0x1f93, 0x1f9b }, + { 0x1f94, 0x1f9c }, { 0x1f95, 0x1f9d }, { 0x1f96, 0x1f9e }, { 0x1f97, 0x1f9f }, { 0x1fa0, 0x1fa8 }, { 0x1fa1, 0x1fa9 }, { 0x1fa2, 0x1faa }, { 0x1fa3, 0x1fab }, + { 0x1fa4, 0x1fac }, { 0x1fa5, 0x1fad }, { 0x1fa6, 0x1fae }, { 0x1fa7, 0x1faf }, { 0x1fb0, 0x1fb8 }, { 0x1fb1, 0x1fb9 }, { 0x1fb3, 0x1fbc }, { 0x1fc3, 0x1fcc }, + { 0x1fd0, 0x1fd8 }, { 0x1fd1, 0x1fd9 }, { 0x1fe0, 0x1fe8 }, { 0x1fe1, 0x1fe9 }, { 0x1fe5, 0x1fec }, { 0x1ff3, 0x1ffc }, { 0x2170, 0x2160 }, { 0x2171, 0x2161 }, + { 0x2172, 0x2162 }, { 0x2173, 0x2163 }, { 0x2174, 0x2164 }, { 0x2175, 0x2165 }, { 0x2176, 0x2166 }, { 0x2177, 0x2167 }, { 0x2178, 0x2168 }, { 0x2179, 0x2169 }, + { 0x217a, 0x216a }, { 0x217b, 0x216b }, { 0x217c, 0x216c }, { 0x217d, 0x216d }, { 0x217e, 0x216e }, { 0x217f, 0x216f }, { 0x24d0, 0x24b6 }, { 0x24d1, 0x24b7 }, + { 0x24d2, 0x24b8 }, { 0x24d3, 0x24b9 }, { 0x24d4, 0x24ba }, { 0x24d5, 0x24bb }, { 0x24d6, 0x24bc }, { 0x24d7, 0x24bd }, { 0x24d8, 0x24be }, { 0x24d9, 0x24bf }, + { 0x24da, 0x24c0 }, { 0x24db, 0x24c1 }, { 0x24dc, 0x24c2 }, { 0x24dd, 0x24c3 }, { 0x24de, 0x24c4 }, { 0x24df, 0x24c5 }, { 0x24e0, 0x24c6 }, { 0x24e1, 0x24c7 }, + { 0x24e2, 0x24c8 }, { 0x24e3, 0x24c9 }, { 0x24e4, 0x24ca }, { 0x24e5, 0x24cb }, { 0x24e6, 0x24cc }, { 0x24e7, 0x24cd }, { 0x24e8, 0x24ce }, { 0x24e9, 0x24cf }, + { 0xff41, 0xff21 }, { 0xff42, 0xff22 }, { 0xff43, 0xff23 }, { 0xff44, 0xff24 }, { 0xff45, 0xff25 }, { 0xff46, 0xff26 }, { 0xff47, 0xff27 }, { 0xff48, 0xff28 }, + { 0xff49, 0xff29 }, { 0xff4a, 0xff2a }, { 0xff4b, 0xff2b }, { 0xff4c, 0xff2c }, { 0xff4d, 0xff2d }, { 0xff4e, 0xff2e }, { 0xff4f, 0xff2f }, { 0xff50, 0xff30 }, + { 0xff51, 0xff31 }, { 0xff52, 0xff32 }, { 0xff53, 0xff33 }, { 0xff54, 0xff34 }, { 0xff55, 0xff35 }, { 0xff56, 0xff36 }, { 0xff57, 0xff37 }, { 0xff58, 0xff38 }, + { 0xff59, 0xff39 }, { 0xff5a, 0xff3a } + }; + +private: + SmallArray m_utfTable; + +private: + void buildTable () { + m_utfTable.emplace (0x80, 0x00, 0 * 6, 0x7f, 0); // 1 byte sequence + m_utfTable.emplace (0xe0, 0xc0, 1 * 6, 0x7ff, 0x80); // 2 byte sequence + m_utfTable.emplace (0xf0, 0xe0, 2 * 6, 0xffff, 0x800); // 3 byte sequence + m_utfTable.emplace (0xf8, 0xf0, 3 * 6, 0x1fffff, 0x10000); // 4 byte sequence + m_utfTable.emplace (0xfc, 0xf8, 4 * 6, 0x3ffffff, 0x200000); // 5 byte sequence + m_utfTable.emplace (0xfe, 0xfc, 5 * 6, 0x7fffffff, 0x4000000); // 6 byte sequence + } + + int32 multiByteToWideChar (wchar_t *wide, const char *mbs) { + int32 len = 0; + + auto ch = *mbs; + auto lval = static_cast (ch); + + for (const auto &table : m_utfTable) { + len++; + + if ((ch & table.cmask) == table.cval) { + lval &= table.lmask; + + if (lval < table.lval) { + return -1; + } + *wide = static_cast (lval); + return len; + } + mbs++; + auto test = (*mbs ^ 0x80) & 0xff; + + if (test & 0xc0) { + return -1; + } + lval = (lval << 6) | test; + } + return -1; + } + + int32 wideCharToMultiByte (char *mbs, wchar_t wide) { + if (!mbs) { + return 0; + } + long lmask = wide; + int32 len = 0; + + for (const auto &table : m_utfTable) { + len++; + + if (lmask <= table.lmask) { + auto ch = table.shift; + *mbs = static_cast (table.cval | (lmask >> ch)); + + while (ch > 0) { + ch -= 6; + mbs++; + + *mbs = 0x80 | ((lmask >> ch) & 0x3F); + } + return len; + } + } + return -1; + } + +public: + Utf8Tools () { + buildTable (); + } + + ~Utf8Tools () = default; + +public: + wchar_t toUpper (wchar_t ch) { + int32 bottom = 0; + int32 top = Utf8MaxChars - 1; + + while (bottom <= top) { + const auto mid = (bottom + top) / 2; + wchar_t cur = static_cast (m_toUpperTable[mid].from); + + if (ch == cur) { + return static_cast (m_toUpperTable[mid].to); + } + if (ch > cur) { + bottom = mid + 1; + } + else { + top = mid - 1; + } + } + return ch; + } + + String strToUpper (const String &in) { + String result (in); + auto ptr = const_cast (result.chars ()); + + int32 len = 0; + wchar_t wide; + + while (*ptr && len < static_cast (result.length ())) { + multiByteToWideChar (&wide, ptr); + ptr += wideCharToMultiByte (ptr, toUpper (wide)); + } + return result; + } +}; + +// expose global utf8 tools +static auto &utf8tools = Utf8Tools::get (); + CR_NAMESPACE_END \ No newline at end of file diff --git a/include/crlib/cr-ulz.h b/include/crlib/cr-ulz.h index 6e7233c..5f3f007 100644 --- a/include/crlib/cr-ulz.h +++ b/include/crlib/cr-ulz.h @@ -74,7 +74,7 @@ public: int32 length = MinMatch; while (length < maxMatch && in[lookup + length] == in[cur + length]) { - length++; + ++length; } if (length > bestLength) { @@ -111,7 +111,7 @@ public: int32 length = MinMatch; while (length < target && in[lookup + length] == in[next + length]) { - length++; + ++length; } if (length == target) { diff --git a/include/engine.h b/include/engine.h index 326e4e9..6873ef0 100644 --- a/include/engine.h +++ b/include/engine.h @@ -113,22 +113,6 @@ struct RefVector { // entity prototype using EntityFunction = void (*) (entvars_t *); -// language hasher -struct HashLangString { - uint32 operator () (const String &key) const { - auto str = reinterpret_cast (const_cast (key.chars ())); - uint32 hash = 0; - - while (*str++) { - if (!isalnum (*str)) { - continue; - } - hash = ((*str << 5) + hash) + *str; - } - return hash; - } -}; - // provides utility functions to not call original engine (less call-cost) class Game final : public Singleton { private: @@ -143,16 +127,15 @@ private: edict_t *m_localEntity; Array m_cvars; - Dictionary m_language; - SharedLibrary m_gameLib; MessageBlock m_msgBlock; - bool m_precached; + bool m_precached; int m_gameFlags; int m_mapFlags; float m_slowFrame; // per second updated frame + public: RefVector vec; @@ -206,9 +189,6 @@ public: // sends local registration stack for engine registration void registerCvars (bool gameVars = false); - // translates bot message into needed language - const char *translate (const char *input); - // do actual network message processing void processMessages (void *ptr); @@ -303,16 +283,6 @@ public: // gets the player team int getTeam (edict_t *ent); - // adds translation pair from config - void addTranslation (const String &original, const String &translated) { - m_language.push (original, translated); - } - - // clear the translation table - void clearTranslation () { - m_language.clear (); - } - // resets the message capture mechanism void resetMessages () { m_msgBlock.msg = NetMsg::None; @@ -367,6 +337,12 @@ public: in.buildVectors (&vec.forward, &vec.right, &vec.up); } + // check the engine visibility wrapper + bool checkVisibility (edict_t *ent, uint8 *set); + + // get pvs/pas visibility set + uint8 *getVisibilitySet (Bot *bot, bool pvs); + // what kind of game engine / game dll / mod / tool we're running ? bool is (const int type) const { return !!(m_gameFlags & type); @@ -402,7 +378,7 @@ public: // prints data to servers console template void print (const char *fmt, Args ...args) { - engfuncs.pfnServerPrint (strncat (strings.format (translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); + engfuncs.pfnServerPrint (strncat (strings.format (conf.translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); } // prints center message to specified player @@ -411,7 +387,7 @@ public: print (fmt, cr::forward (args)...); return; } - sendClientMessage (true, ent, strncat (strings.format (translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); + sendClientMessage (true, ent, strncat (strings.format (conf.translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); } // prints message to client console @@ -420,7 +396,7 @@ public: print (fmt, cr::forward (args)...); return; } - sendClientMessage (false, ent, strncat (strings.format (translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); + sendClientMessage (false, ent, strncat (strings.format (conf.translate (fmt), cr::forward (args)...), "\n", StringBuffer::StaticBufferSize)); } }; @@ -523,11 +499,11 @@ public: public: static inline uint16 fu16 (float value, float scale) { - return cr::clamp (static_cast (value * cr::bit (static_cast (scale))), 0, 0xffff); + return cr::clamp (static_cast (value * cr::bit (static_cast (scale))), 0, USHRT_MAX); } static inline short fs16 (float value, float scale) { - return cr::clamp (static_cast (value * cr::bit (static_cast (scale))), -32767, 32767); + return cr::clamp (static_cast (value * cr::bit (static_cast (scale))), -SHRT_MAX, SHRT_MAX); } }; @@ -700,4 +676,9 @@ public: static Handle CR_STDCALL replacement (Handle module, Name function) { return DynamicEntityLink::get ().search (module, function); } -}; \ No newline at end of file +}; + +// expose globals +static auto &game = Game::get (); +static auto &illum = LightMeasure::get (); +static auto &ents = DynamicEntityLink::get (); \ No newline at end of file diff --git a/include/yapb.h b/include/yapb.h index 3a8e556..30d17d5 100644 --- a/include/yapb.h +++ b/include/yapb.h @@ -501,11 +501,13 @@ namespace TaskPri { constexpr char kPodbotMagic[8] = "PODWAY!"; constexpr int32 kStorageMagic = 0x59415042; +constexpr float kInfiniteDistance = 9999999.0f; constexpr float kGrenadeCheckTime = 2.15f; constexpr float kSprayDistance = 260.0f; constexpr float kDoubleSprayDistance = kSprayDistance * 2; constexpr float kMaxChatterRepeatInteval = 99.0f; +constexpr int kInfiniteDistanceLong = static_cast (kInfiniteDistance); constexpr int kMaxNodeLinks = 8; constexpr int kMaxPracticeDamageValue = 2040; constexpr int kMaxPracticeGoalValue = 2040; @@ -1298,6 +1300,7 @@ private: Array m_activeGrenades; // holds currently active grenades on the map Array m_intrestingEntities; // holds currently intresting entities on the map + SmallArray m_creationTab; // bot creation tab SmallArray m_filters; // task filters @@ -1360,7 +1363,7 @@ public: void execGameEntity (entvars_t *vars); void forEach (ForEachBot handler); void erase (Bot *bot); - + bool isTeamStacked (int team); public: @@ -1573,8 +1576,8 @@ public: int getFacingIndex (); int getFarest (const Vector &origin, float maxDistance = 32.0); - int getNearest (const Vector &origin, float minDistance = 9999.0f, int flags = -1); - int getNearestNoBuckets (const Vector &origin, float minDistance = 9999.0f, int flags = -1); + int getNearest (const Vector &origin, float minDistance = kInfiniteDistance, int flags = -1); + int getNearestNoBuckets (const Vector &origin, float minDistance = kInfiniteDistance, int flags = -1); int getEditorNeareset (); int getDangerIndex (int team, int start, int goal); int getDangerValue (int team, int start, int goal); @@ -1715,6 +1718,22 @@ public: } }; +// language hasher +struct HashLangString { + uint32 operator () (const String &key) const { + auto str = reinterpret_cast (const_cast (key.chars ())); + uint32 hash = 0; + + while (*str++) { + if (!isalnum (*str)) { + continue; + } + hash = ((*str << 5) + hash) + *str; + } + return hash; + } +}; + // mostly config stuff, and some stuff dealing with menus class BotConfig final : public Singleton { private: @@ -1729,6 +1748,8 @@ private: StringArray m_logos; StringArray m_avatars; + Dictionary m_language; + // default tables for personality weapon preferences, overridden by general.cfg SmallArray m_normalWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 12, 10, 24, 25, 13, 11, 8, 7, 22, 23, 18, 21, 17, 19, 15, 17, 9, 14, 16 }; SmallArray m_rusherWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 24, 19, 22, 23, 20, 21, 10, 12, 13, 7, 8, 11, 9, 18, 17, 19, 25, 15, 16 }; @@ -1784,8 +1805,12 @@ public: // fix weapon prices (ie for elite) void adjustWeaponPrices (); + // find weapon info by weaponi d WeaponInfo &findWeaponById (int id); + // translates bot message into needed language + const char *translate (const char *input); + private: bool isCommentLine (const String &line) { const char ch = line.at (0); @@ -2176,7 +2201,7 @@ public: void collectArgs () { m_args.clear (); - for (int i = 0; i < engfuncs.pfnCmd_Argc (); i++) { + for (int i = 0; i < engfuncs.pfnCmd_Argc (); ++i) { m_args.emplace (engfuncs.pfnCmd_Argv (i)); } } @@ -2196,17 +2221,15 @@ public: bool handleMenuCommands (edict_t *ent); }; -#include - // expose bot super-globals static auto &graph = BotGraph::get (); static auto &bots = BotManager::get (); static auto &conf = BotConfig::get (); static auto &util = BotUtils::get (); static auto &ctrl = BotControl::get (); -static auto &game = Game::get (); -static auto &illum = LightMeasure::get (); -static auto &ents = DynamicEntityLink::get (); + +// include game-related stuff +#include // very global convars extern ConVar yb_jasonmode; @@ -2215,6 +2238,7 @@ extern ConVar yb_ignore_enemies; extern ConVar yb_chat; extern ConVar yb_language; extern ConVar yb_show_latency; +extern ConVar yb_enable_query_hook; inline int Game::getTeam (edict_t *ent) { if (game.isNullEntity (ent)) { diff --git a/source/basecode.cpp b/source/basecode.cpp index 3f0ea0d..ea92104 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -165,12 +165,12 @@ void Bot::checkGrenadesThrow () { // don't throw grenades at anything that isn't on the ground! if (!(m_lastEnemy->v.flags & FL_ONGROUND) && !m_lastEnemy->v.waterlevel && m_lastEnemyOrigin.z > pev->absmax.z) { - distance = 9999.0f; + distance = kInfiniteDistance; } // too high to throw? if (m_lastEnemy->v.origin.z > pev->origin.z + 500.0f) { - distance = 9999.0f; + distance = kInfiniteDistance; } // enemy within a good throw distance? @@ -823,7 +823,7 @@ void Bot::getCampDirection (Vector *dest) { if (tempIndex == kInvalidNodeIndex || enemyIndex == kInvalidNodeIndex) { return; } - float minDistance = 99999.0f; + float minDistance = kInfiniteDistance; int lookAtWaypoint = kInvalidNodeIndex; Path &path = graph[tempIndex]; @@ -1288,7 +1288,7 @@ void Bot::buyStuff () { assert (*pref < kNumWeapons); selectedWeapon = &tab[*pref]; - count++; + ++count; if (selectedWeapon->buyGroup == 1) { continue; @@ -1474,7 +1474,7 @@ void Bot::buyStuff () { assert (*pref < kNumWeapons); selectedWeapon = &tab[*pref]; - count++; + ++count; if (selectedWeapon->buyGroup != 1) { continue; @@ -1609,7 +1609,7 @@ void Bot::buyStuff () { break; } - m_buyState++; + ++m_buyState; pushMsgQueue (BotMsg::Buy); } @@ -1731,7 +1731,7 @@ void Bot::setConditions () { pushChatterMessage (Chatter::SniperKilled); } else { - switch (numEnemiesNear (pev->origin, 99999.0f)) { + switch (numEnemiesNear (pev->origin, kInfiniteDistance)) { case 0: if (rg.chance (50)) { pushChatterMessage (Chatter::NoEnemiesLeft); @@ -2198,7 +2198,7 @@ void Bot::checkRadioQueue () { for (const auto &bot : bots) { if (bot->m_notKilled) { if (bot->m_targetEntity == m_radioEntity) { - numFollowers++; + ++numFollowers; } } } @@ -2450,7 +2450,7 @@ void Bot::checkRadioQueue () { // if bot has no enemy if (m_lastEnemyOrigin.empty ()) { - float nearestDistance = 99999.0f; + float nearestDistance = kInfiniteDistance; // take nearest enemy to ordering player for (const auto &client : util.getClients ()) { @@ -2556,7 +2556,7 @@ void Bot::checkRadioQueue () { // check if it's a ct command if (game.getTeam (m_radioEntity) == Team::CT && m_team == Team::CT && util.isFakeClient (m_radioEntity) && bots.getPlantedBombSearchTimestamp () < game.timebase ()) { - float minDistance = 99999.0f; + float minDistance = kInfiniteDistance; int bombPoint = kInvalidNodeIndex; // find nearest bomb waypoint to player @@ -2605,7 +2605,7 @@ void Bot::checkRadioQueue () { // if bot has no enemy if (m_lastEnemyOrigin.empty ()) { - float nearestDistance = 99999.0f; + float nearestDistance = kInfiniteDistance; // take nearest enemy to ordering player for (const auto &client : util.getClients ()) { @@ -2767,15 +2767,15 @@ void Bot::updateAimDir () { void Bot::checkDarkness () { // do not check for darkness at the start of the round - if (m_spawnTime + 5.0f > game.timebase () || !graph.exists (m_currentNodeIndex)) { + if (m_spawnTime + 5.0f > game.timebase () || !graph.exists (m_currentNodeIndex) || cr::fzero (m_path->light)) { return; } // do not check every frame - if (m_checkDarkTime + 2.5f > game.timebase ()) { + if (m_checkDarkTime + 5.0f > game.timebase ()) { return; } - float skyColor = illum.getSkyColor (); + auto skyColor = illum.getSkyColor (); if (mp_flashlight.bool_ () && !m_hasNVG) { auto task = Task (); @@ -2873,7 +2873,7 @@ void Bot::fastFrame () { } edict_t *killer = game.entityOfIndex (m_lastVoteKick); - killer->v.frags++; + ++killer->v.frags; MDLL_ClientKill (killer); } @@ -2898,8 +2898,8 @@ void Bot::frame () { if (m_slowFrameTimestamp > game.timebase ()) { return; } - m_numFriendsLeft = numFriendsNear (pev->origin, 99999.0f); - m_numEnemiesLeft = numEnemiesNear (pev->origin, 99999.0f); + m_numFriendsLeft = numFriendsNear (pev->origin, kInfiniteDistance); + m_numEnemiesLeft = numEnemiesNear (pev->origin, kInfiniteDistance); if (bots.isBombPlanted () && m_team == Team::CT && m_notKilled) { const Vector &bombPosition = graph.getBombPos (); @@ -3521,7 +3521,7 @@ void Bot::camp_ () { campPoints[numFoundPoints] = i; distances[numFoundPoints] = distance; - numFoundPoints++; + ++numFoundPoints; } } } @@ -4261,7 +4261,7 @@ void Bot::escapeFromBomb_ () { else if (!hasActiveGoal ()) { clearSearchNodes (); - int lastSelectedGoal = kInvalidNodeIndex, minPathDistance = 99999; + int lastSelectedGoal = kInvalidNodeIndex, minPathDistance = kInfiniteDistanceLong; float safeRadius = rg.float_ (1248.0f, 2048.0f); for (int i = 0; i < graph.length (); ++i) { @@ -5627,7 +5627,10 @@ bool Bot::isOutOfBombTimer () { void Bot::updateHearing () { int hearEnemyIndex = kInvalidNodeIndex; - float minDistance = 99999.0f; + float minDistance = kInfiniteDistance; + + // setup potential visibility set from engine + auto set = game.getVisibilitySet (this, false); // loop through all enemy clients to check for hearable stuff for (int i = 0; i < game.maxClients (); ++i) { @@ -5636,6 +5639,10 @@ void Bot::updateHearing () { if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent () || client.team == m_team || client.timeSoundLasting < game.timebase ()) { continue; } + + if (!game.checkVisibility (client.ent, set)) { + continue; + } float distance = (client.sound - pev->origin).length (); if (distance > client.hearingDistance) { diff --git a/source/chatlib.cpp b/source/chatlib.cpp index e017552..605fce6 100644 --- a/source/chatlib.cpp +++ b/source/chatlib.cpp @@ -256,12 +256,7 @@ void Bot::prepareChatMessage (const String &message) { // chat reply case 's': - if (m_sayTextBuffer.entityIndex != -1) { - m_chatBuffer.replace ("%s", humanizedName (m_sayTextBuffer.entityIndex)); - } - else { - m_chatBuffer.replace ("%s", getHighfragPlayer ()); - } + m_chatBuffer.replace ("%s", m_sayTextBuffer.entityIndex != -1 ? humanizedName (m_sayTextBuffer.entityIndex) : getHighfragPlayer ()); break; // last bot victim @@ -284,7 +279,7 @@ void Bot::prepareChatMessage (const String &message) { m_chatBuffer.replace ("%e", getPlayerAlive (true)); break; }; - replaceCounter++; + ++replaceCounter; } finishPreparation (); } @@ -292,8 +287,7 @@ void Bot::prepareChatMessage (const String &message) { bool Bot::checkChatKeywords (String &reply) { // this function parse chat buffer, and prepare buffer to keyword searching - String message = m_sayTextBuffer.sayText; - return util.checkKeywords (message.uppercase (), reply); + return util.checkKeywords (utf8tools.strToUpper (m_sayTextBuffer.sayText), reply); } bool Bot::isReplyingToChat () { diff --git a/source/combat.cpp b/source/combat.cpp index ee0a04c..31fbbfc 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -24,7 +24,7 @@ int Bot::numFriendsNear (const Vector &origin, float radius) { } if ((client.origin - origin).lengthSq () < cr::square (radius)) { - count++; + ++count; } } return count; @@ -39,7 +39,7 @@ int Bot::numEnemiesNear (const Vector &origin, float radius) { } if ((client.origin - origin).lengthSq () < cr::square (radius)) { - count++; + ++count; } } return count; @@ -210,6 +210,9 @@ bool Bot::lookupEnemies () { m_visibility = 0; m_enemyOrigin= nullvec; + // setup potential visibility set from engine + auto set = game.getVisibilitySet (this, true); + if (!game.isNullEntity (m_enemy)) { player = m_enemy; @@ -232,7 +235,13 @@ bool Bot::lookupEnemies () { } player = client.ent; - if ((player->v.button & (IN_ATTACK | IN_ATTACK2)) && m_viewDistance < m_maxViewDistance) { + // check the engine PVS + if (!game.checkVisibility (player, set)) { + continue; + } + + // extra skill player can see thru smoke... if beeing attacked + if ((player->v.button & (IN_ATTACK | IN_ATTACK2)) && m_viewDistance < m_maxViewDistance && yb_whose_your_daddy.bool_ ()) { nearestDistance = cr::square (m_maxViewDistance); } @@ -625,14 +634,14 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) { game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr); while (tr.flFraction != 1.0f && numHits < 3) { - numHits++; - thikness++; + ++numHits; + ++thikness; point = tr.vecEndPos + direction; while (engfuncs.pfnPointContents (point) == CONTENTS_SOLID && thikness < 98) { point = point + direction; - thikness++; + ++thikness; } game.testLine (point, dest, TraceIgnore::Everything, ent (), &tr); } @@ -720,7 +729,7 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) { if (tab[choosen].id == id) { break; } - choosen++; + ++choosen; } } @@ -884,7 +893,7 @@ void Bot::fireWeapons () { choosenWeapon = selectIndex; } } - selectIndex++; + ++selectIndex; } selectId = tab[choosenWeapon].id; @@ -914,7 +923,7 @@ void Bot::fireWeapons () { return; } } - selectIndex++; + ++selectIndex; } selectId = Weapon::Knife; // no available ammo, use knife! } @@ -1236,8 +1245,8 @@ bool Bot::usesRifle () { if (m_currentWeapon == tab->id) { break; } - tab++; - count++; + ++tab; + ++count; } if (tab->id && count > 13) { @@ -1255,8 +1264,8 @@ bool Bot::usesPistol () { if (m_currentWeapon == tab->id) { break; } - tab++; - count++; + ++tab; + ++count; } if (tab->id && count < 7) { @@ -1300,7 +1309,7 @@ int Bot::bestPrimaryCarried () { if (weapons & cr::bit (weaponTab[*pref].id)) { weaponIndex = i; } - pref++; + ++pref; } return weaponIndex; } @@ -1326,7 +1335,7 @@ int Bot::bestSecondaryCarried () { weaponIndex = i; break; } - pref++; + ++pref; } return weaponIndex; } @@ -1357,7 +1366,7 @@ bool Bot::rateGroundWeapon (edict_t *ent) { groundIndex = i; break; } - pref++; + ++pref; } int hasWeapon = 0; @@ -1396,7 +1405,7 @@ void Bot::selectBestWeapon () { while (tab[selectIndex].id) { // is the bot NOT carrying this weapon? if (!(pev->weapons & cr::bit (tab[selectIndex].id))) { - selectIndex++; // skip to next weapon + ++selectIndex; // skip to next weapon continue; } @@ -1417,7 +1426,7 @@ void Bot::selectBestWeapon () { if (ammoLeft) { chosenWeaponIndex = selectIndex; } - selectIndex++; + ++selectIndex; } chosenWeaponIndex %= kNumWeapons + 1; @@ -1456,7 +1465,7 @@ int Bot::bestWeaponCarried () { num = i; } ++i; - tab++; + ++tab; } return num; } @@ -1580,7 +1589,7 @@ void Bot::checkReload () { } if (weapons == 0) { - m_reloadState++; + ++m_reloadState; if (m_reloadState > Reload::Secondary) { m_reloadState = Reload::None; @@ -1613,7 +1622,7 @@ void Bot::checkReload () { m_reloadState = Reload::None; return; } - m_reloadState++; + ++m_reloadState; if (m_reloadState > Reload::Secondary) { m_reloadState = Reload::None; diff --git a/source/control.cpp b/source/control.cpp index 70c13c6..1686b05 100644 --- a/source/control.cpp +++ b/source/control.cpp @@ -1172,31 +1172,31 @@ int BotControl::menuGraphPage2 (int item) { Path &path = graph[i]; if (path.flags & NodeFlag::TerroristOnly) { - terrPoints++; + ++terrPoints; } if (path.flags & NodeFlag::CTOnly) { - ctPoints++; + ++ctPoints; } if (path.flags & NodeFlag::Goal) { - goalPoints++; + ++goalPoints; } if (path.flags & NodeFlag::Rescue) { - rescuePoints++; + ++rescuePoints; } if (path.flags & NodeFlag::Camp) { - campPoints++; + ++campPoints; } if (path.flags & NodeFlag::Sniper) { - sniperPoints++; + ++sniperPoints; } if (path.flags & NodeFlag::NoHostage) { - noHostagePoints++; + ++noHostagePoints; } } msg ("Nodes: %d - T Points: %d\n" @@ -1620,7 +1620,7 @@ void BotControl::showMenu (int id) { // make menus looks like we need only once if (!s_menusParsed) { for (auto &parsed : m_menus) { - const String &translated = game.translate (parsed.text.chars ()); + const String &translated = conf.translate (parsed.text.chars ()); // translate all the things parsed.text = translated; diff --git a/source/engine.cpp b/source/engine.cpp index 7b9e2e5..64cc861 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -104,7 +104,7 @@ void Game::levelInitialize (edict_t *entities, int max) { ent->v.renderamt = 127; // set its transparency amount ent->v.effects |= EF_NODRAW; - m_spawnCount[Team::CT]++; + ++m_spawnCount[Team::CT]; } else if (strcmp (classname, "info_player_deathmatch") == 0) { engfuncs.pfnSetModel (ent, ENGINE_STR ("models/player/terror/terror.mdl")); @@ -113,7 +113,7 @@ void Game::levelInitialize (edict_t *entities, int max) { ent->v.renderamt = 127; // set its transparency amount ent->v.effects |= EF_NODRAW; - m_spawnCount[Team::Terrorist]++; + ++m_spawnCount[Team::Terrorist]; } else if (strcmp (classname, "info_vip_start") == 0) { @@ -341,6 +341,49 @@ void Game::playSound (edict_t *ent, const char *sound) { engfuncs.pfnEmitSound (ent, CHAN_WEAPON, sound, 1.0f, ATTN_NORM, 0, 100); } +bool Game::checkVisibility (edict_t *ent, uint8 *set) { + if (!set) { + return true; + } + + if (ent->headnode < 0) { + for (int i = 0; i < ent->num_leafs; ++i) { + auto leaf = ent->leafnums[i]; + + if (set[leaf >> 3] & cr::bit (leaf & 7)) { + return true; + } + } + return false; + } + + for (int i = 0; i < 48; ++i) { + auto leaf = ent->leafnums[i]; + if (leaf == -1) { + break; + } + + if (set[leaf >> 3] & cr::bit (leaf & 7)) { + return true; + } + } + return engfuncs.pfnCheckVisibility (ent, set) > 0; +} + +uint8 *Game::getVisibilitySet (Bot *bot, bool pvs) { + if (is (GameFlags::Xash3D)) { + return nullptr; + } + auto eyes = bot->getEyesPos (); + + if (bot->pev->flags & FL_DUCKING) { + eyes += VEC_HULL_MIN - VEC_DUCK_HULL_MIN; + } + float org[3] { eyes.x, eyes.y, eyes.z }; + + return pvs ? engfuncs.pfnSetFatPVS (org) : engfuncs.pfnSetFatPAS (org); +} + void Game::sendClientMessage (bool console, edict_t *ent, const char *message) { // helper to sending the client message @@ -498,20 +541,6 @@ void Game::registerCvars (bool gameVars) { } } -const char *Game::translate (const char *input) { - // this function translate input string into needed language - - if (isDedicated ()) { - return input; - } - static String result; - - if (m_language.find (input, result)) { - return result.chars (); - } - return input; // nothing found -} - void Game::processMessages (void *ptr) { if (m_msgBlock.msg == NetMsg::None) { return; @@ -993,7 +1022,7 @@ void Game::processMessages (void *ptr) { default: logger.error ("Network message handler error. Call to unrecognized message id (%d).\n", m_msgBlock.msg); } - m_msgBlock.state++; // and finally update network message state + ++m_msgBlock.state; // and finally update network message state } bool Game::loadCSBinary () { @@ -1029,16 +1058,16 @@ bool Game::loadCSBinary () { } return true; }; - + // search the libraries inside game dlls directory for (const auto &lib : libs) { - auto *path = strings.format ("%s/dlls/%s", modname, lib.chars ()); + auto path = strings.format ("%s/dlls/%s", modname, lib.chars ()); // if we can't read file, skip it if (!File::exists (path)) { continue; } - + // special case, czero is always detected first, as it's has custom directory if (strcmp (modname, "czero") == 0) { m_gameFlags |= (GameFlags::ConditionZero | GameFlags::HasBotVoice | GameFlags::HasFakePings); @@ -1075,7 +1104,7 @@ bool Game::loadCSBinary () { } return true; } - + if (entity != nullptr) { m_gameFlags |= (GameFlags::Modern | GameFlags::HasBotVoice | GameFlags::HasFakePings); } @@ -1211,15 +1240,15 @@ void Game::slowFrame () { } ctrl.maintainAdminRights (); - // calculate light levels for all waypoints if needed - graph.initLightLevels (); - // update bot difficulties to newly selected from cvar bots.updateBotDifficulties (); // update client pings util.calculatePings (); + // initialize light levels + graph.initLightLevels (); + // detect csdm detectDeathmatch (); diff --git a/source/graph.cpp b/source/graph.cpp index 9aa9f2f..96f030e 100644 --- a/source/graph.cpp +++ b/source/graph.cpp @@ -51,7 +51,6 @@ int BotGraph::clearConnections (int index) { if (bots.hasBotsOnline ()) { bots.kickEveryone (true); } - const int kInfiniteDistance = 99999; struct Connection { int index; @@ -68,7 +67,7 @@ int BotGraph::clearConnections (int index) { void reset () { index = kInvalidNodeIndex; number = kInvalidNodeIndex; - distance = kInfiniteDistance; + distance = kInfiniteDistanceLong; angles = 0.0f; } }; @@ -86,7 +85,7 @@ int BotGraph::clearConnections (int index) { cur.distance = link.distance; if (cur.index == kInvalidNodeIndex) { - cur.distance = kInfiniteDistance; + cur.distance = kInfiniteDistanceLong; } if (cur.distance < top.distance) { @@ -117,7 +116,7 @@ int BotGraph::clearConnections (int index) { // calculate angles related to the angle of the closeset connected node for (auto &cur : sorted) { if (cur.index == kInvalidNodeIndex) { - cur.distance = kInfiniteDistance; + cur.distance = kInfiniteDistanceLong; cur.angles = 360.0f; } else if (exists (cur.index)) { @@ -415,7 +414,7 @@ void BotGraph::addPath (int addIndex, int pathIndex, float distance) { } // there wasn't any free space. try exchanging it with a long-distance path - int maxDistance = -9999; + int maxDistance = -kInfiniteDistanceLong; int slot = kInvalidNodeIndex; for (int i = 0; i < kMaxNodeLinks; ++i) { @@ -710,7 +709,7 @@ void BotGraph::add (int type, const Vector &pos) { // Ladder nodes need careful connections if (path->flags & NodeFlag::Ladder) { - float minDistance = 9999.0f; + float minDistance = kInfiniteDistance; int destIndex = kInvalidNodeIndex; TraceResult tr; @@ -1960,7 +1959,7 @@ void BotGraph::frame () { m_editor->v.movetype = MOVETYPE_NOCLIP; } - float nearestDistance = 99999.0f; + float nearestDistance = kInfiniteDistance; int nearestIndex = kInvalidNodeIndex; // check if it's time to add jump node @@ -2011,7 +2010,7 @@ void BotGraph::frame () { m_facingAtIndex = getFacingIndex (); // reset the minimal distance changed before - nearestDistance = 999999.0f; + nearestDistance = kInfiniteDistance; // now iterate through all nodes in a map, and draw required ones for (auto &path : m_paths) { @@ -2234,8 +2233,8 @@ void BotGraph::frame () { // show the information about that point graphMessage.assignf ("\n\n\n\n Graph Information:\n\n" - " Node %d of %d, Radius: %.1f\n" - " Flags: %s\n\n", nearestIndex, m_paths.length () - 1, path.radius, getFlagsAsStr (nearestIndex)); + " Node %d of %d, Radius: %.1f, Light: %.1f\n" + " Flags: %s\n\n", nearestIndex, m_paths.length () - 1, path.radius, path.light, getFlagsAsStr (nearestIndex)); // if node is not changed display experience also if (!m_hasChanged) { diff --git a/source/interface.cpp b/source/interface.cpp index 46c62a8..8be2a2b 100644 --- a/source/interface.cpp +++ b/source/interface.cpp @@ -423,7 +423,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *functionTable, int *) { // keep bot number up to date bots.maintainQuota (); - + if (game.is (GameFlags::Metamod)) { RETURN_META (MRES_IGNORED); } @@ -435,7 +435,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *functionTable, int *) { functionTable->pfnCmdStart = [] (const edict_t *player, usercmd_t *cmd, unsigned int random_seed) { auto ent = const_cast (player); - + // if we're handle pings for bots and clients, clear IN_SCORE button so SV_ShouldUpdatePing engine function return false // and SV_EmitPings will not overwrite our results if (game.is (GameFlags::HasFakePings) && yb_show_latency.int_ () == 2) { @@ -534,10 +534,6 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *functionTable, int *interfaceV auto api_GetNewDLLFunctions = game.lib ().resolve (__FUNCTION__); - if (api_GetNewDLLFunctions == nullptr) { - return FALSE; - } - if (!api_GetNewDLLFunctions || !api_GetNewDLLFunctions (functionTable, interfaceVersion)) { logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__); return FALSE; diff --git a/source/manager.cpp b/source/manager.cpp index 8407a52..d6a7850 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -66,12 +66,12 @@ void BotManager::createKillerEntity () { m_killerEntity = engfuncs.pfnCreateNamedEntity (MAKE_STRING ("trigger_hurt")); - m_killerEntity->v.dmg = 9999.0f; + m_killerEntity->v.dmg = kInfiniteDistance; m_killerEntity->v.dmg_take = 1.0f; m_killerEntity->v.dmgtime = 2.0f; m_killerEntity->v.effects |= EF_NODRAW; - engfuncs.pfnSetOrigin (m_killerEntity, Vector (-99999.0f, -99999.0f, -99999.0f)); + engfuncs.pfnSetOrigin (m_killerEntity, Vector (-kInfiniteDistance, -kInfiniteDistance, -kInfiniteDistance)); MDLL_Spawn (m_killerEntity); } @@ -224,12 +224,13 @@ Bot *BotManager::findBotByIndex (int index) { if (index < 0 || index >= kGameMaxPlayers) { return nullptr; } + for (const auto &bot : m_bots) { if (bot->m_index == index) { return bot.get (); } } - return nullptr; // no bot + return nullptr; // no bot`` } Bot *BotManager::findBotByEntity (edict_t *ent) { @@ -501,12 +502,10 @@ void BotManager::serverFill (int selection, int personality, int difficulty, int void BotManager::kickEveryone (bool instant, bool zeroQuota) { // this function drops all bot clients from server (this function removes only yapb's)`q - if (!hasBotsOnline () || !yb_quota.bool_ ()) { - return; + if (yb_quota.bool_ ()) { + ctrl.msg ("Bots are removed from server."); } - ctrl.msg ("Bots are removed from server."); - if (zeroQuota) { decrementQuota (0); } @@ -592,7 +591,7 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) { // if no dead bots found try to find one with lowest amount of frags Bot *selected = nullptr; - float score = 9999.0f; + float score = kInfiniteDistance; // search bots in this team for (const auto &bot : m_bots) { @@ -702,10 +701,10 @@ Twin BotManager::countTeamPlayers () { for (const auto &client : util.getClients ()) { if (client.flags & ClientFlags::Used) { if (client.team2 == Team::Terrorist) { - ts++; + ++ts; } else if (client.team2 == Team::CT) { - cts++; + ++cts; } } } @@ -748,9 +747,9 @@ void BotManager::updateTeamEconomics (int team, bool setTrue) { for (const auto &bot : m_bots) { if (bot->m_team == team) { if (bot->m_moneyAmount <= econLimit[EcoLimit::PrimaryGreater]) { - numPoorPlayers++; + ++numPoorPlayers; } - numTeamPlayers++; // update count of team + ++numTeamPlayers; // update count of team } } m_economicsGood[team] = true; @@ -920,7 +919,7 @@ int BotManager::getHumansCount (bool ignoreSpectators) { if (ignoreSpectators && client.team2 != Team::Terrorist && client.team2 != Team::CT) { continue; } - count++; + ++count; } } return count; @@ -933,7 +932,7 @@ int BotManager::getAliveHumansCount () { for (const auto &client : util.getClients ()) { if ((client.flags & (ClientFlags::Used | ClientFlags::Alive)) && bots[client.ent] == nullptr && !(client.ent->v.flags & FL_FAKECLIENT)) { - count++; + ++count; } } return count; @@ -952,7 +951,7 @@ bool BotManager::isTeamStacked (int team) { for (const auto &client : util.getClients ()) { if ((client.flags & ClientFlags::Used) && client.team2 != Team::Unassigned && client.team2 != Team::Spectator) { - teamCount[client.team2]++; + ++teamCount[client.team2]; } } return teamCount[team] + 1 > teamCount[team == Team::CT ? Team::Terrorist : Team::CT] + limitTeams; @@ -1036,7 +1035,7 @@ void Bot::newRound () { m_askCheckTime = rg.float_ (30.0f, 90.0f); m_minSpeed = 260.0f; m_prevSpeed = 0.0f; - m_prevOrigin = Vector (9999.0f, 9999.0f, 9999.0f); + m_prevOrigin = Vector (kInfiniteDistance, kInfiniteDistance, kInfiniteDistance); m_prevTime = game.timebase (); m_lookUpdateTime = game.timebase (); m_aimErrorTime = game.timebase (); @@ -1962,9 +1961,11 @@ void BotConfig::loadChatConfig () { keywords.clear (); replies.clear (); } - keywords.clear (); - keywords = cr::move (line.substr (4).split (",")); + + for (const auto &key : line.substr (4).split (",")) { + keywords.emplace (utf8tools.strToUpper (key)); + } for (auto &keyword : keywords) { keyword.trim ().trim ("\""); @@ -2007,7 +2008,7 @@ void BotConfig::loadLanguageConfig () { Twin lang; // clear all the translations before new load - game.clearTranslation (); + m_language.clear (); while (file.getLine (line)) { if (isCommentLine (line)) { @@ -2020,7 +2021,7 @@ void BotConfig::loadLanguageConfig () { } if (!lang.second.empty () && !lang.first.empty ()) { - game.addTranslation (lang.first.trim (), lang.second.trim ()); + m_language.push (lang.first.trim (), lang.second.trim ()); } } else if (line.startsWith ("[TRANSLATED]") && !temp.empty ()) { @@ -2179,3 +2180,18 @@ WeaponInfo &BotConfig::findWeaponById (const int id) { } return m_weapons.at (0); } + + +const char *BotConfig::translate (const char *input) { + // this function translate input string into needed language + + if (game.isDedicated ()) { + return input; + } + static String result; + + if (m_language.find (input, result)) { + return result.chars (); + } + return input; // nothing found +} \ No newline at end of file diff --git a/source/navigate.cpp b/source/navigate.cpp index a6b05c2..f0a62b1 100644 --- a/source/navigate.cpp +++ b/source/navigate.cpp @@ -168,7 +168,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) { { // force bomber to select closest goal, if round-start goal was reset by something if (m_hasC4 && bots.getRoundStartTime () + 20.0f < game.timebase ()) { - float minDist = 9999999.0f; + float minDist = kInfiniteDistance; int count = 0; for (auto &point : graph.m_goalPoints) { @@ -236,7 +236,7 @@ void Bot::postprocessGoals (const IntArray &goals, int *result) { if (index > 0) { index--; } - searchCount++; + ++searchCount; continue; } result[index] = rand; @@ -350,9 +350,6 @@ bool Bot::doPlayerAvoidance (const Vector &normal) { void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { m_isStuck = false; - if (doPlayerAvoidance (dirNormal) || m_avoidTime > game.timebase ()) { - return; - } TraceResult tr; // Standing still, no need to check? @@ -625,6 +622,11 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) { } } } + + // avoid players if not already stuck + if (!m_isStuck) { + doPlayerAvoidance (dirNormal); + } } bool Bot::updateNavigation () { @@ -1536,7 +1538,7 @@ bool Bot::findBestNearestNode () { int busy = kInvalidNodeIndex; - float lessDist[3] = { 9999.0f, 9999.0f , 9999.0f }; + float lessDist[3] = { kInfiniteDistance, kInfiniteDistance, kInfiniteDistance }; int lessIndex[3] = { kInvalidNodeIndex, kInvalidNodeIndex , kInvalidNodeIndex }; auto &bucket = graph.getNodesInBucket (pev->origin); @@ -1695,7 +1697,7 @@ void Bot::findValidNode () { } else { findBestNearestNode (); - m_rechoiceGoalCount++; + ++m_rechoiceGoalCount; } }; @@ -1809,7 +1811,7 @@ int Bot::findBombNode () { } int goal = 0, count = 0; - float lastDistance = 999999.0f; + float lastDistance = kInfiniteDistance; // find nearest goal node either to bomb (if "heard" or player) for (auto &point : goals) { @@ -2811,7 +2813,7 @@ int Bot::findCampingDirection () { distTab[count] = (pev->origin - path.origin).lengthSq (); visibility[count] = path.vis.crouch + path.vis.stand; - count++; + ++count; } else { float distance = (pev->origin - path.origin).lengthSq (); @@ -3029,6 +3031,11 @@ bool Bot::isOccupiedPoint (int index) { if (!(client.flags & (ClientFlags::Used | ClientFlags::Alive)) || client.team != m_team || client.ent == ent ()) { continue; } + + // do not check clients far away from us + if ((pev->origin - client.origin).lengthSq () > cr::square (320.0f)) { + continue; + } auto bot = bots[client.ent]; if (bot == this) { @@ -3058,7 +3065,7 @@ edict_t *Bot::lookupButton (const char *targetName) { if (util.isEmptyStr (targetName)) { return nullptr; } - float nearestDistance = 99999.0f; + float nearestDistance = kInfiniteDistance; edict_t *searchEntity = nullptr, *foundEntity = nullptr; // find the nearest button which can open our target diff --git a/source/support.cpp b/source/support.cpp index 2e5815f..e518a53 100644 --- a/source/support.cpp +++ b/source/support.cpp @@ -330,7 +330,7 @@ void BotUtils::attachSoundsToClients (edict_t *ent, const char *sample, float vo int index = game.indexOfPlayer (ent); if (index < 0 || index >= game.maxClients ()) { - float nearestDistance = 99999.0f; + float nearestDistance = kInfiniteDistance; // loop through all players for (int i = 0; i < game.maxClients (); ++i) { @@ -523,7 +523,7 @@ void BotUtils::calculatePings () { client.ping = getPingBitmask (client.ent, loss, ping > 0 ? ping / 2 : rg.int_ (8, 16)); // getting player ping sometimes fails client.pingUpdate = true; // force resend ping - numHumans++; + ++numHumans; average.first += ping; average.second += loss; @@ -578,7 +578,7 @@ void BotUtils::sendPings (edict_t *to) { if (!client.ping) { client.ping = getPingBitmask (client.ent, rg.int_ (5, 10), rg.int_ (15, 40)); } - + msg.start (MSG_ONE_UNRELIABLE, kGamePingSVC, nullvec, to) .writeLong (client.ping) .end (); @@ -635,7 +635,7 @@ int32 BotUtils::sendTo (int socket, const void *message, size_t length, int flag buffer.skip (); // protocol // skip server name, folder, map game - for (size_t i = 0; i < 4; i++) { + for (size_t i = 0; i < 4; ++i) { buffer.skipString (); } buffer.skip (); // steam app id