Get rid of Visual Studio warnings.

Relicensed under the MIT license.
Added safety checks here and there.
This commit is contained in:
jeefo 2019-09-21 23:20:33 +03:00
commit 61fad287e7
48 changed files with 517 additions and 554 deletions

View file

@ -1,23 +1,21 @@
Copyright (c) 2003-2019, YaPB Development Team The MIT License (MIT)
Redistribution and use in source and binary forms, with or without Copyright (c) 2004-2019 Yet Another POD-Bot Contributors <yapb@entix.io>
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the YaPB Dev Team nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND Permission is hereby granted, free of charge, to any person obtaining a copy
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED of this software and associated documentation files (the "Software"), to deal
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE in the Software without restriction, including without limitation the rights
DISCLAIMED. IN NO EVENT SHALL YAPB DEVELOPMENT TEAM BE LIABLE FOR ANY to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES copies of the Software, and to permit persons to whom the Software is
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; furnished to do so, subject to the following conditions:
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT The above copyright notice and this permission notice shall be included in all
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS copies or substantial portions of the Software.
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -33,11 +32,7 @@ public:
// calloc on linux with debug enabled doesn't always zero out memory // calloc on linux with debug enabled doesn't always zero out memory
#if defined (CR_DEBUG) && !defined (CR_WINDOWS) #if defined (CR_DEBUG) && !defined (CR_WINDOWS)
auto *zeroing = reinterpret_cast <uint8 *> (ptr); plat.bzero (ptr);
for (size_t i = 0; i < length; ++i) {
zeroing[i] = 0;
}
#endif #endif
return ptr; return ptr;
} }

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -13,14 +12,6 @@
#define CR_NAMESPACE_BEGIN namespace cr { #define CR_NAMESPACE_BEGIN namespace cr {
#define CR_NAMESPACE_END } #define CR_NAMESPACE_END }
// disable microsoft deprecation warning
#if defined (_MSC_VER)
# if !defined (_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE
# define _WINSOCK_DEPRECATED_NO_WARNINGS
# endif
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -32,14 +31,10 @@ public:
~File () { ~File () {
close (); close ();
} }
public: public:
bool open (const String &file, const String &mode) { bool open (const String &file, const String &mode) {
if (*this) { if (!openFile (file, mode)) {
close ();
}
if ((m_handle = fopen (file.chars (), mode.chars ())) == nullptr) {
return false; return false;
} }
fseek (m_handle, 0L, SEEK_END); fseek (m_handle, 0L, SEEK_END);
@ -157,6 +152,20 @@ public:
} }
plat.createDirectory (path); plat.createDirectory (path);
} }
private:
bool openFile (const String &filename, const String &mode) {
if (*this) {
close ();
}
#if defined (CR_WINDOWS)
fopen_s (&m_handle, filename.chars (), mode.chars ());
#else
m_handle = fopen (filename.chars (), mode.chars ());
#endif
return m_handle != nullptr;
}
}; };
// wrapper for memory file for loading data into the memory // wrapper for memory file for loading data into the memory

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -28,6 +27,7 @@
# include <fcntl.h> # include <fcntl.h>
#elif defined (CR_WINDOWS) #elif defined (CR_WINDOWS)
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h>
#endif #endif
// status codes for http client // status codes for http client
@ -71,12 +71,17 @@ public:
public: public:
bool connect (const String &hostname) { bool connect (const String &hostname) {
auto host = gethostbyname (hostname.chars ()); addrinfo hints, *result = nullptr;
plat.bzero (&hints, sizeof (hints));
if (!host) { hints.ai_flags = AI_NUMERICSERV;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo (hostname.chars (), "80", &hints, &result) != 0) {
return false; return false;
} }
m_socket = static_cast <int> (socket (AF_INET, SOCK_STREAM, 0)); m_socket = static_cast <int> (socket (result->ai_family, result->ai_socktype, 0));
if (m_socket < 0) { if (m_socket < 0) {
return false; return false;
@ -93,24 +98,21 @@ public:
auto timeouts = getTimeouts (); auto timeouts = getTimeouts ();
if (setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, timeouts.first, timeouts.second) == -1) { if (setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, timeouts.first, timeouts.second) == -1) {
logger.error ("Unable to set SO_RCVTIMEO."); logger.message ("Unable to set SO_RCVTIMEO.");
} }
if (setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, timeouts.first, timeouts.second) == -1) { if (setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, timeouts.first, timeouts.second) == -1) {
logger.error ("Unable to set SO_SNDTIMEO."); logger.message ("Unable to set SO_SNDTIMEO.");
} }
sockaddr_in dest; if (::connect (m_socket, result->ai_addr, static_cast <decltype (result->ai_addrlen)> (result->ai_addrlen)) == -1) {
memset (&dest, 0, sizeof (dest));
dest.sin_family = AF_INET;
dest.sin_port = htons (80);
dest.sin_addr.s_addr = inet_addr (inet_ntoa (*(reinterpret_cast <in_addr *> (host->h_addr))));
if (::connect (m_socket, reinterpret_cast <sockaddr *> (&dest), static_cast <int> (sizeof (dest))) == -1) {
disconnect (); disconnect ();
freeaddrinfo (result);
return false; return false;
} }
freeaddrinfo (result);
return true; return true;
} }

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -69,7 +68,7 @@ public:
m_handle = reinterpret_cast <void *> (mbi.AllocationBase); m_handle = reinterpret_cast <void *> (mbi.AllocationBase);
#else #else
Dl_info dli; Dl_info dli;
memset (&dli, 0, sizeof (dli)); plat.bzero (&dli, sizeof (dli));
if (dladdr (address, &dli)) { if (dladdr (address, &dli)) {
return load (dli.dli_fname); return load (dli.dli_fname);

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -37,10 +36,19 @@ private:
return; return;
} }
time_t ticks = time (&ticks); time_t ticks = time (&ticks);
auto tm = localtime (&ticks); tm *timeinfo = nullptr;
#if defined (CR_WINDOWS)
tm get;
localtime_s (&get, &ticks);
timeinfo = &get;
#else
timeinfo = localtime (&ticks);
#endif
auto timebuf = strings.chars (); auto timebuf = strings.chars ();
strftime (timebuf, StringBuffer::StaticBufferSize, "%Y-%m-%d %H:%M:%S", tm); strftime (timebuf, StringBuffer::StaticBufferSize, "%Y-%m-%d %H:%M:%S", timeinfo);
m_handle.puts ("%s (%s): %s\n", timebuf, level, msg); m_handle.puts ("%s (%s): %s\n", timebuf, level, msg);
} }

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -89,6 +88,7 @@ CR_NAMESPACE_END
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <locale.h> #include <locale.h>
#include <string.h>
#include <stdarg.h> #include <stdarg.h>
#if defined (CR_ANDROID) #if defined (CR_ANDROID)
@ -97,6 +97,8 @@ CR_NAMESPACE_END
CR_NAMESPACE_BEGIN CR_NAMESPACE_BEGIN
class String;
// helper struct for platform detection // helper struct for platform detection
struct Platform : public Singleton <Platform> { struct Platform : public Singleton <Platform> {
bool win32 = false; bool win32 = false;
@ -178,14 +180,6 @@ struct Platform : public Singleton <Platform> {
#endif #endif
} }
bool caseStrMatch (const char *str1, const char *str2) {
#if defined(CR_WINDOWS)
return _stricmp (str1, str2) == 0;
#else
return ::strcasecmp (str1, str2) == 0;
#endif
}
float seconds () { float seconds () {
#if defined(CR_WINDOWS) #if defined(CR_WINDOWS)
LARGE_INTEGER count, freq; LARGE_INTEGER count, freq;
@ -213,13 +207,42 @@ struct Platform : public Singleton <Platform> {
#endif #endif
#if defined(CR_WINDOWS) #if defined(CR_WINDOWS)
if (msg) { DestroyWindow (GetForegroundWindow ());
DestroyWindow (GetForegroundWindow ()); MessageBoxA (GetActiveWindow (), msg, "crlib.fatal", MB_ICONSTOP);
MessageBoxA (GetActiveWindow (), msg, "crlib.fatal", MB_ICONSTOP);
}
#endif #endif
::abort (); ::abort ();
} }
// anologue of memset
template <typename U> void bzero (U *ptr, size_t len) noexcept {
#if defined (CR_WINDOWS)
memset (ptr, 0, len);
#else
auto zeroing = reinterpret_cast <uint8 *> (ptr);
for (size_t i = 0; i < len; ++i) {
zeroing[i] = 0;
}
#endif
}
const char *env (const char *var) {
static char result[256];
bzero (result, sizeof (result));
#if defined(CR_WINDOWS)
char *buffer = nullptr;
size_t size = 0;
if (_dupenv_s (&buffer, &size, var) == 0 && buffer != nullptr) {
strncpy_s (result, buffer, sizeof (result));
free (buffer);
}
#else
strncpy (result, getenv (var), cr::bufsize (result));
#endif
return result;
}
}; };
// expose platform singleton // expose platform singleton

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -88,7 +87,7 @@ private:
}; };
public: public:
explicit String () { String () {
reset (); reset ();
assign ("", 0); assign ("", 0);
} }
@ -849,34 +848,60 @@ public:
~StringBuffer () = default; ~StringBuffer () = default;
public: public:
char *chars () { char *chars () noexcept {
if (++m_rotate >= RotationCount) { if (++m_rotate >= RotationCount) {
m_rotate = 0; m_rotate = 0;
} }
return m_data[cr::clamp <size_t> (m_rotate, 0, RotationCount)]; return m_data[cr::clamp <size_t> (m_rotate, 0, RotationCount)];
} }
template <typename U, typename ...Args> U *format (const U *fmt, Args ...args) { template <typename U, typename ...Args> U *format (const U *fmt, Args ...args) noexcept {
auto buffer = Singleton <StringBuffer>::get ().chars (); auto buffer = Singleton <StringBuffer>::get ().chars ();
snprintf (buffer, StaticBufferSize, fmt, args...); snprintf (buffer, StaticBufferSize, fmt, args...);
return buffer; return buffer;
} }
template <typename U> U *format (const U *fmt) { template <typename U> U *format (const U *fmt) noexcept {
auto buffer = Singleton <StringBuffer>::get ().chars (); auto buffer = Singleton <StringBuffer>::get ().chars ();
strncpy (buffer, fmt, StaticBufferSize); copy (buffer, fmt, StaticBufferSize);
return buffer; return buffer;
} }
// checks if string is not empty // checks if string is not empty
bool isEmpty (const char *input) const { bool isEmpty (const char *input) const noexcept {
if (input == nullptr) { if (input == nullptr) {
return true; return true;
} }
return *input == '\0'; return *input == '\0';
} }
bool matches (const char *str1, const char *str2) noexcept {
#if defined(CR_WINDOWS)
return _stricmp (str1, str2) == 0;
#else
return ::strcasecmp (str1, str2) == 0;
#endif
}
template <typename U> U *copy (U *dst, const U *src, size_t len) noexcept {
#if defined(CR_WINDOWS)
strncpy_s (dst, len, src, len - 1);
return dst;
#else
return strncpy (dst, src, len);
#endif
}
template <typename U> U *concat (U *dst, const U *src, size_t len) noexcept {
#if defined(CR_WINDOWS)
strncat_s (dst, len, src, len - 1);
return dst;
#else
return strncat (dst, src, len);
#endif
}
}; };
// expose global string pool // expose global string pool

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -350,7 +349,7 @@ public:
// send server command // send server command
template <typename ...Args> void serverCommand (const char *fmt, Args ...args) { template <typename ...Args> void serverCommand (const char *fmt, Args ...args) {
engfuncs.pfnServerCommand (strncat (strings.format (fmt, cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize)); engfuncs.pfnServerCommand (strings.concat (strings.format (fmt, cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
} }
// send a bot command // send a bot command
@ -360,7 +359,7 @@ public:
// prints data to servers console // prints data to servers console
template <typename ...Args> void print (const char *fmt, Args ...args) { template <typename ...Args> void print (const char *fmt, Args ...args) {
engfuncs.pfnServerPrint (strncat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize)); engfuncs.pfnServerPrint (strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
} }
// prints center message to specified player // prints center message to specified player
@ -369,7 +368,7 @@ public:
print (fmt, cr::forward <Args> (args)...); print (fmt, cr::forward <Args> (args)...);
return; return;
} }
sendClientMessage (true, ent, strncat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize)); sendClientMessage (true, ent, strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
} }
// prints message to client console // prints message to client console
@ -378,7 +377,7 @@ public:
print (fmt, cr::forward <Args> (args)...); print (fmt, cr::forward <Args> (args)...);
return; return;
} }
sendClientMessage (false, ent, strncat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize)); sendClientMessage (false, ent, strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
} }
}; };
@ -535,6 +534,10 @@ public:
m_worldModel = model; m_worldModel = model;
} }
model_t *getWorldModel () const {
return m_worldModel;
}
void enableAnimation (bool enable) { void enableAnimation (bool enable) {
m_doAnimation = enable; m_doAnimation = enable;
} }
@ -607,11 +610,11 @@ public:
class DynamicEntityLink : public Singleton <DynamicEntityLink> { class DynamicEntityLink : public Singleton <DynamicEntityLink> {
private: private:
#if defined (CR_WINDOWS) #if defined (CR_WINDOWS)
# define CastType HMODULE # define MODULE_HANDLE HMODULE
# define LookupSymbol GetProcAddress # define MODULE_SYMBOL GetProcAddress
#else #else
# define CastType void * # define MODULE_HANDLE void *
# define LookupSymbol dlsym # define MODULE_SYMBOL dlsym
#endif #endif
private: private:
@ -650,7 +653,7 @@ public:
if (plat.arm) { if (plat.arm) {
return; return;
} }
m_dlsym.patch (reinterpret_cast <void *> (&LookupSymbol), reinterpret_cast <void *> (&DynamicEntityLink::replacement)); m_dlsym.patch (reinterpret_cast <void *> (&MODULE_SYMBOL), reinterpret_cast <void *> (&DynamicEntityLink::replacement));
m_self.locate (&engfuncs); m_self.locate (&engfuncs);
} }

View file

@ -12,6 +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 CONST_H #ifndef CONST_H
#define CONST_H #define CONST_H
// //

View file

@ -38,7 +38,7 @@ public:
~string_t () = default; ~string_t () = default;
public: public:
const char *chars () const; const char *chars (size_t shift = 0) const;
public: public:
operator int () const { operator int () const {
@ -104,8 +104,8 @@ static inline int MAKE_STRING (const char *val) {
#define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0))) #define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0)))
#endif #endif
inline const char *string_t::chars () const { inline const char *string_t::chars (size_t shift) const {
return STRING (offset); return STRING (offset) + shift;
} }
#endif // EXTDLL_H #endif // EXTDLL_H

View file

@ -1,6 +1,32 @@
/* /*
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net> * Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
* See the file "dllapi.h" in this folder for full information *
* This file is part of Metamod.
*
* Metamod is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* Metamod is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Metamod; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/ */
// Simplified version by Wei Mingzhi // Simplified version by Wei Mingzhi

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -113,6 +112,7 @@ public:
void forEach (ForEachBot handler); void forEach (ForEachBot handler);
void erase (Bot *bot); void erase (Bot *bot);
void handleDeath (edict_t *killer, edict_t *victim); void handleDeath (edict_t *killer, edict_t *victim);
void setLastWinner (int winner);
bool isTeamStacked (int team); bool isTeamStacked (int team);
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned); bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);
@ -142,10 +142,6 @@ public:
return m_lastWinner; return m_lastWinner;
} }
void setLastWinner (int winner) {
m_lastWinner = winner;
}
// get the list of filters // get the list of filters
SmallArray <BotTask> &getFilters () { SmallArray <BotTask> &getFilters () {
return m_filters; return m_filters;

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -13,16 +12,16 @@
#define PRODUCT_NAME "Yet Another POD-Bot" #define PRODUCT_NAME "Yet Another POD-Bot"
#define PRODUCT_SHORT_NAME "YaPB" #define PRODUCT_SHORT_NAME "YaPB"
#define PRODUCT_VERSION "2.92" #define PRODUCT_VERSION "2.92"
#define PRODUCT_AUTHOR "YaPB Dev Team" #define PRODUCT_AUTHOR "YaPB Contributors"
#define PRODUCT_URL "https://yapb.ru/" #define PRODUCT_URL "https://yapb.ru/"
#define PRODUCT_EMAIL "d@entix.io" #define PRODUCT_EMAIL "yapb@entix.io"
#define PRODUCT_LOGTAG "YAPB" #define PRODUCT_LOGTAG "YAPB"
#define PRODUCT_END_YEAR "2019" #define PRODUCT_END_YEAR "2019"
#define PRODUCT_DESCRIPTION PRODUCT_NAME " v" PRODUCT_VERSION " - The Counter-Strike Bot (" PRODUCT_COMMENTS ")" #define PRODUCT_DESCRIPTION PRODUCT_NAME " v" PRODUCT_VERSION " - The Counter-Strike Bot (" PRODUCT_COMMENTS ")"
#define PRODUCT_COPYRIGHT "Copyright © 1999-" PRODUCT_END_YEAR ", by " PRODUCT_AUTHOR #define PRODUCT_COPYRIGHT "Copyright © 2004-" PRODUCT_END_YEAR ", by " PRODUCT_AUTHOR
#define PRODUCT_LEGAL "Half-Life, Counter-Strike, Counter-Strike: Condition Zero, Steam, Valve is a trademark of Valve Corporation" #define PRODUCT_LEGAL "Half-Life, Counter-Strike, Counter-Strike: Condition Zero, Steam, Valve is a trademark of Valve Corporation"
#define PRODUCT_ORIGINAL_NAME "yapb.dll" #define PRODUCT_ORIGINAL_NAME "yapb.dll"
#define PRODUCT_INTERNAL_NAME "skybot" #define PRODUCT_INTERNAL_NAME "podbot"
#define PRODUCT_GIT_HASH "unspecified_hash" #define PRODUCT_GIT_HASH "unspecified_hash"
#define PRODUCT_GIT_COMMIT_AUTHOR "unspecified_author" #define PRODUCT_GIT_COMMIT_AUTHOR "unspecified_author"
#define PRODUCT_GIT_COMMIT_ID 0000 #define PRODUCT_GIT_COMMIT_ID 0000

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#pragma once #pragma once
@ -19,6 +18,11 @@ using namespace cr;
#include <resource.h> #include <resource.h>
// forwards
class Bot;
class BotGraph;
class BotManager;
// defines bots tasks // defines bots tasks
CR_DECLARE_SCOPED_ENUM (Task, CR_DECLARE_SCOPED_ENUM (Task,
Normal = 0, Normal = 0,
@ -455,6 +459,10 @@ public:
// tasks definition // tasks definition
struct BotTask { struct BotTask {
using Function = void (Bot::*) ();
public:
Function func; // corresponding exec function in bot class
Task id; // major task/action carried out Task id; // major task/action carried out
float desire; // desire (filled in) for this task float desire; // desire (filled in) for this task
int data; // additional data (node index) int data; // additional data (node index)
@ -462,7 +470,7 @@ struct BotTask {
bool resume; // if task can be continued if interrupted bool resume; // if task can be continued if interrupted
public: public:
BotTask (Task id, float desire, int data, float time, bool resume) : id (id), desire (desire), data (data), time (time), resume (resume) { } BotTask (Function func, Task id, float desire, int data, float time, bool resume) : func (func), id (id), desire (desire), data (data), time (time), resume (resume) { }
}; };
// weapon properties structure // weapon properties structure
@ -827,7 +835,7 @@ private:
void hide_ (); void hide_ ();
void moveToPos_ (); void moveToPos_ ();
void plantBomb_ (); void plantBomb_ ();
void bombDefuse_ (); void defuseBomb_ ();
void followUser_ (); void followUser_ ();
void throwExplosive_ (); void throwExplosive_ ();
void throwFlashbang_ (); void throwFlashbang_ ();
@ -992,7 +1000,6 @@ public:
void pushChatMessage (int type, bool isTeamSay = false); void pushChatMessage (int type, bool isTeamSay = false);
void pushRadioMessage (int message); void pushRadioMessage (int message);
void pushChatterMessage (int message); void pushChatterMessage (int message);
void handleChatter (const char *tempMessage);
void tryHeadTowardRadioMessage (); void tryHeadTowardRadioMessage ();
void kill (); void kill ();
void kick (); void kick ();

View file

@ -1,25 +1,25 @@
# #
# Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). # Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
# Copyright (c) YaPB Development Team. # Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
# #
# This software is licensed under the BSD-style license. # This software is licensed under the MIT license.
# Additional exceptions apply. For full license details, see LICENSE.txt or visit: # Additional exceptions apply. For full license details, see LICENSE.txt
# https://yapb.ru/license
# #
PROJECT = yapb PROJECT = yapb
SOURCES = ../source SOURCES = ../source
OBJECTS = $(wildcard $(SOURCES)/*.cpp) OBJECTS = $(wildcard $(SOURCES)/*.cpp)
COMPILER_FLAGS = -std=c++11 -m32 -Wall -Wextra -Werror -fno-exceptions -fno-rtti -pedantic COMPILER_FLAGS = -std=c++11 -m32 -Wall -Wextra -Werror -fno-exceptions -fno-rtti
LINKER_FLAGS = -m32 -ldl LINKER_FLAGS = -m32 -ldl
ifeq "$(DEBUG)" "true" ifeq "$(DEBUG)" "true"
COMPILER_FLAGS += -g3 -DCR_DEBUG COMPILER_FLAGS += -g3 -DCR_DEBUG
BINARY_DIR = debug BINARY_DIR = debug
else else
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 COMPILER_FLAGS += -pipe -O3 -march=core2 -msse2 -mfpmath=sse -fno-builtin -fno-threadsafe-statics -funroll-loops -fomit-frame-pointer -fno-stack-protector -fvisibility=hidden -fvisibility-inlines-hidden
BINARY_DIR = release BINARY_DIR = release
LINKER_FLAGS += -static-libgcc
endif endif
INCLUDE = -I../include INCLUDE = -I../include
@ -42,16 +42,18 @@ BINARY_OUTPUT = $(PROJECT).$(LIBRARY_EXT)
ifeq ($(findstring clang,$(COMPILER)),clang) ifeq ($(findstring clang,$(COMPILER)),clang)
ifeq "$(OSX)" "false" ifeq "$(OSX)" "false"
LINKER_FLAGS += -lgcc_eh
else
ifeq "$(DEBUG)" "true" ifeq "$(DEBUG)" "true"
LINKER_FLAGS += -lstdc++ LINKER_FLAGS += -lstdc++
else else
LINKER_FLAGS += -static-libgcc -nostdlib++ -Wunused-command-line-argument -fuse-ld=lld -Wl,-z,notext --no-undefined LINKER_FLAGS += -nostdlib++ -Wunused-command-line-argument -fuse-ld=lld -Wl,-z,notext --no-undefined
endif endif
endif endif
else ifeq ($(findstring gcc,$(COMPILER)),gcc) else ifeq ($(findstring gcc,$(COMPILER)),gcc)
ifneq "$(OSX)" "false" ifneq "$(OSX)" "false"
ifneq "$(DEBUG)" "true" ifneq "$(DEBUG)" "true"
LINKER_FLAGS += -static-libgcc -Wl,--no-undefined -flto=thin LINKER_FLAGS += -Wl,--no-undefined -flto=thin
COMPILER_FLAGS += -funroll-all-loops -flto=thin COMPILER_FLAGS += -funroll-all-loops -flto=thin
endif endif
endif endif
@ -60,7 +62,7 @@ else ifeq ($(findstring icc,$(COMPILER)),icc)
ifneq "$(DEBUG)" "true" ifneq "$(DEBUG)" "true"
COMPILER_FLAGS += -funroll-all-loops -ipo -wd11076 -wd11074 COMPILER_FLAGS += -funroll-all-loops -ipo -wd11076 -wd11074
LINKER_FLAGS += -static-libgcc -cxxlib-nostd -Wl,--no-undefined,-z,notext,--gc-sections -ipo LINKER_FLAGS += -cxxlib-nostd -Wl,--no-undefined,-z,notext,--gc-sections -ipo
endif endif
endif endif

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -93,20 +92,20 @@ bool Bot::isInViewCone (const Vector &origin) {
} }
bool Bot::seesItem (const Vector &destination, const char *itemName) { bool Bot::seesItem (const Vector &destination, const char *itemName) {
TraceResult tr; TraceResult tr {};
// trace a line from bot's eyes to destination.. // trace a line from bot's eyes to destination..
game.testLine (getEyesPos (), destination, TraceIgnore::Monsters, ent (), &tr); game.testLine (getEyesPos (), destination, TraceIgnore::Monsters, ent (), &tr);
// 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 && tr.pHit) {
return strcmp (tr.pHit->v.classname.chars (), itemName) == 0; return strcmp (tr.pHit->v.classname.chars (), itemName) == 0;
} }
return true; return true;
} }
bool Bot::seesEntity (const Vector &dest, bool fromBody) { bool Bot::seesEntity (const Vector &dest, bool fromBody) {
TraceResult tr; TraceResult tr {};
// trace a line from bot's eyes to destination... // trace a line from bot's eyes to destination...
game.testLine (fromBody ? pev->origin : getEyesPos (), dest, TraceIgnore::Everything, ent (), &tr); game.testLine (fromBody ? pev->origin : getEyesPos (), dest, TraceIgnore::Everything, ent (), &tr);
@ -330,7 +329,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 = pent->v.model.chars () + 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
@ -428,7 +427,7 @@ void Bot::checkBreakablesAround () {
edict_t *Bot::lookupBreakable () { edict_t *Bot::lookupBreakable () {
// this function checks if bot is blocked by a shoot able breakable in his moving direction // this function checks if bot is blocked by a shoot able breakable in his moving direction
TraceResult tr; TraceResult tr {};
game.testLine (pev->origin, pev->origin + (m_destOrigin - pev->origin).normalize () * 72.0f, TraceIgnore::None, ent (), &tr); game.testLine (pev->origin, pev->origin + (m_destOrigin - pev->origin).normalize () * 72.0f, TraceIgnore::None, ent (), &tr);
if (tr.flFraction != 1.0f) { if (tr.flFraction != 1.0f) {
@ -539,7 +538,7 @@ void Bot::updatePickups () {
} }
auto classname = ent->v.classname.chars (); auto classname = ent->v.classname.chars ();
auto model = ent->v.model.chars () + 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)) {
@ -830,7 +829,7 @@ void Bot::getCampDirection (Vector *dest) {
// this function check if view on last enemy position is blocked - replace with better vector then // this function check if view on last enemy position is blocked - replace with better vector then
// mostly used for getting a good camping direction vector if not camping on a camp waypoint // mostly used for getting a good camping direction vector if not camping on a camp waypoint
TraceResult tr; TraceResult tr {};
const Vector &src = getEyesPos (); const Vector &src = getEyesPos ();
game.testLine (src, *dest, TraceIgnore::Monsters, ent (), &tr); game.testLine (src, *dest, TraceIgnore::Monsters, ent (), &tr);
@ -1484,7 +1483,7 @@ void Bot::buyStuff () {
break; break;
case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon case BuyState::SecondaryWeapon: // if bot has still some money, buy a better secondary weapon
if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg.int_ (3500, 4500)) || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg.int_ (7500, 9000))) { if (isPistolMode || (isFirstRound && hasDefaultPistols) || (hasDefaultPistols && bots.getLastWinner () == m_team && m_moneyAmount > rg.int_ (2000, 3000)) || (hasPrimaryWeapon () && hasDefaultPistols && m_moneyAmount > rg.int_ (7500, 9000))) {
do { do {
pref--; pref--;
@ -2031,6 +2030,8 @@ void Bot::clearTasks () {
} }
void Bot::startTask (Task id, float desire, int data, float time, bool resume) { void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
static const auto &filter = bots.getFilters ();
for (auto &task : m_tasks) { for (auto &task : m_tasks) {
if (task.id == id) { if (task.id == id) {
if (!cr::fequal (task.desire, desire)) { if (!cr::fequal (task.desire, desire)) {
@ -2039,7 +2040,7 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
return; return;
} }
} }
m_tasks.emplace (id, desire, data, time, resume); m_tasks.emplace (filter[id].func, id, desire, data, time, resume);
clearSearchNodes (); clearSearchNodes ();
ignoreCollision (); ignoreCollision ();
@ -2056,21 +2057,27 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
} }
// this is best place to handle some voice commands report team some info // this is best place to handle some voice commands report team some info
if (rg.chance (90)) { if (yb_radio_mode.int_ () > 1) {
if (tid == Task::Blind) { if (rg.chance (90)) {
pushChatterMessage (Chatter::Blind); if (tid == Task::Blind) {
pushChatterMessage (Chatter::Blind);
}
else if (tid == Task::PlantBomb) {
pushChatterMessage (Chatter::PlantingBomb);
}
} }
else if (tid == Task::PlantBomb) {
pushChatterMessage (Chatter::PlantingBomb);
}
}
if (rg.chance (25) && tid == Task::Camp) { if (rg.chance (25) && tid == Task::Camp) {
if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) { if (game.mapIs (MapFlags::Demolition) && bots.isBombPlanted ()) {
pushChatterMessage (Chatter::GuardingDroppedC4); pushChatterMessage (Chatter::GuardingDroppedC4);
}
else {
pushChatterMessage (Chatter::GoingToCamp);
}
} }
else {
pushChatterMessage (Chatter::GoingToCamp); if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) {
pushChatterMessage (Chatter::GoingToGuardVIPSafety);
} }
} }
@ -2080,15 +2087,11 @@ void Bot::startTask (Task id, float desire, int data, float time, bool resume) {
else { else {
m_chosenGoalIndex = getTask ()->data; m_chosenGoalIndex = getTask ()->data;
} }
if (rg.chance (75) && tid == Task::Camp && m_team == Team::Terrorist && m_inVIPZone) {
pushChatterMessage (Chatter::GoingToGuardVIPSafety);
}
} }
BotTask *Bot::getTask () { BotTask *Bot::getTask () {
if (m_tasks.empty ()) { if (m_tasks.empty ()) {
m_tasks.emplace (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true); startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
} }
return &m_tasks.last (); return &m_tasks.last ();
} }
@ -3200,7 +3203,7 @@ void Bot::spraypaint_ () {
const auto &forward = pev->v_angle.forward (); const auto &forward = pev->v_angle.forward ();
Vector sprayOrigin = getEyesPos () + forward * 128.0f; Vector sprayOrigin = getEyesPos () + forward * 128.0f;
TraceResult tr; TraceResult tr {};
game.testLine (getEyesPos (), sprayOrigin, TraceIgnore::Monsters, ent (), &tr); game.testLine (getEyesPos (), sprayOrigin, TraceIgnore::Monsters, ent (), &tr);
// no wall in front? // no wall in front?
@ -3732,7 +3735,7 @@ void Bot::plantBomb_ () {
} }
} }
void Bot::bombDefuse_ () { void Bot::defuseBomb_ () {
float fullDefuseTime = m_hasDefuser ? 7.0f : 12.0f; float fullDefuseTime = m_hasDefuser ? 7.0f : 12.0f;
float timeToBlowUp = getBombTimeleft (); float timeToBlowUp = getBombTimeleft ();
float defuseRemainingTime = fullDefuseTime; float defuseRemainingTime = fullDefuseTime;
@ -3908,7 +3911,7 @@ void Bot::followUser_ () {
} }
if (m_targetEntity->v.button & IN_ATTACK) { if (m_targetEntity->v.button & IN_ATTACK) {
TraceResult tr; TraceResult tr {};
game.testLine (m_targetEntity->v.origin + m_targetEntity->v.view_ofs, m_targetEntity->v.v_angle.forward () * 500.0f, TraceIgnore::Everything, ent (), &tr); game.testLine (m_targetEntity->v.origin + m_targetEntity->v.view_ofs, m_targetEntity->v.v_angle.forward () * 500.0f, TraceIgnore::Everything, ent (), &tr);
if (!game.isNullEntity (tr.pHit) && util.isPlayer (tr.pHit) && game.getTeam (tr.pHit) != m_team) { if (!game.isNullEntity (tr.pHit) && util.isPlayer (tr.pHit) && game.getTeam (tr.pHit) != m_team) {
@ -4201,7 +4204,7 @@ void Bot::doublejump_ () {
const auto &src = pev->origin + Vector (0.0f, 0.0f, 45.0f); const auto &src = pev->origin + Vector (0.0f, 0.0f, 45.0f);
const auto &dest = src + Vector (0.0f, pev->angles.y, 0.0f).upward () * 256.0f; const auto &dest = src + Vector (0.0f, pev->angles.y, 0.0f).upward () * 256.0f;
TraceResult tr; TraceResult tr {};
game.testLine (src, dest, TraceIgnore::None, ent (), &tr); game.testLine (src, dest, TraceIgnore::None, ent (), &tr);
if (tr.flFraction < 1.0f && tr.pHit == m_doubleJumpEntity && inJump) { if (tr.flFraction < 1.0f && tr.pHit == m_doubleJumpEntity && inJump) {
@ -4373,7 +4376,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, m_pickupItem->v.model.chars () + 9) == 0) { if (strcmp (info[index].model, m_pickupItem->v.model.chars (9)) == 0) {
break; break;
} }
} }
@ -4536,108 +4539,15 @@ void Bot::pickupItem_ () {
void Bot::executeTasks () { void Bot::executeTasks () {
// this is core function that handle task execution // this is core function that handle task execution
switch (getCurrentTaskId ()) { auto func = getTask ()->func;
// normal task
default:
case Task::Normal:
normal_ ();
break;
// bot sprays messy logos all over the place... // run the current task
case Task::Spraypaint: if (func != nullptr) {
spraypaint_ (); (this->*func) ();
break; }
else {
// hunt down enemy logger.error ("Missing callback function of Task %d.", getCurrentTaskId ());
case Task::Hunt: kick (); // drop the player, as it's fatal for bot
huntEnemy_ ();
break;
// bot seeks cover from enemy
case Task::SeekCover:
seekCover_ ();
break;
// plain attacking
case Task::Attack:
attackEnemy_ ();
break;
// Bot is pausing
case Task::Pause:
pause_ ();
break;
// blinded (flashbanged) behaviour
case Task::Blind:
blind_ ();
break;
// camping behaviour
case Task::Camp:
camp_ ();
break;
// hiding behaviour
case Task::Hide:
hide_ ();
break;
// moves to a position specified in position has a higher priority than task_normal
case Task::MoveToPosition:
moveToPos_ ();
break;
// planting the bomb right now
case Task::PlantBomb:
plantBomb_ ();
break;
// bomb defusing behaviour
case Task::DefuseBomb:
bombDefuse_ ();
break;
// follow user behaviour
case Task::FollowUser:
followUser_ ();
break;
// HE grenade throw behaviour
case Task::ThrowExplosive:
throwExplosive_ ();
break;
// flashbang throw behavior (basically the same code like for HE's)
case Task::ThrowFlashbang:
throwFlashbang_ ();
break;
// smoke grenade throw behavior
// a bit different to the others because it mostly tries to throw the sg on the ground
case Task::ThrowSmoke:
throwSmoke_ ();
break;
// bot helps human player (or other bot) to get somewhere
case Task::DoubleJump:
doublejump_ ();
break;
// escape from bomb behaviour
case Task::EscapeFromBomb:
escapeFromBomb_ ();
break;
// shooting breakables in the way action
case Task::ShootBreakable:
shootBreakable_ ();
break;
// picking up items and stuff behaviour
case Task::PickupItem:
pickupItem_ ();
break;
} }
} }
@ -4737,6 +4647,9 @@ void Bot::logic () {
if (canRunHeavyWeight ()) { if (canRunHeavyWeight ()) {
setConditions (); setConditions ();
} }
else if (!game.isNullEntity (m_enemy)) {
trackEnemies ();
}
// some stuff required by by chatter engine // some stuff required by by chatter engine
if (yb_radio_mode.int_ () == 2) { if (yb_radio_mode.int_ () == 2) {
@ -5086,7 +4999,6 @@ void Bot::takeDamage (edict_t *inflictor, int damage, int armor, int bits) {
m_enemyOrigin = m_enemy->v.origin; m_enemyOrigin = m_enemy->v.origin;
pushChatMessage (Chat::TeamAttack); pushChatMessage (Chat::TeamAttack);
handleChatter ("#Bot_TeamAttack");
pushChatterMessage (Chatter::FriendlyFire); pushChatterMessage (Chatter::FriendlyFire);
} }
else { else {
@ -5235,29 +5147,6 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) {
graph.setDangerDamage (m_team, victimIndex, attackerIndex, damageValue); graph.setDangerDamage (m_team, victimIndex, attackerIndex, damageValue);
} }
void Bot::handleChatter (const char *tempMessage) {
// this function is added to prevent engine crashes with: 'Message XX started, before message XX ended', or something.
if ((m_team == Team::CT && strcmp (tempMessage, "#CTs_Win") == 0) || (m_team == Team::Terrorist && strcmp (tempMessage, "#Terrorists_Win") == 0)) {
if (bots.getRoundMidTime () > game.time ()) {
pushChatterMessage (Chatter::QuickWonRound);
}
else {
pushChatterMessage (Chatter::WonTheRound);
}
}
else if (strcmp (tempMessage, "#Bot_TeamAttack") == 0) {
pushChatterMessage (Chatter::FriendlyFire);
}
else if (strcmp (tempMessage, "#Bot_NiceShotCommander") == 0) {
pushChatterMessage (Chatter::NiceShotCommander);
}
else if (strcmp (tempMessage, "#Bot_NiceShotPall") == 0) {
pushChatterMessage (Chatter::NiceShotPall);
}
}
void Bot::pushChatMessage (int type, bool isTeamSay) { void Bot::pushChatMessage (int type, bool isTeamSay) {
if (!conf.hasChatBank (type) || !yb_chat.bool_ ()) { if (!conf.hasChatBank (type) || !yb_chat.bool_ ()) {
return; return;
@ -5352,7 +5241,7 @@ Vector Bot::calcToss (const Vector &start, const Vector &stop) {
// this function returns the velocity at which an object should looped from start to land near end. // this function returns the velocity at which an object should looped from start to land near end.
// returns null vector if toss is not feasible. // returns null vector if toss is not feasible.
TraceResult tr; TraceResult tr {};
float gravity = sv_gravity.float_ () * 0.55f; float gravity = sv_gravity.float_ () * 0.55f;
Vector end = stop - pev->velocity; Vector end = stop - pev->velocity;
@ -5364,7 +5253,7 @@ Vector Bot::calcToss (const Vector &start, const Vector &stop) {
Vector midPoint = start + (end - start) * 0.5f; Vector midPoint = start + (end - start) * 0.5f;
game.testHull (midPoint, midPoint + Vector (0.0f, 0.0f, 500.0f), TraceIgnore::Monsters, head_hull, ent (), &tr); game.testHull (midPoint, midPoint + Vector (0.0f, 0.0f, 500.0f), TraceIgnore::Monsters, head_hull, ent (), &tr);
if (tr.flFraction < 1.0f) { if (tr.flFraction < 1.0f && tr.pHit) {
midPoint = tr.vecEndPos; midPoint = tr.vecEndPos;
midPoint.z = tr.pHit->v.absmin.z - 1.0f; midPoint.z = tr.pHit->v.absmin.z - 1.0f;
} }
@ -5406,7 +5295,7 @@ Vector Bot::calcThrow (const Vector &start, const Vector &stop) {
// returns null vector if throw is not feasible. // returns null vector if throw is not feasible.
Vector velocity = stop - start; Vector velocity = stop - start;
TraceResult tr; TraceResult tr {};
float gravity = sv_gravity.float_ () * 0.55f; float gravity = sv_gravity.float_ () * 0.55f;
float time = velocity.length () / 195.0f; float time = velocity.length () / 195.0f;
@ -5444,7 +5333,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 (ent->v.model.chars () + 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

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -97,7 +96,7 @@ bool Bot::checkBodyParts (edict_t *target) {
return false; return false;
} }
TraceResult result; TraceResult result {};
auto eyes = getEyesPos (); auto eyes = getEyesPos ();
auto spot = target->v.origin; auto spot = target->v.origin;
@ -539,7 +538,7 @@ bool Bot::isFriendInLineOfFire (float distance) {
return false; return false;
} }
TraceResult tr; TraceResult tr {};
game.testLine (getEyesPos (), getEyesPos () + distance * pev->v_angle.normalize (), TraceIgnore::None, ent (), &tr); game.testLine (getEyesPos (), getEyesPos () + distance * pev->v_angle.normalize (), TraceIgnore::None, ent (), &tr);
// check if we hit something // check if we hit something
@ -582,7 +581,7 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
if (penetratePower == 0) { if (penetratePower == 0) {
return false; return false;
} }
TraceResult tr; TraceResult tr {};
float obstacleDistance = 0.0f; float obstacleDistance = 0.0f;
game.testLine (getEyesPos (), dest, TraceIgnore::Monsters, ent (), &tr); game.testLine (getEyesPos (), dest, TraceIgnore::Monsters, ent (), &tr);
@ -632,7 +631,7 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) {
int numHits = 0; int numHits = 0;
Vector point; Vector point;
TraceResult tr; TraceResult tr {};
game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr); game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr);
@ -1197,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 (pev->viewmodel.chars (), "models/shield/v_shield_", 23) == 0; return strncmp (pev->viewmodel.chars (14), "v_shield_", 9) == 0;
} }
bool Bot::isShieldDrawn () { bool Bot::isShieldDrawn () {
@ -1217,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 (enemy->v.viewmodel.chars (), "models/shield/v_shield_", 23) == 0) { if ((enemy->v.weaponanim == 6 || enemy->v.weaponanim == 7) && strncmp (enemy->v.viewmodel.chars (14), "v_shield_", 9) == 0) {
if (util.isInViewCone (pev->origin, enemy)) { if (util.isInViewCone (pev->origin, enemy)) {
return true; return true;
} }
@ -1356,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, ent->v.model.chars () + 9) == 0) { if (strcmp (tab[*pref].model, ent->v.model.chars (9)) == 0) {
groundIndex = i; groundIndex = i;
break; break;
} }

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -22,8 +21,8 @@ Game::Game () {
m_precached = false; m_precached = false;
m_isBotCommand = false; m_isBotCommand = false;
memset (m_drawModels, 0, sizeof (m_drawModels)); plat.bzero (m_drawModels, sizeof (m_drawModels));
memset (m_spawnCount, 0, sizeof (m_spawnCount)); plat.bzero (m_spawnCount, sizeof (m_spawnCount));
m_gameFlags = 0; m_gameFlags = 0;
m_mapFlags = 0; m_mapFlags = 0;
@ -88,7 +87,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) && ent->v.target.chars ()[0] == '\0') { if (is (GameFlags::Legacy) && strings.isEmpty (ent->v.target.chars ())) {
ent->v.target = ent->v.targetname = engfuncs.pfnAllocString ("fake"); ent->v.target = ent->v.targetname = engfuncs.pfnAllocString ("fake");
} }
else { else {
@ -256,7 +255,7 @@ float Game::getWaveLen (const char *fileName) {
unsigned long dataChunkLength; unsigned long dataChunkLength;
} waveHdr; } waveHdr;
memset (&waveHdr, 0, sizeof (waveHdr)); plat.bzero (&waveHdr, sizeof (waveHdr));
if (fp.read (&waveHdr, sizeof (WavHeader)) == 0) { if (fp.read (&waveHdr, sizeof (WavHeader)) == 0) {
logger.error ("Wave File %s - has wrong or unsupported format", filePath); logger.error ("Wave File %s - has wrong or unsupported format", filePath);
@ -465,6 +464,20 @@ bool Game::isSoftwareRenderer () {
if (isDedicated ()) { if (isDedicated ()) {
return true; return true;
} }
auto model = illum.getWorldModel ();
if (model->nodes[0].parent != nullptr) {
return false;
}
const auto child = model->nodes[0].children[0];
if (child < model->nodes || child > model->nodes + model->numnodes) {
return false;
}
if (child->parent != &model->nodes[0]) {
return false;
}
// 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.win32) { if (plat.win32) {
@ -476,7 +489,7 @@ bool Game::isSoftwareRenderer () {
void Game::addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, ConVar *self) { void Game::addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, ConVar *self) {
// this function adds globally defined variable to registration stack // this function adds globally defined variable to registration stack
VarPair pair; VarPair pair {};
pair.reg.name = const_cast <char *> (name); pair.reg.name = const_cast <char *> (name);
pair.reg.string = const_cast <char *> (value); pair.reg.string = const_cast <char *> (value);
@ -747,7 +760,7 @@ bool Game::postload () {
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.hfp ? "libserver_hardfp.so" : "libserver.so"); auto gamedll = strings.format ("%s/%s", plat.env ("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 ());
@ -938,7 +951,7 @@ void LightMeasure::updateLight (int style, char *value) {
return; return;
} }
const auto copyLimit = sizeof (m_lightstyle[style].map) - sizeof ('\0'); const auto copyLimit = sizeof (m_lightstyle[style].map) - sizeof ('\0');
strncpy (m_lightstyle[style].map, value, copyLimit); strings.copy (m_lightstyle[style].map, value, copyLimit);
m_lightstyle[style].map[copyLimit] = '\0'; m_lightstyle[style].map[copyLimit] = '\0';
m_lightstyle[style].length = strlen (m_lightstyle[style].map); m_lightstyle[style].length = strlen (m_lightstyle[style].map);
@ -1072,7 +1085,7 @@ DynamicEntityLink::Handle DynamicEntityLink::search (Handle module, Name functio
Handle ret = nullptr; Handle ret = nullptr;
if (m_dlsym.disable ()) { if (m_dlsym.disable ()) {
ret = LookupSymbol (reinterpret_cast <CastType> (handle), function); ret = MODULE_SYMBOL (reinterpret_cast <MODULE_HANDLE> (handle), function);
m_dlsym.enable (); m_dlsym.enable ();
} }
return ret; return ret;

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -637,7 +636,7 @@ void BotGraph::add (int type, const Vector &pos) {
if (m_paths.length () >= kMaxNodes) { if (m_paths.length () >= kMaxNodes) {
return; return;
} }
m_paths.push (Path ()); m_paths.push (Path {});
index = m_paths.length () - 1; index = m_paths.length () - 1;
path = &m_paths[index]; path = &m_paths[index];
@ -737,7 +736,7 @@ void BotGraph::add (int type, const Vector &pos) {
float minDistance = kInfiniteDistance; float minDistance = kInfiniteDistance;
int destIndex = kInvalidNodeIndex; int destIndex = kInvalidNodeIndex;
TraceResult tr; TraceResult tr {};
// calculate all the paths to this new node // calculate all the paths to this new node
for (const auto &calc : m_paths) { for (const auto &calc : m_paths) {
@ -929,7 +928,7 @@ int BotGraph::getFacingIndex () {
} }
// check if visible, (we're not using visiblity tables here, as they not valid at time of waypoint editing) // check if visible, (we're not using visiblity tables here, as they not valid at time of waypoint editing)
TraceResult tr; TraceResult tr {};
game.testLine (editorEyes, path.origin, TraceIgnore::Everything, m_editor, &tr); game.testLine (editorEyes, path.origin, TraceIgnore::Everything, m_editor, &tr);
if (!cr::fequal (tr.flFraction, 1.0f)) { if (!cr::fequal (tr.flFraction, 1.0f)) {
@ -1076,7 +1075,7 @@ void BotGraph::calculatePathRadius (int index) {
return; return;
} }
} }
TraceResult tr; TraceResult tr {};
bool wayBlocked = false; bool wayBlocked = false;
for (float scanDistance = 32.0f; scanDistance < 128.0f; scanDistance += 16.0f) { for (float scanDistance = 32.0f; scanDistance < 128.0f; scanDistance += 16.0f) {
@ -1098,7 +1097,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", tr.pHit->v.classname.chars (), 9) == 0) { if (tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
path.radius = 0.0f; path.radius = 0.0f;
wayBlocked = true; wayBlocked = true;
@ -1336,7 +1335,7 @@ bool BotGraph::convertOldFormat () {
MemFile fp (getOldFormatGraphName (true)); MemFile fp (getOldFormatGraphName (true));
PODGraphHeader header; PODGraphHeader header;
memset (&header, 0, sizeof (header)); plat.bzero (&header, sizeof (header));
// save for faster access // save for faster access
const char *map = game.getMapName (); const char *map = game.getMapName ();
@ -1350,7 +1349,7 @@ bool BotGraph::convertOldFormat () {
if (header.fileVersion != StorageVersion::Podbot) { if (header.fileVersion != StorageVersion::Podbot) {
return false; return false;
} }
else if (!plat.caseStrMatch (header.mapName, map)) { else if (!strings.matches (header.mapName, map)) {
return false; return false;
} }
else { else {
@ -1693,9 +1692,9 @@ bool BotGraph::saveGraphData () {
void BotGraph::saveOldFormat () { void BotGraph::saveOldFormat () {
PODGraphHeader header {}; PODGraphHeader header {};
strcpy (header.header, kPodbotMagic); strings.copy (header.header, kPodbotMagic, sizeof (kPodbotMagic));
strncpy (header.author, m_editor->v.netname.chars (), cr::bufsize (header.author)); strings.copy (header.author, m_editor->v.netname.chars (), cr::bufsize (header.author));
strncpy (header.mapName, game.getMapName (), cr::bufsize (header.mapName)); strings.copy (header.mapName, game.getMapName (), cr::bufsize (header.mapName));
header.mapName[31] = 0; header.mapName[31] = 0;
header.fileVersion = StorageVersion::Podbot; header.fileVersion = StorageVersion::Podbot;
@ -1739,7 +1738,7 @@ float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Ve
} }
bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) { bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
TraceResult tr; TraceResult tr {};
float distance = (destination - src).length (); float distance = (destination - src).length ();
@ -1751,7 +1750,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", tr.pHit->v.classname.chars ()) == 0) { if (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
} }
@ -1759,7 +1758,7 @@ 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", tr.pHit->v.classname.chars (), 9) == 0) { if (tr.flFraction >= 1.0f || (tr.pHit && 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", tr.pHit->v.classname.chars (), 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);
@ -1827,7 +1826,7 @@ void BotGraph::rebuildVisibility () {
return; return;
} }
TraceResult tr; TraceResult tr {};
uint8 res, shift; uint8 res, shift;
for (const auto &vis : m_paths) { for (const auto &vis : m_paths) {
@ -2525,7 +2524,7 @@ void BotGraph::addBasic () {
Vector ladderRight = ent->v.absmax; Vector ladderRight = ent->v.absmax;
ladderLeft.z = ladderRight.z; ladderLeft.z = ladderRight.z;
TraceResult tr; TraceResult tr {};
Vector up, down, front, back; Vector up, down, front, back;
const Vector &diff = ((ladderLeft - ladderRight) ^ Vector (0.0f, 0.0f, 0.0f)).normalize () * 15.0f; const Vector &diff = ((ladderLeft - ladderRight) ^ Vector (0.0f, 0.0f, 0.0f)).normalize () * 15.0f;
@ -2650,7 +2649,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 (ent->v.model.chars () + 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;
} }
@ -2674,7 +2673,7 @@ void BotGraph::setSearchIndex (int index) {
} }
BotGraph::BotGraph () { BotGraph::BotGraph () {
memset (m_highestDamage, 0, sizeof (m_highestDamage)); plat.bzero (m_highestDamage, sizeof (m_highestDamage));
m_endJumpPoint = false; m_endJumpPoint = false;
m_needsVisRebuild = false; m_needsVisRebuild = false;

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// //
// This software is licensed under the BSD-style license. // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// https://yapb.ru/license //
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
// //
#include <yapb.h> #include <yapb.h>
@ -87,7 +86,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
// engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll // engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll
// functions this time (to use in the bot code). // functions this time (to use in the bot code).
memset (table, 0, sizeof (gamefuncs_t)); plat.bzero (table, sizeof (gamefuncs_t));
if (!(game.is (GameFlags::Metamod))) { if (!(game.is (GameFlags::Metamod))) {
auto api_GetEntityAPI = game.lib ().resolve <int (*) (gamefuncs_t *, int)> ("GetEntityAPI"); auto api_GetEntityAPI = game.lib ().resolve <int (*) (gamefuncs_t *, int)> ("GetEntityAPI");
@ -457,7 +456,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
// engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll // engine, and then calls the MOD DLL's version of GetEntityAPI to get the REAL gamedll
// functions this time (to use in the bot code). Post version, called only by metamod. // functions this time (to use in the bot code). Post version, called only by metamod.
memset (table, 0, sizeof (gamefuncs_t)); plat.bzero (table, sizeof (gamefuncs_t));
table->pfnSpawn = [] (edict_t *ent) { table->pfnSpawn = [] (edict_t *ent) {
// this function asks the game DLL to spawn (i.e, give a physical existence in the virtual // this function asks the game DLL to spawn (i.e, give a physical existence in the virtual
@ -505,7 +504,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) { CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
if (game.is (GameFlags::Metamod)) { if (game.is (GameFlags::Metamod)) {
memset (table, 0, sizeof (enginefuncs_t)); plat.bzero (table, sizeof (enginefuncs_t));
} }
table->pfnChangeLevel = [] (char *s1, char *s2) { table->pfnChangeLevel = [] (char *s1, char *s2) {
@ -811,7 +810,7 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
} }
CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) { CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
memset (table, 0, sizeof (enginefuncs_t)); plat.bzero (table, sizeof (enginefuncs_t));
table->pfnMessageEnd = [] () { table->pfnMessageEnd = [] () {
msgs.stop (); // this allows us to send messages right in handler code msgs.stop (); // this allows us to send messages right in handler code

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -273,7 +272,7 @@ void BotManager::frame () {
void BotManager::addbot (const String &name, int difficulty, int personality, int team, int member, bool manual) { void BotManager::addbot (const String &name, int difficulty, int personality, int team, int member, bool manual) {
// this function putting bot creation process to queue to prevent engine crashes // this function putting bot creation process to queue to prevent engine crashes
CreateQueue create; CreateQueue create {};
// fill the holder // fill the holder
create.name = name; create.name = name;
@ -290,7 +289,7 @@ void BotManager::addbot (const String &name, int difficulty, int personality, in
void BotManager::addbot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool manual) { void BotManager::addbot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool manual) {
// this function is same as the function above, but accept as parameters string instead of integers // this function is same as the function above, but accept as parameters string instead of integers
CreateQueue create; CreateQueue create {};
const String &any = "*"; const String &any = "*";
create.name = (name.empty () || name == any) ? String ("\0") : name; create.name = (name.empty () || name == any) ? String ("\0") : name;
@ -358,10 +357,10 @@ void BotManager::maintainQuota () {
int desiredBotCount = yb_quota.int_ (); int desiredBotCount = yb_quota.int_ ();
int botsInGame = getBotCount (); int botsInGame = getBotCount ();
if (plat.caseStrMatch (yb_quota_mode.str (), "fill")) { if (strings.matches (yb_quota_mode.str (), "fill")) {
botsInGame += humanPlayersInGame; botsInGame += humanPlayersInGame;
} }
else if (plat.caseStrMatch (yb_quota_mode.str (), "match")) { else if (strings.matches (yb_quota_mode.str (), "match")) {
int detectQuotaMatch = yb_quota_match.int_ () == 0 ? yb_quota.int_ () : yb_quota_match.int_ (); int detectQuotaMatch = yb_quota_match.int_ () == 0 ? yb_quota.int_ () : yb_quota_match.int_ ();
desiredBotCount = cr::max <int> (0, detectQuotaMatch * humanPlayersInGame); desiredBotCount = cr::max <int> (0, detectQuotaMatch * humanPlayersInGame);
@ -427,26 +426,26 @@ void BotManager::reset () {
void BotManager::initFilters () { void BotManager::initFilters () {
// table with all available actions for the bots (filtered in & out in bot::setconditions) some of them have subactions included // table with all available actions for the bots (filtered in & out in bot::setconditions) some of them have subactions included
m_filters.emplace (Task::Normal, 0.0f, kInvalidNodeIndex, 0.0f, true); m_filters.emplace (&Bot::normal_, Task::Normal, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::Pause, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::pause_, Task::Pause, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::MoveToPosition, 0.0f, kInvalidNodeIndex, 0.0f, true); m_filters.emplace (&Bot::moveToPos_, Task::MoveToPosition, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::FollowUser, 0.0f, kInvalidNodeIndex, 0.0f, true); m_filters.emplace (&Bot::followUser_, Task::FollowUser, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::PickupItem, 0.0f, kInvalidNodeIndex, 0.0f, true); m_filters.emplace (&Bot::pickupItem_, Task::PickupItem, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::Camp, 0.0f, kInvalidNodeIndex, 0.0f, true); m_filters.emplace (&Bot::camp_, Task::Camp, 0.0f, kInvalidNodeIndex, 0.0f, true);
m_filters.emplace (Task::PlantBomb, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::plantBomb_, Task::PlantBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::DefuseBomb, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::defuseBomb_, Task::DefuseBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Attack, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::attackEnemy_, Task::Attack, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Hunt, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::huntEnemy_, Task::Hunt, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::SeekCover, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::seekCover_, Task::SeekCover, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowExplosive, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::throwExplosive_, Task::ThrowExplosive, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowFlashbang, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::throwFlashbang_, Task::ThrowFlashbang, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ThrowSmoke, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::throwSmoke_, Task::ThrowSmoke, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::DoubleJump, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::doublejump_, Task::DoubleJump, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::EscapeFromBomb, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::escapeFromBomb_, Task::EscapeFromBomb, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::ShootBreakable, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::shootBreakable_, Task::ShootBreakable, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Hide, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::hide_, Task::Hide, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Blind, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::blind_, Task::Blind, 0.0f, kInvalidNodeIndex, 0.0f, false);
m_filters.emplace (Task::Spraypaint, 0.0f, kInvalidNodeIndex, 0.0f, false); m_filters.emplace (&Bot::spraypaint_, Task::Spraypaint, 0.0f, kInvalidNodeIndex, 0.0f, false);
} }
void BotManager::resetFilters () { void BotManager::resetFilters () {
@ -619,6 +618,26 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
return false; return false;
} }
void BotManager::setLastWinner (int winner) {
m_lastWinner = winner;
if (yb_radio_mode.int_ () != 2) {
return;
}
auto notify = findAliveBot ();
if (notify) {
if (notify->m_team == winner) {
if (getRoundMidTime () > game.time ()) {
notify->pushChatterMessage (Chatter::QuickWonRound);
}
else {
notify->pushChatterMessage (Chatter::WonTheRound);
}
}
}
}
void BotManager::setWeaponMode (int selection) { void BotManager::setWeaponMode (int selection) {
// this function sets bots weapon mode // this function sets bots weapon mode
@ -785,12 +804,13 @@ void BotManager::destroy () {
} }
Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) { Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
// this function does core operation of creating bot, it's called by CreateBot (), // this function does core operation of creating bot, it's called by addbot (),
// when bot setup completed, (this is a bot class constructor) // when bot setup completed, (this is a bot class constructor)
int clientIndex = game.indexOfEntity (bot); // we're not initializing all the variables in bot class, so do an ugly thing... memset this
plat.bzero (this, sizeof (*this));
memset (reinterpret_cast <void *> (this), 0, sizeof (*this)); int clientIndex = game.indexOfEntity (bot);
pev = &bot->v; pev = &bot->v;
if (bot->pvPrivateData != nullptr) { if (bot->pvPrivateData != nullptr) {
@ -881,8 +901,8 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
break; break;
} }
memset (&m_ammoInClip, 0, sizeof (m_ammoInClip)); plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip));
memset (&m_ammo, 0, sizeof (m_ammo)); plat.bzero (&m_ammo, sizeof (m_ammo));
m_currentWeapon = 0; // current weapon is not assigned at start m_currentWeapon = 0; // current weapon is not assigned at start
m_voicePitch = rg.int_ (80, 115); // assign voice pitch m_voicePitch = rg.int_ (80, 115); // assign voice pitch
@ -975,10 +995,10 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
for (const auto &notify : bots) { for (const auto &notify : bots) {
if (notify->m_notKilled && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) { if (notify->m_notKilled && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) {
if (!(killer->v.flags & FL_FAKECLIENT)) { if (!(killer->v.flags & FL_FAKECLIENT)) {
notify->handleChatter ("#Bot_NiceShotCommander"); notify->pushChatterMessage (Chatter::NiceShotCommander);
} }
else { else {
notify->handleChatter ("#Bot_NiceShotPall"); notify->pushChatterMessage (Chatter::NiceShotPall);
} }
break; break;
} }
@ -1179,8 +1199,8 @@ void Bot::newRound () {
// if bot died, clear all weapon stuff and force buying again // if bot died, clear all weapon stuff and force buying again
if (!m_notKilled) { if (!m_notKilled) {
memset (&m_ammoInClip, 0, sizeof (m_ammoInClip)); plat.bzero (&m_ammoInClip, sizeof (m_ammoInClip));
memset (&m_ammo, 0, sizeof (m_ammo)); plat.bzero (&m_ammo, sizeof (m_ammo));
m_currentWeapon = 0; m_currentWeapon = 0;
} }
@ -1339,7 +1359,7 @@ void BotManager::captureChatRadio (const char *cmd, const char *arg, edict_t *en
return; return;
} }
if (plat.caseStrMatch (cmd, "say") || plat.caseStrMatch (cmd, "say_team")) { if (strings.matches (cmd, "say") || strings.matches (cmd, "say_team")) {
bool alive = util.isAlive (ent); bool alive = util.isAlive (ent);
int team = -1; int team = -1;
@ -1414,7 +1434,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 (e->v.model.chars () + 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);
@ -1668,10 +1688,10 @@ void BotConfig::loadMainConfig () {
if (cvar != nullptr) { if (cvar != nullptr) {
auto value = const_cast <char *> (keyval[1].trim ().trim ("\"").trim ().chars ()); auto value = const_cast <char *> (keyval[1].trim ().trim ("\"").trim ().chars ());
if (needsToIgnoreVar (ignore, key) && !plat.caseStrMatch (value, cvar->string)) { if (needsToIgnoreVar (ignore, key) && !strings.matches (value, cvar->string)) {
// preserve quota number if it's zero // preserve quota number if it's zero
if (plat.caseStrMatch (cvar->name, "yb_quota") && yb_quota.int_ () <= 0) { if (strings.matches (cvar->name, "yb_quota") && yb_quota.int_ () <= 0) {
engfuncs.pfnCvar_DirectSet (cvar, value); engfuncs.pfnCvar_DirectSet (cvar, value);
continue; continue;
} }

View file

@ -1,10 +1,9 @@
// //
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd"). // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team. // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// //
// This software is licensed under the BSD-style license. // This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Additional exceptions apply. For full license details, see LICENSE.txt
// https://yapb.ru/license
// //
#include <yapb.h> #include <yapb.h>
@ -17,18 +16,6 @@ void MessageDispatcher::netMsgTextMsg () {
return; return;
} }
// bots chatter notification
const auto dispatchChatterMessage = [&] () -> void {
if (yb_radio_mode.int_ () == 2) {
auto notify = bots.findAliveBot ();
if (notify && notify->m_notKilled) {
notify->handleChatter (m_args[msg].chars_);
}
}
};
// lookup cached message // lookup cached message
auto cached = m_textMsgCache[m_args[msg].chars_]; auto cached = m_textMsgCache[m_args[msg].chars_];
@ -50,8 +37,6 @@ void MessageDispatcher::netMsgTextMsg () {
} }
else if (cached & TextMsgCache::CounterWin) { else if (cached & TextMsgCache::CounterWin) {
bots.setLastWinner (Team::CT); // update last winner for economics bots.setLastWinner (Team::CT); // update last winner for economics
dispatchChatterMessage ();
resetBombPosition (); resetBombPosition ();
} }
else if (cached & TextMsgCache::RestartRound) { else if (cached & TextMsgCache::RestartRound) {
@ -70,8 +55,6 @@ void MessageDispatcher::netMsgTextMsg () {
} }
else if (cached & TextMsgCache::TerroristWin) { else if (cached & TextMsgCache::TerroristWin) {
bots.setLastWinner (Team::Terrorist); // update last winner for economics bots.setLastWinner (Team::Terrorist); // update last winner for economics
dispatchChatterMessage ();
resetBombPosition (); resetBombPosition ();
} }
else if ((cached & TextMsgCache::BombPlanted) && !bots.isBombPlanted ()) { else if ((cached & TextMsgCache::BombPlanted) && !bots.isBombPlanted ()) {

View file

@ -1,10 +1,9 @@
//
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// //
// This software is licensed under the BSD-style license. // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// https://yapb.ru/license //
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
// //
#include <yapb.h> #include <yapb.h>
@ -19,7 +18,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 (ent->v.model.chars () + 9, "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)) {
@ -361,7 +360,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
m_isStuck = false; m_isStuck = false;
// if avoiding someone do not consider stuck // if avoiding someone do not consider stuck
TraceResult tr; TraceResult tr {};
doPlayerAvoidance (dirNormal); doPlayerAvoidance (dirNormal);
// Standing still, no need to check? // Standing still, no need to check?
@ -702,7 +701,7 @@ bool Bot::updateNavigation () {
return false; return false;
} }
} }
TraceResult tr; TraceResult tr {};
// check if we are going through a door... // check if we are going through a door...
if (game.mapIs (MapFlags::HasDoors)) { if (game.mapIs (MapFlags::HasDoors)) {
@ -849,7 +848,7 @@ bool Bot::updateLiftHandling () {
// update node time set // update node time set
m_navTimeset = game.time (); m_navTimeset = game.time ();
TraceResult tr; TraceResult tr {};
// wait for something about for lift // wait for something about for lift
auto wait = [&] () { auto wait = [&] () {
@ -867,7 +866,7 @@ bool Bot::updateLiftHandling () {
// trace line to door // trace line to door
game.testLine (pev->origin, m_path->origin, TraceIgnore::Everything, ent (), &tr); game.testLine (pev->origin, m_path->origin, TraceIgnore::Everything, ent (), &tr);
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 (tr.flFraction < 1.0f && tr.pHit && 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;
@ -1817,7 +1816,7 @@ int Bot::findDefendNode (const Vector &origin) {
if (m_currentNodeIndex == kInvalidNodeIndex) { if (m_currentNodeIndex == kInvalidNodeIndex) {
m_currentNodeIndex = changePointIndex (findNearestNode ()); m_currentNodeIndex = changePointIndex (findNearestNode ());
} }
TraceResult tr; TraceResult tr {};
int nodeIndex[kMaxNodeLinks]; int nodeIndex[kMaxNodeLinks];
int minDistance[kMaxNodeLinks]; int minDistance[kMaxNodeLinks];
@ -2016,7 +2015,7 @@ int Bot::findCoverNode (float maxDistance) {
} }
} while (sorting); } while (sorting);
TraceResult tr; TraceResult tr {};
// take the first one which isn't spotted by the enemy // take the first one which isn't spotted by the enemy
for (const auto &index : nodeIndex) { for (const auto &index : nodeIndex) {
@ -2073,7 +2072,7 @@ bool Bot::advanceMovement () {
if (m_pathWalk.empty ()) { if (m_pathWalk.empty ()) {
return false; return false;
} }
TraceResult tr; TraceResult tr {};
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)
@ -2392,7 +2391,7 @@ bool Bot::canStrafeRight (TraceResult *tr) {
bool Bot::canJumpUp (const Vector &normal) { bool Bot::canJumpUp (const Vector &normal) {
// this function check if bot can jump over some obstacle // this function check if bot can jump over some obstacle
TraceResult tr; TraceResult tr {};
// can't jump if not on ground and not on ladder/swimming // can't jump if not on ground and not on ladder/swimming
if (!isOnFloor () && (isOnLadder () || !isInWater ())) { if (!isOnFloor () && (isOnLadder () || !isInWater ())) {
@ -2472,7 +2471,7 @@ bool Bot::doneCanJumpUp (const Vector &normal, const Vector &right) {
Vector src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 63.0f); Vector src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 63.0f);
Vector dest = src + normal * 32.0f; Vector dest = src + normal * 32.0f;
TraceResult tr; TraceResult tr {};
// trace a line forward at maximum jump height... // trace a line forward at maximum jump height...
game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr); game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr);
@ -2541,7 +2540,7 @@ bool Bot::doneCanJumpUp (const Vector &normal, const Vector &right) {
bool Bot::canDuckUnder (const Vector &normal) { bool Bot::canDuckUnder (const Vector &normal) {
// this function check if bot can duck under obstacle // this function check if bot can duck under obstacle
TraceResult tr; TraceResult tr {};
Vector baseHeight; Vector baseHeight;
// use center of the body first... // use center of the body first...
@ -2590,7 +2589,7 @@ bool Bot::canDuckUnder (const Vector &normal) {
} }
bool Bot::isBlockedLeft () { bool Bot::isBlockedLeft () {
TraceResult tr; TraceResult tr {};
float direction = 48.0f; float direction = 48.0f;
if (m_moveSpeed < 0.0f) { if (m_moveSpeed < 0.0f) {
@ -2603,14 +2602,14 @@ 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", tr.pHit->v.classname.chars (), 9) != 0) { if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && tr.pHit && 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;
} }
bool Bot::isBlockedRight () { bool Bot::isBlockedRight () {
TraceResult tr; TraceResult tr {};
float direction = 48.0f; float direction = 48.0f;
if (m_moveSpeed < 0.0f) { if (m_moveSpeed < 0.0f) {
@ -2623,14 +2622,14 @@ 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", tr.pHit->v.classname.chars (), 9) != 0)) { if (game.mapIs (MapFlags::HasDoors) && tr.flFraction < 1.0f && tr.pHit && 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;
} }
bool Bot::checkWallOnLeft () { bool Bot::checkWallOnLeft () {
TraceResult tr; TraceResult tr {};
game.testLine (pev->origin, pev->origin - pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr); game.testLine (pev->origin, pev->origin - pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something... // check if the trace hit something...
@ -2641,7 +2640,7 @@ bool Bot::checkWallOnLeft () {
} }
bool Bot::checkWallOnRight () { bool Bot::checkWallOnRight () {
TraceResult tr; TraceResult tr {};
// do a trace to the right... // do a trace to the right...
game.testLine (pev->origin, pev->origin + pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr); game.testLine (pev->origin, pev->origin + pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
@ -2656,7 +2655,7 @@ bool Bot::checkWallOnRight () {
bool Bot::isDeadlyMove (const Vector &to) { bool Bot::isDeadlyMove (const Vector &to) {
// this function eturns if given location would hurt Bot with falling damage // this function eturns if given location would hurt Bot with falling damage
TraceResult tr; TraceResult tr {};
const auto &direction = (to - pev->origin).normalize (); // 1 unit long const auto &direction = (to - pev->origin).normalize (); // 1 unit long
Vector check = to, down = to; Vector check = to, down = to;
@ -2984,7 +2983,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 (ent->v.model.chars () + 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)) {
@ -3077,7 +3076,7 @@ bool Bot::isReachableNode (int index) {
} }
float ladderDist = (dst - src).length2d (); float ladderDist = (dst - src).length2d ();
TraceResult tr; TraceResult tr {};
game.testLine (src, dst, TraceIgnore::Monsters, ent (), &tr); game.testLine (src, dst, TraceIgnore::Monsters, ent (), &tr);
// if node is visible from current position (even behind head)... // if node is visible from current position (even behind head)...

View file

@ -1,9 +1,9 @@
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
// //
// This software is licensed under the BSD-style license. // Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: // Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
// https://yapb.ru/license //
// This software is licensed under the MIT license.
// Additional exceptions apply. For full license details, see LICENSE.txt
// //
#include <yapb.h> #include <yapb.h>
@ -115,7 +115,7 @@ bool BotUtils::isVisible (const Vector &origin, edict_t *ent) {
if (game.isNullEntity (ent)) { if (game.isNullEntity (ent)) {
return false; return false;
} }
TraceResult tr; TraceResult tr {};
game.testLine (ent->v.origin + ent->v.view_ofs, origin, TraceIgnore::Everything, ent, &tr); game.testLine (ent->v.origin + ent->v.view_ofs, origin, TraceIgnore::Everything, ent, &tr);
if (tr.flFraction != 1.0f) { if (tr.flFraction != 1.0f) {