Merge branch 'master' into chatter-fixes-and-improvements

This commit is contained in:
Владислав Сухов 2024-05-17 18:33:56 +00:00
commit f049391637
26 changed files with 579 additions and 476 deletions

View file

@ -6,6 +6,8 @@
; ;
; Custom configuration file, allow to change some hardcoded stuff in bot code. ; Custom configuration file, allow to change some hardcoded stuff in bot code.
; ;
; NOTE: All changes to this file takes effect only on server restart.
;
; ;
; Custom name for C4 model, for servers that replacing C4 model with it's own. ; Custom name for C4 model, for servers that replacing C4 model with it's own.
@ -28,3 +30,23 @@ AMXParachuteCvar = sv_parachute
; ;
CustomCSDMSpawnPoint = view_spawn CustomCSDMSpawnPoint = view_spawn
;
; Primary cvar for detection if CSDM mod is activated in game.
;
CSDMDetectCvar = csdm_active
;
; Primary cvar to detect if bot is running on Zombie Mod.
;
ZMDetectCvar = zp_delay
;
; For Zombie Mod, the cvars that deals with time before any game mode starts.
;
ZMDelayCvar = zp_delay
;
; For Zombie Mod, determines the team on which infected players are on.
; Valid values: T, CT.
;
ZMInfectedTeam = T

View file

@ -10,11 +10,11 @@
[ORIGINAL] [ORIGINAL]
\yMain Menu\w \yMain Menu\w
1. Control Bots 1. Control bots
2. Features 2. Features
3. Fill Server 3. Fill server
4. End Round 4. End round
0. Exit 0. Exit
@ -32,12 +32,12 @@
[ORIGINAL] [ORIGINAL]
\yBots Features\w \yBots Features\w
1. Weapon Mode Menu 1. Weapon mode menu
2. Waypoint Menu 2. Graph editor
3. Select Personality 3. Select personality
4. Toggle Debug Mode 4. Toggle debug mode
5. Command Menu 5. Command menu
0. Exit 0. Exit
@ -56,13 +56,13 @@
[ORIGINAL] [ORIGINAL]
\yBots Control Menu\w \yBots Control Menu\w
1. Add a Bot, Quick 1. Quick add bot
2. Add a Bot, Specified 2. Add specific bot
3. Remove Random Bot 3. Remove random bot
4. Remove All Bots 4. Remove all bots
5. Remove Bot Menu 5. Bot removal menu
0. Exit 0. Exit
@ -85,10 +85,10 @@
1. Knives only 1. Knives only
2. Pistols only 2. Pistols only
3. Shotguns only 3. Shotguns only
4. Machine Guns only 4. Machine guns only
5. Rifles only 5. Rifles only
6. Sniper Weapons only 6. Sniper weapons only
7. All Weapons 7. All weapons
0. Exit 0. Exit
@ -148,7 +148,7 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\ySelect a team\w \ySelect a Team\w
1. Terrorist Force 1. Terrorist Force
2. Counter-Terrorist Force 2. Counter-Terrorist Force
@ -168,7 +168,7 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Phoenix Connexion 1. Phoenix Connexion
2. L337 Krew 2. L337 Krew
@ -192,7 +192,7 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Seal Team 6 (DEVGRU) 1. Seal Team 6 (DEVGRU)
2. German GSG-9 2. German GSG-9
@ -216,16 +216,16 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\yWaypoint Operations (Page 1)\w \yGraph Editor (Page 1)\w
1. Show/Hide waypoints 1. Show/Hide nodes
2. Cache waypoint 2. Cache node
3. Create path 3. Create path
4. Delete path 4. Delete path
5. Add waypoint 5. Add node
6. Delete waypoint 6. Delete node
7. Set Autopath Distance 7. Set autopath distance
8. Set Radius 8. Set radius
9. Next... 9. Next...
@ -248,15 +248,15 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\yWaypoint Operations (Page 2)\w \yGraph Editor (Page 2)\w
1. Waypoint stats 1. Debug goal
2. Autowaypoint on/off 2. Auto node placement on/off
3. Set flags 3. Set flags
4. Save waypoints 4. Save graph
5. Save without checking 5. Save without checking
6. Load waypoints 6. Load graph
7. Check waypoints 7. Check graph
8. Noclip cheat on/off 8. Noclip cheat on/off
9. Previous... 9. Previous...
@ -280,17 +280,17 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\yWaypoint Radius\w \yNode Radius\w
1. SetRadius 0 1. 0 units
2. SetRadius 8 2. 8 units
3. SetRadius 16 3. 16 units
4. SetRadius 32 4. 32 units
5. SetRadius 48 5. 48 units
6. SetRadius 64 6. 64 units
7. SetRadius 80 7. 80 units
8. SetRadius 96 8. 96 units
9. SetRadius 128 9. 128 units
0. Exit 0. Exit
@ -310,16 +310,16 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\yWaypoint Type\w \yNode Type\w
1. Normal 1. Normal
\r2. Terrorist Important \r2. Terrorist important
3. Counter-Terrorist Important 3. Counter-Terrorist important
\w4. Block with hostage / Ladder \w4. Block with hostage / Ladder
\y5. Rescue Zone \y5. Rescue zone
\w6. Camping \w6. Camping
7. Camp End 7. Camp end
\r8. Map Goal \r8. Map goal
\w9. Jump \w9. Jump
0. Exit 0. Exit
@ -340,13 +340,13 @@
0. Schließen 0. Schließen
[ORIGINAL] [ORIGINAL]
\yToggle Waypoint Flags\w \yToggle Node Flags\w
1. Block with Hostage 1. Block with hostage
2. Terrorists Specific 2. Terrorists specific
3. CTs Specific 3. CTs specific
4. Use Elevator 4. Use elevator
5. Sniper Point (\yFor Camp Points Only!\w) 5. Sniper point (\yfor camp points only!\w)
0. Exit 0. Exit
@ -364,11 +364,11 @@
[ORIGINAL] [ORIGINAL]
\yBot Command Menu\w \yBot Command Menu\w
1. Make Double Jump 1. Make double jump
2. Finish Double Jump 2. Finish double jump
3. Drop the C4 Bomb 3. Drop the C4 bomb
4. Drop the Weapon 4. Drop the weapon
0. Exit 0. Exit
@ -386,13 +386,13 @@
[ORIGINAL] [ORIGINAL]
\yAutoPath Distance\w \yAutoPath Distance\w
1. Distance 0 1. 0 units
2. Distance 100 2. 100 units
3. Distance 130 3. 130 units
4. Distance 160 4. 160 units
5. Distance 190 5. 190 units
6. Distance 220 6. 220 units
7. Distance 250 (Default) 7. 250 units (Default)
0. Exit 0. Exit
@ -412,9 +412,9 @@
[ORIGINAL] [ORIGINAL]
\yCreate Path (Choose Direction)\w \yCreate Path (Choose Direction)\w
1. Outgoing Path 1. Outgoing path
2. Incoming Path 2. Incoming path
3. Bidirectional (Both Ways) 3. Bidirectional (both ways)
0. Exit 0. Exit
@ -548,13 +548,13 @@ Bot '%s' kicked.
Bot '%s' wurde hinausgeworfen. Bot '%s' wurde hinausgeworfen.
[ORIGINAL] [ORIGINAL]
Bots Remove Menu Bot Removal Menu
[TRANSLATED] [TRANSLATED]
Bot entfernen Menü Bot entfernen Menü
[ORIGINAL] [ORIGINAL]
Not a Bot Not a bot
[TRANSLATED] [TRANSLATED]
Kein Bot Kein Bot

View file

@ -10,11 +10,11 @@
[ORIGINAL] [ORIGINAL]
\yMain Menu\w \yMain Menu\w
1. Control Bots 1. Control bots
2. Features 2. Features
3. Fill Server 3. Fill server
4. End Round 4. End round
0. Exit 0. Exit
@ -32,12 +32,12 @@
[ORIGINAL] [ORIGINAL]
\yBots Features\w \yBots Features\w
1. Weapon Mode Menu 1. Weapon mode menu
2. Waypoint Menu 2. Graph editor
3. Select Personality 3. Select personality
4. Toggle Debug Mode 4. Toggle debug mode
5. Command Menu 5. Command menu
0. Exit 0. Exit
@ -45,8 +45,8 @@
\yФункции бота\w \yФункции бота\w
1. Меню выбора режима оружия 1. Меню выбора режима оружия
2. Меню вэйпоинтов 2. Редактор графов
3. Выбрать личность бота 3. Выбрать характер бота
4. Переключить режим отладки 4. Переключить режим отладки
5. Меню команд бота 5. Меню команд бота
@ -56,13 +56,13 @@
[ORIGINAL] [ORIGINAL]
\yBots Control Menu\w \yBots Control Menu\w
1. Add a Bot, Quick 1. Quick add bot
2. Add a Bot, Specified 2. Add specific bot
3. Remove Random Bot 3. Remove random bot
4. Remove All Bots 4. Remove all bots
5. Remove Bot Menu 5. Bot removal menu
0. Exit 0. Exit
@ -85,15 +85,15 @@
1. Knives only 1. Knives only
2. Pistols only 2. Pistols only
3. Shotguns only 3. Shotguns only
4. Machine Guns only 4. Machine guns only
5. Rifles only 5. Rifles only
6. Sniper Weapons only 6. Sniper weapons only
7. All Weapons 7. All weapons
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yВыбор режима оружия\w \yРежим оружия ботов\w
1. Только ножи 1. Только ножи
2. Только пистолеты 2. Только пистолеты
@ -116,12 +116,12 @@
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yВыбор личности ботов\w \yХарактер ботов\w
1. Случайная 1. Случайный
2. Нормальная 2. Нормальный
3. Агрессивная 3. Агрессивный
4. Осторожная 4. Осторожный
0. Выход 0. Выход
@ -148,7 +148,7 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySelect a team\w \ySelect a Team\w
1. Terrorist Force 1. Terrorist Force
2. Counter-Terrorist Force 2. Counter-Terrorist Force
@ -163,12 +163,13 @@
1. Террористы 1. Террористы
2. Контр-террористы 2. Контр-террористы
5. Случайно 5. Авто-выбор
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Phoenix Connexion 1. Phoenix Connexion
2. L337 Krew 2. L337 Krew
3. Arctic Avengers 3. Arctic Avengers
@ -191,7 +192,7 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Seal Team 6 (DEVGRU) 1. Seal Team 6 (DEVGRU)
2. German GSG-9 2. German GSG-9
@ -215,7 +216,8 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Phoenix Connexion 1. Phoenix Connexion
2. L337 Krew 2. L337 Krew
3. Arctic Avengers 3. Arctic Avengers
@ -240,7 +242,7 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySelect an appearance\w \ySelect an Appearance\w
1. Seal Team 6 (DEVGRU) 1. Seal Team 6 (DEVGRU)
2. German GSG-9 2. German GSG-9
@ -266,47 +268,47 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yWaypoint Operations (Page 1)\w \yGraph Editor (Page 1)\w
1. Show/Hide waypoints 1. Show/Hide nodes
2. Cache waypoint 2. Cache node
3. Create path 3. Create path
4. Delete path 4. Delete path
5. Add waypoint 5. Add node
6. Delete waypoint 6. Delete node
7. Set Autopath Distance 7. Set autopath distance
8. Set Radius 8. Set radius
9. Next... 9. Next...
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yОперации с вэйпоинтами (Стр. 1)\w \yРедактор графов (Стр. 1)\w
1. Показать/Скрыть вэйпоинты 1. Показать/Скрыть точки
2. Запомнить вэйпоинт 2. Запомнить точку
3. Создать путь 3. Создать путь
4. Убрать путь 4. Убрать путь
5. Добавить вэйпоинт 5. Добавить точку
6. Удалить вэйпоинт 6. Удалить точку
7. Установить дистанцию автопути 7. Задать дистанцию автопути
8. Установить радиус 8. Задать радиус
9. Далее... 9. Далее...
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yWaypoint Operations (Page 2)\w \yGraph Editor (Page 2)\w
1. Debug goal 1. Debug goal
2. Autowaypoint on/off 2. Auto node placement on/off
3. Set flags 3. Set flags
4. Save waypoints 4. Save graph
5. Save without checking 5. Save without checking
6. Load waypoints 6. Load graph
7. Check waypoints 7. Check graph
8. Noclip cheat on/off 8. Noclip cheat on/off
9. Previous... 9. Previous...
@ -314,15 +316,15 @@
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yОперации с вэйпоинтами (Стр. 2)\w \yРедактор графов (Стр. 2)\w
1. Отладка цели 1. Отладка цели
2. Вкл./Выкл. автовэйпоинт 2. Вкл./Выкл. авторасстановку точек
3. Установить флаг 3. Установить флаг
4. Сохранить вэйпоинты 4. Сохранить граф
5. Сохранить без проверки 5. Сохранить без проверки
6. Загрузить вэйпоинты 6. Загрузить граф
7. Проверить вэйпоинты 7. Проверить граф
8. Вкл./Выкл. режим полёта 8. Вкл./Выкл. режим полёта
9. Назад... 9. Назад...
@ -330,52 +332,52 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yWaypoint Radius\w \yNode Radius\w
1. SetRadius 0 1. 0 units
2. SetRadius 8 2. 8 units
3. SetRadius 16 3. 16 units
4. SetRadius 32 4. 32 units
5. SetRadius 48 5. 48 units
6. SetRadius 64 6. 64 units
7. SetRadius 80 7. 80 units
8. SetRadius 96 8. 96 units
9. SetRadius 128 9. 128 units
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yУстановка радиуса\w \yРадиус точки\w
1. Установить на 0 1. 0 юнитов
2. Установить на 8 2. 8 юнитов
3. Установить на 16 3. 16 юнитов
4. Установить на 32 4. 32 юнита
5. Установить на 48 5. 48 юнитов
6. Установить на 64 6. 64 юнита
7. Установить на 80 7. 80 юнитов
8. Установить на 96 8. 96 юнитов
9. Установить на 128 9. 128 юнитов
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yWaypoint Type\w \yNode Type\w
1. Normal 1. Normal
\r2. Terrorist Important \r2. Terrorist important
3. Counter-Terrorist Important 3. Counter-Terrorist important
\w4. Block with hostage / Ladder \w4. Block with hostage / Ladder
\y5. Rescue Zone \y5. Rescue zone
\w6. Camping \w6. Camping
7. Camp End 7. Camp end
\r8. Map Goal \r8. Map goal
\w9. Jump \w9. Jump
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yТип вэйпоинта\w \yТип точки\w
1. Обычный 1. Обычный
\r2. Важный для Террористов \r2. Важный для Террористов
@ -390,7 +392,7 @@
\w0. Выход \w0. Выход
[ORIGINAL] [ORIGINAL]
\yDebug goal\w \yDebug Goal\w
1. Debug nearest node 1. Debug nearest node
2. Debug facing node 2. Debug facing node
@ -408,28 +410,28 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yToggle Waypoint Flags\w \yToggle Node Flags\w
1. Block with Hostage 1. Block with hostage
2. Terrorists Specific 2. Terrorists specific
3. CTs Specific 3. CTs specific
4. Use Elevator 4. Use elevator
5. Sniper Point (\yFor Camp Points Only!\w) 5. Sniper point (\yfor camp points only!\w)
6. Map Goal 6. Map goal
7. Rescue Zone 7. Rescue zone
8. Crouch Down 8. Crouch down
9. Camp Point 9. Camp point
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yИзменение флагов вэйпоинтов\w \yИзменение флагов точки\w
1. Блокировать с заложником 1. Блокировать с заложником
2. Только для Террористов 2. Только для Террористов
3. Только для Контр-террористов 3. Только для Контр-террористов
4. Использовать лифт 4. Использовать лифт
5. Снайперский (\yТолько для кемперских точек!\w) 5. Снайперский (\yтолько для кемперских точек!\w)
6. Цель карты 6. Цель карты
7. Зона спасения 7. Зона спасения
8. Присесть 8. Присесть
@ -438,10 +440,10 @@
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\ySet Camp Point directions\w \ySet Camp Point Directions\w
1. Camp Start 1. Camp start
2. Camp End 2. Camp end
0. Exit 0. Exit
@ -456,11 +458,11 @@
[ORIGINAL] [ORIGINAL]
\yBot Command Menu\w \yBot Command Menu\w
1. Make Double Jump 1. Make double jump
2. Finish Double Jump 2. Finish double jump
3. Drop the C4 Bomb 3. Drop the C4 bomb
4. Drop the Weapon 4. Drop the weapon
0. Exit 0. Exit
@ -478,45 +480,45 @@
[ORIGINAL] [ORIGINAL]
\yAutoPath Distance\w \yAutoPath Distance\w
1. Distance 0 1. 0 units
2. Distance 100 2. 100 units
3. Distance 130 3. 130 units
4. Distance 160 4. 160 units
5. Distance 190 5. 190 units
6. Distance 220 6. 220 units
7. Distance 250 (Default) 7. 250 units (Default)
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yДистанция автопути\w \yДистанция автопути\w
1. Дистанция 0 1. 0 юнитов
2. Дистанция 100 2. 100 юнитов
3. Дистанция 130 3. 130 юнитов
4. Дистанция 160 4. 160 юнитов
5. Дистанция 190 5. 190 юнитов
6. Дистанция 220 6. 220 юнитов
7. Дистанция 250 (По умолчанию) 7. 250 юнитов (по умолчанию)
0. Выход 0. Выход
[ORIGINAL] [ORIGINAL]
\yCreate Path (Choose Direction)\w \yCreate Path (Choose Direction)\w
1. Outgoing Path 1. Outgoing path
2. Incoming Path 2. Incoming path
3. Bidirectional (Both Ways) 3. Bidirectional (both ways)
4. Jumping Path 4. Jumping path
0. Exit 0. Exit
[TRANSLATED] [TRANSLATED]
\yСоздание пути (выберите направление)\w \yСоздать путь (выберите направление)\w
1. Исходящий путь 1. Исходящий путь
2. Входящий путь 2. Входящий путь
3. Двунаправленный (Оба пути) 3. Двунаправленный (оба пути)
4. Прыговой путь 4. Прыговой путь
0. Выход 0. Выход
@ -696,13 +698,13 @@ Bot '%s' kicked.
Бот '%s' убран. Бот '%s' убран.
[ORIGINAL] [ORIGINAL]
Bots Remove Menu Bot Removal Menu
[TRANSLATED] [TRANSLATED]
Меню убирания ботов Меню убирания ботов
[ORIGINAL] [ORIGINAL]
Not a Bot Not a bot
[TRANSLATED] [TRANSLATED]
Не бот Не бот
@ -2463,9 +2465,9 @@ Allowed values: 'none', 'normal', 'careful', 'rusher'.
If 'none' is specified personality chosen randomly. If 'none' is specified personality chosen randomly.
[TRANSLATED] [TRANSLATED]
Задаёт личность по умолчанию при создании ботов с управлением квотой. Задаёт характер по умолчанию при создании ботов с управлением квотой.
Допустимые значения: 'none', 'normal', 'careful', 'rusher'. Допустимые значения: 'none', 'normal', 'careful', 'rusher'.
Если указано 'none', личность выбирается случайным образом. Если указано 'none', характер выбирается случайным образом.
[ORIGINAL] [ORIGINAL]
Lower bound for base bot ping shown in scoreboard upon creation. Lower bound for base bot ping shown in scoreboard upon creation.
@ -2729,49 +2731,43 @@ header:
magic: %d magic: %d
[TRANSLATED] [TRANSLATED]
магическое число: %d магическое число: %d
[ORIGINAL] [ORIGINAL]
version: %d version: %d
[TRANSLATED] [TRANSLATED]
версия: %d версия: %d
[ORIGINAL] [ORIGINAL]
node_count: %d node_count: %d
[TRANSLATED] [TRANSLATED]
количество точек: %d количество точек: %d
[ORIGINAL] [ORIGINAL]
compressed_size: %dkB compressed_size: %dkB
[TRANSLATED] [TRANSLATED]
размер с сжатием: %dКБ размер с сжатием: %dКБ
[ORIGINAL] [ORIGINAL]
uncompressed_size: %dkB uncompressed_size: %dkB
[TRANSLATED] [TRANSLATED]
размер без сжатия: %dКБ размер без сжатия: %dКБ
[ORIGINAL] [ORIGINAL]
options: %d options: %d
[TRANSLATED] [TRANSLATED]
опции: %d опции: %d
[ORIGINAL] [ORIGINAL]
analyzed: yes analyzed: %s
[TRANSLATED] [TRANSLATED]
проанализировано: да проанализировано: %s
[ORIGINAL]
analyzed: no
[TRANSLATED]
проанализировано: нет
[ORIGINAL] [ORIGINAL]
extensions: extensions:
@ -2783,19 +2779,19 @@ extensions:
author: %s author: %s
[TRANSLATED] [TRANSLATED]
автор: %s автор: %s
[ORIGINAL] [ORIGINAL]
modified_by: %s modified_by: %s
[TRANSLATED] [TRANSLATED]
модифицировано: %s модифицировано: %s
[ORIGINAL] [ORIGINAL]
bsp_size: %d bsp_size: %d
[TRANSLATED] [TRANSLATED]
размер bsp: %d размер bsp: %d
[ORIGINAL] [ORIGINAL]
Force-enable Xash3D sv_forcesimulating cvar. Force-enable Xash3D sv_forcesimulating cvar.
@ -2826,3 +2822,15 @@ You're launched standalone version of %s. Metamod is not installed or not enable
[TRANSLATED] [TRANSLATED]
Вы запустили автономную версию %s. Metamod не установлен или не включён! Вы запустили автономную версию %s. Metamod не установлен или не включён!
[ORIGINAL]
yes
[TRANSLATED]
да
[ORIGINAL]
no
[TRANSLATED]
нет

@ -1 +1 @@
Subproject commit c72215707a9be44eb2582b82a90a4a7f27a9f2e1 Subproject commit d35f784642aa87f8e86930442fcc4fc1087b8f15

View file

@ -47,7 +47,8 @@ CR_DECLARE_SCOPED_ENUM (GameFlags,
HasFakePings = cr::bit (10), // on that game version we can fake bots pings HasFakePings = cr::bit (10), // on that game version we can fake bots pings
HasBotVoice = cr::bit (11), // on that game version we can use chatter HasBotVoice = cr::bit (11), // on that game version we can use chatter
AnniversaryHL25 = cr::bit (12), // half-life 25th anniversary engine AnniversaryHL25 = cr::bit (12), // half-life 25th anniversary engine
Xash3DLegacy = cr::bit (13) // old xash3d-branch Xash3DLegacy = cr::bit (13), // old xash3d-branch
ZombieMod = cr::bit (14) // zombie mod is active
) )
// defines map type // defines map type

View file

@ -269,7 +269,7 @@ public:
public: public:
int32_t getMaxRouteLength () const { int32_t getMaxRouteLength () const {
return length () / 2; return (length () / 2) + (kMaxNodes / 256);
} }
StringRef getAuthor () const { StringRef getAuthor () const {

View file

@ -122,6 +122,7 @@ public:
void setLastWinner (int winner); void setLastWinner (int winner);
void checkBotModel (edict_t *ent, char *infobuffer); void checkBotModel (edict_t *ent, char *infobuffer);
void checkNeedsToBeKicked (); void checkNeedsToBeKicked ();
void refreshCreatureStatus ();
bool isTeamStacked (int team); bool isTeamStacked (int team);
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned); bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);

View file

@ -189,7 +189,8 @@ public:
} }
void init (int32_t length) { void init (int32_t length) {
m_path = cr::makeUnique <int32_t[]> (length); const auto allocSize = static_cast <uint32_t> (length);
m_path = cr::makeUnique <int32_t[]> (allocSize);
} }
}; };
@ -305,6 +306,7 @@ private:
bool m_moveToC4 {}; // ct is moving to bomb bool m_moveToC4 {}; // ct is moving to bomb
bool m_needToSendWelcomeChat {}; // bot needs to greet people on server? bool m_needToSendWelcomeChat {}; // bot needs to greet people on server?
bool m_isCreature {}; // bot is not a player, but something else ? zombie ? bool m_isCreature {}; // bot is not a player, but something else ? zombie ?
bool m_isOnInfectedTeam {}; // bot is zombie (this assumes bot is a creature)
bool m_defuseNotified {}; // bot is notified about bomb defusion bool m_defuseNotified {}; // bot is notified about bomb defusion
bool m_jumpSequence {}; // next path link will be jump link bool m_jumpSequence {}; // next path link will be jump link
bool m_checkFall {}; // check bot fall bool m_checkFall {}; // check bot fall
@ -464,7 +466,7 @@ private:
void updateLookAnglesNewbie (const Vector &direction, float delta); void updateLookAnglesNewbie (const Vector &direction, float delta);
void setIdealReactionTimers (bool actual = false); void setIdealReactionTimers (bool actual = false);
void updateHearing (); void updateHearing ();
void postprocessGoals (const IntArray &goals, int result[]); void postProcessGoals (const IntArray &goals, int result[]);
void updatePickups (); void updatePickups ();
void ensureEntitiesClear (); void ensureEntitiesClear ();
void checkTerrain (float movedDistance, const Vector &dirNormal); void checkTerrain (float movedDistance, const Vector &dirNormal);
@ -499,7 +501,7 @@ private:
void selectWeaponByIndex (int index); void selectWeaponByIndex (int index);
void syncUpdatePredictedIndex (); void syncUpdatePredictedIndex ();
void updatePredictedIndex (); void updatePredictedIndex ();
void refreshModelName (char *infobuffer); void refreshCreatureStatus (char *infobuffer);
void updateRightRef (); void updateRightRef ();
void completeTask (); void completeTask ();

View file

@ -177,7 +177,7 @@ void GraphAnalyze::optimize () {
cleanup (); cleanup ();
auto smooth = [] (const Array <int> &nodes) { auto smooth = [] (const Array <int> &nodes) {
Vector result; Vector result {};
for (const auto &node : nodes) { for (const auto &node : nodes) {
result += graph[node].origin; result += graph[node].origin;
@ -198,7 +198,7 @@ void GraphAnalyze::optimize () {
continue; continue;
} }
const auto &path = graph[i]; const auto &path = graph[i];
Array <int> indexes; Array <int> indexes {};
for (const auto &link : path.links) { for (const auto &link : path.links) {
if (graph.exists (link.index) && !m_optimizedNodes[link.index] if (graph.exists (link.index) && !m_optimizedNodes[link.index]
@ -303,7 +303,7 @@ void GraphAnalyze::displayOverlayMessage () {
void GraphAnalyze::flood (const Vector &pos, const Vector &next, float range) { void GraphAnalyze::flood (const Vector &pos, const Vector &next, float range) {
range *= 0.75f; range *= 0.75f;
TraceResult tr; TraceResult tr {};
game.testHull (pos, { next.x, next.y, next.z + 19.0f }, TraceIgnore::Monsters, head_hull, nullptr, &tr); game.testHull (pos, { next.x, next.y, next.z + 19.0f }, TraceIgnore::Monsters, head_hull, nullptr, &tr);
// we're can't reach next point // we're can't reach next point

View file

@ -887,7 +887,7 @@ void Bot::instantChatter (int type) {
if (m_isAlive) { if (m_isAlive) {
showChatterIcon (true); showChatterIcon (true);
} }
MessageWriter msg; MessageWriter msg {};
const int ownIndex = index (); const int ownIndex = index ();
auto writeChatterSound = [&msg] (ChatterItem item) { auto writeChatterSound = [&msg] (ChatterItem item) {
@ -1161,18 +1161,18 @@ bool Bot::isWeaponRestrictedAMX (int wid) {
// check for weapon restrictions // check for weapon restrictions
if (cr::bit (wid) & (kPrimaryWeaponMask | kSecondaryWeaponMask | Weapon::Shield)) { if (cr::bit (wid) & (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 }; constexpr int kIds[] = { 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 // verify restrictions
return checkRestriction ("amx_restrweapons", ids); return checkRestriction ("amx_restrweapons", kIds);
} }
// check for equipment restrictions // check for equipment restrictions
else { else {
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 }; constexpr int kIds[] = { -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 };
// verify restrictions // verify restrictions
return checkRestriction ("amx_restrequipammo", ids); return checkRestriction ("amx_restrequipammo", kIds);
} }
} }
@ -1253,7 +1253,7 @@ void Bot::buyStuff () {
} }
int count = 0; int count = 0;
Array <int32_t> choices; Array <int32_t> choices {};
// select the priority tab for this personality // select the priority tab for this personality
const int *pref = conf.getWeaponPrefs (m_personality) + kNumWeapons; const int *pref = conf.getWeaponPrefs (m_personality) + kNumWeapons;
@ -1658,10 +1658,10 @@ void Bot::overrideConditions () {
// special handling, if we have a knife in our hands // special handling, if we have a knife in our hands
if (isKnifeMode () && (util.isPlayer (m_enemy) || (cv_attack_monsters && util.isMonster (m_enemy)))) { if (isKnifeMode () && (util.isPlayer (m_enemy) || (cv_attack_monsters && util.isMonster (m_enemy)))) {
const float length = pev->origin.distance2d (m_enemy->v.origin); const float distance2d = pev->origin.distance2d (m_enemy->v.origin);
// do nodes movement if enemy is not reachable with a knife // do nodes movement if enemy is not reachable with a knife
if (length > 250.0f && (m_states & Sense::SeeingEnemy)) { if (distance2d > 250.0f && (m_states & Sense::SeeingEnemy)) {
const int nearestToEnemyPoint = graph.getNearest (m_enemy->v.origin); const int nearestToEnemyPoint = graph.getNearest (m_enemy->v.origin);
if (nearestToEnemyPoint != kInvalidNodeIndex if (nearestToEnemyPoint != kInvalidNodeIndex
@ -1669,18 +1669,18 @@ void Bot::overrideConditions () {
&& cr::abs (graph[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) { && cr::abs (graph[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) {
if (tid != Task::MoveToPosition && !cr::fequal (getTask ()->desire, TaskPri::Hide)) { if (tid != Task::MoveToPosition && !cr::fequal (getTask ()->desire, TaskPri::Hide)) {
startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + length / (m_moveSpeed * 2.0f), true); startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + distance2d / (m_moveSpeed * 2.0f), true);
} }
else { else {
if (tid == Task::MoveToPosition && getTask ()->data != nearestToEnemyPoint) { if (tid == Task::MoveToPosition && getTask ()->data != nearestToEnemyPoint) {
clearTask (Task::MoveToPosition); clearTask (Task::MoveToPosition);
startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + length / (m_moveSpeed * 2.0f), true); startTask (Task::MoveToPosition, TaskPri::Hide, nearestToEnemyPoint, game.time () + distance2d / (m_moveSpeed * 2.0f), true);
} }
} }
} }
} }
else { else {
if (length <= 250.0f && (m_states & Sense::SeeingEnemy) && tid == Task::MoveToPosition) { if (distance2d <= 250.0f && (m_states & Sense::SeeingEnemy) && tid == Task::MoveToPosition) {
clearTask (Task::MoveToPosition); // remove any move tasks clearTask (Task::MoveToPosition); // remove any move tasks
} }
} }
@ -2877,7 +2877,6 @@ void Bot::frame () {
if (m_thinkDelay.time <= game.time ()) { if (m_thinkDelay.time <= game.time ()) {
update (); update ();
// delay next execution for thinking // delay next execution for thinking
m_thinkDelay.time = game.time () + m_thinkDelay.interval; m_thinkDelay.time = game.time () + m_thinkDelay.interval;
@ -3013,7 +3012,7 @@ void Bot::logicDuringFreezetime () {
pev->button |= IN_JUMP; pev->button |= IN_JUMP;
m_jumpTime = game.time (); m_jumpTime = game.time ();
} }
static Array <Bot *> teammates; static Array <Bot *> teammates {};
teammates.clear (); teammates.clear ();
for (const auto &bot : bots) { for (const auto &bot : bots) {
@ -3282,7 +3281,7 @@ void Bot::logic () {
} }
void Bot::spawned () { void Bot::spawned () {
if (game.is (GameFlags::CSDM)) { if (game.is (GameFlags::CSDM | GameFlags::ZombieMod)) {
newRound (); newRound ();
clearTasks (); clearTasks ();
} }
@ -3380,7 +3379,7 @@ void Bot::showDebugOverlay () {
if (!game.isNullEntity (m_pickupItem)) { if (!game.isNullEntity (m_pickupItem)) {
pickup = m_pickupItem->v.classname.str (); pickup = m_pickupItem->v.classname.str ();
} }
String aimFlags; String aimFlags {};
for (uint32_t i = 0u; i < 9u; ++i) { for (uint32_t i = 0u; i < 9u; ++i) {
auto bit = cr::bit (i); auto bit = cr::bit (i);
@ -3718,7 +3717,7 @@ void Bot::debugMsgInternal (StringRef str) {
if (level <= 2) { if (level <= 2) {
return; return;
} }
String printBuf; String printBuf {};
printBuf.assignf ("%s: %s", pev->netname.str (), str); printBuf.assignf ("%s: %s", pev->netname.str (), str);
bool playMessage = false; bool playMessage = false;
@ -3777,9 +3776,9 @@ Vector Bot::isBombAudible () {
} }
bool Bot::canRunHeavyWeight () { bool Bot::canRunHeavyWeight () {
constexpr auto interval = 1.0f / 10.0f; constexpr auto kInterval = 1.0f / 10.0f;
if (m_heavyTimestamp + interval < game.time ()) { if (m_heavyTimestamp + kInterval < game.time ()) {
m_heavyTimestamp = game.time (); m_heavyTimestamp = game.time ();
return true; return true;
@ -4070,7 +4069,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) {
return false; return false;
} }
bool defusingInProgress = false; bool defusingInProgress = false;
constexpr auto distanceToBomb = cr::sqrf (165.0f); constexpr auto kDistanceToBomb = cr::sqrf (165.0f);
for (const auto &client : util.getClients ()) { for (const auto &client : util.getClients ()) {
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive)) { if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive)) {
@ -4086,7 +4085,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) {
} }
// if close enough, mark as progressing // if close enough, mark as progressing
if (bombDistanceSq < distanceToBomb && (bot->getCurrentTaskId () == Task::DefuseBomb || bot->m_hasProgressBar)) { if (bombDistanceSq < kDistanceToBomb && (bot->getCurrentTaskId () == Task::DefuseBomb || bot->m_hasProgressBar)) {
defusingInProgress = true; defusingInProgress = true;
break; break;
} }
@ -4097,7 +4096,7 @@ bool Bot::isBombDefusing (const Vector &bombOrigin) {
if (client.team == m_team) { if (client.team == m_team) {
// if close enough, mark as progressing // if close enough, mark as progressing
if (bombDistanceSq < distanceToBomb && ((client.ent->v.button | client.ent->v.oldbuttons) & IN_USE)) { if (bombDistanceSq < kDistanceToBomb && ((client.ent->v.button | client.ent->v.oldbuttons) & IN_USE)) {
defusingInProgress = true; defusingInProgress = true;
break; break;
} }
@ -4127,7 +4126,27 @@ float Bot::getShiftSpeed () {
return pev->maxspeed * 0.4f; return pev->maxspeed * 0.4f;
} }
void Bot::refreshModelName (char *infobuffer) { void Bot::refreshCreatureStatus (char *infobuffer) {
// if bot is on infected team, assume he is a creature
if (game.is (GameFlags::ZombieMod)) {
static StringRef zmInfectedTeam (conf.fetchCustom ("ZMInfectedTeam"));
// by default infected team is terrorists
Team infectedTeam = Team::Terrorist;
if (zmInfectedTeam == "CT") {
infectedTeam = Team::CT;
}
// if bot is on infected team, and zombie mode is active, assume bot is a creature/zombie
m_isOnInfectedTeam = game.getRealTeam (ent ()) == infectedTeam;
// do not process next if already infected
if (m_isOnInfectedTeam) {
return;
}
}
if (infobuffer == nullptr) { if (infobuffer == nullptr) {
infobuffer = engfuncs.pfnGetInfoKeyBuffer (ent ()); infobuffer = engfuncs.pfnGetInfoKeyBuffer (ent ());
} }
@ -4150,8 +4169,8 @@ void Bot::refreshModelName (char *infobuffer) {
bool Bot::isCreature () { bool Bot::isCreature () {
// current creature models are: zombie, chicken // current creature models are: zombie, chicken
constexpr auto modelMaskZombie = (('o' << 8) + 'z'); constexpr auto kModelMaskZombie = (('o' << 8) + 'z');
constexpr auto modelMaskChicken = (('h' << 8) + 'c'); constexpr auto kModelMaskChicken = (('h' << 8) + 'c');
return m_modelMask == modelMaskZombie || m_modelMask == modelMaskChicken; return m_isOnInfectedTeam || m_modelMask == kModelMaskZombie || m_modelMask == kModelMaskChicken;
} }

View file

@ -195,7 +195,7 @@ void Bot::prepareChatMessage (StringRef message) {
auto getRoundTime = [] () -> String { auto getRoundTime = [] () -> String {
auto roundTimeSecs = static_cast <int> (bots.getRoundEndTime () - game.time ()); auto roundTimeSecs = static_cast <int> (bots.getRoundEndTime () - game.time ());
String roundTime; String roundTime {};
roundTime.assignf ("%02d:%02d", cr::clamp (roundTimeSecs / 60, 0, 59), cr::clamp (cr::abs (roundTimeSecs % 60), 0, 59)); roundTime.assignf ("%02d:%02d", cr::clamp (roundTimeSecs / 60, 0, 59), cr::clamp (cr::abs (roundTimeSecs % 60), 0, 59));
return roundTime; return roundTime;
@ -203,12 +203,12 @@ void Bot::prepareChatMessage (StringRef message) {
// get bot's victim // get bot's victim
auto getMyVictim = [&] () -> String {; auto getMyVictim = [&] () -> String {;
return humanizedName (game.indexOfPlayer (m_lastVictim)); return humanizedName (game.indexOfPlayer (m_lastVictim));
}; };
// get the game name alias // get the game name alias
auto getGameName = [] () -> String { auto getGameName = [] () -> String {
String gameName; String gameName {};
if (game.is (GameFlags::ConditionZero)) { if (game.is (GameFlags::ConditionZero)) {
if (rg.chance (30)) { if (rg.chance (30)) {
@ -308,7 +308,7 @@ bool Bot::isReplyingToChat () {
if (m_sayTextBuffer.entityIndex != -1 && !m_sayTextBuffer.sayText.empty ()) { if (m_sayTextBuffer.entityIndex != -1 && !m_sayTextBuffer.sayText.empty ()) {
// check is time to chat is good // check is time to chat is good
if (m_sayTextBuffer.timeNextChat < game.time () + rg (m_sayTextBuffer.chatDelay / 2, m_sayTextBuffer.chatDelay)) { if (m_sayTextBuffer.timeNextChat < game.time () + rg (m_sayTextBuffer.chatDelay / 2, m_sayTextBuffer.chatDelay)) {
String replyText; String replyText {};
if (rg.chance (m_sayTextBuffer.chatProbability + rg (40, 70)) && checkChatKeywords (replyText)) { if (rg.chance (m_sayTextBuffer.chatProbability + rg (40, 70)) && checkChatKeywords (replyText)) {
prepareChatMessage (replyText); prepareChatMessage (replyText);

View file

@ -793,7 +793,7 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest, int) {
int thikness = 0; int thikness = 0;
int numHits = 0; int numHits = 0;
Vector point; Vector point {};
TraceResult tr {}; TraceResult tr {};
game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr); game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr);
@ -998,7 +998,11 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
if (distance >= 750.0f && !isShieldDrawn ()) { if (distance >= 750.0f && !isShieldDrawn ()) {
pev->button |= IN_ATTACK2; // draw the shield pev->button |= IN_ATTACK2; // draw the shield
} }
else if (isShieldDrawn () || (!game.isNullEntity (m_enemy) && ((m_enemy->v.button & IN_RELOAD) || !seesEntity (m_enemy->v.origin)))) { else if (isShieldDrawn ()
|| m_isReloading
|| !seesEntity (m_enemy->v.origin)
|| (!game.isNullEntity (m_enemy) && (m_enemy->v.button & IN_RELOAD))) {
pev->button |= IN_ATTACK2; // draw out the shield pev->button |= IN_ATTACK2; // draw out the shield
} }
m_shieldCheckTime = game.time () + 1.0f; m_shieldCheckTime = game.time () + 1.0f;
@ -1316,7 +1320,7 @@ void Bot::attackMovement () {
} }
const bool isFullView = !!(m_enemyParts & (Visibility::Head | Visibility::Body)); const bool isFullView = !!(m_enemyParts & (Visibility::Head | Visibility::Body));
if (m_lastFightStyleCheck + 3.0f < game.time ()) { if (m_lastFightStyleCheck < game.time ()) {
if (usesSniper ()) { if (usesSniper ()) {
m_fightStyle = Fight::Stay; m_fightStyle = Fight::Stay;
} }
@ -1368,7 +1372,7 @@ void Bot::attackMovement () {
&& isInViewCone (m_enemyOrigin))) { && isInViewCone (m_enemyOrigin))) {
m_fightStyle = Fight::Strafe; m_fightStyle = Fight::Strafe;
} }
m_lastFightStyleCheck = game.time (); m_lastFightStyleCheck = game.time () + 3.0f;
} }
if (distance < 96.0f && !usesKnife ()) { if (distance < 96.0f && !usesKnife ()) {
@ -1490,7 +1494,7 @@ void Bot::attackMovement () {
} }
if (!isInWater () && !isOnLadder () && (m_moveSpeed > 0.0f || m_strafeSpeed > 0.0f)) { if (!isInWater () && !isOnLadder () && (m_moveSpeed > 0.0f || m_strafeSpeed > 0.0f)) {
Vector right, forward; Vector right {}, forward {};
pev->v_angle.angleVectors (&forward, &right, nullptr); pev->v_angle.angleVectors (&forward, &right, nullptr);
const auto &front = forward * m_moveSpeed * 0.2f; const auto &front = forward * m_moveSpeed * 0.2f;
@ -1752,7 +1756,7 @@ int Bot::bestWeaponCarried () {
void Bot::decideFollowUser () { void Bot::decideFollowUser () {
// this function forces bot to follow user // this function forces bot to follow user
static Array <edict_t *> users; static Array <edict_t *> users {};
users.clear (); users.clear ();
// search friends near us // search friends near us
@ -2311,7 +2315,8 @@ bool Bot::isEnemyNoticeable (float range) {
constexpr float kCloseRange = 300.0f; constexpr float kCloseRange = 300.0f;
constexpr float kFarRange = 1000.0f; constexpr float kFarRange = 1000.0f;
float rangeModifier; float rangeModifier {};
if (range < kCloseRange) { if (range < kCloseRange) {
rangeModifier = 0.0f; rangeModifier = 0.0f;
} }
@ -2327,7 +2332,7 @@ bool Bot::isEnemyNoticeable (float range) {
// moving players are easier to spot // moving players are easier to spot
float playerSpeedSq = m_enemy->v.velocity.lengthSq (); float playerSpeedSq = m_enemy->v.velocity.lengthSq ();
float farChance, closeChance; float farChance {}, closeChance {};
constexpr float kRunSpeed = cr::sqrf (200.0f); constexpr float kRunSpeed = cr::sqrf (200.0f);
constexpr float kWalkSpeed = cr::sqrf (30.0f); constexpr float kWalkSpeed = cr::sqrf (30.0f);

View file

@ -46,8 +46,9 @@ void BotConfig::loadMainConfig (bool isFirstLoad) {
} }
return false; return false;
}; };
String line;
MemFile file; String line {};
MemFile file {};
// this is does the same as exec of engine, but not overwriting values of cvars specified in cv_ignore_cvars_on_changelevel // this is does the same as exec of engine, but not overwriting values of cvars specified in cv_ignore_cvars_on_changelevel
if (openConfig (product.nameLower, "Bot main config file is not found.", &file, false)) { if (openConfig (product.nameLower, "Bot main config file is not found.", &file, false)) {
@ -121,8 +122,8 @@ void BotConfig::loadMainConfig (bool isFirstLoad) {
void BotConfig::loadNamesConfig () { void BotConfig::loadNamesConfig () {
setupMemoryFiles (); setupMemoryFiles ();
String line; String line {};
MemFile file; MemFile file {};
constexpr auto kMaxNameLen = 32; constexpr auto kMaxNameLen = 32;
@ -179,8 +180,8 @@ void BotConfig::loadWeaponsConfig () {
to[i] = data[i].as <int> (); to[i] = data[i].as <int> ();
} }
}; };
String line; String line {};
MemFile file; MemFile file {};
// weapon data initialization // weapon data initialization
if (openConfig ("weapon", "Weapon configuration file not found. Loading defaults.", &file)) { if (openConfig ("weapon", "Weapon configuration file not found. Loading defaults.", &file)) {
@ -231,8 +232,8 @@ void BotConfig::loadWeaponsConfig () {
void BotConfig::loadChatterConfig () { void BotConfig::loadChatterConfig () {
setupMemoryFiles (); setupMemoryFiles ();
String line; String line {};
MemFile file; MemFile file {};
// chatter initialization // chatter initialization
if (game.is (GameFlags::HasBotVoice) && cv_radio_mode.as <int> () == 2 && openConfig ("chatter", "Couldn't open chatter system configuration", &file)) { if (game.is (GameFlags::HasBotVoice) && cv_radio_mode.as <int> () == 2 && openConfig ("chatter", "Couldn't open chatter system configuration", &file)) {
@ -379,8 +380,8 @@ void BotConfig::loadChatterConfig () {
void BotConfig::loadChatConfig () { void BotConfig::loadChatConfig () {
setupMemoryFiles (); setupMemoryFiles ();
String line; String line {};
MemFile file; MemFile file {};
// chat config initialization // chat config initialization
if (openConfig ("chat", "Chat file not found.", &file, true)) { if (openConfig ("chat", "Chat file not found.", &file, true)) {
@ -481,16 +482,20 @@ void BotConfig::loadLanguageConfig () {
if (game.is (GameFlags::Legacy)) { if (game.is (GameFlags::Legacy)) {
return; // legacy versions will use only english translation return; // legacy versions will use only english translation
} }
String line; String line {};
MemFile file; MemFile file {};
// localizer initialization // localizer initialization
if (openConfig ("lang", "Specified language not found.", &file, true)) { if (openConfig ("lang", "Specified language not found.", &file, true)) {
String temp; String temp {};
Twin <String, String> lang; Twin <String, String> lang {};
auto trimWithoutWs = [] (String in) -> String {
return in.trim ("\r\n");
};
auto pushTranslatedMsg = [&] () { auto pushTranslatedMsg = [&] () {
m_language[hashLangString (lang.first.trim ().chars ())] = lang.second.trim (); m_language[hashLangString (trimWithoutWs (lang.first).chars ())] = trimWithoutWs (lang.second);
}; };
// clear all the translations before new load // clear all the translations before new load
@ -519,7 +524,7 @@ void BotConfig::loadLanguageConfig () {
// make sure last string is translated // make sure last string is translated
if (file.eof () && !lang.first.empty ()) { if (file.eof () && !lang.first.empty ()) {
lang.second = line.trim (); lang.second = trimWithoutWs (line);
pushTranslatedMsg (); pushTranslatedMsg ();
} }
} }
@ -537,8 +542,8 @@ void BotConfig::loadAvatarsConfig () {
return; return;
} }
String line; String line {};
MemFile file; MemFile file {};
// avatars initialization // avatars initialization
if (openConfig ("avatars", "Avatars config file not found. Avatars will not be displayed.", &file)) { if (openConfig ("avatars", "Avatars config file not found. Avatars will not be displayed.", &file)) {
@ -556,8 +561,8 @@ void BotConfig::loadAvatarsConfig () {
void BotConfig::loadDifficultyConfig () { void BotConfig::loadDifficultyConfig () {
setupMemoryFiles (); setupMemoryFiles ();
String line; String line {};
MemFile file; MemFile file {};
// initialize defaults // initialize defaults
m_difficulty[Difficulty::Noob] = { m_difficulty[Difficulty::Noob] = {
@ -661,14 +666,19 @@ void BotConfig::loadMapSpecificConfig () {
} }
void BotConfig::loadCustomConfig () { void BotConfig::loadCustomConfig () {
String line; String line {};
MemFile file; MemFile file {};
auto setDefaults = [&] () { auto setDefaults = [&] () {
m_custom["C4ModelName"] = "c4.mdl"; m_custom["C4ModelName"] = "c4.mdl";
m_custom["AMXParachuteCvar"] = "sv_parachute"; m_custom["AMXParachuteCvar"] = "sv_parachute";
m_custom["CustomCSDMSpawnPoint"] = "view_spawn"; m_custom["CustomCSDMSpawnPoint"] = "view_spawn";
m_custom["CSDMDetectCvar"] = "csdm_active";
m_custom["ZMDetectCvar"] = "zp_delay";
m_custom["ZMDelayCvar"] = "zp_delay";
m_custom["ZMInfectedTeam"] = "T";
}; };
setDefaults (); setDefaults ();
// has errors ? // has errors ?
@ -710,8 +720,8 @@ void BotConfig::loadCustomConfig () {
void BotConfig::loadLogosConfig () { void BotConfig::loadLogosConfig () {
setupMemoryFiles (); setupMemoryFiles ();
String line; String line {};
MemFile file; MemFile file {};
// logos initialization // logos initialization
if (openConfig ("logos", "Logos config file not found. Loading defaults.", &file)) { if (openConfig ("logos", "Logos config file not found. Loading defaults.", &file)) {
@ -866,7 +876,8 @@ uint32_t BotConfig::hashLangString (StringRef str) {
auto test = [] (const char ch) { auto test = [] (const char ch) {
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}; };
String res;
String res {};
for (const auto &ch : str) { for (const auto &ch : str) {
if (!test (ch)) { if (!test (ch)) {

View file

@ -231,7 +231,7 @@ int BotControl::cmdCvars () {
const bool isSave = isSaveMain || isSaveMap; const bool isSave = isSaveMain || isSaveMap;
File cfg; File cfg {};
// if save requested, dump cvars to main config // if save requested, dump cvars to main config
if (isSave) { if (isSave) {
@ -375,8 +375,8 @@ int BotControl::cmdNode () {
} }
// should be moved to class? // should be moved to class?
static HashMap <String, BotCmd> commands; static HashMap <String, BotCmd> commands {};
static StringArray descriptions; static StringArray descriptions {};
// fill only once // fill only once
if (descriptions.empty ()) { if (descriptions.empty ()) {
@ -898,7 +898,7 @@ int BotControl::cmdNodeUpload () {
msg ("\n"); msg ("\n");
} }
else { else {
String status; String status {};
auto code = http.getLastStatusCode (); auto code = http.getLastStatusCode ();
if (code == HttpClientResult::Forbidden) { if (code == HttpClientResult::Forbidden) {
@ -1871,7 +1871,8 @@ bool BotControl::executeCommands () {
} }
return false; return false;
}; };
String cmd;
String cmd {};
// give some help // give some help
if (hasArg (1) && arg <StringRef> (1) == "help") { if (hasArg (1) && arg <StringRef> (1) == "help") {
@ -2012,15 +2013,16 @@ void BotControl::showMenu (int id) {
.writeByte (last ? HLFalse : HLTrue) .writeByte (last ? HLFalse : HLTrue)
.writeString (text.chars ()); .writeString (text.chars ());
}; };
constexpr size_t maxMenuSentLength = 140;
constexpr size_t kMaxMenuSentLength = 140;
for (const auto &display : m_menus) { for (const auto &display : m_menus) {
if (display.ident == id) { if (display.ident == id) {
String text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !cv_display_menu_text) ? " " : display.text.chars (); String text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !cv_display_menu_text) ? " " : display.text.chars ();
// split if needed // split if needed
if (text.length () > maxMenuSentLength) { if (text.length () > kMaxMenuSentLength) {
auto chunks = text.split (maxMenuSentLength); auto chunks = text.split (kMaxMenuSentLength);
// send in chunks // send in chunks
for (size_t i = 0; i < chunks.length (); ++i) { for (size_t i = 0; i < chunks.length (); ++i) {
@ -2064,12 +2066,12 @@ void BotControl::kickBotByMenu (int page) {
return; return;
} }
static StringRef headerTitle = conf.translate ("Bots Remove Menu"); static StringRef headerTitle = conf.translate ("Bot Removal Menu");
static StringRef notABot = conf.translate ("Not a Bot"); static StringRef notABot = conf.translate ("Not a bot");
static StringRef backKey = conf.translate ("Back"); static StringRef backKey = conf.translate ("Back");
static StringRef moreKey = conf.translate ("More"); static StringRef moreKey = conf.translate ("More");
String menus; String menus {};
menus.assignf ("\\y%s (%d/4):\\w\n\n", headerTitle, page); menus.assignf ("\\y%s (%d/4):\\w\n\n", headerTitle, page);
int menuKeys = (page == 4) ? cr::bit (9) : (cr::bit (8) | cr::bit (9)); int menuKeys = (page == 4) ? cr::bit (9) : (cr::bit (8) | cr::bit (9));
@ -2270,10 +2272,10 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::Main, keys (4), Menu::Main, keys (4),
"\\yMain Menu\\w\n\n" "\\yMain Menu\\w\n\n"
"1. Control Bots\n" "1. Control bots\n"
"2. Features\n\n" "2. Features\n\n"
"3. Fill Server\n" "3. Fill server\n"
"4. End Round\n\n" "4. End round\n\n"
"0. Exit", "0. Exit",
&BotControl::menuMain); &BotControl::menuMain);
@ -2282,11 +2284,11 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::Features, keys (5), Menu::Features, keys (5),
"\\yBots Features\\w\n\n" "\\yBots Features\\w\n\n"
"1. Weapon Mode Menu\n" "1. Weapon mode menu\n"
"2. Waypoint Menu\n" "2. Graph editor\n"
"3. Select Personality\n\n" "3. Select personality\n\n"
"4. Toggle Debug Mode\n" "4. Toggle debug mode\n"
"5. Command Menu\n\n" "5. Command menu\n\n"
"0. Exit", "0. Exit",
&BotControl::menuFeatures); &BotControl::menuFeatures);
@ -2294,11 +2296,11 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::Control, keys (5), Menu::Control, keys (5),
"\\yBots Control Menu\\w\n\n" "\\yBots Control Menu\\w\n\n"
"1. Add a Bot, Quick\n" "1. Quick add bot\n"
"2. Add a Bot, Specified\n\n" "2. Add specific bot\n\n"
"3. Remove Random Bot\n" "3. Remove random bot\n"
"4. Remove All Bots\n\n" "4. Remove all bots\n\n"
"5. Remove Bot Menu\n\n" "5. Bot removal menu\n\n"
"0. Exit", "0. Exit",
&BotControl::menuControl); &BotControl::menuControl);
@ -2309,10 +2311,10 @@ void BotControl::createMenus () {
"1. Knives only\n" "1. Knives only\n"
"2. Pistols only\n" "2. Pistols only\n"
"3. Shotguns only\n" "3. Shotguns only\n"
"4. Machine Guns only\n" "4. Machine guns only\n"
"5. Rifles only\n" "5. Rifles only\n"
"6. Sniper Weapons only\n" "6. Sniper weapons only\n"
"7. All Weapons\n\n" "7. All weapons\n\n"
"0. Exit", "0. Exit",
&BotControl::menuWeaponMode); &BotControl::menuWeaponMode);
@ -2342,7 +2344,7 @@ void BotControl::createMenus () {
// team select menu // team select menu
m_menus.emplace ( m_menus.emplace (
Menu::TeamSelect, keys (5), Menu::TeamSelect, keys (5),
"\\ySelect a team\\w\n\n" "\\ySelect a Team\\w\n\n"
"1. Terrorist Force\n" "1. Terrorist Force\n"
"2. Counter-Terrorist Force\n\n" "2. Counter-Terrorist Force\n\n"
"5. Auto-select\n\n" "5. Auto-select\n\n"
@ -2352,7 +2354,7 @@ void BotControl::createMenus () {
// terrorist model select menu // terrorist model select menu
m_menus.emplace ( m_menus.emplace (
Menu::TerroristSelect, keys (5), Menu::TerroristSelect, keys (5),
"\\ySelect an appearance\\w\n\n" "\\ySelect an Appearance\\w\n\n"
"1. Phoenix Connexion\n" "1. Phoenix Connexion\n"
"2. L337 Krew\n" "2. L337 Krew\n"
"3. Arctic Avengers\n" "3. Arctic Avengers\n"
@ -2364,7 +2366,7 @@ void BotControl::createMenus () {
// counter-terrorist model select menu // counter-terrorist model select menu
m_menus.emplace ( m_menus.emplace (
Menu::CTSelect, keys (5), Menu::CTSelect, keys (5),
"\\ySelect an appearance\\w\n\n" "\\ySelect an Appearance\\w\n\n"
"1. Seal Team 6 (DEVGRU)\n" "1. Seal Team 6 (DEVGRU)\n"
"2. German GSG-9\n" "2. German GSG-9\n"
"3. UK SAS\n" "3. UK SAS\n"
@ -2376,7 +2378,7 @@ void BotControl::createMenus () {
// condition zero terrorist model select menu // condition zero terrorist model select menu
m_menus.emplace ( m_menus.emplace (
Menu::TerroristSelectCZ, keys (6), Menu::TerroristSelectCZ, keys (6),
"\\ySelect an appearance\\w\n\n" "\\ySelect an Appearance\\w\n\n"
"1. Phoenix Connexion\n" "1. Phoenix Connexion\n"
"2. L337 Krew\n" "2. L337 Krew\n"
"3. Arctic Avengers\n" "3. Arctic Avengers\n"
@ -2389,7 +2391,7 @@ void BotControl::createMenus () {
// condition zero counter-terrorist model select menu // condition zero counter-terrorist model select menu
m_menus.emplace ( m_menus.emplace (
Menu::CTSelectCZ, keys (6), Menu::CTSelectCZ, keys (6),
"\\ySelect an appearance\\w\n\n" "\\ySelect an Appearance\\w\n\n"
"1. Seal Team 6 (DEVGRU)\n" "1. Seal Team 6 (DEVGRU)\n"
"2. German GSG-9\n" "2. German GSG-9\n"
"3. UK SAS\n" "3. UK SAS\n"
@ -2403,40 +2405,40 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::Commands, keys (4), Menu::Commands, keys (4),
"\\yBot Command Menu\\w\n\n" "\\yBot Command Menu\\w\n\n"
"1. Make Double Jump\n" "1. Make double jump\n"
"2. Finish Double Jump\n\n" "2. Finish double jump\n\n"
"3. Drop the C4 Bomb\n" "3. Drop the C4 bomb\n"
"4. Drop the Weapon\n\n" "4. Drop the weapon\n\n"
"0. Exit", "0. Exit",
&BotControl::menuCommands); &BotControl::menuCommands);
// main waypoint menu // main node menu
m_menus.emplace ( m_menus.emplace (
Menu::NodeMainPage1, keys (9), Menu::NodeMainPage1, keys (9),
"\\yWaypoint Operations (Page 1)\\w\n\n" "\\yGraph Editor (Page 1)\\w\n\n"
"1. Show/Hide waypoints\n" "1. Show/Hide nodes\n"
"2. Cache waypoint\n" "2. Cache node\n"
"3. Create path\n" "3. Create path\n"
"4. Delete path\n" "4. Delete path\n"
"5. Add waypoint\n" "5. Add node\n"
"6. Delete waypoint\n" "6. Delete node\n"
"7. Set Autopath Distance\n" "7. Set autopath distance\n"
"8. Set Radius\n\n" "8. Set radius\n\n"
"9. Next...\n\n" "9. Next...\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphPage1); &BotControl::menuGraphPage1);
// main waypoint menu (page 2) // main node menu (page 2)
m_menus.emplace ( m_menus.emplace (
Menu::NodeMainPage2, keys (9), Menu::NodeMainPage2, keys (9),
"\\yWaypoint Operations (Page 2)\\w\n\n" "\\yGraph Editor (Page 2)\\w\n\n"
"1. Debug goal\n" "1. Debug goal\n"
"2. Autowaypoint on/off\n" "2. Auto node placement on/off\n"
"3. Set flags\n" "3. Set flags\n"
"4. Save waypoints\n" "4. Save graph\n"
"5. Save without checking\n" "5. Save without checking\n"
"6. Load waypoints\n" "6. Load graph\n"
"7. Check waypoints\n" "7. Check graph\n"
"8. Noclip cheat on/off\n\n" "8. Noclip cheat on/off\n\n"
"9. Previous...\n\n" "9. Previous...\n\n"
"0. Exit", "0. Exit",
@ -2445,31 +2447,31 @@ void BotControl::createMenus () {
// select nodes radius menu // select nodes radius menu
m_menus.emplace ( m_menus.emplace (
Menu::NodeRadius, keys (9), Menu::NodeRadius, keys (9),
"\\yWaypoint Radius\\w\n\n" "\\yNode Radius\\w\n\n"
"1. SetRadius 0\n" "1. 0 units\n"
"2. SetRadius 8\n" "2. 8 units\n"
"3. SetRadius 16\n" "3. 16 units\n"
"4. SetRadius 32\n" "4. 32 units\n"
"5. SetRadius 48\n" "5. 48 units\n"
"6. SetRadius 64\n" "6. 64 units\n"
"7. SetRadius 80\n" "7. 80 units\n"
"8. SetRadius 96\n" "8. 96 units\n"
"9. SetRadius 128\n\n" "9. 128 units\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphRadius); &BotControl::menuGraphRadius);
// nodes add menu // nodes add menu
m_menus.emplace ( m_menus.emplace (
Menu::NodeType, keys (9), Menu::NodeType, keys (9),
"\\yWaypoint Type\\w\n\n" "\\yNode Type\\w\n\n"
"1. Normal\n" "1. Normal\n"
"\\r2. Terrorist Important\n" "\\r2. Terrorist important\n"
"3. Counter-Terrorist Important\n" "3. Counter-Terrorist important\n"
"\\w4. Block with hostage / Ladder\n" "\\w4. Block with hostage / Ladder\n"
"\\y5. Rescue Zone\n" "\\y5. Rescue zone\n"
"\\w6. Camping\n" "\\w6. Camping\n"
"7. Camp End\n" "7. Camp end\n"
"\\r8. Map Goal\n" "\\r8. Map goal\n"
"\\w9. Jump\n\n" "\\w9. Jump\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphType); &BotControl::menuGraphType);
@ -2477,35 +2479,35 @@ void BotControl::createMenus () {
// debug goal menu // debug goal menu
m_menus.emplace ( m_menus.emplace (
Menu::NodeDebug, keys (3), Menu::NodeDebug, keys (3),
"\\yDebug goal\\w\n\n" "\\yDebug Goal\\w\n\n"
"1. Debug nearest node\n" "1. Debug nearest node\n"
"2. Debug facing node\n" "2. Debug facing node\n"
"3. Stop debugging\n\n" "3. Stop debugging\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphDebug); &BotControl::menuGraphDebug);
// set waypoint flag menu // set node flag menu
m_menus.emplace ( m_menus.emplace (
Menu::NodeFlag, keys (9), Menu::NodeFlag, keys (9),
"\\yToggle Waypoint Flags\\w\n\n" "\\yToggle Node Flags\\w\n\n"
"1. Block with Hostage\n" "1. Block with hostage\n"
"2. Terrorists Specific\n" "2. Terrorists specific\n"
"3. CTs Specific\n" "3. CTs specific\n"
"4. Use Elevator\n" "4. Use elevator\n"
"5. Sniper Point (\\yFor Camp Points Only!\\w)\n" "5. Sniper point (\\yfor camp points only!\\w)\n"
"6. Map Goal\n" "6. Map goal\n"
"7. Rescue Zone\n" "7. Rescue zone\n"
"8. Crouch Down\n" "8. Crouch down\n"
"9. Camp Point\n\n" "9. Camp point\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphFlag); &BotControl::menuGraphFlag);
// set camp directions menu // set camp directions menu
m_menus.emplace ( m_menus.emplace (
Menu::CampDirections, keys (2), Menu::CampDirections, keys (2),
"\\ySet Camp Point directions\\w\n\n" "\\ySet Camp Point Directions\\w\n\n"
"1. Camp Start\n" "1. Camp start\n"
"2. Camp End\n\n" "2. Camp end\n\n"
"0. Exit", "0. Exit",
&BotControl::menuCampDirections); &BotControl::menuCampDirections);
@ -2513,13 +2515,13 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::NodeAutoPath, keys (7), Menu::NodeAutoPath, keys (7),
"\\yAutoPath Distance\\w\n\n" "\\yAutoPath Distance\\w\n\n"
"1. Distance 0\n" "1. 0 units\n"
"2. Distance 100\n" "2. 100 units\n"
"3. Distance 130\n" "3. 130 units\n"
"4. Distance 160\n" "4. 160 units\n"
"5. Distance 190\n" "5. 190 units\n"
"6. Distance 220\n" "6. 220 units\n"
"7. Distance 250 (Default)\n\n" "7. 250 units (default)\n\n"
"0. Exit", "0. Exit",
&BotControl::menuAutoPathDistance); &BotControl::menuAutoPathDistance);
@ -2527,10 +2529,10 @@ void BotControl::createMenus () {
m_menus.emplace ( m_menus.emplace (
Menu::NodePath, keys (4), Menu::NodePath, keys (4),
"\\yCreate Path (Choose Direction)\\w\n\n" "\\yCreate Path (Choose Direction)\\w\n\n"
"1. Outgoing Path\n" "1. Outgoing path\n"
"2. Incoming Path\n" "2. Incoming path\n"
"3. Bidirectional (Both Ways)\n" "3. Bidirectional (both ways)\n"
"4. Jumping Path\n\n" "4. Jumping path\n\n"
"0. Exit", "0. Exit",
&BotControl::menuGraphPath); &BotControl::menuGraphPath);

View file

@ -287,13 +287,13 @@ bool Game::isDedicated () {
const char *Game::getRunningModName () { const char *Game::getRunningModName () {
// this function returns mod name without path // this function returns mod name without path
static String name; static String name {};
if (!name.empty ()) { if (!name.empty ()) {
return name.chars (); return name.chars ();
} }
char engineModName[256]; char engineModName[256] {};
engfuncs.pfnGetGameDir (engineModName); engfuncs.pfnGetGameDir (engineModName);
name = engineModName; name = engineModName;
@ -428,11 +428,11 @@ void Game::sendClientMessage (bool console, edict_t *ent, StringRef message) {
}; };
// do not excess limit // do not excess limit
constexpr size_t maxSendLength = 125; constexpr size_t kMaxSendLength = 125;
// split up the string into chunks if needed (maybe check if it's multibyte?) // split up the string into chunks if needed (maybe check if it's multibyte?)
if (buffer.length () > maxSendLength) { if (buffer.length () > kMaxSendLength) {
auto chunks = buffer.split (maxSendLength); auto chunks = buffer.split (kMaxSendLength);
// send in chunks // send in chunks
for (size_t i = 0; i < chunks.length (); ++i) { for (size_t i = 0; i < chunks.length (); ++i) {
@ -447,11 +447,11 @@ void Game::sendServerMessage (StringRef message) {
// helper to sending the client message // helper to sending the client message
// do not excess limit // do not excess limit
constexpr size_t maxSendLength = 175; constexpr size_t kMaxSendLength = 175;
// split up the string into chunks if needed (maybe check if it's multibyte?) // split up the string into chunks if needed (maybe check if it's multibyte?)
if (message.length () > maxSendLength) { if (message.length () > kMaxSendLength) {
auto chunks = message.split (maxSendLength); auto chunks = message.split (kMaxSendLength);
// send in chunks // send in chunks
for (size_t i = 0; i < chunks.length (); ++i) { for (size_t i = 0; i < chunks.length (); ++i) {
@ -463,7 +463,7 @@ void Game::sendServerMessage (StringRef message) {
} }
void Game::sendHudMessage (edict_t *ent, const hudtextparms_t &htp, StringRef message) { void Game::sendHudMessage (edict_t *ent, const hudtextparms_t &htp, StringRef message) {
constexpr size_t maxSendLength = 512; constexpr size_t kMaxSendLength = 512;
if (game.isNullEntity (ent)) { if (game.isNullEntity (ent)) {
return; return;
@ -490,7 +490,7 @@ void Game::sendHudMessage (edict_t *ent, const hudtextparms_t &htp, StringRef me
if (htp.effect == 2) { if (htp.effect == 2) {
msg.writeShort (MessageWriter::fu16 (htp.fxTime, 8.0f)); msg.writeShort (MessageWriter::fu16 (htp.fxTime, 8.0f));
} }
msg.writeString (message.substr (0, maxSendLength).chars ()); msg.writeString (message.substr (0, kMaxSendLength).chars ());
} }
void Game::prepareBotArgs (edict_t *ent, String str) { void Game::prepareBotArgs (edict_t *ent, String str) {
@ -709,7 +709,7 @@ void Game::registerCvars (bool gameVars) {
self.ptr = engfuncs.pfnCVarGetPointer (reg.name); self.ptr = engfuncs.pfnCVarGetPointer (reg.name);
if (!self.ptr) { if (!self.ptr) {
static cvar_t reg_; static cvar_t reg_ {};
// fix metamod' memlocs not found // fix metamod' memlocs not found
if (is (GameFlags::Metamod)) { if (is (GameFlags::Metamod)) {
@ -951,7 +951,11 @@ void Game::applyGameModes () {
return; return;
} }
static ConVarRef csdm_active ("csdm_active"); static StringRef csdmActiveCvarName = conf.fetchCustom ("CSDMDetectCvar");
static StringRef zmActiveCvarName = conf.fetchCustom ("ZMDetectCvar");
static StringRef zmDelayCvarName = conf.fetchCustom ("ZMDelayCvar");
static ConVarRef csdm_active (csdmActiveCvarName);
static ConVarRef csdm_version ("csdm_version"); static ConVarRef csdm_version ("csdm_version");
static ConVarRef redm_active ("redm_active"); static ConVarRef redm_active ("redm_active");
static ConVarRef mp_freeforall ("mp_freeforall"); static ConVarRef mp_freeforall ("mp_freeforall");
@ -976,12 +980,21 @@ void Game::applyGameModes () {
} }
} }
// some little support for zombie plague // does zombie mod is in use
static ConVarRef zp_delay ("zp_delay"); static ConVarRef zm_active (zmActiveCvarName);
// update our ignore timer if zp_elay exists // do a some little support for zombie plague
if (zp_delay.exists () && zp_delay.value () > 0.0f) { if (zm_active.exists ()) {
cv_ignore_enemies_after_spawn_time.set (zp_delay.value () + 3.0f); static ConVarRef zm_delay (zmDelayCvarName);
// update our ignore timer if zp_delay exists
if (zm_delay.exists () && zm_delay.value () > 0.0f) {
cv_ignore_enemies_after_spawn_time.set (zm_delay.value () + 3.5f);
}
m_gameFlags |= GameFlags::ZombieMod;
}
else {
m_gameFlags &= ~GameFlags::ZombieMod;
} }
} }
@ -1033,6 +1046,9 @@ void Game::slowFrame () {
// kick failed bots // kick failed bots
bots.checkNeedsToBeKicked (); bots.checkNeedsToBeKicked ();
// refresh bot infection (creature) status
bots.refreshCreatureStatus ();
// update next update time // update next update time
m_oneSecondFrame = nextUpdate + time (); m_oneSecondFrame = nextUpdate + time ();
} }
@ -1071,8 +1087,8 @@ bool Game::hasEntityInGame (StringRef classname) {
} }
void Game::printBotVersion () { void Game::printBotVersion () {
String gameVersionStr; String gameVersionStr {};
StringArray botRuntimeFlags; StringArray botRuntimeFlags {};
if (is (GameFlags::Legacy)) { if (is (GameFlags::Legacy)) {
gameVersionStr.assign ("Legacy"); gameVersionStr.assign ("Legacy");
@ -1308,6 +1324,7 @@ float LightMeasure::getLightLevel (const Vector &point) {
} }
return recursiveLightPoint <msurface_t, mnode_t> (m_worldModel->nodes, point, endPoint); return recursiveLightPoint <msurface_t, mnode_t> (m_worldModel->nodes, point, endPoint);
}; };
return !recursiveCheck () ? kInvalidLightLevel : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f); return !recursiveCheck () ? kInvalidLightLevel : 100 * cr::sqrtf (cr::min (75.0f, static_cast <float> (m_point.avg ())) / 75.0f);
} }

View file

@ -76,8 +76,8 @@ int BotGraph::clearConnections (int index) {
}; };
auto &path = m_paths[index]; auto &path = m_paths[index];
Connection sorted[kMaxNodeLinks]; Connection sorted[kMaxNodeLinks] {};
Connection top; Connection top {};
for (int i = 0; i < kMaxNodeLinks; ++i) { for (int i = 0; i < kMaxNodeLinks; ++i) {
auto &cur = sorted[i]; auto &cur = sorted[i];
@ -208,7 +208,6 @@ int BotGraph::clearConnections (int index) {
return false; return false;
}; };
for (int i = 2; i < kMaxNodeLinks; ++i) { for (int i = 2; i < kMaxNodeLinks; ++i) {
while (inspect_p0 (i)) {} while (inspect_p0 (i)) {}
} }
@ -561,7 +560,7 @@ IntArray BotGraph::getNearestInRadius (float radius, const Vector &origin, int m
const float radiusSq = cr::sqrf (radius); const float radiusSq = cr::sqrf (radius);
IntArray result; IntArray result {};
const auto &bucket = getNodesInBucket (origin); const auto &bucket = getNodesInBucket (origin);
if (bucket.length () < kMaxNodeLinks || radius > cr::sqrf (256.0f)) { if (bucket.length () < kMaxNodeLinks || radius > cr::sqrf (256.0f)) {
@ -1274,7 +1273,7 @@ void BotGraph::showFileInfo () {
msg (" compressed_size: %dkB", m_graphHeader.compressed / 1024); msg (" compressed_size: %dkB", m_graphHeader.compressed / 1024);
msg (" uncompressed_size: %dkB", m_graphHeader.uncompressed / 1024); msg (" uncompressed_size: %dkB", m_graphHeader.uncompressed / 1024);
msg (" options: %d", m_graphHeader.options); // display as string ? msg (" options: %d", m_graphHeader.options); // display as string ?
msg (" analyzed: %s", isAnalyzed () ? "yes" : "no"); // display as string ? msg (" analyzed: %s", isAnalyzed () ? conf.translate ("yes") : conf.translate ("no")); // display as string ?
msg (""); msg ("");
@ -1367,7 +1366,7 @@ void BotGraph::syncCollectOnline () {
// decode answer // decode answer
if (lc.open (localFile, "rt")) { if (lc.open (localFile, "rt")) {
String lines; String lines {};
if (lc.getLine (lines)) { if (lc.getLine (lines)) {
wanted = lines.split (","); wanted = lines.split (",");
@ -1429,7 +1428,7 @@ void BotGraph::calculatePathRadius (int index) {
// calculate "wayzones" for the nearest node (meaning a dynamic distance area to vary node origin) // calculate "wayzones" for the nearest node (meaning a dynamic distance area to vary node origin)
auto &path = m_paths[index]; auto &path = m_paths[index];
Vector start, direction; Vector start {}, direction {};
if ((path.flags & (NodeFlag::Ladder | NodeFlag::Goal | NodeFlag::Camp | NodeFlag::Rescue | NodeFlag::Crouch)) || m_jumpLearnNode) { if ((path.flags & (NodeFlag::Ladder | NodeFlag::Goal | NodeFlag::Camp | NodeFlag::Rescue | NodeFlag::Crouch)) || m_jumpLearnNode) {
path.radius = 0.0f; path.radius = 0.0f;
@ -1570,7 +1569,7 @@ void BotGraph::initNarrowPlaces () {
m_narrowChecked = true; m_narrowChecked = true;
return; return;
} }
TraceResult tr; TraceResult tr {};
const auto distance = 178.0f; const auto distance = 178.0f;
const auto worldspawn = game.getStartEntity (); const auto worldspawn = game.getStartEntity ();
@ -1608,7 +1607,7 @@ void BotGraph::initNarrowPlaces () {
} }
const Vector &ang = ((path.origin - m_paths[link.index].origin).normalize () * distance).angles (); const Vector &ang = ((path.origin - m_paths[link.index].origin).normalize () * distance).angles ();
Vector forward, right, upward; Vector forward {}, right {}, upward {};
ang.angleVectors (&forward, &right, &upward); ang.angleVectors (&forward, &right, &upward);
// helper lambda // helper lambda
@ -1823,7 +1822,7 @@ bool BotGraph::canDownload () {
bool BotGraph::saveGraphData () { bool BotGraph::saveGraphData () {
auto options = StorageOption::Graph | StorageOption::Exten; auto options = StorageOption::Graph | StorageOption::Exten;
String editorName; String editorName {};
if (game.isNullEntity (m_editor) && !m_graphAuthor.empty ()) { if (game.isNullEntity (m_editor) && !m_graphAuthor.empty ()) {
editorName = m_graphAuthor; editorName = m_graphAuthor;
@ -1876,7 +1875,7 @@ bool BotGraph::saveGraphData () {
void BotGraph::saveOldFormat () { void BotGraph::saveOldFormat () {
PODGraphHeader header {}; PODGraphHeader header {};
String editorName; String editorName {};
if (game.isNullEntity (m_editor) && !m_graphAuthor.empty ()) { if (game.isNullEntity (m_editor) && !m_graphAuthor.empty ()) {
editorName = m_graphAuthor; editorName = m_graphAuthor;
@ -1896,7 +1895,7 @@ void BotGraph::saveOldFormat () {
header.fileVersion = StorageVersion::Podbot; header.fileVersion = StorageVersion::Podbot;
header.pointNumber = length (); header.pointNumber = length ();
File fp; File fp {};
// file was opened // file was opened
if (fp.open (bstor.buildPath (BotFile::PodbotPWF), "wb")) { if (fp.open (bstor.buildPath (BotFile::PodbotPWF), "wb")) {
@ -2327,7 +2326,7 @@ void BotGraph::frame () {
// very helpful stuff.. // very helpful stuff..
auto getNodeData = [this] (StringRef type, int node) -> String { auto getNodeData = [this] (StringRef type, int node) -> String {
String message, flags; String message {}, flags {};
const auto &p = m_paths[node]; const auto &p = m_paths[node];
bool jumpPoint = false; bool jumpPoint = false;
@ -2384,7 +2383,7 @@ void BotGraph::frame () {
const int dangerIndexCT = practice.getIndex (Team::CT, nearestIndex, nearestIndex); const int dangerIndexCT = practice.getIndex (Team::CT, nearestIndex, nearestIndex);
const int dangerIndexT = practice.getIndex (Team::Terrorist, nearestIndex, nearestIndex); const int dangerIndexT = practice.getIndex (Team::Terrorist, nearestIndex, nearestIndex);
String practiceText; String practiceText {};
practiceText.assignf (" Node practice data (index / damage):\n" practiceText.assignf (" Node practice data (index / damage):\n"
" CT: %d / %d\n" " CT: %d / %d\n"
" T: %d / %d\n\n", dangerIndexCT, dangerIndexCT != kInvalidNodeIndex ? practice.getDamage (Team::CT, nearestIndex, dangerIndexCT) : 0, dangerIndexT, dangerIndexT != kInvalidNodeIndex ? practice.getDamage (Team::Terrorist, nearestIndex, dangerIndexT) : 0); " T: %d / %d\n\n", dangerIndexCT, dangerIndexCT != kInvalidNodeIndex ? practice.getDamage (Team::CT, nearestIndex, dangerIndexCT) : 0, dangerIndexT, dangerIndexT != kInvalidNodeIndex ? practice.getDamage (Team::Terrorist, nearestIndex, dangerIndexT) : 0);
@ -2514,10 +2513,10 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
// ensure valid capacity // ensure valid capacity
assert (length > 8 && length < static_cast <size_t> (kMaxNodes)); assert (length > 8 && length < static_cast <size_t> (kMaxNodes));
PathWalk walk; PathWalk walk {};
walk.init (length); walk.init (length);
Array <bool> visited; Array <bool> visited {};
visited.resize (length); visited.resize (length);
// first check incoming connectivity, initialize the "visited" table // first check incoming connectivity, initialize the "visited" table
@ -2554,7 +2553,7 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
} }
// then check outgoing connectivity // then check outgoing connectivity
Array <IntArray> outgoingPaths; // store incoming paths for speedup Array <IntArray> outgoingPaths {}; // store incoming paths for speedup
outgoingPaths.resize (length); outgoingPaths.resize (length);
for (const auto &path : m_paths) { for (const auto &path : m_paths) {
@ -2630,7 +2629,7 @@ void BotGraph::addBasic () {
ladderLeft.z = ladderRight.z; ladderLeft.z = ladderRight.z;
TraceResult tr {}; TraceResult tr {};
Vector up, down, front, back; Vector up {}, down {}, front {}, back {};
Vector diff = ((ladderLeft - ladderRight) ^ nullptr) * 15.0f; Vector diff = ((ladderLeft - ladderRight) ^ nullptr) * 15.0f;
front = back = game.getEntityOrigin (ent); front = back = game.getEntityOrigin (ent);
@ -2675,7 +2674,7 @@ void BotGraph::addBasic () {
game.searchEntities ("classname", classname, [&] (edict_t *ent) { game.searchEntities ("classname", classname, [&] (edict_t *ent) {
Vector pos = game.getEntityOrigin (ent); Vector pos = game.getEntityOrigin (ent);
TraceResult tr; TraceResult tr {};
game.testLine (pos, pos - Vector (0.0f, 0.0f, 999.0f), TraceIgnore::Monsters, nullptr, &tr); game.testLine (pos, pos - Vector (0.0f, 0.0f, 999.0f), TraceIgnore::Monsters, nullptr, &tr);
tr.vecEndPos.z += 36.0f; tr.vecEndPos.z += 36.0f;
@ -2815,10 +2814,10 @@ void BotGraph::eraseFromBucket (const Vector &pos, int index) {
} }
int BotGraph::locateBucket (const Vector &pos) { int BotGraph::locateBucket (const Vector &pos) {
constexpr auto width = 8192; constexpr auto kWidth = 8192;
auto hash = [&] (float axis, int32_t shift) { auto hash = [&] (float axis, int32_t shift) {
return ((static_cast <int> (axis) + width) & 0x007f80) >> shift; return ((static_cast <int> (axis) + kWidth) & 0x007f80) >> shift;
}; };
return hash (pos.x, 15) + hash (pos.y, 7); return hash (pos.x, 15) + hash (pos.y, 7);
} }

View file

@ -13,12 +13,12 @@ int32_t ServerQueryHook::sendTo (int socket, const void *message, size_t length,
}; };
auto packet = reinterpret_cast <const uint8_t *> (message); auto packet = reinterpret_cast <const uint8_t *> (message);
constexpr int32_t packetLength = 5; constexpr int32_t kPacketLength = 5;
// player replies response // player replies response
if (length > packetLength && memcmp (packet, "\xff\xff\xff\xff", packetLength - 1) == 0) { if (length > kPacketLength && memcmp (packet, "\xff\xff\xff\xff", kPacketLength - 1) == 0) {
if (packet[4] == 'D') { if (packet[4] == 'D') {
QueryBuffer buffer { packet, length, packetLength }; QueryBuffer buffer { packet, length, kPacketLength };
auto count = buffer.read <uint8_t> (); auto count = buffer.read <uint8_t> ();
for (uint8_t i = 0; i < count; ++i) { for (uint8_t i = 0; i < count; ++i) {
@ -32,7 +32,7 @@ int32_t ServerQueryHook::sendTo (int socket, const void *message, size_t length,
return send (buffer.data ()); return send (buffer.data ());
} }
else if (packet[4] == 'I') { else if (packet[4] == 'I') {
QueryBuffer buffer { packet, length, packetLength }; QueryBuffer buffer { packet, length, kPacketLength };
buffer.skip <uint8_t> (); // protocol buffer.skip <uint8_t> (); // protocol
// skip server name, folder, map game // skip server name, folder, map game
@ -48,7 +48,7 @@ int32_t ServerQueryHook::sendTo (int socket, const void *message, size_t length,
return send (buffer.data ()); return send (buffer.data ());
} }
else if (packet[4] == 'm') { else if (packet[4] == 'm') {
QueryBuffer buffer { packet, length, packetLength }; QueryBuffer buffer { packet, length, kPacketLength };
buffer.shiftToEnd (); // shift to the end of buffer buffer.shiftToEnd (); // shift to the end of buffer
buffer.write <uint8_t> (0); // zero out bot count buffer.write <uint8_t> (0); // zero out bot count

View file

@ -174,7 +174,7 @@ BotCreateResult BotManager::create (StringRef name, int difficulty, int personal
// then sends result to bot constructor // then sends result to bot constructor
edict_t *bot = nullptr; edict_t *bot = nullptr;
String resultName; String resultName {};
// do not allow create bots when there is no graph // do not allow create bots when there is no graph
if (!graph.length ()) { if (!graph.length ()) {
@ -254,7 +254,7 @@ BotCreateResult BotManager::create (StringRef name, int difficulty, int personal
} }
if (hasNamePrefix) { if (hasNamePrefix) {
String prefixed; // temp buffer for storing modified name String prefixed {}; // temp buffer for storing modified name
prefixed.assignf ("%s %s", cv_name_prefix.as <StringRef> (), resultName); prefixed.assignf ("%s %s", cv_name_prefix.as <StringRef> (), resultName);
// buffer has been modified, copy to real name // buffer has been modified, copy to real name
@ -624,13 +624,13 @@ void BotManager::serverFill (int selection, int personality, int difficulty, int
else { else {
selection = 5; selection = 5;
} }
constexpr char teams[6][12] = { "", {"Terrorists"}, {"CTs"}, "", "", {"Random"}, }; constexpr char kTeams[6][12] = { "", {"Terrorists"}, {"CTs"}, "", "", {"Random"}, };
const auto toAdd = numToAdd == -1 ? maxClients - (getHumansCount () + getBotCount ()) : numToAdd; const auto toAdd = numToAdd == -1 ? maxClients - (getHumansCount () + getBotCount ()) : numToAdd;
for (int i = 0; i <= toAdd; ++i) { for (int i = 0; i <= toAdd; ++i) {
addbot ("", difficulty, personality, selection, -1, true); addbot ("", difficulty, personality, selection, -1, true);
} }
ctrl.msg ("Fill server with %s bots...", &teams[selection][0]); ctrl.msg ("Fill server with %s bots...", &kTeams[selection][0]);
} }
void BotManager::kickEveryone (bool instant, bool zeroQuota) { void BotManager::kickEveryone (bool instant, bool zeroQuota) {
@ -814,7 +814,7 @@ void BotManager::setLastWinner (int winner) {
void BotManager::checkBotModel (edict_t *ent, char *infobuffer) { void BotManager::checkBotModel (edict_t *ent, char *infobuffer) {
for (const auto &bot : bots) { for (const auto &bot : bots) {
if (bot->ent () == ent) { if (bot->ent () == ent) {
bot->refreshModelName (infobuffer); bot->refreshCreatureStatus (infobuffer);
break; break;
} }
} }
@ -829,12 +829,24 @@ void BotManager::checkNeedsToBeKicked () {
} }
} }
void BotManager::refreshCreatureStatus () {
if (!game.is (GameFlags::ZombieMod)) {
return;
}
for (const auto &bot : bots) {
if (bot->m_isAlive) {
bot->refreshCreatureStatus (nullptr);
}
}
}
void BotManager::setWeaponMode (int selection) { void BotManager::setWeaponMode (int selection) {
// this function sets bots weapon mode // this function sets bots weapon mode
selection--; selection--;
constexpr int std[7][kNumWeapons] = { constexpr int kStd[7][kNumWeapons] = {
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Knife only {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Knife only
{-1, -1, -1, 2, 2, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Pistols only {-1, -1, -1, 2, 2, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Pistols only
{-1, -1, -1, -1, -1, -1, -1, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Shotgun only {-1, -1, -1, -1, -1, -1, -1, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Shotgun only
@ -844,7 +856,7 @@ void BotManager::setWeaponMode (int selection) {
{-1, -1, -1, 2, 2, 0, 1, 2, 2, 2, 1, 2, 0, 2, 0, 0, 1, 0, 1, 1, 2, 2, 0, 1, 2, 1} // Standard {-1, -1, -1, 2, 2, 0, 1, 2, 2, 2, 1, 2, 0, 2, 0, 0, 1, 0, 1, 1, 2, 2, 0, 1, 2, 1} // Standard
}; };
constexpr int as[7][kNumWeapons] = { constexpr int kAs[7][kNumWeapons] = {
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Knife only {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Knife only
{-1, -1, -1, 2, 2, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Pistols only {-1, -1, -1, 2, 2, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Pistols only
{-1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Shotgun only {-1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // Shotgun only
@ -853,19 +865,19 @@ void BotManager::setWeaponMode (int selection) {
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 1, -1, -1}, // Snipers only {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 1, -1, -1}, // Snipers only
{-1, -1, -1, 2, 2, 0, 1, 1, 1, 1, 1, 1, 0, 2, 0, -1, 1, 0, 1, 1, 0, 0, -1, 1, 1, 1} // Standard {-1, -1, -1, 2, 2, 0, 1, 1, 1, 1, 1, 1, 0, 2, 0, -1, 1, 0, 1, 1, 0, 0, -1, 1, 1, 1} // Standard
}; };
constexpr char modes[7][12] = { {"Knife"}, {"Pistol"}, {"Shotgun"}, {"Machine Gun"}, {"Rifle"}, {"Sniper"}, {"Standard"} }; constexpr char kModes[7][12] = { {"Knife"}, {"Pistol"}, {"Shotgun"}, {"Machine Gun"}, {"Rifle"}, {"Sniper"}, {"Standard"} };
// get the raw weapons array // get the raw weapons array
auto tab = conf.getRawWeapons (); auto tab = conf.getRawWeapons ();
// set the correct weapon mode // set the correct weapon mode
for (int i = 0; i < kNumWeapons; ++i) { for (int i = 0; i < kNumWeapons; ++i) {
tab[i].teamStandard = std[selection][i]; tab[i].teamStandard = kStd[selection][i];
tab[i].teamAS = as[selection][i]; tab[i].teamAS = kAs[selection][i];
} }
cv_jasonmode.set (selection == 0 ? 1 : 0); cv_jasonmode.set (selection == 0 ? 1 : 0);
ctrl.msg ("%s weapon mode selected.", &modes[selection][0]); ctrl.msg ("%s weapon mode selected.", &kModes[selection][0]);
} }
void BotManager::listBots () { void BotManager::listBots () {
@ -1370,7 +1382,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
} }
} }
// mark bot as "spawned", and reset it to new-round state when it dead (for csdm only) // mark bot as "spawned", and reset it to new-round state when it dead (for csdm/zombie only)
if (victimBot != nullptr) { if (victimBot != nullptr) {
victimBot->spawned (); victimBot->spawned ();
} }
@ -1519,7 +1531,7 @@ void Bot::newRound () {
for (auto &timer : m_chatterTimes) { for (auto &timer : m_chatterTimes) {
timer = kMaxChatterRepeatInterval; timer = kMaxChatterRepeatInterval;
} }
refreshModelName (nullptr); refreshCreatureStatus (nullptr);
m_isReloading = false; m_isReloading = false;
m_reloadState = Reload::None; m_reloadState = Reload::None;
@ -2195,7 +2207,7 @@ bool BotManager::isLineBlockedBySmoke (const Vector &from, const Vector &to, flo
float alongDist = toGrenade | sightDir; float alongDist = toGrenade | sightDir;
// compute closest point to grenade along line of sight ray // compute closest point to grenade along line of sight ray
Vector close; Vector close {};
// constrain closest point to line segment // constrain closest point to line segment
if (alongDist < 0.0f) { if (alongDist < 0.0f) {

View file

@ -255,19 +255,19 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
int goalChoices[4] = { kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex }; int goalChoices[4] = { kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex, kInvalidNodeIndex };
if (tactic == GoalTactic::Defensive && !(*defensive).empty ()) { // careful goal if (tactic == GoalTactic::Defensive && !(*defensive).empty ()) { // careful goal
postprocessGoals (*defensive, goalChoices); postProcessGoals (*defensive, goalChoices);
} }
else if (tactic == GoalTactic::Camp && !graph.m_campPoints.empty ()) { // camp node goal else if (tactic == GoalTactic::Camp && !graph.m_campPoints.empty ()) { // camp node goal
// pickup sniper points if possible for sniping bots // pickup sniper points if possible for sniping bots
if (!graph.m_sniperPoints.empty () && usesSniper ()) { if (!graph.m_sniperPoints.empty () && usesSniper ()) {
postprocessGoals (graph.m_sniperPoints, goalChoices); postProcessGoals (graph.m_sniperPoints, goalChoices);
} }
else { else {
postprocessGoals (graph.m_campPoints, goalChoices); postProcessGoals (graph.m_campPoints, goalChoices);
} }
} }
else if (tactic == GoalTactic::Offensive && !(*offensive).empty ()) { // offensive goal else if (tactic == GoalTactic::Offensive && !(*offensive).empty ()) { // offensive goal
postprocessGoals (*offensive, goalChoices); postProcessGoals (*offensive, goalChoices);
} }
else if (tactic == GoalTactic::Goal && !graph.m_goalPoints.empty ()) // map goal node else if (tactic == GoalTactic::Goal && !graph.m_goalPoints.empty ()) // map goal node
{ {
@ -299,7 +299,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
} }
} }
else { else {
postprocessGoals (graph.m_goalPoints, goalChoices); postProcessGoals (graph.m_goalPoints, goalChoices);
} }
} }
else if (tactic == GoalTactic::RescueHostage && !graph.m_rescuePoints.empty ()) { else if (tactic == GoalTactic::RescueHostage && !graph.m_rescuePoints.empty ()) {
@ -359,7 +359,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offensive) {
return m_chosenGoalIndex = goalChoices[0]; // return and store goal return m_chosenGoalIndex = goalChoices[0]; // return and store goal
} }
void Bot::postprocessGoals (const IntArray &goals, int result[]) { void Bot::postProcessGoals (const IntArray &goals, int result[]) {
// this function filters the goals, so new goal is not bot's old goal, and array of goals doesn't contains duplicate goals // this function filters the goals, so new goal is not bot's old goal, and array of goals doesn't contains duplicate goals
int recurseCount = 0; int recurseCount = 0;
@ -369,6 +369,10 @@ void Bot::postprocessGoals (const IntArray &goals, int result[]) {
return true; return true;
} }
if (!isOccupiedNode (index)) {
return true;
}
// check if historical goal // check if historical goal
for (const auto &hg : m_goalHist) { for (const auto &hg : m_goalHist) {
if (hg == index) { if (hg == index) {
@ -381,8 +385,9 @@ void Bot::postprocessGoals (const IntArray &goals, int result[]) {
return true; return true;
} }
} }
return isOccupiedNode (index); return false;
}; };
static IntArray resulting {}; static IntArray resulting {};
resulting.clear (); resulting.clear ();
@ -400,7 +405,9 @@ void Bot::postprocessGoals (const IntArray &goals, int result[]) {
refill (graph.m_goalPoints); refill (graph.m_goalPoints);
} }
else { else {
resulting.insert (0, goals); if (!goals.empty ()) {
resulting.insert (0, goals);
}
} }
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
@ -514,7 +521,7 @@ void Bot::doPlayerAvoidance (const Vector &normal) {
const float interval = m_frameInterval * (pev->velocity.lengthSq2d () > 0.0f ? 7.5f : 2.0f); const float interval = m_frameInterval * (pev->velocity.lengthSq2d () > 0.0f ? 7.5f : 2.0f);
// use our movement angles, try to predict where we should be next frame // use our movement angles, try to predict where we should be next frame
Vector right, forward; Vector right {}, forward {};
m_moveAngles.angleVectors (&forward, &right, nullptr); m_moveAngles.angleVectors (&forward, &right, nullptr);
Vector predict = pev->origin + forward * pev->maxspeed * interval; Vector predict = pev->origin + forward * pev->maxspeed * interval;
@ -865,8 +872,7 @@ void Bot::checkFall () {
else if (pev->origin.z + 128.0f < m_checkFallPoint[1].z && pev->origin.z + 128.0f < m_checkFallPoint[0].z) { else if (pev->origin.z + 128.0f < m_checkFallPoint[1].z && pev->origin.z + 128.0f < m_checkFallPoint[0].z) {
fixFall = true; fixFall = true;
} }
else if (m_currentNodeIndex != kInvalidNodeIndex) {
if (m_currentNodeIndex != kInvalidNodeIndex) {
if (pev->origin.distanceSq (m_checkFallPoint[1]) <= cr::sqrf (32.0f) && pev->origin.z + 16.0f < m_checkFallPoint[1].z) { if (pev->origin.distanceSq (m_checkFallPoint[1]) <= cr::sqrf (32.0f) && pev->origin.z + 16.0f < m_checkFallPoint[1].z) {
fixFall = true; fixFall = true;
} }
@ -1938,7 +1944,7 @@ int Bot::findNearestNode () {
const float distanceSq = path.origin.distanceSq (pev->origin); const float distanceSq = path.origin.distanceSq (pev->origin);
if (distanceSq < nearestDistanceSq) { if (distanceSq < nearestDistanceSq) {
TraceResult tr; TraceResult tr {};
game.testLine (getEyesPos (), path.origin, TraceIgnore::Monsters, ent (), &tr); game.testLine (getEyesPos (), path.origin, TraceIgnore::Monsters, ent (), &tr);
if (tr.flFraction >= 1.0f && !tr.fStartSolid) { if (tr.flFraction >= 1.0f && !tr.fStartSolid) {
@ -2125,7 +2131,7 @@ int Bot::findDefendNode (const Vector &origin) {
} while (sorting); } while (sorting);
if (nodeIndex[0] == kInvalidNodeIndex) { if (nodeIndex[0] == kInvalidNodeIndex) {
IntArray found; IntArray found {};
for (const auto &path : graph) { for (const auto &path : graph) {
if (origin.distanceSq (path.origin) < cr::sqrf (kMaxDistance) if (origin.distanceSq (path.origin) < cr::sqrf (kMaxDistance)
@ -2168,7 +2174,7 @@ int Bot::findCoverNode (float maxDistance) {
const int srcIndex = m_currentNodeIndex; const int srcIndex = m_currentNodeIndex;
const int enemyIndex = graph.getNearest (m_lastEnemyOrigin); const int enemyIndex = graph.getNearest (m_lastEnemyOrigin);
IntArray enemies; IntArray enemies {};
int nodeIndex[kMaxNodeLinks] {}; int nodeIndex[kMaxNodeLinks] {};
float nearestDistance[kMaxNodeLinks] {}; float nearestDistance[kMaxNodeLinks] {};
@ -2467,8 +2473,8 @@ bool Bot::advanceMovement () {
bool willJump = false; bool willJump = false;
float jumpDistanceSq = 0.0f; float jumpDistanceSq = 0.0f;
Vector src; Vector src {};
Vector dst; Vector dst {};
// try to find out about future connection flags // try to find out about future connection flags
if (m_pathWalk.hasNext ()) { if (m_pathWalk.hasNext ()) {
@ -2685,7 +2691,7 @@ bool Bot::isBlockedForward (const Vector &normal, TraceResult *tr) {
bool Bot::canStrafeLeft (TraceResult *tr) { bool Bot::canStrafeLeft (TraceResult *tr) {
// this function checks if bot can move sideways // this function checks if bot can move sideways
Vector right, forward; Vector right {}, forward {};
pev->v_angle.angleVectors (&forward, &right, nullptr); pev->v_angle.angleVectors (&forward, &right, nullptr);
Vector src = pev->origin; Vector src = pev->origin;
@ -2698,7 +2704,6 @@ bool Bot::canStrafeLeft (TraceResult *tr) {
if (tr->flFraction < 1.0f) { if (tr->flFraction < 1.0f) {
return false; // bot's body will hit something return false; // bot's body will hit something
} }
src = dest; src = dest;
dest = dest + forward * 40.0f; dest = dest + forward * 40.0f;
@ -2715,7 +2720,7 @@ bool Bot::canStrafeLeft (TraceResult *tr) {
bool Bot::canStrafeRight (TraceResult *tr) { bool Bot::canStrafeRight (TraceResult *tr) {
// this function checks if bot can move sideways // this function checks if bot can move sideways
Vector right, forward; Vector right {}, forward {};
pev->v_angle.angleVectors (&forward, &right, nullptr); pev->v_angle.angleVectors (&forward, &right, nullptr);
Vector src = pev->origin; Vector src = pev->origin;
@ -2894,7 +2899,7 @@ bool Bot::canDuckUnder (const Vector &normal) {
// this function check if bot can duck under obstacle // this function check if bot can duck under obstacle
TraceResult tr {}; TraceResult tr {};
Vector baseHeight; Vector baseHeight {};
// use center of the body first... // use center of the body first...
if (isDucking ()) { if (isDucking ()) {
@ -2946,7 +2951,7 @@ bool Bot::isBlockedLeft () {
if (m_moveSpeed < 0.0f) { if (m_moveSpeed < 0.0f) {
direction = -48.0f; direction = -48.0f;
} }
Vector right, forward; Vector right {}, forward {};
pev->angles.angleVectors (&forward, &right, nullptr); pev->angles.angleVectors (&forward, &right, nullptr);
// do a trace to the left... // do a trace to the left...
@ -2966,7 +2971,7 @@ bool Bot::isBlockedRight () {
if (m_moveSpeed < 0.0f) { if (m_moveSpeed < 0.0f) {
direction = -48.0f; direction = -48.0f;
} }
Vector right, forward; Vector right {}, forward {};
pev->angles.angleVectors (&forward, &right, nullptr); pev->angles.angleVectors (&forward, &right, nullptr);
// do a trace to the right... // do a trace to the right...

View file

@ -473,7 +473,7 @@ bool DijkstraAlgo::find (int srcIndex, int destIndex, NodeAdderFn onAddedNode, i
} }
} }
} }
static SmallArray <int> pathInReverse; static SmallArray <int> pathInReverse {};
pathInReverse.clear (); pathInReverse.clear ();
for (int i = destIndex; i != kInvalidNodeIndex; i = m_parent[i]) { for (int i = destIndex; i != kInvalidNodeIndex; i = m_parent[i]) {

View file

@ -153,7 +153,7 @@ void BotPractice::save () {
if (!graph.length () || graph.hasChanged ()) { if (!graph.length () || graph.hasChanged ()) {
return; // no action return; // no action
} }
SmallArray <DangerSaveRestore> data; SmallArray <DangerSaveRestore> data {};
data.reserve (m_data.length ()); data.reserve (m_data.length ());
// copy hash-map data to our vector // copy hash-map data to our vector
@ -167,7 +167,7 @@ void BotPractice::load () {
if (!graph.length ()) { if (!graph.length ()) {
return; // no action return; // no action
} }
SmallArray <DangerSaveRestore> data; SmallArray <DangerSaveRestore> data {};
m_data.clear (); m_data.clear ();
const bool dataLoaded = bstor.load <DangerSaveRestore> (data); const bool dataLoaded = bstor.load <DangerSaveRestore> (data);

View file

@ -331,7 +331,7 @@ String BotStorage::buildPath (int32_t file, bool isMemoryLoad, bool withoutMapNa
{ BotFile::EbotEWP, FilePath (folders.ebot, "ewp")}, { BotFile::EbotEWP, FilePath (folders.ebot, "ewp")},
}; };
static StringArray path; static StringArray path {};
path.clear (); path.clear ();
// if not memory file we're don't need game dir // if not memory file we're don't need game dir
@ -389,7 +389,7 @@ int32_t BotStorage::storageToBotFile (int32_t options) {
void BotStorage::unlinkFromDisk () { void BotStorage::unlinkFromDisk () {
// this function removes graph file from the hard disk // this function removes graph file from the hard disk
StringArray unlinkable; StringArray unlinkable {};
bots.kickEveryone (true); bots.kickEveryone (true);
// if we're delete graph, delete all corresponding to it files // if we're delete graph, delete all corresponding to it files
@ -413,7 +413,7 @@ void BotStorage::unlinkFromDisk () {
StringRef BotStorage::getRunningPath () { StringRef BotStorage::getRunningPath () {
// this function get's relative path against bot library (bot library should reside in bin dir) // this function get's relative path against bot library (bot library should reside in bin dir)
static String path; static String path {};
// we're do not do relative (against bot's library) paths on android // we're do not do relative (against bot's library) paths on android
if (plat.android) { if (plat.android) {
@ -441,7 +441,7 @@ StringRef BotStorage::getRunningPath () {
} }
StringRef BotStorage::getRunningPathVFS () { StringRef BotStorage::getRunningPathVFS () {
static String path; static String path {};
// we're do not do relative (against bot's library) paths on android // we're do not do relative (against bot's library) paths on android
if (plat.android) { if (plat.android) {

View file

@ -149,7 +149,7 @@ void BotSupport::decalTrace (entvars_t *pev, TraceResult *trace, int logotypeInd
.writeByte (decalIndex); .writeByte (decalIndex);
} }
else { else {
MessageWriter msg; MessageWriter msg {};
msg.start (MSG_BROADCAST, SVC_TEMPENTITY) msg.start (MSG_BROADCAST, SVC_TEMPENTITY)
.writeByte (message) .writeByte (message)
@ -282,7 +282,7 @@ void BotSupport::checkWelcome () {
auto graphModified = graph.getModifiedBy (); auto graphModified = graph.getModifiedBy ();
// legacy welcome message, to respect the original code // legacy welcome message, to respect the original code
constexpr StringRef legacyWelcomeMessage = "Welcome to POD-Bot V2.5 by Count Floyd\n" constexpr StringRef kLegacyWelcomeMessage = "Welcome to POD-Bot V2.5 by Count Floyd\n"
"Visit http://www.nuclearbox.com/podbot/ or\n" "Visit http://www.nuclearbox.com/podbot/ or\n"
" http://www.botepidemic.com/podbot for Updates\n"; " http://www.botepidemic.com/podbot for Updates\n";
@ -328,7 +328,7 @@ void BotSupport::checkWelcome () {
// send the hud message // send the hud message
game.sendHudMessage (receiveEnt, textParams, game.sendHudMessage (receiveEnt, textParams,
sendLegacyWelcome ? legacyWelcomeMessage.chars () : modernWelcomeMessage.chars ()); sendLegacyWelcome ? kLegacyWelcomeMessage.chars () : modernWelcomeMessage.chars ());
m_welcomeReceiveTime = 0.0f; m_welcomeReceiveTime = 0.0f;
m_needToSendWelcome = false; m_needToSendWelcome = false;
@ -440,7 +440,7 @@ void BotSupport::syncCalculatePings () {
if (!(client.flags & ClientFlags::Used) || isFakeClient (client.ent)) { if (!(client.flags & ClientFlags::Used) || isFakeClient (client.ent)) {
continue; continue;
} }
int ping, loss; int ping {}, loss {};
engfuncs.pfnGetPlayerStats (client.ent, &ping, &loss); engfuncs.pfnGetPlayerStats (client.ent, &ping, &loss);
// @note: for those who asking on a email, we CAN call pfnGetPlayerStats hl-engine function in a separate thread // @note: for those who asking on a email, we CAN call pfnGetPlayerStats hl-engine function in a separate thread
@ -502,7 +502,7 @@ void BotSupport::syncCalculatePings () {
} }
void BotSupport::emitPings (edict_t *to) { void BotSupport::emitPings (edict_t *to) {
static MessageWriter msg; static MessageWriter msg {};
auto isThirdpartyBot = [] (edict_t *ent) { auto isThirdpartyBot = [] (edict_t *ent) {
return !bots[ent] && (ent->v.flags & FL_FAKECLIENT); return !bots[ent] && (ent->v.flags & FL_FAKECLIENT);
@ -530,7 +530,7 @@ void BotSupport::emitPings (edict_t *to) {
} }
void BotSupport::resetPings (edict_t *to) { void BotSupport::resetPings (edict_t *to) {
static MessageWriter msg; static MessageWriter msg {};
// no reset if game isn't support them // no reset if game isn't support them
if (!game.is (GameFlags::HasFakePings)) { if (!game.is (GameFlags::HasFakePings)) {
@ -636,7 +636,7 @@ float BotSupport::getWaveLength (StringRef filename) {
uint32_t dataChunkLength; uint32_t dataChunkLength;
} header {}; } header {};
static WaveEndianessHelper weh; static WaveEndianessHelper weh {};
if (fp.read (&header, sizeof (WavHeader)) == 0) { if (fp.read (&header, sizeof (WavHeader)) == 0) {
logger.error ("Wave File %s - has wrong or unsupported format", filePath); logger.error ("Wave File %s - has wrong or unsupported format", filePath);

View file

@ -972,7 +972,7 @@ void Bot::defuseBomb_ () {
// if defusing is not already started, maybe crouch before // if defusing is not already started, maybe crouch before
if (!m_hasProgressBar && m_duckDefuseCheckTime < game.time ()) { if (!m_hasProgressBar && m_duckDefuseCheckTime < game.time ()) {
Vector botDuckOrigin, botStandOrigin; Vector botDuckOrigin {}, botStandOrigin {};
if (pev->button & IN_DUCK) { if (pev->button & IN_DUCK) {
botDuckOrigin = pev->origin; botDuckOrigin = pev->origin;

View file

@ -285,8 +285,8 @@ void Bot::updateLookAnglesNewbie (const Vector &direction, float delta) {
const float noTargetRatio = 0.3f; const float noTargetRatio = 0.3f;
const float offsetDelay = 1.2f; const float offsetDelay = 1.2f;
Vector stiffness; Vector stiffness {};
Vector randomize; Vector randomize {};
m_idealAngles = direction.get2d (); m_idealAngles = direction.get2d ();
m_idealAngles.clampAngles (); m_idealAngles.clampAngles ();
@ -368,7 +368,7 @@ bool Frustum::isObjectInsidePlane (const Plane &plane, const Vector &center, flo
} }
void Frustum::calculate (Planes &planes, const Vector &viewAngle, const Vector &viewOffset) { void Frustum::calculate (Planes &planes, const Vector &viewAngle, const Vector &viewOffset) {
Vector forward, right, up; Vector forward {}, right {}, up {};
viewAngle.angleVectors (&forward, &right, &up); viewAngle.angleVectors (&forward, &right, &up);
auto fc = viewOffset + forward * kMaxViewDistance; auto fc = viewOffset + forward * kMaxViewDistance;
@ -541,7 +541,6 @@ void Bot::setAimDirection () {
const auto &destOrigin = m_destOrigin + pev->view_ofs; const auto &destOrigin = m_destOrigin + pev->view_ofs;
m_lookAt = destOrigin; m_lookAt = destOrigin;
if (m_moveToGoal && m_seeEnemyTime + 4.0f < game.time () if (m_moveToGoal && m_seeEnemyTime + 4.0f < game.time ()
&& !m_isStuck && !(pev->button & IN_DUCK) && !m_isStuck && !(pev->button & IN_DUCK)
&& m_currentNodeIndex != kInvalidNodeIndex && m_currentNodeIndex != kInvalidNodeIndex

View file

@ -19,7 +19,7 @@ void GraphVistable::rebuild () {
return; return;
} }
TraceResult tr {}; TraceResult tr {};
uint8_t res, shift; uint8_t res {}, shift {};
if (!graph.exists (m_sliceIndex)) { if (!graph.exists (m_sliceIndex)) {
m_sliceIndex = 0; m_sliceIndex = 0;