build: reworked build and package to simplify process
build: reworked build and package to simplify process build: windows dll is now compiled by clang, msvc build added to extras package fix: clear all the implicit conversions in the code (also fixed some bugs) fix: crash on never xash3d-fwgs engine fix: fixed bad bot behaviors on aarch64 fix: crash on some maps due to missing previous node fix: finally removed memset(this) within bot creatin
This commit is contained in:
parent
ae4e12c48c
commit
53df621dfc
35 changed files with 1004 additions and 949 deletions
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -1,30 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: jeefo
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Video**
|
||||
If it's problem with AI behaviour, add video to help explain your problem.
|
||||
|
||||
**Environment details:**
|
||||
- OS: [e.g. windows 10 / linux debian 10.4]
|
||||
- Engine: [e.g. rehlds 3.8.0.702 / vanilla 8684]
|
||||
- GameDLL: [e.g. regamedll 5.18.0.479 / vanilla]
|
||||
- Metamod: [e.g. metamod-r / metamod-p / metamod]
|
||||
- Bot Version: [e.g. 4.1.566]
|
||||
- Game mode: [e.g. csdm / public / zombie]
|
||||
|
||||
Additionally, please provide list of AMX Mod X plugins: ``amxx plugins`` and list of Metamod plugins: ``meta plugins``.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
145
.github/workflows/build.yml
vendored
145
.github/workflows/build.yml
vendored
|
|
@ -12,117 +12,84 @@ on:
|
|||
types: [published]
|
||||
|
||||
jobs:
|
||||
unix:
|
||||
bot-build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: j4sdk/x86-buildtools:lunar
|
||||
options: --hostname github-actions
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: linux-x86
|
||||
bin: yapb.so
|
||||
opts: CXX=gcc-11 CXX_LD=gold meson setup build
|
||||
|
||||
- name: macos-x86
|
||||
bin: yapb.dylib
|
||||
opts: meson setup build --cross-file=x86-darwin
|
||||
|
||||
name: ${{ matrix.name }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
container: j4sdk/x86-buildtools:latest
|
||||
arch: ['linux-x86', 'linux-x86-gcc', 'linux-aarch64', 'darwin-x86', 'windows-x86', 'windows-x86-gcc']
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Configure Build
|
||||
- name: Configure meson
|
||||
shell: bash
|
||||
run: |
|
||||
${{ matrix.opts }}
|
||||
|
||||
- name: Compile Source
|
||||
if [[ ${{matrix.arch}} == linux-x86 ]]; then
|
||||
CXX=clang CXX_LD=lld meson setup ${{matrix.arch}}
|
||||
elif [[ ${{matrix.arch}} == linux-x86-gcc ]]; then
|
||||
CXX=gcc CXX_LD=gold meson setup ${{matrix.arch}}
|
||||
else
|
||||
meson setup ${{matrix.arch}}/ --cross-file ${{matrix.arch}}
|
||||
fi
|
||||
- name: Build sources
|
||||
shell: bash
|
||||
run: |
|
||||
meson compile -v -C build
|
||||
|
||||
- name: Upload Artifacts
|
||||
meson compile -C ${{matrix.arch}}
|
||||
echo "artifcat=${{matrix.arch}}/`ls ${{matrix.arch}}/ | egrep '^yapb.(so|dylib|dll)$' | head -1`" >> $GITHUB_ENV
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.bin }}
|
||||
path: build/${{ matrix.bin }}
|
||||
name: ${{matrix.arch}}
|
||||
path: ${{env.artifcat}}
|
||||
|
||||
windows:
|
||||
name: windows-x86
|
||||
runs-on: windows-2022
|
||||
bot-msvc:
|
||||
env:
|
||||
name: windows-x86-msvc
|
||||
|
||||
name: bot-build (windows-x86-msvc)
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Setup MSBuild
|
||||
- name: Setup msbuild
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: amd64_x86
|
||||
|
||||
- name: Setup Meson
|
||||
- name: Install meson
|
||||
run: |
|
||||
python -m pip install --upgrade meson ninja
|
||||
|
||||
- name: Configure Build
|
||||
- name: Configure meson
|
||||
run: |
|
||||
meson setup build
|
||||
|
||||
- name: Compile Source
|
||||
meson setup ${{env.name}}
|
||||
- name: Build sources
|
||||
run: |
|
||||
meson compile -v -C build
|
||||
|
||||
- name: Upload Artifacts
|
||||
meson compile -C ${{env.name}}
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: yapb.dll
|
||||
path: build/yapb.dll
|
||||
name: ${{env.name}}
|
||||
path: ${{env.name}}/yapb.dll
|
||||
|
||||
linux-arm64:
|
||||
name: linux-arm64
|
||||
|
||||
runs-on: self-hosted
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Configure Build
|
||||
run: |
|
||||
CXX=clang-12 CXX_LD=lld-12 meson setup build
|
||||
|
||||
- name: Compile Source
|
||||
run: |
|
||||
meson compile -v -C build
|
||||
|
||||
- name: Rename Binary
|
||||
run: |
|
||||
mv build/yapb.so build/yapb.arm64.so
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: yapb.arm64.so
|
||||
path: build/yapb.arm64.so
|
||||
|
||||
publish:
|
||||
bot-release:
|
||||
if: |
|
||||
github.event_name == 'release' &&
|
||||
github.event.action == 'published'
|
||||
|
||||
name: publish
|
||||
name: bot-release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [unix, windows, linux-arm64]
|
||||
needs: [bot-build, bot-msvc]
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
|
|
@ -130,38 +97,32 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Signing Tools
|
||||
- name: Install signing tools
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get upgrade -y
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends osslsigncode
|
||||
|
||||
- name: Get Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Setup Meson
|
||||
- name: Configure meson
|
||||
run: |
|
||||
python -m pip install --upgrade meson ninja urllib3
|
||||
|
||||
- name: Create Packages
|
||||
python -m pip install --upgrade meson ninja requests
|
||||
- name: Create packages
|
||||
run: |
|
||||
meson setup dist
|
||||
ninja -C dist package
|
||||
env:
|
||||
CS_CERTIFICATE: ${{ secrets.CS_CERTIFICATE }}
|
||||
CS_CERTIFICATE_PASSWORD: ${{ secrets.CS_CERTIFICATE_PASSWORD }}
|
||||
|
||||
- name: Publish Release
|
||||
CS_CERTIFICATE: ${{secrets.CS_CERTIFICATE}}
|
||||
CS_CERTIFICATE_PASSWORD: ${{secrets.CS_CERTIFICATE_PASSWORD}}
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: pkg/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.API_TOKEN }}
|
||||
GITHUB_TOKEN: ${{secrets.API_TOKEN}}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,13 @@ yb_walking_allowed "1"
|
|||
//
|
||||
yb_camping_allowed "1"
|
||||
|
||||
//
|
||||
// Allows bots to partially avoid grenades.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_avoid_grenades "1"
|
||||
|
||||
//
|
||||
// Lower bound of time from which time for camping is calculated
|
||||
// ---
|
||||
|
|
@ -130,6 +137,13 @@ yb_destroy_breakables_around "1"
|
|||
//
|
||||
yb_object_pickup_radius "450.0"
|
||||
|
||||
//
|
||||
// The radius on which bot destroy breakables around it, when not touching with them.
|
||||
// ---
|
||||
// Default: "400.0", Min: "64.0", Max: "1024.0"
|
||||
//
|
||||
yb_object_destroy_radius "400.0"
|
||||
|
||||
//
|
||||
// Specifies the paths for the bot chatter sound files.
|
||||
// ---
|
||||
|
|
@ -158,6 +172,13 @@ yb_attack_monsters "0"
|
|||
//
|
||||
yb_pickup_custom_items "0"
|
||||
|
||||
//
|
||||
// Allows or disallows bots to pickup best weapons.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_pickup_best "1"
|
||||
|
||||
//
|
||||
// Allows or disallows bots to do map objectives, i.e. plant/defuse bombs, and saves hostages.
|
||||
// ---
|
||||
|
|
@ -268,19 +289,40 @@ yb_password_key "_ybpw"
|
|||
//
|
||||
yb_csdm_mode "0"
|
||||
|
||||
//
|
||||
// Specifies the maximum health of breakable object, that bot will consider to destroy.
|
||||
// ---
|
||||
// Default: "500.0", Min: "1.0", Max: "3000.0"
|
||||
//
|
||||
yb_breakable_health_limit "500.0"
|
||||
|
||||
//
|
||||
// Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_graph_fixcamp "1"
|
||||
yb_graph_fixcamp "0"
|
||||
|
||||
//
|
||||
// Specifies the URL from bots will be able to download graph in case of missing local one. Set to empty, if no downloads needed.
|
||||
// ---
|
||||
// Default: "yapb.jeefo.net"
|
||||
//
|
||||
yb_graph_url "yapb.jeefo.net"
|
||||
yb_graph_url "yapb-gcdn.akamaized.net"
|
||||
|
||||
//
|
||||
// Every N graph nodes placed on map, the graph will be saved automatically (without checks).
|
||||
// ---
|
||||
// Default: "15", Min: "0", Max: "2048"
|
||||
//
|
||||
yb_graph_auto_save_count "15"
|
||||
|
||||
//
|
||||
// Maximum distance to draw graph nodes from editor viewport.
|
||||
// ---
|
||||
// Default: "400", Min: "64", Max: "3072"
|
||||
//
|
||||
yb_graph_draw_distance "400"
|
||||
|
||||
//
|
||||
// Kick bots to automatically make room for human players.
|
||||
|
|
@ -289,6 +331,13 @@ yb_graph_url "yapb.jeefo.net"
|
|||
//
|
||||
yb_autovacate "1"
|
||||
|
||||
//
|
||||
// Kick the bot immediately when a human player joins the server (yb_autovacate must be enabled).
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_kick_after_player_connect "1"
|
||||
|
||||
//
|
||||
// Specifies the number bots to be added to the game.
|
||||
// ---
|
||||
|
|
@ -402,7 +451,7 @@ yb_show_avatars "1"
|
|||
yb_show_latency "2"
|
||||
|
||||
//
|
||||
// Allows to save bot names upon changelevel, so bot names will be the same after a map change
|
||||
// Allows to save bot names upon changelevel, so bot names will be the same after a map change.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
|
|
@ -436,6 +485,20 @@ yb_ping_base_min "7"
|
|||
//
|
||||
yb_ping_base_max "34"
|
||||
|
||||
//
|
||||
// Interval in which bots are added to the game.
|
||||
// ---
|
||||
// Default: "0.1", Min: "0.1", Max: "1.0"
|
||||
//
|
||||
yb_quota_adding_interval "0.1"
|
||||
|
||||
//
|
||||
// Interval on which overall bot quota are checked.
|
||||
// ---
|
||||
// Default: "0.4", Min: "0.4", Max: "2.0"
|
||||
//
|
||||
yb_quota_maintain_interval "0.4"
|
||||
|
||||
//
|
||||
// Specifies the language for bot messages and menus.
|
||||
// ---
|
||||
|
|
@ -443,6 +506,27 @@ yb_ping_base_max "34"
|
|||
//
|
||||
yb_language "en"
|
||||
|
||||
//
|
||||
// Randomly disconnect and connect bots, simulating players join/quit.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_rotate_bots "0"
|
||||
|
||||
//
|
||||
// Specifies minimum amount of seconds bot keep connected, if rotation active.
|
||||
// ---
|
||||
// Default: "360.0", Min: "120.0", Max: "7200.0"
|
||||
//
|
||||
yb_rotate_stay_min "360.0"
|
||||
|
||||
//
|
||||
// Specifies maximum amount of seconds bot keep connected, if rotation active.
|
||||
// ---
|
||||
// Default: "3600.0", Min: "1800.0", Max: "14400.0"
|
||||
//
|
||||
yb_rotate_stay_max "3600.0"
|
||||
|
||||
//
|
||||
// Enables or disables extra hard difficulty for bots.
|
||||
// ---
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 19242b19194bf39dc97a5d51d27bd1f60f701597
|
||||
Subproject commit dade2ade585d7fbd3ac91dec93cd70c92225e832
|
||||
22
inc/config.h
22
inc/config.h
|
|
@ -38,20 +38,20 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
Array <StringArray> m_chat;
|
||||
Array <Array <ChatterItem>> m_chatter;
|
||||
Array <StringArray> m_chat {};
|
||||
Array <Array <ChatterItem>> m_chatter {};
|
||||
|
||||
Array <BotName> m_botNames;
|
||||
Array <Keywords> m_replies;
|
||||
SmallArray <WeaponInfo> m_weapons;
|
||||
SmallArray <WeaponProp> m_weaponProps;
|
||||
Array <BotName> m_botNames {};
|
||||
Array <Keywords> m_replies {};
|
||||
SmallArray <WeaponInfo> m_weapons {};
|
||||
SmallArray <WeaponProp> m_weaponProps {};
|
||||
|
||||
StringArray m_logos;
|
||||
StringArray m_avatars;
|
||||
StringArray m_logos {};
|
||||
StringArray m_avatars {};
|
||||
|
||||
HashMap <uint32, String, Hash <int32>> m_language;
|
||||
HashMap <int32, DifficultyData> m_difficulty;
|
||||
HashMap <String, String> m_custom;
|
||||
HashMap <uint32, String, Hash <int32>> m_language {};
|
||||
HashMap <int32, DifficultyData> m_difficulty {};
|
||||
HashMap <String, String> m_custom {};
|
||||
|
||||
// default tables for personality weapon preferences, overridden by weapon.cfg
|
||||
SmallArray <int32> m_normalWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 12, 10, 24, 25, 13, 11, 8, 7, 22, 23, 18, 21, 17, 19, 15, 17, 9, 14, 16 };
|
||||
|
|
|
|||
|
|
@ -63,21 +63,21 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
StringArray m_args;
|
||||
Array <BotCmd> m_cmds;
|
||||
Array <BotMenu> m_menus;
|
||||
Deque <PrintQueue> m_printQueue;
|
||||
IntArray m_campIterator;
|
||||
StringArray m_args {};
|
||||
Array <BotCmd> m_cmds {};
|
||||
Array <BotMenu> m_menus {};
|
||||
Deque <PrintQueue> m_printQueue {};
|
||||
IntArray m_campIterator {};
|
||||
|
||||
edict_t *m_ent;
|
||||
Bot *m_djump;
|
||||
edict_t *m_ent {};
|
||||
Bot *m_djump {};
|
||||
|
||||
bool m_isFromConsole;
|
||||
bool m_rapidOutput;
|
||||
bool m_isMenuFillCommand;
|
||||
bool m_ignoreTranslate;
|
||||
bool m_isFromConsole {};
|
||||
bool m_rapidOutput {};
|
||||
bool m_isMenuFillCommand {};
|
||||
bool m_ignoreTranslate {};
|
||||
|
||||
int m_menuServerFillTeam;
|
||||
int m_menuServerFillTeam {};
|
||||
int m_interMenuData[4] = { 0, };
|
||||
|
||||
float m_printQueueFlushTimestamp {};
|
||||
|
|
|
|||
42
inc/engine.h
42
inc/engine.h
|
|
@ -112,27 +112,27 @@ public:
|
|||
using EntitySearch = Lambda <EntitySearchResult (edict_t *)>;
|
||||
|
||||
private:
|
||||
int m_drawModels[DrawLine::Count] { };
|
||||
int m_spawnCount[Team::Unassigned] { };
|
||||
int m_drawModels[DrawLine::Count] {};
|
||||
int m_spawnCount[Team::Unassigned] {};
|
||||
|
||||
// bot client command
|
||||
StringArray m_botArgs;
|
||||
StringArray m_botArgs {};
|
||||
|
||||
edict_t *m_startEntity;
|
||||
edict_t *m_localEntity;
|
||||
edict_t *m_startEntity {};
|
||||
edict_t *m_localEntity {};
|
||||
|
||||
Array <edict_t *> m_breakables;
|
||||
SmallArray <ConVarReg> m_cvars;
|
||||
SharedLibrary m_gameLib;
|
||||
EngineWrap m_engineWrap;
|
||||
Array <edict_t *> m_breakables {};
|
||||
SmallArray <ConVarReg> m_cvars {};
|
||||
SharedLibrary m_gameLib {};
|
||||
EngineWrap m_engineWrap {};
|
||||
|
||||
bool m_precached;
|
||||
bool m_precached {};
|
||||
|
||||
int m_gameFlags {};
|
||||
int m_mapFlags {};
|
||||
|
||||
float m_oneSecondFrame; // per second updated
|
||||
float m_halfSecondFrame; // per half second update
|
||||
float m_oneSecondFrame {}; // per second updated
|
||||
float m_halfSecondFrame {}; // per half second update
|
||||
|
||||
public:
|
||||
Game ();
|
||||
|
|
@ -240,8 +240,8 @@ public:
|
|||
}
|
||||
|
||||
// gets custom engine argv for client command
|
||||
const char *botArgv (size_t index) const {
|
||||
if (index >= m_botArgs.length ()) {
|
||||
const char *botArgv (int32 index) const {
|
||||
if (static_cast <size_t> (index) >= m_botArgs.length ()) {
|
||||
return "";
|
||||
}
|
||||
return m_botArgs[index].chars ();
|
||||
|
|
@ -517,7 +517,7 @@ public:
|
|||
class LightMeasure final : public Singleton <LightMeasure> {
|
||||
private:
|
||||
lightstyle_t m_lightstyle[MAX_LIGHTSTYLES] {};
|
||||
int m_lightstyleValue[MAX_LIGHTSTYLEVALUE] {};
|
||||
uint32 m_lightstyleValue[MAX_LIGHTSTYLEVALUE] {};
|
||||
bool m_doAnimation = false;
|
||||
|
||||
Color m_point;
|
||||
|
|
@ -563,8 +563,8 @@ public:
|
|||
|
||||
// simple handler for parsing and rewriting queries (fake queries)
|
||||
class QueryBuffer {
|
||||
SmallArray <uint8> m_buffer;
|
||||
size_t m_cursor;
|
||||
SmallArray <uint8> m_buffer {};
|
||||
size_t m_cursor {};
|
||||
|
||||
public:
|
||||
QueryBuffer (const uint8 *msg, size_t length, size_t shift) : m_cursor (0) {
|
||||
|
|
@ -640,7 +640,7 @@ private:
|
|||
#if defined (CR_WINDOWS)
|
||||
# define DLSYM_FUNCTION GetProcAddress
|
||||
# define DLCLOSE_FUNCTION FreeLibrary
|
||||
# define DLSYM_RETURN PVOID
|
||||
# define DLSYM_RETURN SharedLibrary::Handle
|
||||
# define DLSYM_HANDLE HMODULE
|
||||
#else
|
||||
# define DLSYM_FUNCTION dlsym
|
||||
|
|
@ -654,7 +654,7 @@ private:
|
|||
|
||||
Detour <decltype (DLSYM_FUNCTION)> m_dlsym;
|
||||
Detour <decltype (DLCLOSE_FUNCTION)> m_dlclose;
|
||||
HashMap <StringRef, DLSYM_RETURN> m_exports;
|
||||
HashMap <StringRef, SharedLibrary::Func> m_exports;
|
||||
|
||||
SharedLibrary m_self;
|
||||
|
||||
|
|
@ -663,7 +663,7 @@ public:
|
|||
|
||||
public:
|
||||
void initialize ();
|
||||
DLSYM_RETURN lookup (SharedLibrary::Handle module, const char *function);
|
||||
SharedLibrary::Func lookup (SharedLibrary::Handle module, const char *function);
|
||||
|
||||
int close (DLSYM_HANDLE module) {
|
||||
if (m_self.handle () == module) {
|
||||
|
|
@ -701,7 +701,7 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
static DLSYM_RETURN CR_STDCALL lookupHandler (SharedLibrary::Handle module, const char *function) {
|
||||
static SharedLibrary::Func CR_STDCALL lookupHandler (SharedLibrary::Handle module, const char *function) {
|
||||
return EntityLinkage::instance ().lookup (module, function);
|
||||
}
|
||||
|
||||
|
|
|
|||
77
inc/graph.h
77
inc/graph.h
|
|
@ -186,10 +186,10 @@ struct PODPath {
|
|||
// this structure links nodes returned from pathfinder
|
||||
class PathWalk final : public DenyCopying {
|
||||
private:
|
||||
size_t m_cursor = 0;
|
||||
size_t m_length = 0;
|
||||
size_t m_cursor {};
|
||||
size_t m_length {};
|
||||
|
||||
UniquePtr <int32[]> m_path;
|
||||
UniquePtr <int32[]> m_path {};
|
||||
|
||||
public:
|
||||
explicit PathWalk () = default;
|
||||
|
|
@ -263,60 +263,59 @@ private:
|
|||
int x, y, z;
|
||||
};
|
||||
|
||||
int m_editFlags;
|
||||
int m_loadAttempts;
|
||||
int m_cacheNodeIndex;
|
||||
int m_lastJumpNode;
|
||||
int m_findWPIndex;
|
||||
int m_facingAtIndex;
|
||||
int m_editFlags {};
|
||||
int m_loadAttempts {};
|
||||
int m_cacheNodeIndex {};
|
||||
int m_lastJumpNode {};
|
||||
int m_findWPIndex {};
|
||||
int m_facingAtIndex {};
|
||||
int m_highestDamage[kGameTeamNum] {};
|
||||
int m_autoSaveCount;
|
||||
int m_autoSaveCount {};
|
||||
|
||||
float m_timeJumpStarted;
|
||||
float m_autoPathDistance;
|
||||
float m_pathDisplayTime;
|
||||
float m_arrowDisplayTime;
|
||||
float m_timeJumpStarted {};
|
||||
float m_autoPathDistance {};
|
||||
float m_pathDisplayTime {};
|
||||
float m_arrowDisplayTime {};
|
||||
|
||||
bool m_isOnLadder;
|
||||
bool m_endJumpPoint;
|
||||
bool m_jumpLearnNode;
|
||||
bool m_hasChanged;
|
||||
bool m_needsVisRebuild;
|
||||
bool m_narrowChecked;
|
||||
bool m_isOnLadder {};
|
||||
bool m_endJumpPoint {};
|
||||
bool m_jumpLearnNode {};
|
||||
bool m_hasChanged {};
|
||||
bool m_needsVisRebuild {};
|
||||
bool m_narrowChecked {};
|
||||
|
||||
Vector m_learnVelocity;
|
||||
Vector m_learnPosition;
|
||||
Vector m_bombOrigin;
|
||||
Vector m_lastNode;
|
||||
Vector m_learnVelocity {};
|
||||
Vector m_learnPosition {};
|
||||
Vector m_bombOrigin {};
|
||||
Vector m_lastNode {};
|
||||
|
||||
IntArray m_terrorPoints;
|
||||
IntArray m_ctPoints;
|
||||
IntArray m_goalPoints;
|
||||
IntArray m_campPoints;
|
||||
IntArray m_sniperPoints;
|
||||
IntArray m_rescuePoints;
|
||||
IntArray m_visitedGoals;
|
||||
IntArray m_terrorPoints {};
|
||||
IntArray m_ctPoints {};
|
||||
IntArray m_goalPoints {};
|
||||
IntArray m_campPoints {};
|
||||
IntArray m_sniperPoints {};
|
||||
IntArray m_rescuePoints {};
|
||||
IntArray m_visitedGoals {};
|
||||
|
||||
SmallArray <int32> m_buckets[kMaxBucketsInsidePos][kMaxBucketsInsidePos][kMaxBucketsInsidePos];
|
||||
SmallArray <Matrix> m_matrix;
|
||||
SmallArray <Practice> m_practice;
|
||||
SmallArray <Path> m_paths;
|
||||
SmallArray <uint8> m_vistable;
|
||||
SmallArray <Matrix> m_matrix {};
|
||||
SmallArray <Practice> m_practice {};
|
||||
SmallArray <Path> m_paths {};
|
||||
SmallArray <uint8> m_vistable {};
|
||||
|
||||
String m_graphAuthor;
|
||||
String m_graphModified;
|
||||
String m_graphAuthor {};
|
||||
String m_graphModified {};
|
||||
|
||||
ExtenHeader m_extenHeader {};
|
||||
StorageHeader m_graphHeader {};
|
||||
|
||||
edict_t *m_editor;
|
||||
edict_t *m_editor {};
|
||||
|
||||
public:
|
||||
BotGraph ();
|
||||
~BotGraph () = default;
|
||||
|
||||
public:
|
||||
|
||||
int getFacingIndex ();
|
||||
int getFarest (const Vector &origin, float maxDistance = 32.0);
|
||||
int getNearest (const Vector &origin, float minDistance = kInfiniteDistance, int flags = -1);
|
||||
|
|
|
|||
|
|
@ -54,13 +54,13 @@ public:
|
|||
using UniqueBot = UniquePtr <Bot>;
|
||||
|
||||
private:
|
||||
float m_timeRoundStart;
|
||||
float m_timeRoundEnd;
|
||||
float m_timeRoundMid;
|
||||
float m_timeRoundStart {};
|
||||
float m_timeRoundEnd {};
|
||||
float m_timeRoundMid {};
|
||||
|
||||
float m_autoKillCheckTime; // time to kill all the bots ?
|
||||
float m_maintainTime; // time to maintain bot creation
|
||||
float m_quotaMaintainTime; // time to maintain bot quota
|
||||
float m_autoKillCheckTime {}; // time to kill all the bots ?
|
||||
float m_maintainTime {}; // time to maintain bot creation
|
||||
float m_quotaMaintainTime {}; // time to maintain bot quota
|
||||
float m_grenadeUpdateTime {}; // time to update active grenades
|
||||
float m_entityUpdateTime {}; // time to update intresting entities
|
||||
float m_plantSearchUpdateTime {}; // time to update for searching planted bomb
|
||||
|
|
@ -68,26 +68,26 @@ private:
|
|||
float m_timeBombPlanted {}; // time the bomb were planted
|
||||
float m_lastRadioTime[kGameTeamNum] {}; // global radio time
|
||||
|
||||
int m_lastWinner; // the team who won previous round
|
||||
int m_lastDifficulty; // last bots difficulty
|
||||
int m_bombSayStatus; // some bot is issued whine about bomb
|
||||
int m_lastWinner {}; // the team who won previous round
|
||||
int m_lastDifficulty {}; // last bots difficulty
|
||||
int m_bombSayStatus {}; // some bot is issued whine about bomb
|
||||
int m_lastRadio[kGameTeamNum] {}; // last radio message for team
|
||||
|
||||
bool m_leaderChoosen[kGameTeamNum] {}; // is team leader choose theese round
|
||||
bool m_economicsGood[kGameTeamNum] {}; // is team able to buy anything
|
||||
bool m_bombPlanted;
|
||||
bool m_botsCanPause;
|
||||
bool m_roundOver;
|
||||
bool m_bombPlanted {};
|
||||
bool m_botsCanPause {};
|
||||
bool m_roundOver {};
|
||||
|
||||
Array <edict_t *> m_activeGrenades; // holds currently active grenades on the map
|
||||
Array <edict_t *> m_intrestingEntities; // holds currently intresting entities on the map
|
||||
Array <edict_t *> m_activeGrenades {}; // holds currently active grenades on the map
|
||||
Array <edict_t *> m_intrestingEntities {}; // holds currently intresting entities on the map
|
||||
|
||||
Deque <String> m_saveBotNames; // bots names that persist upon changelevel
|
||||
Deque <BotRequest> m_addRequests; // bot creation tab
|
||||
SmallArray <BotTask> m_filters; // task filters
|
||||
SmallArray <UniqueBot> m_bots; // all available bots
|
||||
Deque <String> m_saveBotNames {}; // bots names that persist upon changelevel
|
||||
Deque <BotRequest> m_addRequests {}; // bot creation tab
|
||||
SmallArray <BotTask> m_filters {}; // task filters
|
||||
SmallArray <UniqueBot> m_bots {}; // all available bots
|
||||
|
||||
edict_t *m_killerEntity; // killer entity for bots
|
||||
edict_t *m_killerEntity {}; // killer entity for bots
|
||||
FrustumData m_frustumData {};
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -82,22 +82,22 @@ private:
|
|||
};
|
||||
|
||||
private:
|
||||
HashMap <String, int32> m_textMsgCache; // cache strings for faster access for textmsg
|
||||
HashMap <String, int32> m_showMenuCache; // cache for the showmenu message
|
||||
HashMap <String, int32> m_statusIconCache; // cache for status icon message
|
||||
HashMap <String, int32> m_teamInfoCache; // cache for teaminfo message
|
||||
HashMap <String, int32> m_textMsgCache {}; // cache strings for faster access for textmsg
|
||||
HashMap <String, int32> m_showMenuCache {}; // cache for the showmenu message
|
||||
HashMap <String, int32> m_statusIconCache {}; // cache for status icon message
|
||||
HashMap <String, int32> m_teamInfoCache {}; // cache for teaminfo message
|
||||
|
||||
private:
|
||||
Bot *m_bot {}; // owner of a message
|
||||
NetMsg m_current {}; // ongoing message id
|
||||
|
||||
SmallArray <Args> m_args; // args collected from write* functions
|
||||
SmallArray <Args> m_args {}; // args collected from write* functions
|
||||
|
||||
HashMap <String, NetMsg> m_wanted; // wanted messages
|
||||
HashMap <int32, NetMsg> m_reverseMap; // maps engine message id to our message id
|
||||
HashMap <String, NetMsg> m_wanted {}; // wanted messages
|
||||
HashMap <int32, NetMsg> m_reverseMap {}; // maps engine message id to our message id
|
||||
|
||||
HashMap <NetMsg, int32, MsgHash> m_maps; // maps our message to id to engine message id
|
||||
HashMap <NetMsg, MsgFunc, MsgHash> m_handlers; // maps our message id to handler function
|
||||
HashMap <NetMsg, int32, MsgHash> m_maps {}; // maps our message to id to engine message id
|
||||
HashMap <NetMsg, MsgFunc, MsgHash> m_handlers {}; // maps our message id to handler function
|
||||
|
||||
private:
|
||||
void netMsgTextMsg ();
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@
|
|||
class Product final : public Singleton <Product> {
|
||||
public:
|
||||
struct Build {
|
||||
StringRef hash { MODULE_BUILD_HASH };
|
||||
StringRef author { MODULE_BUILD_AUTHOR };
|
||||
StringRef count { MODULE_BUILD_COUNT };
|
||||
StringRef machine { MODULE_BUILD_MACHINE };
|
||||
StringRef compiler { MODULE_BUILD_COMPILER };
|
||||
StringRef id { MODULE_BOT_BUILD_ID };
|
||||
} build { };
|
||||
StringRef hash { MODULE_COMMIT_COUNT };
|
||||
StringRef count { MODULE_COMMIT_HASH };
|
||||
StringRef author { MODULE_AUTHOR };
|
||||
StringRef machine { MODULE_MACHINE };
|
||||
StringRef compiler { MODULE_COMPILER };
|
||||
StringRef id { MODULE_BUILD_ID };
|
||||
} build {};
|
||||
|
||||
public:
|
||||
StringRef name { "YaPB" };
|
||||
|
|
@ -38,7 +38,7 @@ public:
|
|||
StringRef logtag { "YB" };
|
||||
StringRef dtime { __DATE__ " " __TIME__ };
|
||||
StringRef date { __DATE__ };
|
||||
StringRef version { MODULE_BOT_VERSION "." MODULE_BUILD_COUNT };
|
||||
StringRef version { MODULE_VERSION "." MODULE_COMMIT_COUNT };
|
||||
StringRef cmdPri { "yb" };
|
||||
StringRef cmdSec { "yapb" };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,15 +21,15 @@ CR_DECLARE_SCOPED_ENUM (Noise,
|
|||
|
||||
class BotSupport final : public Singleton <BotSupport> {
|
||||
private:
|
||||
bool m_needToSendWelcome;
|
||||
float m_welcomeReceiveTime;
|
||||
bool m_needToSendWelcome {};
|
||||
float m_welcomeReceiveTime {};
|
||||
|
||||
StringArray m_sentences;
|
||||
SmallArray <Client> m_clients;
|
||||
SmallArray <Twin <String, String>> m_tags;
|
||||
StringArray m_sentences {};
|
||||
SmallArray <Client> m_clients {};
|
||||
SmallArray <Twin <String, String>> m_tags {};
|
||||
|
||||
HashMap <int32, String> m_weaponAlias;
|
||||
HashMap <String, int32> m_noiseCache;
|
||||
HashMap <int32, String> m_weaponAlias {};
|
||||
HashMap <String, int32> m_noiseCache {};
|
||||
Detour <decltype (sendto)> m_sendToDetour { "ws2_32.dll", "sendto", sendto };
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -8,12 +8,11 @@
|
|||
#pragma once
|
||||
|
||||
// fallback if no git or custom build
|
||||
#define MODULE_BUILD_HASH "0"
|
||||
#define MODULE_BUILD_AUTHOR "yapb@jeefo.net"
|
||||
#define MODULE_BUILD_COUNT "0"
|
||||
#define MODULE_BUILD_MACHINE "localhost"
|
||||
#define MODULE_BUILD_COMPILER "unknown"
|
||||
|
||||
#define MODULE_BOT_VERSION "4.3"
|
||||
#define MODULE_BOT_VERSION_FILE 4,3,0,000
|
||||
#define MODULE_BOT_BUILD_ID "0:0"
|
||||
#define MODULE_COMMIT_COUNT "0"
|
||||
#define MODULE_COMMIT_HASH "0"
|
||||
#define MODULE_AUTHOR "default@mail.net"
|
||||
#define MODULE_MACHINE "localhost"
|
||||
#define MODULE_COMPILER "default"
|
||||
#define MODULE_VERSION "4.0"
|
||||
#define MODULE_VERSION_FILE 4,0,0,000
|
||||
#define MODULE_BUILD_ID "0:0"
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
// generated by meson build system
|
||||
#ifndef MODULE_BUILD_HASH
|
||||
# define MODULE_BUILD_HASH "@hash@"
|
||||
# define MODULE_BUILD_AUTHOR @author@
|
||||
# define MODULE_BUILD_COUNT "@count@"
|
||||
# define MODULE_BUILD_MACHINE "@machine@"
|
||||
# define MODULE_BUILD_COMPILER "@compiler@"
|
||||
# define MODULE_BOT_VERSION "@version@"
|
||||
# define MODULE_BOT_VERSION_FILE @version_win@,@count@
|
||||
# define MODULE_BOT_BUILD_ID "@count@:@hash@"
|
||||
# define MODULE_COMMIT_COUNT "@count@"
|
||||
# define MODULE_COMMIT_HASH "@hash@"
|
||||
# define MODULE_AUTHOR @author@
|
||||
# define MODULE_MACHINE "@machine@"
|
||||
# define MODULE_COMPILER "@compiler@"
|
||||
# define MODULE_VERSION "@version@"
|
||||
# define MODULE_VERSION_FILE @winver@,@count@
|
||||
# define MODULE_BUILD_ID "@count@:@hash@"
|
||||
#endif
|
||||
|
|
|
|||
164
inc/yapb.h
164
inc/yapb.h
|
|
@ -349,7 +349,7 @@ CR_DECLARE_SCOPED_ENUM (Reload,
|
|||
)
|
||||
|
||||
// collision probes
|
||||
CR_DECLARE_SCOPED_ENUM (CollisionProbe,
|
||||
CR_DECLARE_SCOPED_ENUM (CollisionProbe, uint32,
|
||||
Jump = cr::bit (0), // probe jump when colliding
|
||||
Duck = cr::bit (1), // probe duck when colliding
|
||||
Strafe = cr::bit (2) // probe strafing when colliding
|
||||
|
|
@ -367,7 +367,7 @@ CR_DECLARE_SCOPED_ENUM (BotMsg,
|
|||
)
|
||||
|
||||
// sensing states
|
||||
CR_DECLARE_SCOPED_ENUM (Sense,
|
||||
CR_DECLARE_SCOPED_ENUM_TYPE (Sense, uint32,
|
||||
SeeingEnemy = cr::bit (0), // seeing an enemy
|
||||
HearingEnemy = cr::bit (1), // hearing an enemy
|
||||
SuspectEnemy = cr::bit (2), // suspect enemy behind obstacle
|
||||
|
|
@ -378,7 +378,7 @@ CR_DECLARE_SCOPED_ENUM (Sense,
|
|||
)
|
||||
|
||||
// positions to aim at
|
||||
CR_DECLARE_SCOPED_ENUM (AimFlags,
|
||||
CR_DECLARE_SCOPED_ENUM_TYPE (AimFlags, uint32,
|
||||
Nav = cr::bit (0), // aim at nav point
|
||||
Camp = cr::bit (1), // aim at camp vector
|
||||
PredictPath = cr::bit (2), // aim at predicted path
|
||||
|
|
@ -590,12 +590,12 @@ struct Client {
|
|||
|
||||
// define chatting collection structure
|
||||
struct ChatCollection {
|
||||
int chatProbability;
|
||||
float chatDelay;
|
||||
float timeNextChat;
|
||||
int entityIndex;
|
||||
String sayText;
|
||||
StringArray lastUsedSentences;
|
||||
int chatProbability {};
|
||||
float chatDelay {};
|
||||
float timeNextChat {};
|
||||
int entityIndex {};
|
||||
String sayText {};
|
||||
StringArray lastUsedSentences {};
|
||||
};
|
||||
|
||||
// include bot graph stuff
|
||||
|
|
@ -622,7 +622,7 @@ private:
|
|||
|
||||
int m_oldButtons {}; // our old buttons
|
||||
int m_reloadState {}; // current reload state
|
||||
int m_voicePitch; // bot voice pitch
|
||||
int m_voicePitch {}; // bot voice pitch
|
||||
int m_loosedBombNodeIndex {}; // nearest to loosed bomb node
|
||||
int m_plantedBombNodeIndex {}; // nearest to planted bomb node
|
||||
int m_currentNodeIndex {}; // current node index
|
||||
|
|
@ -636,18 +636,17 @@ private:
|
|||
int m_liftState {}; // state of lift handling
|
||||
int m_radioSelect {}; // radio entry
|
||||
|
||||
|
||||
float m_headedTime {};
|
||||
float m_prevTime {}; // time previously checked movement speed
|
||||
float m_heavyTimestamp; // is it time to execute heavy-weight functions
|
||||
float m_heavyTimestamp {}; // is it time to execute heavy-weight functions
|
||||
float m_prevSpeed {}; // speed some frames before
|
||||
float m_timeDoorOpen {}; // time to next door open check
|
||||
float m_lastChatTime {}; // time bot last chatted
|
||||
float m_timeLogoSpray {}; // time bot last spray logo
|
||||
float m_knifeAttackTime {}; // time to rush with knife (at the beginning of the round)
|
||||
float m_duckDefuseCheckTime {}; // time to check for ducking for defuse
|
||||
float m_frameInterval; // bot's frame interval
|
||||
float m_lastCommandTime; // time bot last thinked
|
||||
float m_frameInterval {}; // bot's frame interval
|
||||
float m_lastCommandTime {}; // time bot last thinked
|
||||
float m_reloadCheckTime {}; // time to check reloading
|
||||
float m_zoomCheckTime {}; // time to check zoom again
|
||||
float m_shieldCheckTime {}; // time to check shiled drawing again
|
||||
|
|
@ -685,15 +684,15 @@ private:
|
|||
float m_minSpeed {}; // minimum speed in normal mode
|
||||
float m_oldCombatDesire {}; // holds old desire for filtering
|
||||
float m_itemCheckTime {}; // time next search for items needs to be done
|
||||
float m_joinServerTime; // time when bot joined the game
|
||||
float m_playServerTime; // time bot spent in the game
|
||||
float m_joinServerTime {}; // time when bot joined the game
|
||||
float m_playServerTime {}; // time bot spent in the game
|
||||
float m_changeViewTime {}; // timestamp to change look at while at freezetime
|
||||
float m_breakableTime {}; // breakeble acquired time
|
||||
|
||||
bool m_moveToGoal {}; // bot currently moving to goal??
|
||||
bool m_isStuck {}; // bot is stuck
|
||||
bool m_isReloading {}; // bot is reloading a gun
|
||||
bool m_forceRadio; // should bot use radio anyway?
|
||||
bool m_forceRadio {}; // should bot use radio anyway?
|
||||
bool m_defendedBomb {}; // defend action issued
|
||||
bool m_defendHostage {}; // defend action issued
|
||||
bool m_duckDefuse {}; // should or not bot duck to defuse bomb
|
||||
|
|
@ -708,14 +707,14 @@ private:
|
|||
bool m_moveToC4 {}; // ct is moving to bomb
|
||||
bool m_grenadeRequested {}; // bot requested change to grenade
|
||||
|
||||
Pickup m_pickupType; // type of entity which needs to be used/picked up
|
||||
PathWalk m_pathWalk; // pointer to current node from path
|
||||
Dodge m_combatStrafeDir; // direction to strafe
|
||||
Fight m_fightStyle; // combat style to use
|
||||
CollisionState m_collisionState; // collision State
|
||||
FindPath m_pathType; // which pathfinder to use
|
||||
Pickup m_pickupType {}; // type of entity which needs to be used/picked up
|
||||
PathWalk m_pathWalk {}; // pointer to current node from path
|
||||
Dodge m_combatStrafeDir {}; // direction to strafe
|
||||
Fight m_fightStyle {}; // combat style to use
|
||||
CollisionState m_collisionState {}; // collision State
|
||||
FindPath m_pathType {}; // which pathfinder to use
|
||||
uint8 m_enemyParts {}; // visibility flags
|
||||
TraceResult m_lastTrace[TraceChannel::Num]; // last trace result
|
||||
TraceResult m_lastTrace[TraceChannel::Num] {}; // last trace result
|
||||
|
||||
edict_t *m_pickupItem {}; // pointer to entity of item to use/pickup
|
||||
edict_t *m_itemIgnore {}; // pointer to entity to ignore for pickup
|
||||
|
|
@ -725,31 +724,31 @@ private:
|
|||
edict_t *m_targetEntity {}; // the entity that the bot is trying to reach
|
||||
edict_t *m_avoidGrenade {}; // pointer to grenade entity to avoid
|
||||
|
||||
Vector m_liftTravelPos; // lift travel position
|
||||
Vector m_moveAngles; // bot move angles
|
||||
Vector m_idealAngles; // angle wanted
|
||||
Vector m_randomizedIdealAngles; // angle wanted with noise
|
||||
Vector m_angularDeviation; // angular deviation from current to ideal angles
|
||||
Vector m_aimSpeed; // aim speed calculated
|
||||
Vector m_aimLastError; // last calculated aim error
|
||||
Vector m_prevOrigin; // origin some frames before
|
||||
Vector m_lookAt; // vector bot should look at
|
||||
Vector m_throw; // origin of node to throw grenades
|
||||
Vector m_enemyOrigin; // target origin chosen for shooting
|
||||
Vector m_grenade; // calculated vector for grenades
|
||||
Vector m_entity; // origin of entities like buttons etc.
|
||||
Vector m_camp; // aiming vector when camping.
|
||||
Vector m_desiredVelocity; // desired velocity for jump nodes
|
||||
Vector m_breakableOrigin; // origin of breakable
|
||||
Vector m_liftTravelPos {}; // lift travel position
|
||||
Vector m_moveAngles {}; // bot move angles
|
||||
Vector m_idealAngles {}; // angle wanted
|
||||
Vector m_randomizedIdealAngles {}; // angle wanted with noise
|
||||
Vector m_angularDeviation {}; // angular deviation from current to ideal angles
|
||||
Vector m_aimSpeed {}; // aim speed calculated
|
||||
Vector m_aimLastError {}; // last calculated aim error
|
||||
Vector m_prevOrigin {}; // origin some frames before
|
||||
Vector m_lookAt {}; // vector bot should look at
|
||||
Vector m_throw {}; // origin of node to throw grenades
|
||||
Vector m_enemyOrigin {}; // target origin chosen for shooting
|
||||
Vector m_grenade {}; // calculated vector for grenades
|
||||
Vector m_entity {}; // origin of entities like buttons etc.
|
||||
Vector m_camp {}; // aiming vector when camping.
|
||||
Vector m_desiredVelocity {}; // desired velocity for jump nodes
|
||||
Vector m_breakableOrigin {}; // origin of breakable
|
||||
|
||||
Array <edict_t *> m_ignoredBreakable; // list of ignored breakables
|
||||
Array <edict_t *> m_hostages; // pointer to used hostage entities
|
||||
Array <Route> m_routes; // pointer
|
||||
Array <int32> m_goalHistory; // history of selected goals
|
||||
Array <edict_t *> m_ignoredBreakable {}; // list of ignored breakables
|
||||
Array <edict_t *> m_hostages {}; // pointer to used hostage entities
|
||||
Array <Route> m_routes {}; // pointer
|
||||
Array <int32> m_goalHistory {}; // history of selected goals
|
||||
|
||||
BinaryHeap <RouteTwin> m_routeQue;
|
||||
BinaryHeap <RouteTwin> m_routeQue {};
|
||||
Path *m_path {}; // pointer to the current path node
|
||||
String m_chatBuffer; // space for strings (say text...)
|
||||
String m_chatBuffer {}; // space for strings (say text...)
|
||||
FrustumPlane m_frustum[FrustumSide::Num] {};
|
||||
|
||||
private:
|
||||
|
|
@ -879,8 +878,8 @@ private:
|
|||
void focusEnemy ();
|
||||
void selectBestWeapon ();
|
||||
void selectSecondary ();
|
||||
void selectWeaponByName (const char *name);
|
||||
void selectWeaponById (int num);
|
||||
void selectWeaponByName (StringRef name);
|
||||
void selectWeaponByIndex (int index);
|
||||
|
||||
void completeTask ();
|
||||
void tasks ();
|
||||
|
|
@ -938,17 +937,17 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
entvars_t *pev;
|
||||
entvars_t *pev {};
|
||||
|
||||
int m_index; // saved bot index
|
||||
int m_wantedTeam; // player team bot wants select
|
||||
int m_wantedSkin; // player model bot wants to select
|
||||
int m_difficulty; // bots hard level
|
||||
int m_moneyAmount; // amount of money in bot's bank
|
||||
int m_index {}; // saved bot index
|
||||
int m_wantedTeam {}; // player team bot wants select
|
||||
int m_wantedSkin {}; // player model bot wants to select
|
||||
int m_difficulty {}; // bots hard level
|
||||
int m_moneyAmount {}; // amount of money in bot's bank
|
||||
|
||||
float m_spawnTime {}; // time this bot spawned
|
||||
float m_timeTeamOrder {}; // time of last radio command
|
||||
float m_slowFrameTimestamp; // time to per-second think
|
||||
float m_slowFrameTimestamp {}; // time to per-second think
|
||||
float m_nextBuyTime {}; // next buy time
|
||||
float m_checkDarkTime {}; // check for darkness time
|
||||
float m_preventFlashing {}; // bot turned away from flashbang
|
||||
|
|
@ -957,11 +956,11 @@ public:
|
|||
float m_blindSidemoveSpeed {}; // mad side move speeds when bot is blind
|
||||
float m_fallDownTime {}; // time bot started to fall
|
||||
float m_duckForJump {}; // is bot needed to duck for double jump
|
||||
float m_baseAgressionLevel; // base aggression level (on initializing)
|
||||
float m_baseFearLevel; // base fear level (on initializing)
|
||||
float m_agressionLevel; // dynamic aggression level (in game)
|
||||
float m_fearLevel; // dynamic fear level (in game)
|
||||
float m_nextEmotionUpdate; // next time to sanitize emotions
|
||||
float m_baseAgressionLevel {}; // base aggression level (on initializing)
|
||||
float m_baseFearLevel {}; // base fear level (on initializing)
|
||||
float m_agressionLevel {}; // dynamic aggression level (in game)
|
||||
float m_fearLevel {}; // dynamic fear level (in game)
|
||||
float m_nextEmotionUpdate {}; // next time to sanitize emotions
|
||||
float m_updateTime {}; // skip some frames in bot thinking
|
||||
float m_updateInterval {}; // interval between frames
|
||||
float m_goalValue {}; // ranking value for this node
|
||||
|
|
@ -980,21 +979,21 @@ public:
|
|||
float m_shootTime {}; // time to shoot
|
||||
float m_timeLastFired {}; // time to last firing
|
||||
float m_difficultyChange {}; // time when auto-difficulty was last applied to this bot
|
||||
float m_kpdRatio; // kill per death ratio
|
||||
float m_healthValue; // clamped bot health
|
||||
float m_stayTime; // stay time before reconnect
|
||||
float m_kpdRatio {}; // kill per death ratio
|
||||
float m_healthValue {}; // clamped bot health
|
||||
float m_stayTime {}; // stay time before reconnect
|
||||
|
||||
int m_blindNodeIndex {}; // node index to cover when blind
|
||||
int m_flashLevel {}; // flashlight level
|
||||
int m_basePing; // base ping for bot
|
||||
int m_basePing {}; // base ping for bot
|
||||
int m_numEnemiesLeft {}; // number of enemies alive left on map
|
||||
int m_numFriendsLeft {}; // number of friend alive left on map
|
||||
int m_retryJoin; // retry count for chosing team/class
|
||||
int m_startAction; // team/class selection state
|
||||
int m_retryJoin {}; // retry count for chosing team/class
|
||||
int m_startAction {}; // team/class selection state
|
||||
int m_voteKickIndex {}; // index of player to vote against
|
||||
int m_lastVoteKick {}; // last index
|
||||
int m_voteMap {}; // number of map to vote for
|
||||
int m_logotypeIndex; // index for logotype
|
||||
int m_logotypeIndex {}; // index for logotype
|
||||
int m_buyState {}; // current count in buying
|
||||
int m_blindButton {}; // buttons bot press, when blind
|
||||
int m_radioOrder {}; // actual command
|
||||
|
|
@ -1002,14 +1001,14 @@ public:
|
|||
int m_chosenGoalIndex {}; // used for experience, same as above
|
||||
int m_lastDamageType {}; // stores last damage
|
||||
int m_team {}; // bot team
|
||||
int m_currentWeapon; // one current weapon for each bot
|
||||
int m_weaponType; // current weapon type
|
||||
int m_currentWeapon {}; // one current weapon for each bot
|
||||
int m_weaponType {}; // current weapon type
|
||||
int m_ammoInClip[kMaxWeapons] {}; // ammo in clip for each weapons
|
||||
int m_ammo[MAX_AMMO_SLOTS] {}; // total ammo amounts
|
||||
|
||||
bool m_isVIP {}; // bot is vip?
|
||||
bool m_notKilled; // has the player been killed or has he just respawned
|
||||
bool m_notStarted; // team/class not chosen yet
|
||||
bool m_notKilled {}; // has the player been killed or has he just respawned
|
||||
bool m_notStarted {}; // team/class not chosen yet
|
||||
bool m_ignoreBuyDelay {}; // when reaching buyzone in the middle of the round don't do pauses
|
||||
bool m_inBombZone {}; // bot in the bomb zone or not
|
||||
bool m_inBuyZone {}; // bot currently in buy zone
|
||||
|
|
@ -1033,17 +1032,17 @@ public:
|
|||
edict_t *m_lastVictim {}; // pointer to killed entity
|
||||
edict_t *m_trackingEdict {}; // pointer to last tracked player when camping/hiding
|
||||
|
||||
Vector m_pathOrigin; // origin of node
|
||||
Vector m_destOrigin; // origin of move destination
|
||||
Vector m_position; // position to move to in move to position task
|
||||
Vector m_doubleJumpOrigin; // origin of double jump
|
||||
Vector m_lastEnemyOrigin; // vector to last enemy origin
|
||||
Vector m_pathOrigin {}; // origin of node
|
||||
Vector m_destOrigin {}; // origin of move destination
|
||||
Vector m_position {}; // position to move to in move to position task
|
||||
Vector m_doubleJumpOrigin {}; // origin of double jump
|
||||
Vector m_lastEnemyOrigin {}; // vector to last enemy origin
|
||||
|
||||
ChatCollection m_sayTextBuffer; // holds the index & the actual message of the last unprocessed text message of a player
|
||||
BurstMode m_weaponBurstMode; // bot using burst mode? (famas/glock18, but also silencer mode)
|
||||
Personality m_personality; // bots type
|
||||
Array <BotTask> m_tasks;
|
||||
Deque <int32> m_msgQueue;
|
||||
ChatCollection m_sayTextBuffer {}; // holds the index & the actual message of the last unprocessed text message of a player
|
||||
BurstMode m_weaponBurstMode {}; // bot using burst mode? (famas/glock18, but also silencer mode)
|
||||
Personality m_personality {}; // bots type
|
||||
Array <BotTask> m_tasks {};
|
||||
Deque <int32> m_msgQueue {};
|
||||
|
||||
public:
|
||||
Bot (edict_t *bot, int difficulty, int personality, int team, int skin);
|
||||
|
|
@ -1101,6 +1100,7 @@ public:
|
|||
bool canSkipNextTrace (TraceChannel channel);
|
||||
|
||||
int getAmmo ();
|
||||
int getAmmo (int id);
|
||||
int getNearestToPlantedBomb ();
|
||||
|
||||
float getFrameInterval ();
|
||||
|
|
@ -1112,6 +1112,8 @@ public:
|
|||
return m_ammoInClip[m_currentWeapon];
|
||||
}
|
||||
|
||||
bool isLowOnAmmo (const int index, const float factor) const;
|
||||
|
||||
Vector getCenter () const {
|
||||
return (pev->absmax + pev->absmin) * 0.5;
|
||||
};
|
||||
|
|
|
|||
345
meson.build
345
meson.build
|
|
@ -5,13 +5,12 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
# version is now passed into the bot dll
|
||||
project (
|
||||
'yapb',
|
||||
'cpp',
|
||||
|
||||
version: '4.3',
|
||||
license: 'MIT',
|
||||
|
||||
default_options: [
|
||||
'buildtype=release',
|
||||
'b_ndebug=if-release',
|
||||
|
|
@ -22,211 +21,202 @@ project (
|
|||
'optimization=3',
|
||||
'default_library=static',
|
||||
'cpp_eh=none',
|
||||
'cpp_rtti=false',
|
||||
'b_vscrt=static_from_buildtype',
|
||||
'b_lto=true',
|
||||
'b_lto_mode=default',
|
||||
'b_lundef=true',
|
||||
],
|
||||
meson_version: '>=0.56.0')
|
||||
meson_version: '>=0.58.0')
|
||||
|
||||
find_program ('ninja', required: true)
|
||||
find_program ('git', required: true)
|
||||
find_program ('hostname', required: true)
|
||||
find_program('ninja', required: true)
|
||||
|
||||
cpp = meson.get_compiler ('cpp')
|
||||
sys = host_machine.system ()
|
||||
target = host_machine.cpu_family ()
|
||||
version = meson.project_version ()
|
||||
count = run_command ('git', 'rev-list', '--count', 'HEAD', check: false).stdout ().strip ()
|
||||
|
||||
cpp_id = cpp.get_id ()
|
||||
cpp_version = cpp.version ()
|
||||
|
||||
optmize = get_option ('buildtype') == 'release' or get_option ('buildtype') == 'debugoptimized'
|
||||
|
||||
msvc = cpp_id == 'msvc' or cpp_id == 'clang-cl'
|
||||
gcc = cpp_id == 'gcc'
|
||||
clang = cpp_id == 'clang'
|
||||
|
||||
win32 = sys == 'windows'
|
||||
linux = sys == 'linux'
|
||||
mac = sys == 'darwin'
|
||||
aarch64 = target == 'aarch64'
|
||||
compiler= meson.get_compiler('cpp')
|
||||
cross = meson.is_cross_build ()
|
||||
os = host_machine.system()
|
||||
cpu = host_machine.cpu_family()
|
||||
cxx = compiler.get_id()
|
||||
build_type = get_option ('buildtype')
|
||||
|
||||
# cpp and ldflags from scratch
|
||||
cxxflags = []
|
||||
ldflags = []
|
||||
ccflags = []
|
||||
|
||||
cdata = configuration_data()
|
||||
# custom flags
|
||||
flags_versioned = ['-DVERSION_GENERATED']
|
||||
|
||||
if win32
|
||||
cdata.set ('version_win', ','.join (version.split ('.')))
|
||||
cdata.set ('machine', run_command ('hostname', check: false).stdout ().strip ())
|
||||
else
|
||||
cdata.set ('version_win', version)
|
||||
cdata.set ('machine', run_command ('hostname', '-f', check: false).stdout ().strip ())
|
||||
# git is optional, but it's setups our version info
|
||||
git = find_program('git', required: false)
|
||||
|
||||
if git.found()
|
||||
run_command('git', 'config', '--global', '--add', 'safe.directory', '*', check: false)
|
||||
|
||||
# get the commit data
|
||||
count = run_command('git', 'rev-list', '--count', 'HEAD', check: false).stdout().strip()
|
||||
hash = run_command ('git', 'rev-parse', '--short', 'HEAD', check: false).stdout().strip()
|
||||
author = run_command ('git', 'log', '--pretty="%ae"', '-1', check: false).stdout().strip()
|
||||
|
||||
hostname = find_program('hostname', required: false)
|
||||
|
||||
if hostname.found()
|
||||
machine = run_command('hostname', check: false).stdout().strip()
|
||||
else
|
||||
machine = 'unknown'
|
||||
endif
|
||||
|
||||
bot_version = meson.project_version()
|
||||
cxx_version = compiler.version()
|
||||
|
||||
if os == 'windows'
|
||||
winver = ','.join(bot_version.split('.'))
|
||||
else
|
||||
winver = bot_version
|
||||
endif
|
||||
|
||||
cxxflags += flags_versioned
|
||||
version_data = configuration_data()
|
||||
|
||||
version_data.set('count', count)
|
||||
version_data.set('hash', hash)
|
||||
version_data.set('author', author)
|
||||
version_data.set('machine', machine)
|
||||
version_data.set('version', bot_version)
|
||||
version_data.set('winver', winver)
|
||||
version_data.set('compiler', '@0@ @1@'.format (cxx, cxx_version))
|
||||
|
||||
configure_file (input: 'inc/version.h.in', output: 'version.build.h', configuration: version_data)
|
||||
endif
|
||||
|
||||
cdata.set ('hash', run_command ('git', 'rev-parse', '--short', 'HEAD', check: false).stdout ().strip ())
|
||||
cdata.set ('author', run_command ('git', 'log', '--pretty="%ae"', '-1', check: false).stdout ().strip ())
|
||||
|
||||
cdata.set ('count', count)
|
||||
cdata.set ('version', version)
|
||||
|
||||
cdata.set ('compiler', cpp_id + ' ' + cpp_version)
|
||||
|
||||
configure_file (input: 'inc/version.h.in', output: 'version.build.h', configuration: cdata)
|
||||
|
||||
ccflags += '-DVERSION_GENERATED'
|
||||
|
||||
if clang or gcc
|
||||
ccflags += [
|
||||
'-fno-threadsafe-statics',
|
||||
'-fno-exceptions',
|
||||
'-fno-rtti'
|
||||
# configure flags gcc and clang
|
||||
if cxx == 'clang' or cxx == 'gcc'
|
||||
cxxflags += [
|
||||
'-mtune=generic', '-fno-threadsafe-statics'
|
||||
]
|
||||
|
||||
if not aarch64
|
||||
ccflags += '-m32'
|
||||
endif
|
||||
|
||||
if not mac
|
||||
ccflags += [
|
||||
'-pedantic',
|
||||
]
|
||||
endif
|
||||
|
||||
if optmize
|
||||
if (clang or gcc) and not mac
|
||||
if not aarch64 and not (clang and win32)
|
||||
ccflags += [
|
||||
'-fdata-sections',
|
||||
'-ffunction-sections'
|
||||
]
|
||||
endif
|
||||
|
||||
if gcc
|
||||
ccflags += '-fgraphite-identity'
|
||||
ldflags += '-flto-partition=none'
|
||||
endif
|
||||
|
||||
if not aarch64 and not (clang and win32)
|
||||
ldflags += [
|
||||
'-Wl,--version-script=../ldscript.lds',
|
||||
'-Wl,--gc-sections'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if linux
|
||||
ldflags += [
|
||||
'-lm',
|
||||
'-ldl'
|
||||
]
|
||||
if not aarch64
|
||||
ldflags += '-m32'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if linux or mac or (win32 and (gcc or clang))
|
||||
if mac
|
||||
ccflags += '-mmacosx-version-min=10.9'
|
||||
ldflags += [
|
||||
'-lstdc++',
|
||||
'-mmacosx-version-min=10.9'
|
||||
if cpu == 'aarch64'
|
||||
cxxflags += [
|
||||
'-march=armv8-a+fp+simd',
|
||||
]
|
||||
else
|
||||
ldflags += '-static-libgcc'
|
||||
cxxflags += [
|
||||
'-march=x86-64', '-mmmx', '-msse', '-msse2', '-msse3', '-mssse3', '-mfpmath=sse'
|
||||
]
|
||||
endif
|
||||
|
||||
if not optmize
|
||||
ccflags += [
|
||||
'-g3',
|
||||
'-ggdb',
|
||||
'-DCR_DEBUG'
|
||||
]
|
||||
else
|
||||
ccflags += [
|
||||
'-mtune=generic',
|
||||
'-fno-builtin',
|
||||
'-funroll-loops',
|
||||
'-fomit-frame-pointer',
|
||||
'-fno-stack-protector',
|
||||
'-fvisibility=hidden',
|
||||
'-fvisibility-inlines-hidden'
|
||||
# setup optimization flags
|
||||
if build_type == 'release'
|
||||
cxxflags += [
|
||||
'-funroll-loops', '-fomit-frame-pointer', '-fno-stack-protector', '-fvisibility=hidden', '-fvisibility-inlines-hidden'
|
||||
]
|
||||
|
||||
if not aarch64
|
||||
ccflags += [
|
||||
'-msse2',
|
||||
'-mfpmath=sse',
|
||||
if os != 'darwin' and os != 'windows' and cpu != 'aarch64'
|
||||
cxxflags += [
|
||||
'-fdata-sections',
|
||||
'-ffunction-sections'
|
||||
]
|
||||
else
|
||||
ccflags += '-march=armv8-a+fp+simd'
|
||||
endif
|
||||
|
||||
if clang and not mac
|
||||
ldflags += [
|
||||
'-nostdlib++',
|
||||
'-Wunused-command-line-argument'
|
||||
'-Wl,--version-script=../ext/ldscripts/version.lds',
|
||||
'-Wl,--gc-sections'
|
||||
]
|
||||
elif gcc and not mac
|
||||
ldflags += '-Wl,--no-undefined'
|
||||
|
||||
if cxx == 'gcc'
|
||||
cxxflags += [
|
||||
'-fgraphite-identity', '-floop-nest-optimize'
|
||||
]
|
||||
ldflags += [
|
||||
'-fgraphite-identity', '-floop-nest-optimize', '-flto-partition=none'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
else
|
||||
cxxflags += ['-g3', '-ggdb', '-DDEBUG', '-D_FORTIFY_SOURCE=2']
|
||||
endif
|
||||
|
||||
# special script for mingw-64 builds
|
||||
if os == 'windows' and cxx == 'gcc' and compiler.version().version_compare('<12.0')
|
||||
ldflags += [
|
||||
'-Xlinker', '--script', '-Xlinker', '../ext/ldscripts/i386pe.lds'
|
||||
]
|
||||
endif
|
||||
|
||||
# always statically link libgcc on non darwin platforms
|
||||
if os != 'darwin'
|
||||
if cross or (cxx != 'clang' and os == 'windows')
|
||||
ldflags += '-static-libgcc'
|
||||
endif
|
||||
else
|
||||
cxxflags += '-mmacosx-version-min=10.9'
|
||||
|
||||
ldflags += [
|
||||
'-lstdc++', '-mmacosx-version-min=10.9'
|
||||
]
|
||||
endif
|
||||
|
||||
# by default we buid 32bit binaries
|
||||
if cpu != 'aarch64' and not get_option('64bit')
|
||||
cxxflags += '-m32'
|
||||
ldflags += '-m32'
|
||||
|
||||
if cross and cxx == 'clang' and os == 'windows'
|
||||
ldflags += '-Wl,/MACHINE:X86'
|
||||
cxxflags += '-Wl,/MACHINE:X86'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if win32 and msvc
|
||||
ldflags += [
|
||||
'/MACHINE:X86',
|
||||
'user32.lib',
|
||||
'ws2_32.lib'
|
||||
]
|
||||
|
||||
ccflags += [
|
||||
'/TP',
|
||||
'/D _WIN32_WINNT=0x0501',
|
||||
'/D _USING_V110_SDK71_',
|
||||
'/Zc:threadSafeInit-'
|
||||
]
|
||||
|
||||
if optmize
|
||||
ccflags += [
|
||||
'/GL',
|
||||
'/GS-',
|
||||
'/Ob2',
|
||||
'/Oy',
|
||||
'/Oi',
|
||||
'/Ot',
|
||||
'/fp:precise',
|
||||
'/GF'
|
||||
]
|
||||
# link needed libraries
|
||||
if os == 'linux'
|
||||
ldflags += [
|
||||
'/LTCG',
|
||||
'delayimp.lib',
|
||||
'/DELAYLOAD:user32.dll',
|
||||
'/SUBSYSTEM:WINDOWS,5.01',
|
||||
]
|
||||
'-lm','-ldl'
|
||||
]
|
||||
elif os == 'windows'
|
||||
if cxx == 'gcc' or (cross and cxx == 'clang')
|
||||
ldflags += '-Wl,--kill-at'
|
||||
endif
|
||||
|
||||
ldflags += [
|
||||
'-luser32', '-lws2_32'
|
||||
]
|
||||
endif
|
||||
elif os == 'windows' and (cxx =='msvc' or cxx == 'clang-cl')
|
||||
if not get_option('64bit') and cxx == 'clang'
|
||||
cxxflags += '/MACHINE:X86'
|
||||
ldflags += '/MACHINE:X86'
|
||||
endif
|
||||
|
||||
elif win32 and (clang or gcc)
|
||||
ldflags += [
|
||||
'-Wl,--kill-at',
|
||||
'-luser32',
|
||||
'-lws2_32'
|
||||
cxxflags += [
|
||||
'/TP', '/D _WIN32_WINNT=0x0501', '/D _USING_V110_SDK71_', '/Zc:threadSafeInit-'
|
||||
]
|
||||
|
||||
if clang
|
||||
ldflags += '-Wl,/MACHINE:X86'
|
||||
ccflags += '-Wl,/MACHINE:X86'
|
||||
else
|
||||
ldflags += ['-Xlinker', '--script', '-Xlinker', '../i386pe.lds']
|
||||
# minor optimizations for release build
|
||||
if build_type == 'release'
|
||||
cxxflags += [
|
||||
'/GS-', '/Ob2', '/Oy', '/Oi', '/Ot', '/fp:precise', '/GF', '/GS-', '/GF', '/arch:SSE2'
|
||||
]
|
||||
|
||||
# add wpo if msvc
|
||||
if cxx == 'msvc'
|
||||
cxxflags += [
|
||||
'/GL'
|
||||
]
|
||||
endif
|
||||
|
||||
# add linker flags
|
||||
ldflags += [
|
||||
'/LTCG', 'delayimp.lib', '/DELAYLOAD:user32.dll', '/DELAYLOAD:ws2_32.dll', '/SUBSYSTEM:WINDOWS,5.01',
|
||||
]
|
||||
endif
|
||||
|
||||
ldflags += [
|
||||
'user32.lib', 'ws2_32.lib'
|
||||
]
|
||||
endif
|
||||
|
||||
add_global_arguments (ccflags, language: 'cpp')
|
||||
# pass our hell to meson
|
||||
add_global_arguments (cxxflags, language: 'cpp')
|
||||
add_global_link_arguments (ldflags, language: 'cpp')
|
||||
|
||||
# add the sources
|
||||
sources = files (
|
||||
'src/botlib.cpp',
|
||||
'src/chatlib.cpp',
|
||||
|
|
@ -243,24 +233,27 @@ sources = files (
|
|||
'src/support.cpp'
|
||||
)
|
||||
|
||||
# add the include directories
|
||||
includes = include_directories ([
|
||||
'.', 'inc', 'ext', 'ext/crlib'
|
||||
], is_system: true)
|
||||
|
||||
if win32
|
||||
# if have git and on windows add windows-specific version info
|
||||
if os == 'windows' and git.found()
|
||||
sources += import('windows').compile_resources (
|
||||
'vc/yapb.rc',
|
||||
include_directories: includes,
|
||||
args: ['-DVERSION_GENERATED']
|
||||
args: flags_versioned
|
||||
)
|
||||
endif
|
||||
|
||||
shared_library (
|
||||
meson.project_name (),
|
||||
# instruct meson we're want our little shared lib bot
|
||||
shared_library(
|
||||
meson.project_name(),
|
||||
sources,
|
||||
include_directories: includes,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
name_prefix: '')
|
||||
|
||||
run_target ('package',
|
||||
command: ['python3', meson.project_source_root () + '/package.py', '@0@.@1@'.format (version, count)])
|
||||
run_target('package',
|
||||
command: ['python3', meson.project_source_root() + '/package.py', '@0@.@1@'.format(bot_version, count)])
|
||||
9
meson_options.txt
Normal file
9
meson_options.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
# Copyright © 2004-2023 YaPB Project <yapb@jeefo.net>.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
option('64bit', type : 'boolean', value : false,
|
||||
description: 'Enables bot build with as 64-bit binary.')
|
||||
415
package.py
415
package.py
|
|
@ -7,295 +7,310 @@
|
|||
#
|
||||
|
||||
import os, sys, subprocess, base64
|
||||
import urllib3
|
||||
import glob, requests
|
||||
import pathlib, shutil
|
||||
import zipfile, tarfile
|
||||
import datetime, calendar
|
||||
|
||||
class CodeSign (object):
|
||||
def __init__(self, product, url, verify_signature=False):
|
||||
class BotSign(object):
|
||||
def __init__(self, product: str, url: str):
|
||||
self.signing = True
|
||||
|
||||
self.ossl_path = "/usr/bin/osslsigncode"
|
||||
self.local_key = os.path.join (pathlib.Path ().absolute (), "key.pfx");
|
||||
self.ossl_path = '/usr/bin/osslsigncode'
|
||||
self.local_key = os.path.join(pathlib.Path().absolute(), 'bot_release_key.pfx');
|
||||
|
||||
self.product = product
|
||||
self.url = url
|
||||
self.verify_signature = verify_signature
|
||||
|
||||
if not os.path.exists (self.ossl_path):
|
||||
if not os.path.exists(self.ossl_path):
|
||||
self.signing = False
|
||||
|
||||
if not "CS_CERTIFICATE" in os.environ:
|
||||
if not 'CS_CERTIFICATE' in os.environ:
|
||||
self.signing = False
|
||||
|
||||
if not "CS_CERTIFICATE_PASSWORD" in os.environ:
|
||||
if not 'CS_CERTIFICATE_PASSWORD' in os.environ:
|
||||
self.signing = False
|
||||
|
||||
if self.signing:
|
||||
self.password = os.environ.get ("CS_CERTIFICATE_PASSWORD")
|
||||
self.password = os.environ.get('CS_CERTIFICATE_PASSWORD')
|
||||
|
||||
encoded = os.environ.get ("CS_CERTIFICATE")
|
||||
encoded = os.environ.get('CS_CERTIFICATE')
|
||||
|
||||
if len (encoded) < 64:
|
||||
print ('Damaged certificate. Signing disabled.')
|
||||
if len(encoded) < 64:
|
||||
print('Damaged certificate. Signing disabled.')
|
||||
self.signing = False
|
||||
return
|
||||
|
||||
decoded = base64.b64decode (encoded)
|
||||
decoded = base64.b64decode(encoded)
|
||||
|
||||
with open (self.local_key, "wb") as key:
|
||||
key.write (decoded)
|
||||
with open(self.local_key, 'wb') as key:
|
||||
key.write(decoded)
|
||||
|
||||
def has(self):
|
||||
return self.signing
|
||||
|
||||
def sign_file_inplace (self, filename):
|
||||
signed_filename = filename + ".signed"
|
||||
sign = []
|
||||
def sign_file_inplace(self, filename):
|
||||
signed_filename = filename + '.signed'
|
||||
signed_cmdline = []
|
||||
|
||||
sign.append (self.ossl_path)
|
||||
sign.append ("sign")
|
||||
sign.append ("-pkcs12")
|
||||
sign.append (self.local_key)
|
||||
sign.append ("-pass")
|
||||
sign.append (self.password)
|
||||
sign.append ("-n")
|
||||
sign.append (self.product)
|
||||
sign.append ("-i")
|
||||
sign.append (self.url)
|
||||
sign.append ("-h")
|
||||
sign.append ("sha384")
|
||||
sign.append ("-t")
|
||||
sign.append ("http://timestamp.sectigo.com")
|
||||
sign.append ("-in")
|
||||
sign.append (filename)
|
||||
sign.append ("-out")
|
||||
sign.append (signed_filename)
|
||||
signed_cmdline.append (self.ossl_path)
|
||||
signed_cmdline.append ('sign')
|
||||
signed_cmdline.append ('-pkcs12')
|
||||
signed_cmdline.append (self.local_key)
|
||||
signed_cmdline.append ('-pass')
|
||||
signed_cmdline.append (self.password)
|
||||
signed_cmdline.append ('-n')
|
||||
signed_cmdline.append (self.product)
|
||||
signed_cmdline.append ('-i')
|
||||
signed_cmdline.append (self.url)
|
||||
signed_cmdline.append ('-h')
|
||||
signed_cmdline.append ('sha384')
|
||||
signed_cmdline.append ('-t')
|
||||
signed_cmdline.append ('http://timestamp.sectigo.com')
|
||||
signed_cmdline.append ('-in')
|
||||
signed_cmdline.append (filename)
|
||||
signed_cmdline.append ('-out')
|
||||
signed_cmdline.append (signed_filename)
|
||||
|
||||
result = subprocess.run (sign, capture_output=True, text=True)
|
||||
result = subprocess.run (signed_cmdline, capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
os.unlink (filename)
|
||||
shutil.move (signed_filename, filename)
|
||||
os.unlink(filename)
|
||||
shutil.move(signed_filename, filename)
|
||||
|
||||
print ("Signing result: {}".format (result.stdout))
|
||||
return False
|
||||
|
||||
if self.verify_signature:
|
||||
verify = []
|
||||
verify.append (self.ossl_path)
|
||||
verify.append ("verify")
|
||||
verify.append (filename)
|
||||
class BotPackage(object):
|
||||
def __init__(self, name: str, archive: str, artifact: dict, extra: bool = False):
|
||||
self.name = name
|
||||
self.archive = archive
|
||||
self.artifact = artifact
|
||||
self.extra = extra
|
||||
|
||||
verify = subprocess.run (verify, capture_output=True, text=True)
|
||||
print (verify.stdout)
|
||||
|
||||
else:
|
||||
print (result.stdout)
|
||||
|
||||
|
||||
class BotRelease (object):
|
||||
class BotRelease(object):
|
||||
def __init__(self):
|
||||
print ("Initializing Packaging")
|
||||
|
||||
meson_src_root_env = "MESON_SOURCE_ROOT"
|
||||
|
||||
if meson_src_root_env in os.environ:
|
||||
os.chdir (os.environ.get (meson_src_root_env))
|
||||
|
||||
self.work_dir = os.path.join (pathlib.Path ().absolute (), "cfg")
|
||||
self.bot_dir = os.path.join (self.work_dir, "addons", "yapb")
|
||||
self.pkg_dir = os.path.join (pathlib.Path ().absolute (), "pkg")
|
||||
|
||||
if len (sys.argv) < 2:
|
||||
raise Exception("Missing required parameters.")
|
||||
if len(sys.argv) < 2:
|
||||
raise Exception('Missing required parameters.')
|
||||
|
||||
self.project = 'yapb'
|
||||
self.version = sys.argv[1]
|
||||
self.artifacts = 'artifacts'
|
||||
self.graphs = 'yapb-gcdn.akamaized.net'
|
||||
self.win32exe = 'https://github.com/yapb/setup/releases/latest/download/botsetup.exe'
|
||||
|
||||
self.cs = CodeSign ("YaPB", "https://yapb.jeefo.net/")
|
||||
meson_src_root_env = 'MESON_SOURCE_ROOT'
|
||||
|
||||
if self.cs.has ():
|
||||
print ("Code Signing Enabled")
|
||||
if meson_src_root_env in os.environ:
|
||||
os.chdir(os.environ.get(meson_src_root_env))
|
||||
else:
|
||||
print ("Code Signing Disabled")
|
||||
raise Exception(f'No direct access, only via meson build.')
|
||||
|
||||
os.makedirs (self.pkg_dir, exist_ok=True)
|
||||
path = pathlib.Path().absolute()
|
||||
|
||||
self.pkg_win32 = os.path.join (self.pkg_dir, "yapb-{}-windows.zip".format (self.version))
|
||||
self.pkg_linux = os.path.join (self.pkg_dir, "yapb-{}-linux.tar.xz".format (self.version))
|
||||
self.pkg_macos = os.path.join (self.pkg_dir, "yapb-{}-macos.zip".format (self.version))
|
||||
if not os.path.isdir(os.path.join(path, self.artifacts)):
|
||||
raise Exception('Artifacts directory missing.')
|
||||
|
||||
self.pkg_win32_sfx = self.pkg_win32.replace ("zip", "exe")
|
||||
self.pkg_win32_sfx_url = "https://github.com/yapb/setup/releases/latest/download/botsetup.exe"
|
||||
print(f'Releasing {self.project} v{self.version}')
|
||||
|
||||
def make_directories (self):
|
||||
dirs = [
|
||||
"bin",
|
||||
os.path.join ("data", "pwf"),
|
||||
os.path.join ("data", "train"),
|
||||
os.path.join ("data", "graph"),
|
||||
os.path.join ("data", "logs")
|
||||
]
|
||||
self.work_dir = os.path.join(path, 'release')
|
||||
shutil.copytree(f'{path}/cfg', self.work_dir, dirs_exist_ok=True)
|
||||
|
||||
for dir in dirs:
|
||||
os.makedirs (os.path.join (self.bot_dir, dir), exist_ok=True)
|
||||
self.bot_dir = os.path.join(self.work_dir, 'addons', self.project)
|
||||
self.pkg_dir = os.path.join(path, 'pkg')
|
||||
|
||||
def http_pull (self, url, local_file):
|
||||
http = urllib3.PoolManager (10, headers = {"user-agent": "YaPB"})
|
||||
data = http.urlopen ("GET", url)
|
||||
self.cs = BotSign('YaPB', 'https://yapb.jeefo.net/')
|
||||
|
||||
with open (local_file, "wb") as file:
|
||||
file.write (data.data)
|
||||
if self.cs.has():
|
||||
print('Signing enabled')
|
||||
else:
|
||||
print('Signing disabled')
|
||||
|
||||
def get_graph_file (self, name):
|
||||
file = os.path.join (self.bot_dir, "data", "graph", "{}.graph".format (name))
|
||||
url = "https://yapb.jeefo.net/graph/{}.graph".format (name)
|
||||
os.makedirs(self.pkg_dir, exist_ok=True)
|
||||
self.http_pull(self.win32exe, 'botsetup.exe')
|
||||
|
||||
if os.path.exists (file):
|
||||
self.pkg_matrix = []
|
||||
self.pkg_matrix.append (BotPackage('windows', 'zip', {'windows-x86': 'dll'}))
|
||||
self.pkg_matrix.append (BotPackage('windows', 'exe', {'windows-x86': 'dll'}))
|
||||
self.pkg_matrix.append (BotPackage('linux', 'tar.xz', {'linux-x86': 'so'}))
|
||||
self.pkg_matrix.append (BotPackage('darwin', 'zip', {'darwin-x86': 'dylib'}))
|
||||
self.pkg_matrix.append (BotPackage('extras', 'zip', {'linux-aarch64': 'so', 'linux-x86-gcc': 'so', 'windows-x86-gcc': 'dll', 'windows-x86-msvc': 'dll'}, extra=True))
|
||||
|
||||
def create_dirs(self):
|
||||
for dir in ['pwf', 'train', 'graph', 'logs']:
|
||||
os.makedirs(os.path.join(self.bot_dir, 'data', dir), exist_ok=True)
|
||||
|
||||
def http_pull(self, url: str, tp: str):
|
||||
headers = {
|
||||
'User-Agent': 'YaPB/4',
|
||||
}
|
||||
with requests.get(url, headers=headers) as r:
|
||||
r.raise_for_status()
|
||||
|
||||
with open(tp, 'wb') as f:
|
||||
f.write(r.content)
|
||||
|
||||
def get_graph_file(self, name: str):
|
||||
file = os.path.join(self.bot_dir, 'data', 'graph', f'{name}.graph')
|
||||
url = f'http://{self.graphs}/graph/{name}.graph'
|
||||
|
||||
if os.path.exists(file):
|
||||
return
|
||||
|
||||
self.http_pull (url, file)
|
||||
self.http_pull(url, file)
|
||||
|
||||
def get_default_graphs (self):
|
||||
print ("Downloading graphs: ")
|
||||
def create_graphs(self):
|
||||
default_list = 'default.graph.txt'
|
||||
self.http_pull(f'http://{self.graphs}/DEFAULT.txt', default_list)
|
||||
|
||||
default_list = "default.graph.txt"
|
||||
self.http_pull ("https://gs.yapb.jeefo.net//DEFAULT.txt", default_list)
|
||||
|
||||
with open (default_list) as file:
|
||||
files = [line.rstrip () for line in file.readlines ()]
|
||||
with open(default_list) as file:
|
||||
files = [line.rstrip() for line in file.readlines()]
|
||||
|
||||
for file in files:
|
||||
print (" " + file)
|
||||
print(f'Getting graphs: {file} ', end='\r', flush=True)
|
||||
self.get_graph_file(file)
|
||||
|
||||
self.get_graph_file (file)
|
||||
print()
|
||||
|
||||
def unlink_binaries (self):
|
||||
libs = ["yapb.so", "yapb.arm64.so", "yapb.dll", "yapb.dylib"]
|
||||
|
||||
for lib in libs:
|
||||
path = os.path.join (self.bot_dir, "bin", lib)
|
||||
|
||||
if os.path.exists (path):
|
||||
os.remove (path)
|
||||
|
||||
def sign_binary (self, binary):
|
||||
if self.cs.has () and (binary.endswith ("dll") or binary.endswith ("exe")):
|
||||
print ("Signing {}".format (binary))
|
||||
self.cs.sign_file_inplace (binary)
|
||||
|
||||
def copy_binary (self, binary):
|
||||
dest_path = os.path.join (self.bot_dir, "bin", os.path.basename (binary))
|
||||
shutil.copy (binary, dest_path)
|
||||
|
||||
self.sign_binary (dest_path)
|
||||
|
||||
def compress_directory (self, path, handle):
|
||||
length = len (path) + 1
|
||||
def compress_directory(self, path: str, handle: zipfile.ZipFile):
|
||||
length = len(path) + 1
|
||||
empty_dirs = []
|
||||
|
||||
for root, dirs, files in os.walk (path):
|
||||
empty_dirs.extend ([dir for dir in dirs if os.listdir (os.path.join (root, dir)) == []])
|
||||
for root, dirs, files in os.walk(path):
|
||||
empty_dirs.extend([dir for dir in dirs if os.listdir(os.path.join(root, dir)) == []])
|
||||
|
||||
for file in files:
|
||||
file_path = os.path.join (root, file)
|
||||
handle.write (file_path, file_path[length:])
|
||||
file_path = os.path.join(root, file)
|
||||
handle.write(file_path, file_path[length:])
|
||||
|
||||
for dir in empty_dirs:
|
||||
dir_path = os.path.join (root, dir)
|
||||
dir_path = os.path.join(root, dir)
|
||||
|
||||
zif = zipfile.ZipInfo (dir_path[length:] + "/")
|
||||
handle.writestr (zif, "")
|
||||
zif = zipfile.ZipInfo(dir_path[length:] + '/')
|
||||
handle.writestr(zif, '')
|
||||
|
||||
empty_dirs = []
|
||||
|
||||
def create_zip (self, dir):
|
||||
zf = zipfile.ZipFile (dir, "w", zipfile.ZIP_DEFLATED, compresslevel=9)
|
||||
zf.comment = bytes (self.version, encoding = "ascii")
|
||||
def create_zip(self, dest: str, custom_dir: str = None):
|
||||
zf = zipfile.ZipFile(dest, 'w', zipfile.ZIP_DEFLATED, compresslevel=9)
|
||||
zf.comment = bytes(self.version, encoding = 'ascii')
|
||||
|
||||
self.compress_directory (self.work_dir, zf)
|
||||
zf.close ()
|
||||
self.compress_directory(custom_dir if custom_dir else self.work_dir, zf)
|
||||
zf.close()
|
||||
|
||||
def convert_zip_txz (self, zfn, txz):
|
||||
timeshift = int ((datetime.datetime.now () - datetime.datetime.utcnow ()).total_seconds ())
|
||||
def convert_zip_txz(self, zfn: str, txz: str):
|
||||
timeshift = int((datetime.datetime.now() - datetime.datetime.utcnow()).total_seconds())
|
||||
|
||||
with zipfile.ZipFile (zfn) as zipf:
|
||||
with tarfile.open (txz, "w:xz") as tarf:
|
||||
for zif in zipf.infolist ():
|
||||
tif = tarfile.TarInfo (name = zif.filename)
|
||||
with zipfile.ZipFile(zfn) as zipf:
|
||||
with tarfile.open(txz, 'w:xz') as tarf:
|
||||
for zif in zipf.infolist():
|
||||
tif = tarfile.TarInfo(name = zif.filename)
|
||||
tif.size = zif.file_size
|
||||
tif.mtime = calendar.timegm (zif.date_time) - timeshift
|
||||
tif.mtime = calendar.timegm(zif.date_time) - timeshift
|
||||
|
||||
tarf.addfile (tarinfo = tif, fileobj = zipf.open (zif.filename))
|
||||
tarf.addfile(tarinfo = tif, fileobj = zipf.open(zif.filename))
|
||||
|
||||
os.remove (zfn)
|
||||
os.remove(zfn)
|
||||
|
||||
def install_binary (self, ext, unlink_existing = True):
|
||||
lib = "yapb.{}".format (ext)
|
||||
binary = os.path.join (self.artifacts, lib)
|
||||
def convert_zip_sfx(self, zfn: str, exe: str):
|
||||
with open('botsetup.exe', 'rb') as sfx, open(zfn, 'rb') as zfn, open(exe, 'wb') as dest:
|
||||
dest.write(sfx.read())
|
||||
dest.write(zfn.read())
|
||||
|
||||
if os.path.isdir (binary):
|
||||
binary = os.path.join (binary, lib)
|
||||
self.sign_binary(exe)
|
||||
|
||||
if not os.path.exists (binary):
|
||||
print ("Packaging failed for {}. Skipping...".format (lib))
|
||||
return False
|
||||
def unlink_binaries(self):
|
||||
path = os.path.join(self.bot_dir, 'bin');
|
||||
|
||||
if unlink_existing:
|
||||
self.unlink_binaries ()
|
||||
shutil.rmtree(path, ignore_errors=True)
|
||||
os.makedirs(path, exist_ok=True)
|
||||
|
||||
self.copy_binary (binary)
|
||||
def sign_binary(self, binary: str):
|
||||
if self.cs.has() and (binary.endswith('dll') or binary.endswith('exe')):
|
||||
self.cs.sign_file_inplace(binary)
|
||||
|
||||
return True
|
||||
def copy_binary(self, binary: str, artifact: str):
|
||||
if artifact:
|
||||
dest_path = os.path.join(self.bot_dir, 'bin', artifact)
|
||||
os.makedirs(dest_path, exist_ok=True)
|
||||
|
||||
def create_pkg_win32 (self):
|
||||
print ("Generating Win32 ZIP")
|
||||
dest_path = os.path.join(dest_path, os.path.basename(binary))
|
||||
else:
|
||||
dest_path = os.path.join(self.bot_dir, 'bin', os.path.basename(binary))
|
||||
|
||||
if not self.install_binary ("dll"):
|
||||
shutil.copy(binary, dest_path)
|
||||
self.sign_binary(dest_path)
|
||||
|
||||
def install_binary(self, pkg: BotPackage):
|
||||
num_artifacts_errors = 0
|
||||
num_artifacts = len(pkg.artifact)
|
||||
|
||||
for artifact in pkg.artifact:
|
||||
binary = os.path.join(self.artifacts, artifact, f'{self.project}.{pkg.artifact[artifact]}')
|
||||
binary_base = os.path.basename(binary)
|
||||
|
||||
if not os.path.exists(binary):
|
||||
num_artifacts_errors += 1
|
||||
print(f'[{binary_base}: FAIL]', end=' ')
|
||||
continue
|
||||
|
||||
print(f'[{binary_base}: OK]', end=' ')
|
||||
|
||||
if num_artifacts == 1:
|
||||
self.unlink_binaries()
|
||||
|
||||
self.copy_binary(binary, artifact if pkg.extra else None)
|
||||
|
||||
return num_artifacts_errors < num_artifacts
|
||||
|
||||
def create_pkg(self, pkg: BotPackage):
|
||||
dest = os.path.join (self.pkg_dir, f'{self.project}-{self.version}-{pkg.name}.{pkg.archive}')
|
||||
dest_tmp = f'{dest}.tmp'
|
||||
|
||||
if os.path.exists(dest):
|
||||
os.remove(dest)
|
||||
self.unlink_binaries()
|
||||
|
||||
print(f'Generating {os.path.basename(dest)}:', end=' ')
|
||||
|
||||
if not self.install_binary(pkg):
|
||||
print(' -> Failed...')
|
||||
return
|
||||
|
||||
self.create_zip (self.pkg_win32)
|
||||
self.http_pull (self.pkg_win32_sfx_url, "botsetup.exe")
|
||||
if dest.endswith('zip') or dest.endswith('exe'):
|
||||
if pkg.extra:
|
||||
dest_dir = os.path.join(self.bot_dir, 'bin')
|
||||
self.create_zip(dest_tmp, dest_dir)
|
||||
else:
|
||||
self.create_zip(dest_tmp)
|
||||
|
||||
print ("Generating Win32 EXE")
|
||||
if dest.endswith('exe'):
|
||||
self.convert_zip_sfx(dest_tmp, dest)
|
||||
else:
|
||||
shutil.move(dest_tmp, dest)
|
||||
elif dest.endswith('tar.xz'):
|
||||
self.create_zip(dest_tmp)
|
||||
self.convert_zip_txz(dest_tmp, dest)
|
||||
|
||||
with open ("botsetup.exe", "rb") as sfx, open (self.pkg_win32, "rb") as zfn, open (self.pkg_win32_sfx, "wb") as exe:
|
||||
exe.write (sfx.read ())
|
||||
exe.write (zfn.read ())
|
||||
print('-> Success...')
|
||||
self.unlink_binaries()
|
||||
|
||||
self.sign_binary (self.pkg_win32_sfx)
|
||||
if os.path.exists(dest_tmp):
|
||||
os.remove(dest_tmp)
|
||||
|
||||
def create_pkg_linux (self):
|
||||
print ("Generating Linux TXZ")
|
||||
def create_pkgs(self):
|
||||
for pkg in self.pkg_matrix:
|
||||
self.create_pkg(pkg)
|
||||
|
||||
self.unlink_binaries ()
|
||||
self.install_binary ("arm64.so")
|
||||
print('Finished release')
|
||||
|
||||
if not self.install_binary ("so", False):
|
||||
return
|
||||
@staticmethod
|
||||
def run():
|
||||
r = BotRelease()
|
||||
|
||||
tmp_file = "tmp.zip"
|
||||
|
||||
self.create_zip (tmp_file)
|
||||
self.convert_zip_txz (tmp_file, self.pkg_linux)
|
||||
|
||||
def create_pkg_macos (self):
|
||||
print ("Generating macOS ZIP")
|
||||
|
||||
if not self.install_binary ("dylib"):
|
||||
return
|
||||
|
||||
self.create_zip (self.pkg_macos)
|
||||
|
||||
def create_pkgs (self):
|
||||
self.create_pkg_linux ()
|
||||
self.create_pkg_win32 ()
|
||||
self.create_pkg_macos ()
|
||||
|
||||
release = BotRelease ()
|
||||
|
||||
release.make_directories ()
|
||||
release.get_default_graphs ()
|
||||
release.create_pkgs ()
|
||||
r.create_dirs()
|
||||
r.create_graphs()
|
||||
r.create_pkgs()
|
||||
|
||||
# entry point
|
||||
if __name__ == "__main__":
|
||||
BotRelease.run()
|
||||
120
src/botlib.cpp
120
src/botlib.cpp
|
|
@ -71,8 +71,8 @@ void Bot::pushMsgQueue (int message) {
|
|||
}
|
||||
|
||||
float Bot::isInFOV (const Vector &destination) {
|
||||
float entityAngle = cr::modAngles (destination.yaw ()); // find yaw angle from source to destination...
|
||||
float viewAngle = cr::modAngles (pev->v_angle.y); // get bot's current view angle...
|
||||
float entityAngle = cr::wrapAngle360 (destination.yaw ()); // find yaw angle from source to destination...
|
||||
float viewAngle = cr::wrapAngle360 (pev->v_angle.y); // get bot's current view angle...
|
||||
|
||||
// return the absolute value of angle to destination entity
|
||||
// zero degrees means straight ahead, 45 degrees to the left or
|
||||
|
|
@ -232,7 +232,8 @@ void Bot::checkGrenadesThrow () {
|
|||
}
|
||||
break;
|
||||
|
||||
case Weapon::Flashbang: {
|
||||
case Weapon::Flashbang:
|
||||
{
|
||||
int nearest = graph.getNearest ((m_lastEnemy->v.velocity * 0.5f).get2d () + m_lastEnemy->v.origin);
|
||||
|
||||
if (nearest != kInvalidNodeIndex) {
|
||||
|
|
@ -339,7 +340,7 @@ void Bot::avoidGrenades () {
|
|||
if (m_preventFlashing < game.time () && m_personality == Personality::Rusher && m_difficulty == Difficulty::Expert && strcmp (model, "flashbang.mdl") == 0) {
|
||||
// don't look at flash bang
|
||||
if (!(m_states & Sense::SeeingEnemy)) {
|
||||
m_lookAt.y = cr::normalizeAngles ((game.getEntityOrigin (pent) - getEyesPos ()).angles ().y + 180.0f);
|
||||
m_lookAt.y = cr::wrapAngle ((game.getEntityOrigin (pent) - getEyesPos ()).angles ().y + 180.0f);
|
||||
|
||||
m_canChooseAimDirection = false;
|
||||
m_preventFlashing = game.time () + rg.get (1.0f, 2.0f);
|
||||
|
|
@ -636,6 +637,7 @@ void Bot::updatePickups () {
|
|||
const auto &config = conf.getWeapons ();
|
||||
const auto &primary = config[primaryWeaponCarried];
|
||||
const auto &secondary = config[secondaryWeaponCarried];
|
||||
|
||||
const auto &primaryProp = conf.getWeaponProp (primary.id);
|
||||
const auto &secondaryProp = conf.getWeaponProp (secondary.id);
|
||||
|
||||
|
|
@ -950,7 +952,7 @@ void Bot::showChaterIcon (bool show) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto sendBotVoice = [] (bool show, edict_t *ent, int ownId) {
|
||||
auto sendBotVoice = [&show] (edict_t *ent, int ownId) {
|
||||
MessageWriter (MSG_ONE, msgs.id (NetMsg::BotVoice), nullptr, ent) // begin message
|
||||
.writeByte (show) // switch on/off
|
||||
.writeByte (ownId);
|
||||
|
|
@ -964,13 +966,13 @@ void Bot::showChaterIcon (bool show) {
|
|||
}
|
||||
|
||||
if (!show && (client.iconFlags[ownIndex] & ClientFlags::Icon) && client.iconTimestamp[ownIndex] < game.time ()) {
|
||||
sendBotVoice (false, client.ent, entindex ());
|
||||
sendBotVoice (client.ent, entindex ());
|
||||
|
||||
client.iconTimestamp[ownIndex] = 0.0f;
|
||||
client.iconFlags[ownIndex] &= ~ClientFlags::Icon;
|
||||
}
|
||||
else if (show && !(client.iconFlags[ownIndex] & ClientFlags::Icon)) {
|
||||
sendBotVoice (true, client.ent, entindex ());
|
||||
sendBotVoice (client.ent, entindex ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1225,43 +1227,36 @@ bool Bot::isWeaponRestrictedAMX (int weaponIndex) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check for weapon restrictions
|
||||
if (cr::bit (weaponIndex) & (kPrimaryWeaponMask | kSecondaryWeaponMask | Weapon::Shield)) {
|
||||
auto restrictedWeapons = game.findCvar ("amx_restrweapons");
|
||||
auto checkRestriction = [&weaponIndex] (StringRef cvar, const int *data) -> bool {
|
||||
auto restrictedWeapons = game.findCvar (cvar);
|
||||
|
||||
if (restrictedWeapons.empty ()) {
|
||||
return false;
|
||||
}
|
||||
constexpr int indices[] = { 4, 25, 20, -1, 8, -1, 12, 19, -1, 5, 6, 13, 23, 17, 18, 1, 2, 21, 9, 24, 7, 16, 10, 22, -1, 3, 15, 14, 0, 11 };
|
||||
|
||||
// find the weapon index
|
||||
int index = indices[weaponIndex - 1];
|
||||
int index = data[weaponIndex - 1];
|
||||
|
||||
// validate index range
|
||||
if (index < 0 || index >= static_cast <int> (restrictedWeapons.length ())) {
|
||||
return false;
|
||||
}
|
||||
return restrictedWeapons[index] != '0';
|
||||
return restrictedWeapons[static_cast <size_t> (index)] != '0';
|
||||
};
|
||||
|
||||
// check for weapon restrictions
|
||||
if (cr::bit (weaponIndex) & (kPrimaryWeaponMask | kSecondaryWeaponMask | Weapon::Shield)) {
|
||||
constexpr int ids[] = { 4, 25, 20, -1, 8, -1, 12, 19, -1, 5, 6, 13, 23, 17, 18, 1, 2, 21, 9, 24, 7, 16, 10, 22, -1, 3, 15, 14, 0, 11 };
|
||||
|
||||
// verify restrictions
|
||||
return checkRestriction ("amx_restrweapons", ids);
|
||||
}
|
||||
|
||||
// check for equipment restrictions
|
||||
else {
|
||||
auto restrictedEquipment = game.findCvar ("amx_restrequipammo");
|
||||
constexpr int ids[] = { -1, -1, -1, 3, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 0, 1, 5 };
|
||||
|
||||
if (restrictedEquipment.empty ()) {
|
||||
return false;
|
||||
}
|
||||
constexpr int indices[] = { -1, -1, -1, 3, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 0, 1, 5 };
|
||||
|
||||
// find the weapon index
|
||||
int index = indices[weaponIndex - 1];
|
||||
|
||||
// validate index range
|
||||
if (index < 0 || index >= static_cast <int> (restrictedEquipment.length ())) {
|
||||
return false;
|
||||
}
|
||||
return restrictedEquipment[index] != '0';
|
||||
// verify restrictions
|
||||
return checkRestriction ("amx_restrequipammo", ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1294,7 +1289,7 @@ int Bot::pickBestWeapon (int *vec, int count, int moneySave) {
|
|||
bool needMoreRandomWeapon = (m_personality == Personality::Careful) || (rg.chance (25) && m_personality == Personality::Normal);
|
||||
|
||||
if (needMoreRandomWeapon) {
|
||||
auto buyFactor = (m_moneyAmount - static_cast <float> (moneySave)) / (16000.0f - static_cast <float> (moneySave)) * 3.0f;
|
||||
auto buyFactor = (static_cast <float> (m_moneyAmount) - static_cast <float> (moneySave)) / (16000.0f - static_cast <float> (moneySave)) * 3.0f;
|
||||
|
||||
if (buyFactor < 1.0f) {
|
||||
buyFactor = 1.0f;
|
||||
|
|
@ -1537,7 +1532,7 @@ void Bot::buyStuff () {
|
|||
break;
|
||||
|
||||
case BuyState::ArmorVestHelm: // if armor is damaged and bot has some money, buy some armor
|
||||
if (pev->armorvalue < rg.get (50, 80) && teamHasGoodEconomics && (isPistolMode || (teamHasGoodEconomics && hasPrimaryWeapon ()))) {
|
||||
if (pev->armorvalue < rg.get (50.0f, 80.0f) && teamHasGoodEconomics && (isPistolMode || (teamHasGoodEconomics && hasPrimaryWeapon ()))) {
|
||||
// if bot is rich, buy kevlar + helmet, else buy a single kevlar
|
||||
if (m_moneyAmount > 1500 && !isWeaponRestricted (Weapon::ArmorHelm)) {
|
||||
issueCommand ("buyequip;menuselect 2");
|
||||
|
|
@ -1988,7 +1983,7 @@ void Bot::filterTasks () {
|
|||
timeHeard += 10.0f;
|
||||
ratio = timeHeard * 0.1f;
|
||||
}
|
||||
bool lowAmmo = m_ammoInClip[m_currentWeapon] < conf.findWeaponById (m_currentWeapon).maxClip * 0.18f;
|
||||
bool lowAmmo = isLowOnAmmo (m_currentWeapon, 0.18f);
|
||||
bool sniping = m_sniperStopTime <= game.time () && lowAmmo;
|
||||
|
||||
if (bots.isBombPlanted () || m_isStuck || usesKnife ()) {
|
||||
|
|
@ -2169,6 +2164,10 @@ BotTask *Bot::getTask () {
|
|||
return &m_tasks.last ();
|
||||
}
|
||||
|
||||
bool Bot::isLowOnAmmo (const int id, const float factor) const {
|
||||
return static_cast <float> (m_ammoInClip[id]) < static_cast <float> (conf.findWeaponById (id).maxClip) * factor;
|
||||
}
|
||||
|
||||
void Bot::clearTask (Task id) {
|
||||
// this function removes one task from the bot task stack.
|
||||
|
||||
|
|
@ -2868,7 +2867,7 @@ void Bot::updateAimDir () {
|
|||
auto radius = graph[index].radius;
|
||||
|
||||
if (radius > 0.0f) {
|
||||
return Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (2.0f, 4.0f);
|
||||
return Vector (pev->angles.x, cr::wrapAngle (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (2.0f, 4.0f);
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
|
@ -3952,7 +3951,7 @@ void Bot::defuseBomb_ () {
|
|||
graph.setBombOrigin (true);
|
||||
|
||||
if (m_numFriendsLeft != 0 && rg.chance (50)) {
|
||||
if (timeToBlowUp <= 3.0) {
|
||||
if (timeToBlowUp <= 3.0f) {
|
||||
if (cv_radio_mode.int_ () == 2) {
|
||||
pushChatterMessage (Chatter::BarelyDefused);
|
||||
}
|
||||
|
|
@ -4016,7 +4015,7 @@ void Bot::defuseBomb_ () {
|
|||
selectWeaponByName ("weapon_knife");
|
||||
|
||||
if (weaponIndex > 0 && weaponIndex < kNumWeapons) {
|
||||
selectWeaponById (weaponIndex);
|
||||
selectWeaponByIndex (weaponIndex);
|
||||
}
|
||||
m_isReloading = false;
|
||||
}
|
||||
|
|
@ -4588,16 +4587,16 @@ void Bot::pickupItem_ () {
|
|||
|
||||
if (index < 7) {
|
||||
// secondary weapon. i.e., pistol
|
||||
int wid = 0;
|
||||
int weaponIndex = 0;
|
||||
|
||||
for (index = 0; index < 7; ++index) {
|
||||
if (pev->weapons & cr::bit (info[index].id)) {
|
||||
wid = index;
|
||||
weaponIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
if (wid > 0) {
|
||||
selectWeaponById (wid);
|
||||
if (weaponIndex > 0) {
|
||||
selectWeaponByIndex (weaponIndex);
|
||||
issueCommand ("drop");
|
||||
|
||||
if (hasShield ()) {
|
||||
|
|
@ -4608,15 +4607,17 @@ void Bot::pickupItem_ () {
|
|||
}
|
||||
else {
|
||||
// primary weapon
|
||||
int wid = bestWeaponCarried ();
|
||||
int weaponIndex = bestWeaponCarried ();
|
||||
bool niceWeapon = rateGroundWeapon (m_pickupItem);
|
||||
|
||||
if ((wid == Weapon::Shield || wid > 6 || hasShield ()) && niceWeapon) {
|
||||
selectWeaponById (wid);
|
||||
auto tab = conf.getRawWeapons ();
|
||||
|
||||
if ((tab->id == Weapon::Shield || weaponIndex > 6 || hasShield ()) && niceWeapon) {
|
||||
selectWeaponByIndex (weaponIndex);
|
||||
issueCommand ("drop");
|
||||
}
|
||||
|
||||
if (!wid || !niceWeapon) {
|
||||
if (!weaponIndex || !niceWeapon) {
|
||||
m_itemIgnore = m_pickupItem;
|
||||
m_pickupItem = nullptr;
|
||||
m_pickupType = Pickup::None;
|
||||
|
|
@ -4640,10 +4641,10 @@ void Bot::pickupItem_ () {
|
|||
// near to shield?
|
||||
else if (itemDistance < 50.0f) {
|
||||
// get current best weapon to check if it's a primary in need to be dropped
|
||||
int wid = bestWeaponCarried ();
|
||||
int weaponIndex = bestWeaponCarried ();
|
||||
|
||||
if (wid > 6) {
|
||||
selectWeaponById (wid);
|
||||
if (weaponIndex > 6) {
|
||||
selectWeaponByIndex (weaponIndex);
|
||||
issueCommand ("drop");
|
||||
}
|
||||
}
|
||||
|
|
@ -5059,7 +5060,7 @@ void Bot::logic () {
|
|||
pev->button &= ~IN_DUCK;
|
||||
|
||||
m_moveSpeed = -pev->maxspeed;
|
||||
m_strafeSpeed = pev->maxspeed * m_needAvoidGrenade;
|
||||
m_strafeSpeed = pev->maxspeed * static_cast <float> (m_needAvoidGrenade);
|
||||
}
|
||||
|
||||
// time to reach waypoint
|
||||
|
|
@ -5222,11 +5223,11 @@ void Bot::showDebugOverlay () {
|
|||
}
|
||||
String aimFlags;
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
bool hasFlag = m_aimFlags & cr::bit (i);
|
||||
for (uint32 i = 0u; i < 9u; ++i) {
|
||||
auto bit = cr::bit (i);
|
||||
|
||||
if (hasFlag) {
|
||||
aimFlags.appendf (" %s", flags[cr::bit (i)]);
|
||||
if (m_aimFlags & bit) {
|
||||
aimFlags.appendf (" %s", flags[static_cast <int32> (bit)]);
|
||||
}
|
||||
}
|
||||
auto weapon = util.weaponIdToAlias (m_currentWeapon);
|
||||
|
|
@ -5289,7 +5290,11 @@ bool Bot::hasHostage () {
|
|||
}
|
||||
|
||||
int Bot::getAmmo () {
|
||||
const auto &prop = conf.getWeaponProp (m_currentWeapon);
|
||||
return getAmmo (m_currentWeapon);
|
||||
}
|
||||
|
||||
int Bot::getAmmo (int id) {
|
||||
const auto &prop = conf.getWeaponProp (id);
|
||||
|
||||
if (prop.ammo1 == -1 || prop.ammo1 > kMaxWeapons - 1) {
|
||||
return 0;
|
||||
|
|
@ -5408,11 +5413,12 @@ void Bot::updatePracticeValue (int damage) {
|
|||
if (graph.length () < 1 || graph.hasChanged () || m_chosenGoalIndex < 0 || m_prevGoalIndex < 0) {
|
||||
return;
|
||||
}
|
||||
auto health = static_cast <int> (m_healthValue);
|
||||
|
||||
// only rate goal waypoint if bot died because of the damage
|
||||
// FIXME: could be done a lot better, however this cares most about damage done by sniping or really deadly weapons
|
||||
if (m_healthValue - damage <= 0) {
|
||||
graph.setDangerValue (m_team, m_chosenGoalIndex, m_prevGoalIndex, cr::clamp (graph.getDangerValue (m_team, m_chosenGoalIndex, m_prevGoalIndex) - static_cast <int> (m_healthValue / 20), -kMaxPracticeGoalValue, kMaxPracticeGoalValue));
|
||||
if (health - damage <= 0) {
|
||||
graph.setDangerValue (m_team, m_chosenGoalIndex, m_prevGoalIndex, cr::clamp (graph.getDangerValue (m_team, m_chosenGoalIndex, m_prevGoalIndex) - health / 20, -kMaxPracticeGoalValue, kMaxPracticeGoalValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5453,10 +5459,10 @@ void Bot::updatePracticeDamage (edict_t *attacker, int damage) {
|
|||
graph.setDangerDamage (victimIndex, victimIndex, victimIndex, cr::clamp (graph.getDangerDamage (victimTeam, victimIndex, victimIndex), 0, kMaxPracticeDamageValue));
|
||||
}
|
||||
}
|
||||
float updateDamage = util.isFakeClient (attacker) ? 10.0f : 7.0f;
|
||||
auto updateDamage = util.isFakeClient (attacker) ? 10 : 7;
|
||||
|
||||
// store away the damage done
|
||||
int damageValue = cr::clamp (graph.getDangerDamage (m_team, victimIndex, attackerIndex) + static_cast <int> (damage / updateDamage), 0, kMaxPracticeDamageValue);
|
||||
int damageValue = cr::clamp (graph.getDangerDamage (m_team, victimIndex, attackerIndex) + damage / updateDamage, 0, kMaxPracticeDamageValue);
|
||||
|
||||
if (damageValue > graph.getHighestDamageForTeam (m_team)) {
|
||||
graph.setHighestDamageForTeam (m_team, damageValue);
|
||||
|
|
@ -6047,7 +6053,7 @@ float Bot::getShiftSpeed () {
|
|||
if (getCurrentTaskId () == Task::SeekCover || (pev->flags & FL_DUCKING) || (pev->button & IN_DUCK) || (m_oldButtons & IN_DUCK) || (m_currentTravelFlags & PathFlag::Jump) || (m_path != nullptr && m_path->flags & NodeFlag::Ladder) || isOnLadder () || isInWater () || m_isStuck) {
|
||||
return pev->maxspeed;
|
||||
}
|
||||
return static_cast <float> (pev->maxspeed * 0.4f);
|
||||
return pev->maxspeed * 0.4f;
|
||||
}
|
||||
|
||||
void Bot::calculateFrustum () {
|
||||
|
|
|
|||
|
|
@ -61,12 +61,12 @@ void BotSupport::addChatErrors (String &line) {
|
|||
|
||||
// "length / 2" percent of time drop a character
|
||||
if (rg.chance (percentile)) {
|
||||
line.erase (rg.get (length / 8, length - length / 8), 1);
|
||||
line.erase (static_cast <size_t> (rg.get (length / 8, length - length / 8), 1));
|
||||
}
|
||||
|
||||
// "length" / 4 precent of time swap character
|
||||
if (rg.chance (percentile / 2)) {
|
||||
size_t pos = rg.get (length / 8, 3 * length / 8); // choose random position in string
|
||||
size_t pos = static_cast <size_t> (rg.get (length / 8, 3 * length / 8)); // choose random position in string
|
||||
cr::swap (line[pos], line[pos + 1]);
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ void Bot::prepareChatMessage (StringRef message) {
|
|||
|
||||
// get bot's victim
|
||||
auto getMyVictim = [&] () -> String {;
|
||||
return humanizedName (game.indexOfPlayer (m_lastVictim));
|
||||
return humanizedName (game.indexOfPlayer (m_lastVictim));
|
||||
};
|
||||
|
||||
// get the game name alias
|
||||
|
|
|
|||
|
|
@ -461,8 +461,8 @@ Vector Bot::getBodyOffsetError (float distance) {
|
|||
}
|
||||
|
||||
if (m_aimErrorTime < game.time ()) {
|
||||
const float error = distance / (cr::clamp (m_difficulty, 1, 3) * 1000.0f);
|
||||
Vector &maxs = m_enemy->v.maxs, &mins = m_enemy->v.mins;
|
||||
const float error = distance / (cr::clamp (static_cast <float> (m_difficulty), 1.0f, 3.0f) * 1000.0f);
|
||||
auto &maxs = m_enemy->v.maxs, &mins = m_enemy->v.mins;
|
||||
|
||||
m_aimLastError = Vector (rg.get (mins.x * error, maxs.x * error), rg.get (mins.y * error, maxs.y * error), rg.get (mins.z * error, maxs.z * error));
|
||||
m_aimErrorTime = game.time () + rg.get (1.0f, 1.2f);
|
||||
|
|
@ -728,7 +728,7 @@ bool Bot::needToPauseFiring (float distance) {
|
|||
const float yPunch = cr::deg2rad (pev->punchangle.y);
|
||||
|
||||
const float interval = getFrameInterval ();
|
||||
const float tolerance = (100.0f - m_difficulty * 25.0f) / 99.0f;
|
||||
const float tolerance = (100.0f - static_cast <float> (m_difficulty) * 25.0f) / 99.0f;
|
||||
|
||||
// check if we need to compensate recoil
|
||||
if (cr::tanf (cr::sqrtf (cr::abs (xPunch * xPunch) + cr::abs (yPunch * yPunch))) * distance > offset + 30.0f + tolerance) {
|
||||
|
|
@ -848,10 +848,8 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
const auto &prop = conf.getWeaponProp (tab[index].id);
|
||||
|
||||
// if automatic weapon press attack
|
||||
if (tab[choosen].primaryFireHold && m_ammo[prop.ammo1] > tab[index].minPrimaryAmmo) {
|
||||
if (tab[choosen].primaryFireHold && getAmmo (tab[index].id) > tab[index].minPrimaryAmmo) {
|
||||
pev->button |= IN_ATTACK;
|
||||
}
|
||||
|
||||
|
|
@ -953,9 +951,7 @@ void Bot::fireWeapons () {
|
|||
|
||||
// is the bot carrying this weapon?
|
||||
if (weapons & cr::bit (id)) {
|
||||
const auto &prop = conf.getWeaponProp (id);
|
||||
|
||||
if (prop.ammo1 != -1 && prop.ammo1 < kMaxWeapons && m_ammo[prop.ammo1] >= tab[selectIndex].minPrimaryAmmo) {
|
||||
if (getAmmo (id) >= tab[selectIndex].minPrimaryAmmo) {
|
||||
|
||||
// available ammo found, reload weapon
|
||||
if (m_reloadState == Reload::None || m_reloadCheckTime > game.time ()) {
|
||||
|
|
@ -1431,10 +1427,9 @@ void Bot::selectBestWeapon () {
|
|||
if (tab[selectIndex].id == m_currentWeapon && (getAmmoInClip () < 0 || getAmmoInClip () >= tab[selectIndex].minPrimaryAmmo)) {
|
||||
ammoLeft = true;
|
||||
}
|
||||
const auto &prop = conf.getWeaponProp (id);
|
||||
|
||||
// is no ammo required for this weapon OR enough ammo available to fire
|
||||
if (prop.ammo1 < 0 || (prop.ammo1 < kMaxWeapons && m_ammo[prop.ammo1] >= tab[selectIndex].minPrimaryAmmo)) {
|
||||
if (getAmmo (id) >= tab[selectIndex].minPrimaryAmmo) {
|
||||
ammoLeft = true;
|
||||
}
|
||||
|
||||
|
|
@ -1485,14 +1480,13 @@ int Bot::bestWeaponCarried () {
|
|||
return num;
|
||||
}
|
||||
|
||||
void Bot::selectWeaponByName (const char *name) {
|
||||
issueCommand (name);
|
||||
void Bot::selectWeaponByName (StringRef name) {
|
||||
issueCommand (name.chars ());
|
||||
}
|
||||
|
||||
void Bot::selectWeaponById (int num) {
|
||||
void Bot::selectWeaponByIndex (int index) {
|
||||
auto tab = conf.getRawWeapons ();
|
||||
|
||||
issueCommand (tab[num].name);
|
||||
issueCommand (tab[index].name);
|
||||
}
|
||||
|
||||
void Bot::decideFollowUser () {
|
||||
|
|
@ -1599,7 +1593,7 @@ void Bot::checkReload () {
|
|||
m_reloadCheckTime = game.time () + 3.0f;
|
||||
|
||||
if (m_reloadState != Reload::None) {
|
||||
int weaponIndex = 0;
|
||||
int wid = 0;
|
||||
int weapons = pev->weapons;
|
||||
|
||||
if (m_reloadState == Reload::Primary) {
|
||||
|
|
@ -1620,15 +1614,15 @@ void Bot::checkReload () {
|
|||
|
||||
for (int i = 1; i < kMaxWeapons; ++i) {
|
||||
if (weapons & cr::bit (i)) {
|
||||
weaponIndex = i;
|
||||
wid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const auto &prop = conf.getWeaponProp (weaponIndex);
|
||||
const auto &prop = conf.getWeaponProp (wid);
|
||||
|
||||
if (m_ammoInClip[weaponIndex] < conf.findWeaponById (weaponIndex).maxClip * 0.8f && prop.ammo1 != -1 && prop.ammo1 < kMaxWeapons && m_ammo[prop.ammo1] > 0) {
|
||||
if (m_currentWeapon != weaponIndex) {
|
||||
selectWeaponByName (prop.classname.chars ());
|
||||
if (isLowOnAmmo (prop.id, 0.75f) && getAmmo (prop.id) > 0) {
|
||||
if (m_currentWeapon != prop.id) {
|
||||
selectWeaponByName (prop.classname);
|
||||
}
|
||||
pev->button &= ~IN_ATTACK;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ void BotConfig::loadMainConfig (bool isFirstLoad) {
|
|||
}
|
||||
file.close ();
|
||||
}
|
||||
else {
|
||||
game.serverCommand (strings.format ("%s cvars save", product.cmdPri));
|
||||
}
|
||||
|
||||
// android is abit hard to play, lower the difficulty by default
|
||||
if (plat.android && cv_difficulty.int_ () > 3) {
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ int BotControl::cmdKickBot () {
|
|||
enum args { alias = 1, team };
|
||||
|
||||
// if team is specified, kick from specified tram
|
||||
if (strValue (alias).find ("_ct", 0) != String::InvalidIndex || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
if (strValue (alias).endsWith ("_ct") || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
bots.kickFromTeam (Team::CT);
|
||||
}
|
||||
else if (strValue (alias).find ("_t", 0) != String::InvalidIndex || intValue (team) == 1 || strValue (team) == "t") {
|
||||
else if (strValue (alias).endsWith ("_t") || intValue (team) == 1 || strValue (team) == "t") {
|
||||
bots.kickFromTeam (Team::Terrorist);
|
||||
}
|
||||
else {
|
||||
|
|
@ -73,10 +73,10 @@ int BotControl::cmdKillBots () {
|
|||
enum args { alias = 1, team, max };
|
||||
|
||||
// if team is specified, kick from specified tram
|
||||
if (strValue (alias).find ("_ct", 0) != String::InvalidIndex || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
if (strValue (alias).endsWith ("_ct") || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
bots.killAllBots (Team::CT);
|
||||
}
|
||||
else if (strValue (alias).find ("_t", 0) != String::InvalidIndex || intValue (team) == 1 || strValue (team) == "t") {
|
||||
else if (strValue (alias).endsWith ("_t") || intValue (team) == 1 || strValue (team) == "t") {
|
||||
bots.killAllBots (Team::Terrorist);
|
||||
}
|
||||
else {
|
||||
|
|
@ -488,7 +488,7 @@ int BotControl::cmdNodeSave () {
|
|||
else {
|
||||
if (graph.checkNodes (false)) {
|
||||
graph.saveGraphData ();
|
||||
msg ("All nodes has been saved and written to disk.");
|
||||
msg ("All nodes has been saved and written to disk.\n*** Please don't forget to share your work by typing \"%s g upload\". Thank you! ***", product.cmdPri);
|
||||
}
|
||||
else {
|
||||
msg ("Could not save save nodes to disk. Graph check has failed.");
|
||||
|
|
@ -1943,7 +1943,7 @@ void BotControl::kickBotByMenu (int page) {
|
|||
|
||||
for (auto &menu : m_menus) {
|
||||
if (menu.ident == id) {
|
||||
menu.slots = menuKeys & static_cast <uint32> (-1);
|
||||
menu.slots = static_cast <int> (static_cast <uint32> (menuKeys) & static_cast <uint32> (-1));
|
||||
menu.text = menus;
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ void Game::checkCvarsBounds () {
|
|||
if (is (GameFlags::Xash3D)) {
|
||||
static cvar_t *sv_forcesimulating = engfuncs.pfnCVarGetPointer ("sv_forcesimulating");
|
||||
|
||||
if (sv_forcesimulating && sv_forcesimulating->value != 1.0f) {
|
||||
if (sv_forcesimulating && !cr::fequal (sv_forcesimulating->value, 1.0f)) {
|
||||
game.print ("Force-enable Xash3D sv_forcesimulating cvar.");
|
||||
engfuncs.pfnCVarSetFloat ("sv_forcesimulating", 1.0f);
|
||||
}
|
||||
|
|
@ -798,7 +798,7 @@ bool Game::loadCSBinary () {
|
|||
auto entity = m_gameLib.resolve <EntityFunction> ("weapon_famas");
|
||||
|
||||
// detect xash engine
|
||||
if (engfuncs.pfnCVarGetPointer ("build") != nullptr) {
|
||||
if (engfuncs.pfnCVarGetPointer ("host_ver") != nullptr) {
|
||||
m_gameFlags |= (GameFlags::Legacy | GameFlags::Xash3D);
|
||||
|
||||
if (entity != nullptr) {
|
||||
|
|
@ -1035,7 +1035,7 @@ bool Game::isShootableBreakable (edict_t *ent) {
|
|||
auto limit = cv_breakable_health_limit.float_ ();
|
||||
|
||||
if ((strcmp (ent->v.classname.chars (), "func_breakable") == 0 && ent->v.health < limit) || (strcmp (ent->v.classname.chars (), "func_pushable") == 0 && (ent->v.spawnflags & SF_PUSH_BREAKABLE) && ent->v.health < limit) || (strcmp (ent->v.classname.chars (), "func_wall") == 0 && ent->v.health < limit)) {
|
||||
if (ent->v.takedamage != DAMAGE_NO && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY)) {
|
||||
if (ent->v.takedamage > 0.0f && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY)) {
|
||||
return (ent->v.movetype == MOVETYPE_PUSH || ent->v.movetype == MOVETYPE_PUSHSTEP);
|
||||
}
|
||||
}
|
||||
|
|
@ -1112,8 +1112,7 @@ void LightMeasure::animateLight () {
|
|||
m_lightstyleValue[j] = 256;
|
||||
continue;
|
||||
}
|
||||
int value = m_lightstyle[j].map[index % m_lightstyle[j].length] - 'a';
|
||||
m_lightstyleValue[j] = value * 22;
|
||||
m_lightstyleValue[j] = static_cast <uint32> (m_lightstyle[j].map[index % m_lightstyle[j].length] - 'a') * 22u;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "1", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
||||
ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "0", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
||||
ConVar cv_graph_url ("yb_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one. Set to empty, if no downloads needed.", false, 0.0f, 0.0f);
|
||||
ConVar cv_graph_auto_save_count ("yb_graph_auto_save_count", "15", "Every N graph nodes placed on map, the graph will be saved automatically (without checks).", true, 0.0f, kMaxNodes);
|
||||
ConVar cv_graph_draw_distance ("yb_graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f);
|
||||
|
|
@ -33,7 +33,6 @@ void BotGraph::reset () {
|
|||
for (int team = Team::Terrorist; team < kGameTeamNum; ++team) {
|
||||
m_highestDamage[team] = 1;
|
||||
}
|
||||
|
||||
m_graphAuthor.clear ();
|
||||
m_graphModified.clear ();
|
||||
}
|
||||
|
|
@ -59,7 +58,7 @@ int BotGraph::clearConnections (int index) {
|
|||
struct Connection {
|
||||
int index {};
|
||||
int number {};
|
||||
int distance {};
|
||||
float distance {};
|
||||
float angles {};
|
||||
|
||||
public:
|
||||
|
|
@ -71,7 +70,7 @@ int BotGraph::clearConnections (int index) {
|
|||
void reset () {
|
||||
index = kInvalidNodeIndex;
|
||||
number = kInvalidNodeIndex;
|
||||
distance = kInfiniteDistanceLong;
|
||||
distance = kInfiniteDistance;
|
||||
angles = 0.0f;
|
||||
}
|
||||
};
|
||||
|
|
@ -86,14 +85,14 @@ int BotGraph::clearConnections (int index) {
|
|||
|
||||
cur.number = i;
|
||||
cur.index = link.index;
|
||||
cur.distance = link.distance;
|
||||
cur.distance = static_cast <float> (link.distance);
|
||||
|
||||
if (cur.index == kInvalidNodeIndex) {
|
||||
cur.distance = kInfiniteDistanceLong;
|
||||
cur.distance = kInfiniteDistance;
|
||||
}
|
||||
|
||||
if (cur.distance < top.distance) {
|
||||
top.distance = link.distance;
|
||||
top.distance = static_cast <float> (link.distance);
|
||||
top.number = i;
|
||||
top.index = cur.index;
|
||||
}
|
||||
|
|
@ -173,7 +172,7 @@ int BotGraph::clearConnections (int index) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((cur.distance + prev2.distance) * 1.1f / 2.0f < static_cast <float> (prev.distance)) {
|
||||
if ((cur.distance + prev2.distance) * 1.1f / 2.0f < prev.distance) {
|
||||
if (path.links[prev.number].index == prev.index) {
|
||||
ctrl.msg ("Removing a useless (P.0.1) connection from index = %d to %d.", index, prev.index);
|
||||
|
||||
|
|
@ -215,7 +214,7 @@ int BotGraph::clearConnections (int index) {
|
|||
// check pass 1
|
||||
if (exists (top.index) && exists (sorted[0].index) && exists (sorted[1].index)) {
|
||||
if ((sorted[1].angles - top.angles < 80.0f || 360.0f - (sorted[1].angles - top.angles) < 80.0f) && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) && !(path.links[sorted[0].number].flags & PathFlag::Jump)) {
|
||||
if ((sorted[1].distance + top.distance) * 1.1f / 2.0f < static_cast <float> (sorted[0].distance)) {
|
||||
if ((sorted[1].distance + top.distance) * 1.1f / 2.0f < sorted[0].distance) {
|
||||
if (path.links[sorted[0].number].index == sorted[0].index) {
|
||||
ctrl.msg ("Removing a useless (P.1.1) connection from index = %d to %d.", index, sorted[0].index);
|
||||
|
||||
|
|
@ -257,7 +256,7 @@ int BotGraph::clearConnections (int index) {
|
|||
}
|
||||
|
||||
if (cur.angles - prev.angles < 40.0f) {
|
||||
if (prev.distance < static_cast <float> (cur.distance * 1.1f)) {
|
||||
if (prev.distance < cur.distance * 1.1f) {
|
||||
|
||||
// leave alone ladder connections and don't remove jump connections..
|
||||
if (((path.flags & NodeFlag::Ladder) && (m_paths[cur.index].flags & NodeFlag::Ladder)) || (path.links[cur.number].flags & PathFlag::Jump)) {
|
||||
|
|
@ -290,7 +289,7 @@ int BotGraph::clearConnections (int index) {
|
|||
ctrl.msg ("Failed to remove a useless (P.2) connection from index = %d to %d.", index, cur.index);
|
||||
}
|
||||
}
|
||||
else if (cur.distance < static_cast <float> (prev.distance * 1.1f)) {
|
||||
else if (cur.distance < prev.distance * 1.1f) {
|
||||
// leave alone ladder connections and don't remove jump connections..
|
||||
if (((path.flags & NodeFlag::Ladder) && (m_paths[prev.index].flags & NodeFlag::Ladder)) || (path.links[prev.number].flags & PathFlag::Jump)) {
|
||||
return false;
|
||||
|
|
@ -338,7 +337,7 @@ int BotGraph::clearConnections (int index) {
|
|||
// check pass 3
|
||||
if (exists (top.index) && exists (sorted[0].index)) {
|
||||
if ((top.angles - sorted[0].angles < 40.0f || (360.0f - top.angles - sorted[0].angles) < 40.0f) && (!(m_paths[sorted[0].index].flags & NodeFlag::Ladder) || !(path.flags & NodeFlag::Ladder)) && !(path.links[sorted[0].number].flags & PathFlag::Jump)) {
|
||||
if (top.distance * 1.1f < static_cast <float> (sorted[0].distance)) {
|
||||
if (top.distance * 1.1f < sorted[0].distance) {
|
||||
if (path.links[sorted[0].number].index == sorted[0].index) {
|
||||
ctrl.msg ("Removing a useless (P.3.1) connection from index = %d to %d.", index, sorted[0].index);
|
||||
|
||||
|
|
@ -364,7 +363,7 @@ int BotGraph::clearConnections (int index) {
|
|||
ctrl.msg ("Failed to remove a useless (P.3) connection from index = %d to %d.", sorted[0].index, index);
|
||||
}
|
||||
}
|
||||
else if (sorted[0].distance * 1.1f < static_cast <float> (top.distance) && !(path.links[top.number].flags & PathFlag::Jump)) {
|
||||
else if (sorted[0].distance * 1.1f < top.distance && !(path.links[top.number].flags & PathFlag::Jump)) {
|
||||
if (path.links[top.number].index == top.index) {
|
||||
ctrl.msg ("Removing a useless (P.3.3) connection from index = %d to %d.", index, sorted[0].index);
|
||||
|
||||
|
|
@ -903,7 +902,7 @@ void BotGraph::setRadius (int index, float radius) {
|
|||
int node = exists (index) ? index : getEditorNearest ();
|
||||
|
||||
if (node != kInvalidNodeIndex) {
|
||||
m_paths[node].radius = static_cast <float> (radius);
|
||||
m_paths[node].radius = radius;
|
||||
|
||||
// play "done" sound...
|
||||
game.playSound (m_editor, "common/wpn_hudon.wav");
|
||||
|
|
@ -1235,7 +1234,7 @@ void BotGraph::calculatePathRadius (int index) {
|
|||
|
||||
break;
|
||||
}
|
||||
direction.y = cr::normalizeAngles (direction.y + static_cast <float> (circleRadius));
|
||||
direction.y = cr::wrapAngle (direction.y + static_cast <float> (circleRadius));
|
||||
}
|
||||
|
||||
if (wayBlocked) {
|
||||
|
|
@ -1362,7 +1361,7 @@ bool BotGraph::loadPathMatrix () {
|
|||
|
||||
if (distance < (matrix + (i * count) + j)->dist) {
|
||||
(matrix + (i * count) + j)->dist = static_cast <int16> (distance);
|
||||
(matrix + (i * count) + j)->index = static_cast <int16> ((matrix + (i * count) + k)->index);
|
||||
(matrix + (i * count) + j)->index = (matrix + (i * count) + k)->index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1625,11 +1624,11 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
|||
logger.error ("Unable to open %s file for writing (filename: '%s').", name, filename);
|
||||
return false;
|
||||
}
|
||||
int32 rawLength = data.template length <int32> () * sizeof (U);
|
||||
auto rawLength = data.length () * sizeof (U);
|
||||
SmallArray <uint8> compressed (rawLength + sizeof (uint8) * ULZ::Excess);
|
||||
|
||||
// try to compress
|
||||
auto compressedLength = ulz.compress (reinterpret_cast <uint8 *> (data.data ()), rawLength, reinterpret_cast <uint8 *> (compressed.data ()));
|
||||
auto compressedLength = static_cast <size_t> (ulz.compress (reinterpret_cast <uint8 *> (data.data ()), static_cast <int32> (rawLength), reinterpret_cast <uint8 *> (compressed.data ())));
|
||||
|
||||
if (compressedLength > 0) {
|
||||
StorageHeader hdr {};
|
||||
|
|
@ -1638,8 +1637,8 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
|||
hdr.version = version;
|
||||
hdr.options = options;
|
||||
hdr.length = length ();
|
||||
hdr.compressed = compressedLength;
|
||||
hdr.uncompressed = rawLength;
|
||||
hdr.compressed = static_cast <int32> (compressedLength);
|
||||
hdr.uncompressed = static_cast <int32> (rawLength);
|
||||
|
||||
file.write (&hdr, sizeof (StorageHeader));
|
||||
file.write (compressed.data (), sizeof (uint8), compressedLength);
|
||||
|
|
@ -1788,15 +1787,18 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
|||
if ((hdr.options & options) != options) {
|
||||
return raiseLoadingError (isGraph, file, "Incorrect storage format for %s (filename: '%s').", name, filename);
|
||||
}
|
||||
SmallArray <uint8> compressed (hdr.compressed + sizeof (uint8) * ULZ::Excess);
|
||||
auto compressedSize = static_cast <size_t> (hdr.compressed);
|
||||
auto numberNodes = static_cast <size_t> (hdr.length);
|
||||
|
||||
SmallArray <uint8> compressed (compressedSize + sizeof (uint8) * ULZ::Excess);
|
||||
|
||||
// graph is not resized upon load
|
||||
if (isGraph) {
|
||||
resizeData (hdr.length);
|
||||
resizeData (numberNodes);
|
||||
}
|
||||
|
||||
// read compressed data
|
||||
if (file.read (compressed.data (), sizeof (uint8), hdr.compressed) == static_cast <size_t> (hdr.compressed)) {
|
||||
if (file.read (compressed.data (), sizeof (uint8), compressedSize) == compressedSize) {
|
||||
|
||||
// try to uncompress
|
||||
if (ulz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast <uint8 *> (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) {
|
||||
|
|
@ -1837,6 +1839,7 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
|||
else {
|
||||
return raiseLoadingError (isGraph, file, "Unable to read ULZ data for %s (filename: '%s').", name, filename);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BotGraph::loadGraphData () {
|
||||
|
|
@ -2031,7 +2034,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
|||
game.testLine (sourceNew, destinationNew, TraceIgnore::Monsters, m_editor, &tr);
|
||||
|
||||
// check if we didn't hit anything, if not then it's in mid-air
|
||||
if (tr.flFraction >= 1.0) {
|
||||
if (tr.flFraction >= 1.0f) {
|
||||
return false; // can't reach this one
|
||||
}
|
||||
}
|
||||
|
|
@ -2143,10 +2146,10 @@ void BotGraph::rebuildVisibility () {
|
|||
res &= 2;
|
||||
}
|
||||
}
|
||||
shift = (path.number % 4) << 1;
|
||||
shift = static_cast <uint8> ((path.number % 4) << 1);
|
||||
|
||||
m_vistable[vis.number * m_paths.length () + path.number] &= ~(3 << shift);
|
||||
m_vistable[vis.number * m_paths.length () + path.number] |= res << shift;
|
||||
m_vistable[vis.number * length () + path.number] &= static_cast <uint8> (~(3 << shift));
|
||||
m_vistable[vis.number * length () + path.number] |= res << shift;
|
||||
|
||||
if (!(res & 2)) {
|
||||
++crouchCount;
|
||||
|
|
@ -2168,7 +2171,7 @@ bool BotGraph::isVisible (int srcIndex, int destIndex) {
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8 res = m_vistable[srcIndex * m_paths.length () + destIndex];
|
||||
uint8 res = m_vistable[srcIndex * length () + destIndex];
|
||||
res >>= (destIndex % 4) << 1;
|
||||
|
||||
return !((res & 3) == 3);
|
||||
|
|
@ -2179,7 +2182,7 @@ bool BotGraph::isDuckVisible (int srcIndex, int destIndex) {
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8 res = m_vistable[srcIndex * m_paths.length () + destIndex];
|
||||
uint8 res = m_vistable[srcIndex * length () + destIndex];
|
||||
res >>= (destIndex % 4) << 1;
|
||||
|
||||
return !((res & 2) == 2);
|
||||
|
|
@ -2190,7 +2193,7 @@ bool BotGraph::isStandVisible (int srcIndex, int destIndex) {
|
|||
return false;
|
||||
}
|
||||
|
||||
uint8 res = m_vistable[srcIndex * m_paths.length () + destIndex];
|
||||
uint8 res = m_vistable[srcIndex * length () + destIndex];
|
||||
res >>= (destIndex % 4) << 1;
|
||||
|
||||
return !((res & 1) == 1);
|
||||
|
|
@ -2498,18 +2501,29 @@ void BotGraph::frame () {
|
|||
auto getNodeData = [&] (StringRef type, int node) -> String {
|
||||
String message, flags;
|
||||
|
||||
const auto &path = m_paths[node];
|
||||
const auto &p = m_paths[node];
|
||||
bool jumpPoint = false;
|
||||
|
||||
// iterate through connections and find, if it's a jump path
|
||||
for (const auto &link : path.links) {
|
||||
for (const auto &link : p.links) {
|
||||
|
||||
// check if we got a valid connection
|
||||
if (link.index != kInvalidNodeIndex && (link.flags & PathFlag::Jump)) {
|
||||
jumpPoint = true;
|
||||
}
|
||||
}
|
||||
flags.assignf ("%s%s%s%s%s%s%s%s%s%s%s%s", (path.flags & NodeFlag::Lift) ? " LIFT" : "", (path.flags & NodeFlag::Crouch) ? " CROUCH" : "", (path.flags & NodeFlag::Camp) ? " CAMP" : "", (path.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "", (path.flags & NodeFlag::CTOnly) ? " CT" : "", (path.flags & NodeFlag::Sniper) ? " SNIPER" : "", (path.flags & NodeFlag::Goal) ? " GOAL" : "", (path.flags & NodeFlag::Ladder) ? " LADDER" : "", (path.flags & NodeFlag::Rescue) ? " RESCUE" : "", (path.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "", (path.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : "");
|
||||
flags.assignf ("%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
(p.flags & NodeFlag::Lift) ? " LIFT" : "",
|
||||
(p.flags & NodeFlag::Crouch) ? " CROUCH" : "",
|
||||
(p.flags & NodeFlag::Camp) ? " CAMP" : "",
|
||||
(p.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "",
|
||||
(p.flags & NodeFlag::CTOnly) ? " CT" : "",
|
||||
(p.flags & NodeFlag::Sniper) ? " SNIPER" : "",
|
||||
(p.flags & NodeFlag::Goal) ? " GOAL" : "",
|
||||
(p.flags & NodeFlag::Ladder) ? " LADDER" : "",
|
||||
(p.flags & NodeFlag::Rescue) ? " RESCUE" : "",
|
||||
(p.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "",
|
||||
(p.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : "");
|
||||
|
||||
if (flags.empty ()) {
|
||||
flags.assign ("(none)");
|
||||
|
|
@ -2519,7 +2533,7 @@ void BotGraph::frame () {
|
|||
message.assignf (" %s node:\n"
|
||||
" Node %d of %d, Radius: %.1f, Light: %.1f\n"
|
||||
" Flags: %s\n"
|
||||
" Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, path.radius, path.light, flags, path.origin.x, path.origin.y, path.origin.z);
|
||||
" Origin: (%.1f, %.1f, %.1f)\n", type, node, m_paths.length () - 1, p.radius, p.light, flags, p.origin.x, p.origin.y, p.origin.z);
|
||||
return message;
|
||||
};
|
||||
|
||||
|
|
@ -2669,11 +2683,16 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
}
|
||||
|
||||
// perform DFS instead of floyd-warshall, this shit speedup this process in a bit
|
||||
auto length = cr::min (static_cast <size_t> (kMaxNodes), m_paths.length ());
|
||||
|
||||
// ensure valid capacity
|
||||
assert (length > 8 && length < static_cast <size_t> (kMaxNodes));
|
||||
|
||||
PathWalk walk;
|
||||
walk.init (m_paths.length ());
|
||||
walk.init (length);
|
||||
|
||||
Array <bool> visited;
|
||||
visited.resize (m_paths.length ());
|
||||
visited.resize (length);
|
||||
|
||||
// first check incoming connectivity, initialize the "visited" table
|
||||
for (auto &visit : visited) {
|
||||
|
|
@ -2710,10 +2729,10 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
|
||||
// then check outgoing connectivity
|
||||
Array <IntArray> outgoingPaths; // store incoming paths for speedup
|
||||
outgoingPaths.resize (m_paths.length ());
|
||||
outgoingPaths.resize (length);
|
||||
|
||||
for (const auto &path : m_paths) {
|
||||
outgoingPaths[path.number].resize (m_paths.length () + 1);
|
||||
outgoingPaths[path.number].resize (length + 1);
|
||||
|
||||
for (const auto &link : path.links) {
|
||||
if (exists (link.index)) {
|
||||
|
|
@ -3123,8 +3142,8 @@ void BotGraph::convertFromPOD (Path &path, const PODPath &pod) {
|
|||
path.links[i].flags = pod.conflags[i];
|
||||
path.links[i].velocity = pod.velocity[i];
|
||||
}
|
||||
path.vis.stand = pod.vis.stand;
|
||||
path.vis.crouch = pod.vis.crouch;
|
||||
path.vis.stand = 0;
|
||||
path.vis.crouch = 0;
|
||||
}
|
||||
|
||||
void BotGraph::convertToPOD (const Path &path, PODPath &pod) {
|
||||
|
|
|
|||
|
|
@ -1010,12 +1010,12 @@ CR_EXPORT int Server_GetPhysicsInterface (int version, server_physics_api_t *phy
|
|||
return HLTrue;
|
||||
}
|
||||
|
||||
DLSYM_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *function) {
|
||||
SharedLibrary::Func EntityLinkage::lookup (SharedLibrary::Handle module, const char *function) {
|
||||
static const auto &gamedll = game.lib ().handle ();
|
||||
static const auto &self = m_self.handle ();
|
||||
|
||||
const auto resolve = [&] (SharedLibrary::Handle handle) {
|
||||
return reinterpret_cast <DLSYM_RETURN> (m_dlsym (static_cast <DLSYM_HANDLE> (handle), function));
|
||||
return m_dlsym (handle, function);
|
||||
};
|
||||
|
||||
if (ents.needsBypass () && !strcmp (function, "CreateInterface")) {
|
||||
|
|
@ -1028,10 +1028,16 @@ DLSYM_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *fu
|
|||
}
|
||||
|
||||
// if requested module is yapb module, put in cache the looked up symbol
|
||||
if (self != module || (plat.win && (static_cast <uint16> (reinterpret_cast <unsigned long> (function) >> 16) & 0xffff) == 0)) {
|
||||
if (self != module) {
|
||||
return resolve (module);
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
if (HIWORD (function) == 0) {
|
||||
return resolve (module);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_exports.has (function)) {
|
||||
return m_exports[function];
|
||||
}
|
||||
|
|
@ -1057,7 +1063,7 @@ void EntityLinkage::callPlayerFunction (edict_t *ent) {
|
|||
playerFunction = game.lib ().resolve <EntityFunction> ("player");
|
||||
}
|
||||
else {
|
||||
playerFunction = reinterpret_cast <EntityFunction> (lookup (game.lib ().handle (), "player"));
|
||||
playerFunction = reinterpret_cast <EntityFunction> (reinterpret_cast <void *> (lookup (game.lib ().handle (), "player")));
|
||||
}
|
||||
|
||||
if (!playerFunction) {
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ void BotManager::touchKillerEntity (Bot *bot) {
|
|||
KeyValueData kv {};
|
||||
kv.szClassName = const_cast <char *> (prop.classname.chars ());
|
||||
kv.szKeyName = "damagetype";
|
||||
kv.szValue = const_cast <char *> (strings.format ("%d", cr::bit (4)));
|
||||
kv.szValue = strings.format ("%d", cr::bit (4));
|
||||
kv.fHandled = HLFalse;
|
||||
|
||||
MDLL_KeyValue (m_killerEntity, &kv);
|
||||
|
|
@ -782,7 +782,6 @@ void BotManager::listBots () {
|
|||
ctrl.msg ("%-3.5s\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.4s\t%-3.4s\t%-3.5s\t%-3.8s", "index", "name", "personality", "team", "difficulty", "frags", "alive", "timeleft");
|
||||
|
||||
for (const auto &bot : bots) {
|
||||
;
|
||||
ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%-3.0f secs", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", bot->m_team == Team::CT ? "CT" : "T", bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_notKilled ? "yes" : "no", bot->m_stayTime - game.time ());
|
||||
}
|
||||
ctrl.msg ("%d bots", m_bots.length ());
|
||||
|
|
@ -819,7 +818,7 @@ float BotManager::getAverageTeamKPD (bool calcForBots) {
|
|||
}
|
||||
|
||||
if (calc.second > 0) {
|
||||
return calc.first / calc.second;
|
||||
return calc.first / static_cast <float> (calc.second);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
|
@ -930,10 +929,10 @@ void BotManager::balanceBotDifficulties () {
|
|||
float score = bot->m_kpdRatio;
|
||||
|
||||
// if kd ratio is going to go to low, we need to try to set higher difficulty
|
||||
if (score < 0.8 || (score <= 1.2 && ratioBots < ratioPlayer)) {
|
||||
if (score < 0.8f || (score <= 1.2f && ratioBots < ratioPlayer)) {
|
||||
updateDifficulty (bot.get (), +1);
|
||||
}
|
||||
else if (score > 4.0f || (score >= 2.5 && ratioBots > ratioPlayer)) {
|
||||
else if (score > 4.0f || (score >= 2.5f && ratioBots > ratioPlayer)) {
|
||||
updateDifficulty (bot.get (), -1);
|
||||
}
|
||||
}
|
||||
|
|
@ -949,9 +948,6 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
|
|||
// this function does core operation of creating bot, it's called by addbot (),
|
||||
// when bot setup completed, (this is a bot class constructor)
|
||||
|
||||
// we're not initializing all the variables in bot class, so do an ugly thing... memset this
|
||||
plat.bzero (this, sizeof (*this));
|
||||
|
||||
int clientIndex = game.indexOfEntity (bot);
|
||||
pev = &bot->v;
|
||||
|
||||
|
|
@ -1458,7 +1454,7 @@ void Bot::resetPathSearchType () {
|
|||
switch (m_personality) {
|
||||
default:
|
||||
case Personality::Normal:
|
||||
m_pathType = morale ? FindPath::Optimal : FindPath::Safe;
|
||||
m_pathType = morale ? FindPath::Optimal : FindPath::Fast;
|
||||
break;
|
||||
|
||||
case Personality::Rusher:
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ void MessageDispatcher::netMsgScoreInfo () {
|
|||
|
||||
// if we're have bot, set the kd ratio
|
||||
if (bot != nullptr) {
|
||||
bot->m_kpdRatio = bot->pev->frags / cr::max <long> (m_args[deaths].long_, 1);
|
||||
bot->m_kpdRatio = bot->pev->frags / cr::max (static_cast <float> (m_args[deaths].long_), 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ private:
|
|||
public:
|
||||
// get the bot version string
|
||||
virtual const char *getBotVersion () override {
|
||||
return MODULE_BOT_VERSION "." MODULE_BUILD_COUNT;
|
||||
return MODULE_VERSION "." MODULE_COMMIT_COUNT;
|
||||
}
|
||||
|
||||
// checks if bots are currently in game
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ int Bot::findBestGoal () {
|
|||
tactic = 4;
|
||||
return findGoalPost (tactic, defensiveNodes, offensiveNodes);
|
||||
}
|
||||
auto difficulty = static_cast <float> (m_difficulty);
|
||||
|
||||
offensive = m_agressionLevel * 100.0f;
|
||||
defensive = m_fearLevel * 100.0f;
|
||||
|
|
@ -94,8 +95,8 @@ int Bot::findBestGoal () {
|
|||
else if (m_team == Team::CT) {
|
||||
// on hostage maps force more bots to save hostages
|
||||
if (game.mapIs (MapFlags::HostageRescue)) {
|
||||
defensive -= 25.0f - m_difficulty * 0.5f;
|
||||
offensive += 25.0f + m_difficulty * 5.0f;
|
||||
defensive -= 25.0f - difficulty * 0.5f;
|
||||
offensive += 25.0f + difficulty * 5.0f;
|
||||
}
|
||||
else {
|
||||
defensive -= 25.0f;
|
||||
|
|
@ -112,8 +113,8 @@ int Bot::findBestGoal () {
|
|||
}
|
||||
return m_chosenGoalIndex = findBombNode ();
|
||||
}
|
||||
defensive += 25.0f + m_difficulty * 4.0f;
|
||||
offensive -= 25.0f - m_difficulty * 0.5f;
|
||||
defensive += 25.0f + difficulty * 4.0f;
|
||||
offensive -= 25.0f - difficulty * 0.5f;
|
||||
|
||||
if (m_personality != Personality::Rusher) {
|
||||
defensive += 10.0f;
|
||||
|
|
@ -121,7 +122,7 @@ int Bot::findBestGoal () {
|
|||
}
|
||||
else if (game.mapIs (MapFlags::Demolition) && m_team == Team::Terrorist && bots.getRoundStartTime () + 10.0f < game.time ()) {
|
||||
// send some terrorists to guard planted bomb
|
||||
if (!m_defendedBomb && bots.isBombPlanted () && getCurrentTaskId () != Task::EscapeFromBomb && getBombTimeleft () >= 15.0) {
|
||||
if (!m_defendedBomb && bots.isBombPlanted () && getCurrentTaskId () != Task::EscapeFromBomb && getBombTimeleft () >= 15.0f) {
|
||||
return pushToHistroy (m_chosenGoalIndex = graph.getNearest (graph.getBombOrigin ()));
|
||||
}
|
||||
}
|
||||
|
|
@ -456,21 +457,18 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
|
||||
// bot is stuc, but not yet decided what to do?
|
||||
if (m_collisionState == CollisionState::Undecided) {
|
||||
int bits = 0;
|
||||
uint32 bits = 0;
|
||||
|
||||
if (isOnLadder ()) {
|
||||
bits |= CollisionProbe::Strafe;
|
||||
}
|
||||
else if (isInWater ()) {
|
||||
bits |= (CollisionProbe::Jump | CollisionProbe::Strafe);
|
||||
}
|
||||
else {
|
||||
bits |= (CollisionProbe::Strafe | CollisionProbe::Jump);
|
||||
}
|
||||
|
||||
// collision check allowed if not flying through the air
|
||||
if (isOnFloor () || isOnLadder () || isInWater ()) {
|
||||
int state[kMaxCollideMoves * 2 + 1] {};
|
||||
uint32 state[kMaxCollideMoves * 2 + 1] {};
|
||||
int i = 0;
|
||||
|
||||
Vector src {}, dst {};
|
||||
|
|
@ -689,7 +687,7 @@ bool Bot::updateNavigation () {
|
|||
|
||||
// if graph node radius non zero vary origin a bit depending on the body angles
|
||||
if (m_path->radius > 0.0f) {
|
||||
m_pathOrigin += Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (0.0f, m_path->radius);
|
||||
m_pathOrigin += Vector (pev->angles.x, cr::wrapAngle (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (0.0f, m_path->radius);
|
||||
}
|
||||
m_navTimeset = game.time ();
|
||||
}
|
||||
|
|
@ -726,7 +724,7 @@ bool Bot::updateNavigation () {
|
|||
}
|
||||
}
|
||||
|
||||
if (!(graph[m_previousNodes[0]].flags & NodeFlag::Ladder)) {
|
||||
if (graph.exists (m_previousNodes[0]) && (graph[m_previousNodes[0]].flags & NodeFlag::Ladder)) {
|
||||
if (cr::abs (m_pathOrigin.z - pev->origin.z) > 5.0f) {
|
||||
m_pathOrigin.z += pev->origin.z - m_pathOrigin.z;
|
||||
}
|
||||
|
|
@ -1325,7 +1323,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
// this function finds a path from srcIndex to destIndex
|
||||
|
||||
auto dangerFactor = [&] () -> float {
|
||||
return rg.get (cv_path_danger_factor_min.float_ (), cv_path_danger_factor_max.float_ ()) * 2.0f / cr::clamp (m_difficulty, 1, 3);
|
||||
return rg.get (cv_path_danger_factor_min.float_ (), cv_path_danger_factor_max.float_ ()) * 2.0f / cr::clamp (static_cast <float> (m_difficulty), 1.0f, 4.0f);
|
||||
};
|
||||
|
||||
// least kills and number of nodes to goal for a team
|
||||
|
|
@ -1403,11 +1401,13 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
|
||||
for (const auto &link : parent.links) {
|
||||
if (link.index == currentIndex) {
|
||||
const auto distance = static_cast <float> (link.distance);
|
||||
|
||||
// we don't like ladder or crouch point
|
||||
if (current.flags & (NodeFlag::Crouch | NodeFlag::Ladder)) {
|
||||
return link.distance * 1.5f;
|
||||
return distance * 1.5f;
|
||||
}
|
||||
return static_cast <float> (link.distance);
|
||||
return distance;
|
||||
}
|
||||
}
|
||||
return 65355.0f;
|
||||
|
|
@ -1608,7 +1608,7 @@ void Bot::clearSearchNodes () {
|
|||
}
|
||||
|
||||
void Bot::clearRoute () {
|
||||
m_routes.resize (graph.length ());
|
||||
m_routes.resize (static_cast <size_t> (graph.length ()));
|
||||
|
||||
for (int i = 0; i < graph.length (); ++i) {
|
||||
auto route = &m_routes[i];
|
||||
|
|
@ -1633,7 +1633,7 @@ int Bot::findAimingNode (const Vector &to) {
|
|||
if (destIndex == kInvalidNodeIndex) {
|
||||
return kInvalidNodeIndex;
|
||||
}
|
||||
const float kMaxDistance = ((m_states & Sense::HearingEnemy) || (m_states & Sense::HearingEnemy) || m_seeEnemyTime + 3.0f > game.time ()) ? 0.0f : 512.0f;
|
||||
const float kMaxDistance = ((m_states & Sense::HearingEnemy) || (m_states & Sense::SuspectEnemy) || m_seeEnemyTime + 3.0f > game.time ()) ? 0.0f : 512.0f;
|
||||
|
||||
while (destIndex != m_currentNodeIndex) {
|
||||
destIndex = (graph.m_matrix.data () + (destIndex * graph.length ()) + m_currentNodeIndex)->index;
|
||||
|
|
@ -2411,7 +2411,7 @@ bool Bot::advanceMovement () {
|
|||
|
||||
// if wayzone radius non zero vary origin a bit depending on the body angles
|
||||
if (m_path->radius > 0.0f) {
|
||||
m_pathOrigin += Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (0.0f, m_path->radius);
|
||||
m_pathOrigin += Vector (pev->angles.x, cr::wrapAngle (pev->angles.y + rg.get (-90.0f, 90.0f)), 0.0f).forward () * rg.get (0.0f, m_path->radius);
|
||||
}
|
||||
|
||||
if (isOnLadder ()) {
|
||||
|
|
@ -2432,17 +2432,17 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
// use some TraceLines to determine if anything is blocking the current path of the bot.
|
||||
|
||||
// first do a trace from the bot's eyes forward...
|
||||
Vector src = getEyesPos ();
|
||||
Vector forward = src + normal * 24.0f;
|
||||
auto src = getEyesPos ();
|
||||
auto forward = src + normal * 24.0f;
|
||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
||||
|
||||
const auto &right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
||||
bool traceResult = false;
|
||||
|
||||
auto checkDoor = [&traceResult] (TraceResult *tr) {
|
||||
auto checkDoor = [&traceResult] (TraceResult *result) {
|
||||
if (!game.mapIs (MapFlags::HasDoors)) {
|
||||
return false;
|
||||
}
|
||||
return !traceResult && tr->flFraction < 1.0f && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) != 0;
|
||||
return !traceResult && result->flFraction < 1.0f && strncmp ("func_door", result->pHit->v.classname.chars (), 9) != 0;
|
||||
};
|
||||
|
||||
// trace from the bot's eyes straight forward...
|
||||
|
|
@ -2596,11 +2596,11 @@ bool Bot::canJumpUp (const Vector &normal) {
|
|||
if (!isOnFloor () && (isOnLadder () || !isInWater ())) {
|
||||
return false;
|
||||
}
|
||||
const auto &right = Vector (0.0f, pev->angles.y, 0.0f).right (); // convert current view angle to vectors for traceline math...
|
||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right (); // convert current view angle to vectors for traceline math...
|
||||
|
||||
// check for normal jump height first...
|
||||
Vector src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
||||
Vector dest = src + normal * 32.0f;
|
||||
auto src = pev->origin + Vector (0.0f, 0.0f, -36.0f + 45.0f);
|
||||
auto dest = src + normal * 32.0f;
|
||||
|
||||
// trace a line forward at maximum jump height...
|
||||
game.testLine (src, dest, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
|
@ -2762,7 +2762,7 @@ bool Bot::canDuckUnder (const Vector &normal) {
|
|||
}
|
||||
|
||||
// convert current view angle to vectors for TraceLine math...
|
||||
const auto &right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
||||
auto right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
||||
|
||||
// now check same height to one side of the bot...
|
||||
src = baseHeight + right * 16.0f;
|
||||
|
|
@ -2900,14 +2900,14 @@ bool Bot::isDeadlyMove (const Vector &to) {
|
|||
void Bot::changePitch (float speed) {
|
||||
// this function turns a bot towards its ideal_pitch
|
||||
|
||||
float idealPitch = cr::normalizeAngles (pev->idealpitch);
|
||||
float curent = cr::normalizeAngles (pev->v_angle.x);
|
||||
float idealPitch = cr::wrapAngle (pev->idealpitch);
|
||||
float curent = cr::wrapAngle (pev->v_angle.x);
|
||||
|
||||
// turn from the current v_angle pitch to the idealpitch by selecting
|
||||
// the quickest way to turn to face that direction
|
||||
|
||||
// find the difference in the curent and ideal angle
|
||||
float normalizePitch = cr::normalizeAngles (idealPitch - curent);
|
||||
float normalizePitch = cr::wrapAngle (idealPitch - curent);
|
||||
|
||||
if (normalizePitch > 0.0f) {
|
||||
if (normalizePitch > speed) {
|
||||
|
|
@ -2920,7 +2920,7 @@ void Bot::changePitch (float speed) {
|
|||
}
|
||||
}
|
||||
|
||||
pev->v_angle.x = cr::normalizeAngles (curent + normalizePitch);
|
||||
pev->v_angle.x = cr::wrapAngle (curent + normalizePitch);
|
||||
|
||||
if (pev->v_angle.x > 89.9f) {
|
||||
pev->v_angle.x = 89.9f;
|
||||
|
|
@ -2935,14 +2935,14 @@ void Bot::changePitch (float speed) {
|
|||
void Bot::changeYaw (float speed) {
|
||||
// this function turns a bot towards its ideal_yaw
|
||||
|
||||
float idealPitch = cr::normalizeAngles (pev->ideal_yaw);
|
||||
float curent = cr::normalizeAngles (pev->v_angle.y);
|
||||
float idealPitch = cr::wrapAngle (pev->ideal_yaw);
|
||||
float curent = cr::wrapAngle (pev->v_angle.y);
|
||||
|
||||
// turn from the current v_angle yaw to the ideal_yaw by selecting
|
||||
// the quickest way to turn to face that direction
|
||||
|
||||
// find the difference in the curent and ideal angle
|
||||
float normalizePitch = cr::normalizeAngles (idealPitch - curent);
|
||||
float normalizePitch = cr::wrapAngle (idealPitch - curent);
|
||||
|
||||
if (normalizePitch > 0.0f) {
|
||||
if (normalizePitch > speed) {
|
||||
|
|
@ -2954,7 +2954,7 @@ void Bot::changeYaw (float speed) {
|
|||
normalizePitch = -speed;
|
||||
}
|
||||
}
|
||||
pev->v_angle.y = cr::normalizeAngles (curent + normalizePitch);
|
||||
pev->v_angle.y = cr::wrapAngle (curent + normalizePitch);
|
||||
pev->angles.y = pev->v_angle.y;
|
||||
}
|
||||
|
||||
|
|
@ -3084,7 +3084,7 @@ void Bot::updateLookAnglesNewbie (const Vector &direction, float delta) {
|
|||
Vector spring { 13.0f, 13.0f, 0.0f };
|
||||
Vector damperCoefficient { 0.22f, 0.22f, 0.0f };
|
||||
|
||||
const float offset = cr::clamp (m_difficulty, 1, 4) * 25.0f;
|
||||
const float offset = cr::clamp (static_cast <float> (m_difficulty), 1.0f, 4.0f) * 25.0f;
|
||||
|
||||
Vector influence = Vector (0.25f, 0.17f, 0.0f) * (100.0f - offset) / 100.f;
|
||||
Vector randomization = Vector (2.0f, 0.18f, 0.0f) * (100.0f - offset) / 100.f;
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ void BotSupport::checkWelcome () {
|
|||
bool needToSendMsg = (graph.length () > 0 ? m_needToSendWelcome : true);
|
||||
auto receiveEntity = game.getLocalEntity ();
|
||||
|
||||
if (isAlive (receiveEntity) && m_welcomeReceiveTime < 1.0 && needToSendMsg) {
|
||||
if (isAlive (receiveEntity) && m_welcomeReceiveTime < 1.0f && needToSendMsg) {
|
||||
m_welcomeReceiveTime = game.time () + 4.0f; // receive welcome message in four seconds after game has commencing
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +509,7 @@ void BotSupport::simulateNoise (int playerIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
if (noise.dist <= 0.0) {
|
||||
if (noise.dist <= 0.0f) {
|
||||
return; // didn't issue sound?
|
||||
}
|
||||
|
||||
|
|
@ -613,7 +613,7 @@ void BotSupport::calculatePings () {
|
|||
if (!bot) {
|
||||
continue;
|
||||
}
|
||||
int part = static_cast <int> (average.first * 0.2f);
|
||||
int part = static_cast <int> (static_cast <float> (average.first) * 0.2f);
|
||||
|
||||
int botPing = bot->m_basePing + rg.get (average.first - part, average.first + part) + rg.get (bot->m_difficulty / 2, bot->m_difficulty);
|
||||
int botLoss = rg.get (average.second / 2, average.second);
|
||||
|
|
|
|||
22
vc/yapb.rc
22
vc/yapb.rc
|
|
@ -16,21 +16,21 @@
|
|||
#include VERSION_HEADER
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION MODULE_BOT_VERSION_FILE
|
||||
PRODUCTVERSION MODULE_BOT_VERSION_FILE
|
||||
FILEVERSION MODULE_VERSION_FILE
|
||||
PRODUCTVERSION MODULE_VERSION_FILE
|
||||
FILEOS 0x40004
|
||||
FILETYPE 0x2 {
|
||||
BLOCK "StringFileInfo" {
|
||||
BLOCK "040904E4" {
|
||||
VALUE "CompanyName", "YaPB Project" "\0"
|
||||
VALUE "FileDescription", "YaPB v" MODULE_BOT_VERSION "." MODULE_BUILD_COUNT " - The Counter-Strike Bot" "\0"
|
||||
VALUE "LegalCopyright", "Copyright \251 2023 YaPB Project" "\0"
|
||||
VALUE "OriginalFilename", "yapb.dll" "\0"
|
||||
VALUE "ProductName", "YaPB" "\0"
|
||||
VALUE "InternalName", "YaPB DLL" "\0"
|
||||
VALUE "FileVersion", MODULE_BOT_VERSION "." MODULE_BUILD_COUNT "\0"
|
||||
VALUE "ProductVersion", MODULE_BOT_VERSION "." MODULE_BUILD_COUNT "\0"
|
||||
VALUE "SpecialBuild", MODULE_BOT_BUILD_ID "\0"
|
||||
VALUE "CompanyName", "YaPB Project" "\0"
|
||||
VALUE "FileDescription", "YaPB v" MODULE_VERSION "." MODULE_COMMIT_COUNT " - The Counter-Strike Bot" "\0"
|
||||
VALUE "LegalCopyright", "Copyright \251 2023 YaPB Project" "\0"
|
||||
VALUE "OriginalFilename", "yapb.dll" "\0"
|
||||
VALUE "ProductName", "YaPB" "\0"
|
||||
VALUE "InternalName", "YaPB DLL" "\0"
|
||||
VALUE "FileVersion", MODULE_VERSION "." MODULE_COMMIT_COUNT "\0"
|
||||
VALUE "ProductVersion", MODULE_VERSION "." MODULE_COMMIT_COUNT "\0"
|
||||
VALUE "SpecialBuild", MODULE_BUILD_ID "\0"
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo" {
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\vc;..\inc;..\ext;..\ext\crlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;CR_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<PrecompiledHeaderFile>yapb.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>.\debug\inf\yapb.pch</PrecompiledHeaderOutputFile>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue