DDNet-insta based on DDRaceNetwork, a Teeworlds mod. See the website for more information.
For build instructions visit the ddnet repo.
A ddnet based pvp mod. With the focus on correct 0.6 and 0.7 support and staying close to and up to date with ddnet. While being highly configurable and feature rich.
Implementing most of the relevant pvp gametypes: ctf, dm, gctf, ictf, gdm, idm, gtdm, itdm, zCatch, bolofng, solofng, boomfng, fng, tsmash, foot
The name ddnet-insta is short for DummyDragRaceNetwork Instagib. Because it started out as a ddnet based modification with the focus on gCTF with the possible future scope for also other instagib (one shot kills) gametypes such as iCTF, zCatch and fng. But it now has expanded to support also damage based gameplay such as teeworlds vanilla CTF and DM. So currently it aims to support any kind of round based pvp gametype that can be implemented without causing too much maintenance cost.
NOTE FOR DEVELOPERS:
It also tries to be extendable and fork friendly. If you want to build a pvp gamemode with score points and rounds. This code base should get you started quite easily. Just create a new folder for your gamemode. After wiring it up in your_mod.cpp and cmakelist you should be able to build almost any gametype without ever having to edit code outside of your gamemode directory. Just look at the existing gamemodes for examples. A simple mode to look at would be vanilla deathmatch. Adding your own stats columns and rank/top commands can be done in a few lines of code without writing any SQL.
- Stay close and up to date with upstream ddnet. Keep the git diff in files edited by ddnet as minimal as possible to keep merging cheap.
 - Be generic, consistent and configurable. If possible the same config variables and concepts should be applied to all gametypes.
For example configs such as anticamper should not be 
sv_zcatch_anticamperbutsv_anticamperand work in all gametypes. - Support latest ddnet and teeworlds clients fully and correctly.
 - Be friendly to downstream projects. Commits and releases should warn about breaking changes. Downstream projects should have an easy time to add new gametypes that can be updated to new ddnet-insta versions without a lot of effort.
 
Every players kills, deaths, wins and more statistics are persisted in a database.
There are no accounts. The stats are tacked on the players names. What exactly is tracked
depends on the sv_gametype. But here are some chat commands that work in any gamemode:
/statsShows the current round stats. Takes a player name as optional argument./statsallShows the all time stats. Takes a player name as optional argument./top5killsShows the all time top 5 players by amount of kills. Takes an offset as optional argument/top5kills 5to see rank 5 till 10 for example./rank_killsShow the all time rank of a players kills compared to others. Takes a player name as optional argument./rankto list all rank commands for the current gametype/topto list all top commands for the current gametype
If a vote is added starting with a [ ] in the display name. It will be used as a checkbox.
If the underlying config is currently set that checkbox will be ticked and users see [x] in the vote menu.
This feature is optional and if you do not put any  [ ] in your config it will not be using any checkboxes.
It is only applied for ddnet-insta settings not for all ddnet configs.
It is recommended to set sv_vote_checkboxes 0 at the start of your autoexec and sv_vote_checkboxes 1
at the end so it does not update all votes for every setting it loads.
Newer DDNet clients do not show duplicated messages multiple times. This is not always wanted when using call binds for team communication during pvp games. So there is sv_unstack_chat to revert that ddnet feature and ensure every message is sent properly in chat.
ddnet-insta uses the 0.6/0.7 server side version bridge from ddnet. So all gametypes are playable by latest teeworlds clients and ddnet clients at the same time.
In 0.7 there was a ready change added which allows users to pause the game. It only continues when everyone presses the ready bind.
This feature is now also possible for 0.6 clients using the /pause chat command. This feature should be turned off on public servers sv_player_ready_mode 0 because it will be used by trolls.
In 0.6 dead players join the spectators team in the zCatch gamemode.
In 0.7 they are marked as dead players and are separate from spectators.
The official teeworlds 0.7 client does block voting on the client side for spectators.
To make sv_spectator_votes portable and fair for both 0.6 and 0.7 players there is an option to allow
0.7 clients to vote as spectators. It is a bit hacky so it is hidden behind then config sv_spectator_votes_sixup 1
when that is set it will make the 0.7 clients believe they are in game and unlock the call vote menu.
But this also means that to join the game the users have to press the "spectate" button.
The vanilla teeworlds client does not send a rcon username but the ddnet client does.
DDNet servers and thus also ddnet-insta have regular rcon passwords but also users with username and password.
These can be added using the rcon command auth_add or auth_add_p.
On regular ddnet servers it is impossible for teeworlds clients to login using these credentials.
In ddnet-insta it is possible for 0.7 players to send username:password as the password.
And it will log them in if those are valid credentials.
By default ddnet-insta tries to be ready to be used in competetive games. Being as close to prior implementations of the gametypes as possible. With that being said there are lots of opt in configurations to customize the gameplay.
Check the Configs section for a complete list. One of the highlights would be dropping the flag in CTF gametypes.
Most of the settings that affect the gameplay can be shown to the user with sv_show_settings_motd
so they know what is going on:
Make sure to also reload or switch the map when changing the gametype.
sv_gametype ctf
Vanilla teeworlds capture the flag. Is a team based mode where players can collect shields/health and weapons. Capturing the enemy flag scores your team 100 points.
ddnet-insta is based on ddnet but it aims to fully implement correct teeworlds gameplay for the vanilla modes. But there are vanilla gameplay features that require you to set some configs. And the 0.5 wallhammer bug is intentionally not fixed like it is in the official teeworlds 0.6 and 0.7 versions.
sv_gametype dm
Vanilla teeworlds deathmatch. Is a free for all mode where players can collect shields/health and weapons. First player to reach the scorelimit wins.
ddnet-insta is based on ddnet but it aims to fully implement correct teeworlds gameplay for the vanilla modes. But there are vanilla gameplay features that require you to set some configs. And the 0.5 wallhammer bug is intentionally not fixed like it is in the official teeworlds 0.6 and 0.7 versions.
sv_gametype iCTF
Instagib capture the flag. Is a team based mode where every player only has a laser rifle. It kills with one shot and capturing the enemy flag scores your team 100 points.
sv_gametype gCTF
Grenade capture the flag. Is a team based mode where every player only has a rocket launcher. It kills with one shot and capturing the enemy flag scores your team 100 points.
sv_gametype iDM
Laser death match. One shot kills. First to reach the scorelimit wins.
sv_gametype gDM
Grenade death match. One shot kills. First to reach the scorelimit wins.
sv_gametype iTDM
Laser team death match. One shot kills. First team to reach the scorelimit wins.
sv_gametype gTDM
Grenade team death match. One shot kills. First team to reach the scorelimit wins.
sv_gametype zCatch
If you get killed you stay dead until your killer dies. Last man standing wins.
It is an instagib gametype so one shot kills. You can choose the weapon with
sv_spawn_weapons the options are grenade or laser.
sv_gametype bolofng
Freeze next generation mode with grenade. One grenade hit freezes enemies. Frozen enemies can be sacrificed to the gods by killing them in special spikes. First player to reach the scorelimit wins.
sv_gametype solofng
Like bolofng but with laser.
sv_gametype boomfng
Like bolofng but with teams.
sv_gametype fng
Like boomfng but with laser.
sv_gametype tsmash
A hammer deathmatch where you only die from spikes. Every time you are hit you loose health which increases the knockback you take. Pickup hearts and shields to reduce knockback.
sv_gametype ttsmash
Like TSmash but with teams.
sv_gametype foot
A football (soccer) teamplay mode. Where the grenade is your ball. And you have to score it into the enemy goal.
ddnet-insta inherited all configs from ddnet. So make sure to also check ddnet's documentation. The following ddnet configs are highly recommended to set in ddnet-insta to get the best pvp experience.
# autoexec_server.cfg
sv_tune_reset 0
sv_destroy_bullets_on_death 0
sv_destroy_lasers_on_death 0
sv_no_weak_hook 1
sv_vote_veto_time 0
conn_timeout 10
conn_timeout_protection 5
ddnet also has something called a reset file. Which is a special config.
By default it is loaded from reset.cfg and it can be set to a custom location
using the config sv_reset_file
In this reset.cfg it is recommeded to set the following configs to get a more classic pvp experience.
# reset.cfg
sv_team 0
sv_old_laser 1 # wallshot should not collide with own tee
tune laser_bounce_num 1
Below is a list of all the settings that were added in ddnet-insta.
sv_gametypeGame type (gctf, ictf, gdm, idm, gtdm, itdm, ctf, dm, tdm, zcatch, bolofng, solofng, boomfng, fng)sv_spectator_votesAllow spectators to votesv_spectator_votes_sixupAllow 0.7 players to vote as spec if sv_spectator_vote is 1 (hacky dead spec)sv_bang_commandschat cmds like !1vs1 0=off 1=read only no votes 2=all commandssv_redirect_and_shutdown_on_round_end0=off otherwise it is the port all players will be redirected to on round endsv_countdown_unpauseNumber of seconds to freeze the game in a countdown before match continues after pausesv_countdown_round_startNumber of seconds to freeze the game in a countdown before match starts (0 enables only for survival gamemodes, -1 disables)sv_scorelimitScore limit (0 disables)sv_timelimitTime limit in minutes (0 disables)sv_player_ready_modeWhen enabled, players can pause/unpause the game and start the game on warmup via their ready statesv_force_ready_allminutes after which a game will be force unpaused (0=off) related to sv_player_ready_modesv_stop_and_go_chatpause then game when someone writes 'pause' or 'stop' and start with 'go' or 'start'sv_powerupsAllow powerups like ninjasv_teambalance_timeHow many minutes to wait before autobalancing teams (0=off)sv_teamdamageTeam damagesv_team_score_normalPoints a team receives for grabbing into normal spikessv_team_score_goldPoints a team receives for grabbing into golden spikessv_team_score_greenPoints a team receives for grabbing into green spikes(non 4-teams fng only)sv_team_score_purplePoints a team receives for grabbing into purple spikes(non 4-teams fng only)sv_team_score_teamPoints a team receives for grabbing into team spikessv_player_score_normalPoints a player receives for grabbing into normal spikessv_player_score_goldPoints a player receives for grabbing into golden spikessv_player_score_greenPoints a player receives for grabbing into green spikes(non 4-teams fng only)sv_player_score_purplePoints a player receives for grabbing into purple spikes(non 4-teams fng only)sv_player_score_teamPoints a player receives for grabbing into team spikessv_wrong_spike_freezeThe time, in seconds, a player gets frozen, if he grabbed a frozen opponent into the opponents spikes (0=off, fng only)sv_hammer_scale_xlinearly scale up hammer x power, percentage, for hammering enemies and unfrozen teammates (needs sv_fng_hammer)sv_hammer_scale_ylinearly scale up hammer y power, percentage, for hammering enemies and unfrozen teammates (needs sv_fng_hammer)sv_hit_freeze_delayHow many seconds will players remain frozen after being hit with a weapon (only fng)sv_melt_hammer_scale_xlinearly scale up hammer x power, percentage, for hammering frozen teammates (needs sv_fng_hammer)sv_melt_hammer_scale_ylinearly scale up hammer y power, percentage, for hammering frozen teammates (needs sv_fng_hammer)sv_fng_hammeruse sv_hammer_scale_x/y and sv_melt_hammer_scale_x/y tuning for hammersv_spike_soundPlay flag capture sound when sacrificing an enemy into the spikes !0.6 only! (0=off/1=only the killer and the victim/2=everyone near the victim)sv_laser_text_pointsdisplay laser text in the world on scoring (only fng for now)sv_announce_stealsshow in chat when someone stole a kill (only fng for now)sv_grenade_ammo_regenActivate or deactivate grenade ammo regeneration in generalsv_grenade_ammo_regen_timeGrenade ammo regeneration time in milisecondssv_grenade_ammo_regen_numMaximum number of grenades if ammo regeneration onsv_grenade_ammo_regen_speedGive grenades back that push own playersv_grenade_ammo_regen_on_killRefill nades on kill (0=off, 1=1, 2=all)sv_grenade_ammo_regen_reset_on_fireReset regen time if shot is firedsv_sprayprotectionSpray protectionsv_only_hook_killsOnly count kills when enemy is hookedsv_only_wallshot_killsOnly count kills when enemy is wallshotted (needs laser)sv_kill_hookHook killssv_killingspree_killsHow many kills are needed to be on a killing-spree (0=off)sv_killingspree_reset_on_round_end0=allow spreeing across games 1=end spree on round endsv_damage_needed_for_killGrenade damage needed to kill in instagib modessv_swap_flagsswap blue and red flag spawns in ctf modessv_allow_zoomallow ddnet clients to use the client side zoom featuresv_strict_snap_distanceonly send players close by (helps against zoom cheats)sv_anticamperToggle to enable/disable Anticampersv_anticamper_freezeIf a player should freeze on camping (and how long) or diesv_anticamper_timeHow long to wait till the player dies/freezessv_anticamper_rangeDistance how far away the player must move to escape anticampersv_release_gameauto release on kill (only affects sv_gametype zCatch)sv_zcatch_require_multiple_ips_to_startonly start games if 5 or more different ips are connectedsv_respawn_protection_msDelay in milliseconds a tee can not damage or get damaged after spawningsv_drop_flag_on_selfkilldrop flag on selfkill (activates chat cmd '/drop flag')sv_drop_flag_on_votedrop flag on vote yes (activates chat cmd '/drop flag')sv_reload_time_on_hit0=default/off ticks it takes to shoot again after a shot was hit (see also sv_fast_hit_full_auto)sv_fast_hit_full_autorequire fire button repress when sv_reload_time_on_hit is setsv_punish_freeze_disconnectfreeze player for 20 seconds on rejoin when leaving server while being frozensv_self_damage_respawn_delay_mstime in miliseconds it takes to respawn after dying by self damagesv_self_kill_respawn_delay_mstime in miliseconds it takes to respawn after sending kill bindsv_enemy_kill_respawn_delay_mstime in miliseconds it takes to respawn after getting killed by enemiessv_world_kill_respawn_delay_mstime in miliseconds it takes to respawn after touching a deathtilesv_game_kill_respawn_delay_mstime in miliseconds it takes to respawn after team change, round start and so onsv_chat_ratelimit_long_messagesNeeds sv_spamprotection 0 (0=off, 1=only messages longer than 12 chars are limited)sv_chat_ratelimit_spectatorsNeeds sv_spamprotection 0 (0=off, 1=specs have slow chat)sv_chat_ratelimit_public_chatNeeds sv_spamprotection 0 (0=off, 1=non team chat is slow)sv_chat_ratelimit_non_callsNeeds sv_spamprotection 0 (0=off, 1=ratelimit all but call binds such as 'help')sv_chat_ratelimit_spamNeeds sv_spamprotection 0 (0=off, 1=ratelimit chat detected as spam)sv_chat_ratelimit_debugLogs which of the ratelimits kicked insv_require_chat_flag_to_chatclients have to send playerflag chat to use public chat (commands are unrelated)sv_always_track_statsTrack stats no matter how many players are onlinesv_debug_catchDebug zCatch ticks caught and in gamesv_debug_statsVerbose logging for the SQL player statssv_vote_checkboxesFill [ ] checkbox in vote name if the config is already setsv_hide_adminsOnly send admin status to other authed playerssv_show_settings_motdShow insta game settings in motd on joinsv_unstack_chatRevert ddnet clients duplicated chat message stackingsv_casual_rounds1=start rounds automatically, 0=require restart vote to properly start gamesv_allow_team_change_during_pauseallow players to join the game or spectators during pausesv_tournamentPrint messages saying tournament is running. No other effects.sv_tournament_chat0=off, 1=Spectators can not public chat, 2=Nobody can public chatsv_tournament_chat_smartTurns sv_tournament_chat on on restart and off on round endsv_tournament_join_msgsHide join/leave of spectators in chat !0.6 only for now! (0=off,1=hidden,2=shown for specs)sv_round_stats_format_discord0=csv 1=psv 2=ascii table 3=markdown table 4=jsonsv_round_stats_format_http0=csv 1=psv 2=ascii table 3=markdown table 4=jsonsv_round_stats_format_file0=csv 1=psv 2=ascii table 3=markdown table 4=jsonsv_print_round_statsprint top players in chat on round endsv_kill_tile_destroys_ballDestroy the ball when it touches death tile (only foot)sv_ball_bounce_frictionThe ball looses that much speed after a bounce (only foot)sv_ball_explodeShould the grenades explode (only foot)sv_ball_respawn_delayRespawn time of the ball (only foot)sv_score_diffDifference between the team-scores before a team can win (only foot)sv_sudden_death_score_diffDifference between the team-scores before a team can win in sudden death (only foot)sv_suicide_penaltyIndicates if score is decremented on suicidesv_spawn_weaponspossible values: grenade, lasersv_zcatch_colorsColor scheme for zCatch options: teetime, savandersv_display_scorevalues: points, round_points, spree, current_spree, win_points, wins, kills, round_killssv_tournament_welcome_chatChat message shown in chat on join when sv_tournament is 1sv_round_stats_discord_webhooksIf set will post score stats there on round end. Can be a comma separated list.sv_round_stats_http_endpointsIf set will post score stats there on round end. Can be a comma separated list.sv_round_stats_output_fileIf set will write score stats there on round end
hammerGives a hammer to yougunGives a gun to youunhammerRemoves a hammer from youungunRemoves a gun from yougodmodeRemoves damagerainbowToggle rainbow skin on or offforce_readySets a player to ready (when the game is paused)chatSend a message in chat bypassing all mute featuresshuffle_teamsShuffle the current teamsswap_teamsSwap the current teamsswap_teams_randomSwap the current teams or not (random chance)force_teambalanceForce team balanceadd_map_to_poolCan be picked by random_map_from_pool command (entries can be duplicated to increase chance)clear_map_poolClears pool used by random_map_from_pool commandrandom_map_from_poolChanges to random map from pool (see add_map_to_pool)gctf_antibotruns the antibot command gctf (depends on closed source module)known_antibotruns the antibot command known (depends on antibob antibot module)redirectRedirect client to given port use victim "all" to redirect all but your selfdeep_jailiddeep freeze (undeep tile works) will be restored on respawn and reconnectdeep_jailipdeep freeze (undeep tile works) will be restored on respawn and reconnectdeep_jailslist all perma deeped players deeped by deep_jailid and deep_jailip commandsundeep_jaillist all perma deeped players deeped by deep_jailid and deep_jailip commands
Most ddnet slash chat commands were inherited and are still functional. But /pause and /spec got removed since it is conflicting with pausing games and usually not wanted for pvp games.
ddnet-insta then added a bunch of own slash chat commands and also bang (!) chat commands
!ready!pause/pause/readyto pause the game. Needssv_player_ready_mode 1and 0.7 clients can also send the 0.7 ready change message!shuffle/shufflecall vote to shuffle teams!swap/swapcall vote to swap teams!swap_random/swap_randomcall vote to swap teams to random sides!settingsshow current game settings in the message of the day. It will show if spray protection is on or off and similar game relevant settings.!1v1!2v2!v1!v2!1on1... call vote to change in game slots!restart ?(seconds)call vote to restart game with optional parameter of warmup seconds (default: 10)/drop flagif it is a CTF gametype the flagger can drop the flag without dying if eithersv_drop_flag_on_selfkillorsv_drop_flag_on_voteis set/creditsShows the credits of the current ddnet-insta mode"/credits_instaShows the credits of the entire ddnet-insta project"/credits_ddnetShows the credits of the DDNet mod"/rankLists available rank commands/top5Lists available top commands/topLists available top commands/specvotedToggles spec on the currently voted player"/statsShows the current round stats of player name (your stats by default)/statsallShows the all time stats of player name (your stats by default)/stats_allShows the all time stats of player name (your stats by default)/multisShows the all time fng multi kill stats/stealsShows all time and round fng kill steal stats/round_topShows the top players of the current round/scorechange which type of score is displayed in scoreboard/pointsShows the all time points rank of player name (your stats by default)/rank_pointsShows the all time points rank of player name (your stats by default)/rank_killsShows the all time kills rank of player name (your stats by default)/top5killsShows the all time best ranks by kills/rank_flagsShows the all time flag time rank of player name (your stats by default)/top5flagsShows the all time best ranks by flag time/top5capsShows the all time best ranks by amount of flag captures/rank_capsShows the all time flag capture rank of player name (your stats by default)/top5spikesShows the all time best ranks by spike kills
At the end of every round the stats about every players score can be published to discord (and other destinations).
The following configs determine which format the stats will be represented in.
sv_round_stats_format_discord0=csv 1=psv 2=ascii table 3=markdown table 4=jsonsv_round_stats_format_http0=csv 1=psv 2=ascii table 3=markdown table 4=jsonsv_round_stats_format_file0=csv 1=psv 2=ascii table 3=markdown table 4=json
And these configs determin where the stats will be sent to.
sv_round_stats_discord_webhooksWill do a discord webhook POST request to that url. The url has to look like this:https://discord.com/api/webhooks/1232962289217568799/8i_a89XXXXXXXXXXXXXXXXXXXXXXXIf you don't know how to setup a discord webhook, don't worry its quite simple. You need to have admin access to a discord server and then you can follow this 1 minute youtube tutorial.sv_round_stats_http_endpointIt will do a http POST request to that url with the round stats as payload. You can set this to your custom api endpoint that collect stats. Example:https://api.zillyhuhn.com/insta/round_statssv_round_stats_output_fileIt will write the round stats to a file located at that path. You could then read that file with another tool or expose it with an http server. It can be a relaltive path then it uses your storage.cfg location. Or a absolute path if it starts with a slash. The file will be overwritten on every round end. To avoid that you can use the%tplaceholder in the filename and it will expand to a timestamp to avoid file name collisions. Example values:stats.json,/tmp/round_stats_%t.csv
The first two rows are special. The first is a csv header.
The second one is the red and blue team score.
After that each row is two players each. Red player first and blue player second.
If player names include commas their name will be quoted (see the example player foo,bar).
So this is how the result of a 2x2 could look like:
red_name, red_score, blue_name, blue_score
red, 24, blue, 3
"foo,bar", 15, (1)ChillerDrago, 2
ChillerDragon, 0, ChillerDragon.*, 1
---> Server: unnamed server, Map: tmp/maps-07/ctf5_spikes, Gametype: gctf.
(Length: 0 min 17 sec, Scorelimit: 1, Timelimit: 0)
**Red Team:**                                       
Clan: **|*KoG*|**                                   
Id: 0 | Name: ChillerDragon | Score: 2 | Kills: 1 | Deaths: 0 | Ratio: 1.00
**Blue Team:**                                      
Clan: **|*KoG*|**                                   
Id: 1 | Name: ChillerDragon.* | Score: 0 | Kills: 0 | Deaths: 1 | Ratio: 0.00
---------------------                               
**Red: 1 | Blue 0**  
Here is how it would display when posted on discord:
+-----------------+-----------+------------+
| map             | red_score | blue_score |
+-----------------+-----------+------------+
| ctf5            | 203       | 1          |
+-----------------+-----------+------------+
+-----+------+-----------------+--------+--------+--------+--------+------------+---------------+
| id  | team | name            | score  | kills  | deaths | ratio  | flag_grabs | flag_captures |
+-----+------+-----------------+--------+--------+--------+--------+------------+---------------+
| 0   | red  | foo             | 1      | 1      | 3      | 0.3%   | 0          | 0             |
| 1   | blue | bar             | 1      | 2      | 5      | 0.4%   | 0          | 0             |
| 2   | red  | ChillerDragon   | 19     | 7      | 2      | 3.5%   | 0          | 0             |
| 3   | blue | ChillerDragon.* | 2      | 2      | 5      | 0.4%   | 0          | 0             |
+-----+------+-----------------+--------+--------+--------+--------+------------+---------------+
NOT IMPLEMENTED YET
{
        "server": "unnamed server",
        "map": "tmp/maps-07/ctf5_spikes",
        "game_type": "gctf",
        "game_duration_seconds": 67,
        "score_limit": 200,
        "time_limit": 0,
        "score_red": 203,
        "score_blue": 0,
        "players": [
                {
                        "id": 0,
                        "team": "red",
                        "name": "ChillerDragon",
                        "score": 15,
                        "kills": 3,
                        "deaths": 1,
                        "ratio": 3,
                        "flag_grabs": 3,
                        "flag_captures": 2
                },
                {
                        "id": 1,
                        "team": "blue",
                        "name": "ChillerDragon.*",
                        "score": 0,
                        "kills": 0,
                        "deaths": 3,
                        "ratio": 0,
                        "flag_grabs": 0,
                        "flag_captures": 0
                }
        ]
}







