Records (Replays) in Team Fortress 2 is an opportunity, on the server side, to create a record of the playerβs last life, and on the client side, to view, edit, save, and publish it. It is an extension of SourceTV.
Entries must be explicitly enabled on the server command line, enabled and configured in the configuration file that is executed before loading the map. In addition, the web server must be pre-configured to deliver records to players.
For clarity, we will add a separate subdomain replay.example.org to the DNS, create the directory /var/www/replay.example.org, and for convenience we will write the logs into separate files and let the user read the game.
From root, we create directories, set the owner (game: game) and rights β to the game user for writing, the rest (the web server) for reading. You can also make symbolic links for convenience. This web server will be common to both game servers, but each of them will use separate directories for posting entries.
# mkdir -p /var/www/replay.example.org/{htdocs/server1,htdocs/server2,log} # chown -R game:game /var/www/replay.example.org # chmod -R 755 /var/www/replay.example.org # ln -s /var/www/replay.example.org/log /home/game/log/www-replay
In our default configuration, all web server logs are owned by nginx: adm and 640 permissions, that is, they are not available to regular users. Adjust this for this case:
# touch /var/www/replay.example.org/log/{access,error}.log # chmod 644 /var/www/replay.example.org/log/*.log
Thus, the user of the game, our logs will be available for reading. But only until their first rotation. We fix this too. In the /etc/logrotate.d directory we copy the nginx file to srcds-nginx, in it we set the path to the logs and in the create 640 nginx adm
fix the access rights mask from 640 to 644:
#/etc/logrotate.d/srcds-nginx /var/www/stat.example.org/log/*.log /var/www/fastdl.example.org/log/*.log /var/www/replay.example.org/log/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 `cat /var/run/nginx.pid` fi endscript }
Here we are in the paths for rotation at the same time indicated directories with logs from the statistics server HLstatsX and from the Fast Download server.
As root, create a web server configuration file, /etc/nginx/conf.d/replay.example.org.conf:
# /etc/nginx/conf.d/replay.example.org.conf server { server_name replay.example.org; listen 80; root /var/www/replay.example.org/htdocs; disable_symlinks on; autoindex off; access_log /var/www/replay.example.org/log/access.log main; error_log /var/www/replay.example.org/log/error.log warn; }
This, of course, is a somewhat simplified version. Since in our case the web server is located on the same computer as the game servers and shares one channel with them on the Internet, it makes sense to register additional restrictions on the width of the channel for uploading records. But, unlike the Fast Download settings, there is no need to install additional checks on the referer.
We set the call to replay.example.org.conf in the main /etc/nginx/nginx.conf file if not yet, then test the configuration and restart nginx.
# nginx -t # systemctl reload nginx
Further we continue as the user of game.
By default, when resolving records, the servers will try to execute the configuration file ~ / tf2 / tf / cfg / replay.cfg at startup. Since we include records on both servers, the individual settings of which must be different, as in the previous cases, we prepare individual files for each server.
In the ~ / tf2 / tf / cfg directory there is a file replay_example.cfg, we study it and create our own. For the first server, ~ / cfg / replay1.cfg:
echo "*** ~/cfg/replay1.cfg" replay_name " " replay_local_fileserver_path /var/www/replay.example.org/htdocs/server1 replay_fileserver_offload_enable 0 replay_fileserver_host replay.example.org replay_fileserver_path /server1 replay_enable 1
Here:
replay_name
the name of the special bot to record, as it will be visible in the list of spectators.
replay_local_fileserver_path
directory where the finished files with records will be placed. It must be individual for each game server and available for reading by a web server.
replay_fileserver_offload_enable
if 1, then the records are uploaded via ftp to another server, which already distributes them themselves via http. Not our case.
if 0, then the distribution is handled by a web server on our machine.
replay_fileserver_host
web server name or ip
replay_fileserver_path
the url part is the path to the entries as displayed by the web server.
replay_enable
actually includes records on the server.
Thus, from the replay_local_fileserver_path, replay_fileserver_host, replay_fileserver_path and replay_fileserver_protocol not mentioned here replay_file_fileserver (= "http") and replay_fileserver_port (= "80") variables, the url of the type " http://replay.example.org:80/serverpage ", is formed; for downloading records. And the replay_local_fileserver_path variable sets the actual directory location in the file system and is equal to root from the nginx + replay_fileserver_path configuration file.
Copy this file to replay2.cfg, fix server1 paths -> server2
echo "*** ~/cfg/replay2.cfg" replay_name "My replay bot" replay_local_fileserver_path /var/www/replay.example.org/htdocs/server2 replay_fileserver_offload_enable 0 replay_fileserver_host replay.example.org replay_fileserver_path /server2 replay_enable 1
Make links in ~ / tf2 / tf / cfg:
$ ln -s -v ~/cfg/replay{1,2}.cfg ~/tf2/tf/cfg/
It should be borne in mind that these configuration files are executed only during the initial launch of the server, after autoexec.cfg. When changing cards, they are not involved.
From more or less useful console variables:
replay_dopublishtest
performs a server (gaming and web) readiness test for records β checks the availability of paths in the file system, the name of the web server, and so on.
replay_data_lifespan
sets the number of days (by default, 1 day), after which the records on the server will be marked as "stale", which will allow manual or automatic cleaning to delete them.
replay_docleanup
removes "stale" entries. With the parameter 'force' removes all entries altogether.
replay_fileserver_autocleanup
the default is 0 - off, starts the automatic cleaning of "stale" records between rounds.
replay_dofileserver_cleanup_on_start
the default is 1 - on, when the server starts, it starts automatic cleaning of "stale" entries, both in ~ / tf2 / tf / replay / server {1,2} and in the web server directory /var/www/replay.example. org / htdocs / server {1,2}.
replay_record_voice
default 1 - on, record voice chat of players.
The list of actual, in this version of the Steam engine, variables can be viewed by typing in the server console find replay_
.
In the startup scripts of servers start {1,2} .sh, we add to the command line:
For the first server:
CMDLINE="... -replay reply1.cfg -replayserverdir server1 \ ...
For the second:
CMDLINE="... -replay reply2.cfg -replayserverdir server2 \ ...
Here the "-replay" command includes the recording functions and executes the specified configuration file when the server starts. The second command, "-replayserverdir" as a parameter takes the name of the directory (from the path ~ / tf2 / tf / replay /), in which each server will accumulate records.
Everything, you can run the server and try. In the game client, in the server browser, near the name of our server, a characteristic Records icon will appear next to the VAC shield.
When recordings are turned on, a bot appears in the server in observer mode, which actually keeps records and at the same time occupies one game slot. Therefore, the maximum number of players set at the server startup "+ maxplayers 24" is increased by one, that is, in our case it becomes equal to twenty-five (and when you turn on SteamTV - twenty-six).
In the old tutorials on setting up records, the server command line parameter "-replay_port" is usually specified, but we donβt mention it because it was canceled back in 2011 - store.steampowered.com/news/6282/
When using plug-ins that facilitate mass actions on players (including those bundled with SourceMod), you should be careful about the bot records. In any case, do not accidentally kick it from the server :)
Record files, although small in size, still occupy disk space, both in the replay directory and in / var / www /. And it happens that, despite the established date of aging in one day (replay_data_lifespan 1) and the included auto-cleaning of these directories (replay_dofileserver_cleanup_on_start 1), old files are not automatically deleted. Even when manually starting replay_docleanup. Therefore, for security, we will add a forced cleaning of old records by running crontab -e
and adding it to the end:
0 3 * * * /usr/bin/find ~/tf2/tf/replay/server{1,2}/* -type f -mtime +10 -delete 0 3 * * * /usr/bin/find /var/www/replay.example.org/htdocs/server{1,2}/* -type f -mtime +10 -delete
Beforehand, it would be nice to make sure that cron uses a shell that supports the extension of brackets - "{1,2}"
Reading access.log shows that sometimes players, or rather their gaming clients, when they connect to our server, try to say the recordings of the games they played three weeks ago.
Another point is to keep in mind that the Records are eating processor time. An example download is given at the end of the "Bots" section.
Now set up SourceTV. This is useful for online broadcasts of world championships, when we will host them.
SourceTV allows viewers, through their Team Fortress 2 clients, to watch the game progress on the server. When using chains of proxy servers, the size of the audience is practically unlimited, but in this case, when the game will be broadcast only by our game server, it makes sense to limit the number of viewers, since each of them consumes both processor resources and a channel to the Internet.
Since during the initial setup of the launch of the game servers we have already indicated in the command line "+ tv_port" with our port number for each server, we can immediately go to the configuration files.
Just as for setting up records, SourceTV must be activated before loading the map, that is, the "tv_enable 1" command must be executed either on the server launch command line or in the autoexec.cfg file. In addition, it was experimentally established that the "tv_name" command has a similar requirement.
Since the SourceTV settings of our servers are fixed and we donβt plan to change with every change of card, weβll include all of the common in autoexec.cfg, the individual ones in autoexec {1,2} .cfg.
In ~ / cfg / autoexec.cfg we add general settings:
//... // SourceTV // tv_title " !" // // tv_password "" // tv_maxclients 5 // tv_maxrate 0 // (1) POV (0) tv_transmitall 1 // tv_delay 20 // - tv_allow_camera_man 0 // //tv_record <filename> // //tv_stoprecord // tv_autorecord 1
Here:
tv_title
the title in the window of the viewer when viewing the broadcast.
tv_password
password to connect to the broadcast.
tv_maxclients
The maximum number of viewers, from 0 to 255, is 128 by default. If you do not need an online broadcast, but only a recording of the game (tv_record, tv_autorecord), then you can set it to zero.
tv_maxrate
the maximum channel width for each player, by default - 8000 bps, when set to 0 - without restrictions. The parameter is closely linked with the previous parameter, especially if the server is planned to be fully filled with viewers.
tv_transmitall
by default ("0"), only that which is shown by the SourceTV operator (AI or specially trained person) is transmitted to the audience. When set to "1", viewers are given all the information about the game, and they can switch between POVs from different players, or even hover above / below the map. When the parameter is turned on, the required channel width for each viewer increases by two to three times.
tv_delay
broadcast delay to viewers in seconds, default is 30. Used to reduce cheating when the viewer can give hints to the player.
tv_delaymapchange
delay ("1") or not ("0" is the default) to change the card until the broadcast ends (due to the tv_delay delay).
tv_delaymapchange_protect
protects ("1" - by default) or not ("0") from manually changing the card until the round ends.
tv_allow_camera_man
allow ("1" - the default) or not ("0"), observer players become SourceTV operators. If "0" - then only automatic camera control.
tv_autorecord
when turned on ("1"), all games automatically begin to be recorded in files with names like auto-<YYYYMMDD>-<hhmm>-< >.dem
to the ~ / tf2 / tf directory, for example, "auto-20160630-2208-koth_sawmill .dem ".
When setting a password ("tv_password <password>"), viewers will not be able to connect from the server browser - they will constantly be refused with the message: "Disconnect: Bad spectator password", and in the server console it will be written "Dropped <player> from server (Bad spectator password) ". To connect, viewers will need to enter thepassword <>
in the console (~
) of the game, close the console, and then try to connect. Or immediately enterconnect 192.0.2.0:27020; password <>
in the consoleconnect 192.0.2.0:27020; password <>
connect 192.0.2.0:27020; password <>
.
In ~ / cfg / autoexec1.cfg we append to the end:
//... // SourceTV tv_enable 1 // tv_name "SourceTV at Public Server No 1"
Here:
tv_name
the name of the SourceTV server, as it will be displayed in the server browser, in the "Watch" tab.
tv_enable
includes ("1") or not ("0", the default) SourceTV on the server.
Similarly, we adjust ~ / cfg / autoexec2.cfg
//... tv_enable 1 tv_name "SoutceTV at Private Server No 2" tv_autorecord 0
But for the second server, we have disabled automatic recording in autoexec2.cfg. There is a problem when you turn on automatic recording ("tv_autorecord 1") on cards connected from Steam Workshop, whose name looks like "workshop /", or "workshop / .ugc" - that is, in any case contains a slash "/", which leads to a clumsy formation of the file name for tv_autorecord in the auto-<YYYYMMDD>-<hhmm>-< >.dem
scheme and swearing in the logs of the form:
Failed to write file /home/game/tf2/tf/replay/server2/sessions/20160702-074150-workshop/cp_orange_x3.ugc454299390.dmx Failed to write file /home/game/tf2/tf/replay/server2/blocks/20160702-074150-workshop/cp_orange_x3.ugc454299390_part_0.dmx ******************************************************************************** * * Replay recording shutting down due to publishing error! Recording will begin * at the beginning of the next round, but may fail again. * ******************************************************************************** ERROR: Publish timed out after 60 seconds.
and, as a result, disabling records. Alternatively, you can think of a scheme using "tv_record", which allows you to manually specify the file name to write.
When SourceTV is turned on, a bot appears in the server in observer mode, which is engaged in broadcasting the game and at the same time occupies one game slot. Therefore, the maximum number of players set at the server startup "+ maxplayers 24" is increased by one, that is, in our case it becomes equal to twenty-five (and when you turn on Replay - twenty-six).
So, the commands are spelled out, restart the server and see what happens. Since we also have recordings that also occupy their gaming slot, we see:
*** ~/cfg/autoexec.cfg (global) -------------------------------------------------------- sv_pure set to 2. -------------------------------------------------------- maxplayers set to 25 *** ~/cfg/autoexec1.cfg Server logging enabled. Server logging data to file /home/game/log/server1/L1008000.log maxplayers set to 26 (extra slot was added for SourceTV) ... Cannot verify load for invalid steam ID [A:1:0:1] Cannot verify load for invalid steam ID [A:1:1:1] Recording SourceTV demo to auto-20161008-1155-cp_granary.dem... Connection to game coordinator established. *** ~/cfg/server1.cfg ... SourceTV broadcast active. Connection to Steam servers successful. Public IP is 192.0.2.0.
So, at the beginning, the maximum number of players on the server was increased from 24 to 25 - this worked out the command-line parameter "-replay", the recordings started. Then another extra slot was added for SourceTV - it worked "tv_enable 1" from autoexec1.cfg. We do not pay attention to the abuse about invalid steam ID [A: 1: 0: 1] - these are our recording and broadcasting bots, for which the server has added game slots. Then the demo was started writing to the file ~ / tf2 / tf / auto-20161008-1155-cp_granary.dem - the "tv_autorecord 1" parameter from autoexec.cfg worked. Finally, we were told that SourceTV broadcast active.
It worked. You can populate any card with bots, connect with the viewer and see how the broadcast looks in different modes tv_transmitall, tv_allow_camera_man.
It may happen that the slots are added, but about "SourceTV broadcast active." not a word, and when you enter the tv_status
command in the server console, it swears "SourceTV not active.", although tv_enable
entered right there says that everything is ok - "tv_enable = 1 (def. 0)". In this case, you should try to change the map - changelevel < >
. If everything worked after the change, it means that SourceTV didnβt initially activate until the first map was loaded - you need to look at the settings.
Commands that may come in handy:
tv_record < >
starts recording saved to file <file name>. All events are recorded, regardless of what the operator sees.
tv_stoprecord
stops recording.
tv_clients
shows information about connected viewers.
tv_msg
send a message to all viewers (will appear in the middle of the screen).
tv_status
displays a brief information about the status of the server - online time, FPS, number of viewers, channel band used, and the like.
The list of actual, in this version of the game server, variables can be viewed by typing in the server console find tv_
.
If we use maps, models, sounds that are not included in the standard delivery of Team Fortress 2 and are missing from the Steam Workshop on our servers, then when a new player is connected, he will need to download our gaming materials to his gaming computer (if he has not). By default, they will be downloaded from our game server - this mode is called Slow Download. But since the game server is still not a specialized web server, then with frequent installation of new user maps and high load, it would be reasonable to assign the functions on the return of cards (as well as sounds, models, etc.) to a specially trained web server. Which, by a happy coincidence, we already have. This functionality is called Fast Download.
To use Fast Download, you must specify the web server to use a directory with the structure of subdirectories
dir/maps dir/materials dir/sound ...
where "dir" is the root directory for fast download. We cannot create it in / home / game - we have a home directory with rwx rights ------, which does not allow the web server to see these files. Therefore, we will create these directories somewhere outside the user's home directory game.
To simplify the configuration, we will register a separate subdomain of fastdl.example.org in our DNS, create the directory /var/www/fastdl.example.org, and for convenience we will write the logs into separate files and let the game user read them.
From root, we create directories, set the owner (game: game) and rights β to the game user for writing, the rest (the web server) for reading. You can also make symbolic links for convenience. Catalog Fast Download will be common to both game servers.
# mkdir -p /var/www/fastdl.example.org/htdocs/{maps,materials,sound} # mkdir /var/www/fastdl.example.org/log # chown -R game:game /var/www/fastdl.example.org # chmod -R 755 /var/www/fastdl.example.org # ln -s /var/www/fastdl.example.org/htdocs /home/game/fastdl # ln -s /var/www/fastdl.example.org/log /home/game/log/www-fastdl
In our default configuration, all web server logs are owned by nginx: adm and 640 permissions, that is, they are not available to regular users. Adjust this for this case:
# touch /var/www/fastdl.example.org/log/{access,error}.log # chmod 644 /var/www/fastdl.example.org/log/*.log
Thus, the user game, our logs will be available for reading. But only until their first rotation. We fix this too. In the /etc/logrotate.d directory we copy the nginx file to srcds-nginx, in it we set the path to the logs and in the create 640 nginx adm
fix the access rights mask from 640 to 644:
#/etc/logrotate.d/srcds-nginx /var/www/stat.example.org/log/*.log /var/www/fastdl.example.org/log/*.log /var/www/replay.example.org/log/*.log { daily missingok rotate 52 compress delaycompress notifempty create 644 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 `cat /var/run/nginx.pid` fi endscript }
Here we are in the paths for rotation at the same time indicated directories with logs from the statistics server HLstatsX and from the server with records.
There is another fun moment to consider. For most servers, it is unlikely to become relevant, but still. Nothing prevents the owner of any game server with user cards like ours, not from malice, but to save your traffic, in your Fast Download settings, specify the address of our web server (it is easy to find it - just enter sv_downloadurl
in the game console client by connecting to the server).
You can detect such parasites by referer, with whom maps are downloaded from us. So, when downloading the map by the game client, at the filing of our game server, a record of the following type appears in the web server log
198.51.100.0 http://fastdl.example.org - [16/Jun/2016:20:08:28 +0600] "GET /maps/cp_orange_x5.bsp.bz2 HTTP/1.1" 200 2685506 "hl2://192.0.2.0:27015" "Half-Life 2" 0.453 "-"
Pay attention to the referer. We take this into account when setting up.
So, we are going to set up a web server. First, we make a determination whether referer downloads our map with the correct one. /etc/nginx/nginx.conf, http {}, fastdl.example.org, :
# /etc/nginx/nginx.conf http { # <...> map $http_referer $bad_client { default 1; "hl2://192.0.2.0:27015" 0; "hl2://192.0.2.0:27016" 0; } include /etc/nginx/conf.d/fastdl.example.org.conf; }
It's simple. $http_referer , $bad_client ( 1) 0.
/etc/nginx/conf.d/fastdl.example.org.conf.
#/etc/nginx/conf.d/fastdl.example.org.conf server { server_name fastdl.example.org; listen 80; root /var/www/fastdl.example.org/htdocs; disable_symlinks on; default_type application/octet-stream; if ($bad_client) { # https://habrahabr.ru/post/272261/, return 403; } access_log /var/www/fastdl.example.org/log/access.log main; error_log /var/www/fastdl.example.org/log/error.log warn; }
β $bad_client, .
, nginx valid_referers, $http_referer, , . map .
fastdl.example.org.conf nginx.conf , nginx.
# nginx -t # systemctl reload nginx
game.
, ( bzip2), (.bsp) . , - cp_orange_x5 ( β , Steam Workshop), :
$ mv cp_orange_x5.bsp ~/fastdl/maps $ ln -s ~/fastdl/maps/cp_orange_x5.bsp ~/tf2/tf/maps $ bzip2 --compress --keep --verbose --best ~/fastdl/maps/cp_orange_x5.bsp
~/fastdl/maps, . , , , . < >.cfg ~/tf2/tf/cfg ( ~/cfg, ).
~/cfg/autoexec.cfg:
//... // Fast Download // -, // Fast Download sv_downloadurl "" sv_downloadurl "http://fastdl.example.org" // (, ). . sv_allowupload 0 // // Slow Download. . sv_allowdownload 1
. , . , , autoexec.cfg Fast Download.
- β exec <configfile>
. Fast Download , autoexec.cfg, "" , server.cfg. , . , autoexec.cfg :-)
SteamApps\common\Team Fortress 2\tf\download\maps\ cp_orange_x5.bsp, β ( ).
, , , Fast Download ( "Downloading maps/cp_orange_x5.bsp.bz2" β .bz2 ):
( _x3, ).
, , " " (cl_downloadfilter mapsonly), "Map is missing".
http://fastdl.example.org/maps/cp_orange_x5.bsp.bz2 , "403 Forbidden" β , referer hl2://192.0.2.0
, .
:
Fast Download ( sv_downloadurl), -, , < >.bsp.bz2, 404 , .bz2 β < >.bsp. , ~/tf2/tf/maps Slow Download, , .
Team Fortress 2 β . , ( sv_cheats 0), . β "", (sv_cheats 1).
TF wiki , King of the Hill ( koth_*
), Payload ( pl_*
), Dustbowl Gorge, Capture the Flag ( ctf_*
) Mann Manor ( cp_manor_event
). , . . , . .
koth_sawmill, by design. 24 . , 24 , . , 24, . β . β . , . , ~/cfg/koth_sawmill.cfg:
echo "*** ~/cfg/koth_sawmill.cfg" // tf_bot_difficulty 3 // tf_bot_join_after_player 0 // tf_bot_keep_class_after_death 0 // tf_bot_quota_mode fill // tf_bot_quota 24
:
tf_bot_difficulty 3
. 0=easy, 1=normal, 2=hard, 3=expert.
tf_bot_join_after_player 0
(0), (1), .
tf_bot_keep_class_after_death 0
, (, , ...), (1) (0), .
tf_bot_quota 24
, . , tf_bot_quota_mode "fill" "match", , +maxplayers .
tf_bot_quota_mode fill
:
"normal" β / (tf_bot_add / tf_bot_kick)
"fill" β ( + ) , tf_bot_quota
"match" β 1:N, N tf_bot_quota.
tf_bot_add [] [] [] [] []
, (, , maxplayers)
[] β Demoman, Engineer, HeavyWeapons, Medic, Pyro, Scout, Soldier, Sniper, Spy
[] β red blue
[] β tf_bot_difficulty, . 0=easy, 1=normal, 2=hard, 3=expert.
, ~/cfg, ~/tf2/tf/cfg:
$ ln -s ~/cfg/koth_sawmill.cfg ~/tf2/tf/cfg
, , : changelevel koth_sawmill
. , expert-lvl tf_bot_difficulty 1 :-)
. cp_orange_x3.
koth_sawmill.cfg cp_orange_x3.cfg, Steam Workshop:
$ mkdir ~/tf2/tf/cfg/workshop $ cp ~/cfg/koth_sawmill.cfg ~/tf2/tf/cfg/workshop/cp_orange_x3.ugc454299390.cfg
cp_orange_x3.ugc454299390.cfg echo , .
. changelevel workshop/cp_orange_x3.ugc454299390
. β , :
. , : sv_cheats 1
β - nav_generate
β ( < >.nav), . ...
Generating Navigation Mesh... Sampling walkable space... Sampling walkable space... Sampling walkable space... Creating navigation areas from sampled data... Connecting navigation areas... Merging navigation areas... Created new fencetop area 1781(fc537be) between 3(1f542dcf) and 49(274fa843) Finding hiding spots...DONE Finding encounter spots...DONE Finding sniper spots...DONE Computing mesh visibility... Computing mesh visibility... 0% Computing mesh visibility... 1% Computing mesh visibility... 5% Computing mesh visibility... 17% Can't compute incursion distances from the Red spawn room(s). <...> Can't compute incursion distances from the Blue spawn room(s). <...> Computing mesh visibility... 84% Optimizing mesh visibility... NavMesh Visibility List Lengths: min = 12, avg = 104, max = 280 Computing mesh visibility...DONE Finding earliest occupy times...DONE Start custom... Post custom... Custom game-specific analysis...DONE Generation complete! 77.8 seconds elapsed. Navigation map '/home/game/tf2/tf\maps\workshop/cp_orange_x3.ugc454299390.nav' saved. [TF Workshop] Preparing map ID 454299390 [TF Workshop] Successfully prepared client map from workshop [ workshop/cp_orange_x3.ugc454299390 ] ---- Host_Changelevel ---- .
. "sv_cheats 0" server2.cfg. , , sv_cheats 0, β , .
β , . , , . .
- , . Navigation Mesh Commands , Steam Users Forum .
"" (Puppet bots). , , . . TF Wiki, . https://youtu.be/Dn9970dxQ2g
, , , . , top Atom N2800:
24 ( , ), 12, . , . , , 7%. tf_bot_join_after_player 1 .
, , β ( ), (koth_sawmill.cfg cp_orange_x3.ugc454299390.cfg ) , , . , β , - " ", , .nav . , , tf_bot_quota 0 server{1,2}.cfg β , .
Source: https://habr.com/ru/post/312928/