]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Added Team KeepAway gamemode from Mario/team_keepaway branch, Team KeepAway gamemode...
authorLegendaryGuard <rootuser999@gmail.com>
Mon, 15 Feb 2021 12:44:50 +0000 (13:44 +0100)
committerLegendaryGuard <rootuser999@gmail.com>
Mon, 15 Feb 2021 12:44:50 +0000 (13:44 +0100)
22 files changed:
gamemodes-client.cfg
gamemodes-server.cfg
gfx/menu/luma/gametype_tka.tga [new file with mode: 0644]
gfx/menu/luminos/gametype_tka.tga [new file with mode: 0644]
gfx/menu/wickedx/gametype_tka.tga [new file with mode: 0644]
gfx/menu/xaw/gametype_tka.tga [new file with mode: 0644]
notifications.cfg
qcsrc/common/gamemodes/gamemode/_mod.inc
qcsrc/common/gamemodes/gamemode/_mod.qh
qcsrc/common/gamemodes/gamemode/tka/_mod.inc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/_mod.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/cl_tka.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/cl_tka.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/sv_tka.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/tka.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/tka/tka.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/waypoints/all.inc
qcsrc/common/scores.qh
qcsrc/common/stats.qh
qcsrc/menu/xonotic/util.qc
qcsrc/server/world.qc

index 49867e4cdf935d4d7dfc8be2daf1df5a16361dca..4bd648f674d840cb7073050ae3bc8f6eb868cea6 100644 (file)
@@ -32,7 +32,8 @@ alias cl_hook_gamestart_ka
 alias cl_hook_gamestart_ft
 alias cl_hook_gamestart_inv
 alias cl_hook_gamestart_duel
-alias cl_hook_gamestart_surv //LegendGuard adds survival client hook from Mario/survival 15-02-2021
+alias cl_hook_gamestart_sv //LegendGuard adds survival client hook from Mario/survival 15-02-2021
+alias cl_hook_gamestart_tka //LegendGuard adds team keepaway client hook from Mario/team_keepaway 15-02-2021
 alias cl_hook_gameend "rpn /cl_matchcount dup load 1 + =" // increase match count every time a game ends
 alias cl_hook_shutdown
 alias cl_hook_activeweapon
index 310236039633d5a42eb4f4a9aeece990af133cc9..4a39bfe4961e9b9ff9f7ff2e3e6c53b5bd981d48 100644 (file)
@@ -59,7 +59,8 @@ alias sv_vote_gametype_hook_ons
 alias sv_vote_gametype_hook_rc
 alias sv_vote_gametype_hook_tdm
 alias sv_vote_gametype_hook_duel
-alias sv_vote_gametype_hook_sv ////LegendGuard adds survival hook from Mario/survival 15-02-2021
+alias sv_vote_gametype_hook_sv //LegendGuard adds survival hook from Mario/survival 15-02-2021
+alias sv_hook_gamestart_tka //LegendGuard adds team keepaway hook from Mario/team_keepaway 15-02-2021
 
 // Example preset to allow 1v1ctf to be used for the gametype voting screen.
 // Aliases can have max 31 chars so the gametype can have max 9 chars.
@@ -210,13 +211,21 @@ set g_duel_respawn_delay_large_count 0
 set g_duel_respawn_delay_max 0
 set g_duel_respawn_waves 0
 set g_duel_weapon_stay 0
-set g_sv_respawn_delay_small 0 ////LegendGuard adds survival cvars from Mario/survival 15-02-2021
+set g_sv_respawn_delay_small 0 //LegendGuard adds survival cvars from Mario/survival 15-02-2021
 set g_sv_respawn_delay_small_count 0
 set g_sv_respawn_delay_large 0
 set g_sv_respawn_delay_large_count 0
 set g_sv_respawn_delay_max 0
 set g_sv_respawn_waves 0
 set g_sv_weapon_stay 0
+set g_tka_respawn_delay_small 0 //LegendGuard adds team keepaway cvars from Mario/team_keepaway 15-02-2021
+set g_tka_respawn_delay_small_count 0
+set g_tka_respawn_delay_large 0
+set g_tka_respawn_delay_large_count 0
+set g_tka_respawn_delay_max 0
+set g_tka_respawn_waves 0
+set g_tka_weapon_stay 0
+
 
 
 // =========
@@ -576,4 +585,36 @@ set g_survival_hunter_count 0.25 "number of players who will become hunters, set
 set g_survival_punish_teamkill 1 "kill the player when they kill an ally"
 set g_survival_reward_survival 1 "give a point to all surviving players if the round timelimit is reached, in addition to the points given for kills"
 set g_survival_warmup 10 "how long the players will have time to run around the map before the round starts"
-set g_survival_round_timelimit 180 "round time limit in seconds"
\ No newline at end of file
+set g_survival_round_timelimit 180 "round time limit in seconds"
+
+//LegendGuard adds tema keepaway cvars from Mario/team_keepaway 15-02-2021
+// ===============
+//  team keepaway
+// ===============
+set g_tka 0 "another game mode which focuses around a ball"
+set g_tka_on_dm_maps 0 "when this is set, all DM and KA maps automatically support TKA"
+set g_tka_teams 2 "how many teams are in team keepaway (set by mapinfo)"
+set g_tka_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
+set g_tka_teams_override 0     "how many teams are in team keepaway"
+set g_tka_point_limit -1 "TKA point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_tka_point_leadlimit -1 "TKA point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_tka_score_team 1 "allow points to be awarded to teammates for any kill when the ball is in your team's possession"
+set g_tka_score_bckill 1 "points for killing the ball barrier (Ball Carrier Kill)"
+set g_tka_score_killac 1 "points for kills while holding the ball (Kill As Carrier)"
+set g_tka_score_timeinterval 1 "amount of time it takes between intervals for timepoints to be added to the score"
+set g_tka_score_timepoints 0 "points to add to score per timeinterval, 0 for no points"
+set g_tka_ballcarrier_effects 8 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
+set g_tka_ballcarrier_highspeed 1 "speed multiplier done to the person holding the ball (recommended when used with some mutators)"
+set g_tka_ballcarrier_damage   1       "damage multiplier while holding the ball"
+set g_tka_ballcarrier_force    1       "force multiplier while holding the ball"
+set g_tka_ballcarrier_selfdamage       1       "self damage multiplier while holding the ball"
+set g_tka_ballcarrier_selfforce        1       "self force multiplier while holding the ball"
+set g_tka_noncarrier_warn      1       "warn players when they kill without holding the ball"
+set g_tka_noncarrier_damage    1       "damage done to other players if both you and they don't have the ball"
+set g_tka_noncarrier_force     1       "force done to other players if both you and they don't have the ball"
+set g_tka_noncarrier_selfdamage        1       "self damage if you don't have the ball"
+set g_tka_noncarrier_selfforce 1       "self force if you don't have the ball"
+set g_tkaball_effects 0 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
+set g_tkaball_trail_color      254     "particle trail color from player/ball"
+set g_tkaball_damageforcescale 3 "Scale of force which is applied to the ball by weapons/explosions/etc"
+set g_tkaball_respawntime      10      "if no one picks up the ball, how long to wait until the ball respawns"
\ No newline at end of file
diff --git a/gfx/menu/luma/gametype_tka.tga b/gfx/menu/luma/gametype_tka.tga
new file mode 100644 (file)
index 0000000..b61fc08
Binary files /dev/null and b/gfx/menu/luma/gametype_tka.tga differ
diff --git a/gfx/menu/luminos/gametype_tka.tga b/gfx/menu/luminos/gametype_tka.tga
new file mode 100644 (file)
index 0000000..b4adb18
Binary files /dev/null and b/gfx/menu/luminos/gametype_tka.tga differ
diff --git a/gfx/menu/wickedx/gametype_tka.tga b/gfx/menu/wickedx/gametype_tka.tga
new file mode 100644 (file)
index 0000000..74d422d
Binary files /dev/null and b/gfx/menu/wickedx/gametype_tka.tga differ
diff --git a/gfx/menu/xaw/gametype_tka.tga b/gfx/menu/xaw/gametype_tka.tga
new file mode 100644 (file)
index 0000000..d8e1ba5
Binary files /dev/null and b/gfx/menu/xaw/gametype_tka.tga differ
index 1f6fa2c97c23441bb5fd9f509bbce17345ee8114..437050fd1a1cb2baa73f47dcff9b0d52a48c7559 100644 (file)
@@ -283,6 +283,7 @@ seta notification_INFO_SCORES "1" "0 = off, 1 = print to console, 2 = print to c
 seta notification_INFO_SPECTATE_WARNING "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_SUPERSPEC_MISSING_UID "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_SUPERWEAPON_PICKUP "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+
 //LegendGuard adds survival notifications from Mario/survival 15-02-2021
 seta notification_INFO_SURVIVAL_HUNTER_WIN "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_SURVIVAL_SUVIVOR_WIN "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
index cd4c86e02c35111e27d68c5b9299e0c66b56b82e..19c1589b73f7bea706d4f0fc0ae3744262ff37db 100644 (file)
@@ -17,3 +17,4 @@
 #include <common/gamemodes/gamemode/race/_mod.inc>
 #include <common/gamemodes/gamemode/survival/_mod.inc> //LegendGuard adds _mod.inc from Mario/survival 15-02-2021
 #include <common/gamemodes/gamemode/tdm/_mod.inc>
+#include <common/gamemodes/gamemode/tka/_mod.inc> //LegendGuard adds _mod.inc from Mario/team_keepaway 15-02-2021
\ No newline at end of file
index 4aa6fa41b5f6068e73636d66610fe6b7c5e0ec89..91dd1c6467badd27b441bea5c9ba01bd60efbded 100644 (file)
@@ -17,3 +17,4 @@
 #include <common/gamemodes/gamemode/race/_mod.qh>
 #include <common/gamemodes/gamemode/survival/_mod.qh> //LegendGuard adds _mod.qh from Mario/survival 15-02-2021
 #include <common/gamemodes/gamemode/tdm/_mod.qh>
+#include <common/gamemodes/gamemode/tka/_mod.qh> //LegendGuard adds _mod.qh from Mario/team_keepaway 15-02-2021
\ No newline at end of file
diff --git a/qcsrc/common/gamemodes/gamemode/tka/_mod.inc b/qcsrc/common/gamemodes/gamemode/tka/_mod.inc
new file mode 100644 (file)
index 0000000..6a33efd
--- /dev/null
@@ -0,0 +1,8 @@
+// generated file; do not modify
+#include <common/gamemodes/gamemode/tka/tka.qc>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/tka/cl_tka.qc>
+#endif
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/tka/sv_tka.qc>
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/tka/_mod.qh b/qcsrc/common/gamemodes/gamemode/tka/_mod.qh
new file mode 100644 (file)
index 0000000..e35dee6
--- /dev/null
@@ -0,0 +1,8 @@
+// generated file; do not modify
+#include <common/gamemodes/gamemode/tka/tka.qh>
+#ifdef CSQC
+    #include <common/gamemodes/gamemode/tka/cl_tka.qh>
+#endif
+#ifdef SVQC
+    #include <common/gamemodes/gamemode/tka/sv_tka.qh>
+#endif
diff --git a/qcsrc/common/gamemodes/gamemode/tka/cl_tka.qc b/qcsrc/common/gamemodes/gamemode/tka/cl_tka.qc
new file mode 100644 (file)
index 0000000..eda7c4f
--- /dev/null
@@ -0,0 +1,55 @@
+#include "cl_tka.qh"
+
+#include <client/draw.qh>
+#include <client/hud/panel/modicons.qh>
+
+// Keepaway HUD mod icon
+int tkaball_prevstatus; // last remembered status
+float tkaball_statuschange_time; // time when the status changed
+
+// we don't need to reset for team keepaway since it immediately
+// autocorrects prevstatus as to if the player has the ball or not
+
+void HUD_Mod_TeamKeepaway(vector pos, vector mySize)
+{
+       mod_active = 1; // team keepaway should always show the mod HUD
+
+       float tkaball_alpha = blink(0.85, 0.15, 5);
+
+       int stat_items = STAT(TKA_BALLSTATUS);
+       int tkaball = (stat_items & TKA_BALL_CARRYING);
+
+       if(tkaball != tkaball_prevstatus)
+       {
+               tkaball_statuschange_time = time;
+               tkaball_prevstatus = tkaball;
+       }
+
+       vector tkaball_pos, tkaball_size;
+
+       if(mySize.x > mySize.y) {
+               tkaball_pos = pos + eX * 0.25 * mySize.x;
+               tkaball_size = vec2(0.5 * mySize.x, mySize.y);
+       } else {
+               tkaball_pos = pos + eY * 0.25 * mySize.y;
+               tkaball_size = vec2(mySize.x, 0.5 * mySize.y);
+       }
+
+       float tkaball_statuschange_elapsedtime = time - tkaball_statuschange_time;
+       float f = bound(0, tkaball_statuschange_elapsedtime*2, 1);
+
+       if(tkaball_prevstatus && f < 1)
+               drawpic_aspect_skin_expanding(tkaball_pos, "keepawayball_carrying", tkaball_size, '1 1 1', panel_fg_alpha * tkaball_alpha, DRAWFLAG_NORMAL, f);
+
+       if(stat_items & TKA_BALL_CARRYING) // TODO: unique team based icon while carrying
+               drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * tkaball_alpha * f, DRAWFLAG_NORMAL);
+       else if(stat_items & TKA_BALL_TAKEN_RED)
+               drawpic_aspect_skin(pos, "tka_taken_red", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * tkaball_alpha * f, DRAWFLAG_NORMAL);
+       else if(stat_items & TKA_BALL_TAKEN_RED)
+               drawpic_aspect_skin(pos, "tka_taken_blue", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * tkaball_alpha * f, DRAWFLAG_NORMAL);
+       else if(stat_items & TKA_BALL_TAKEN_RED)
+               drawpic_aspect_skin(pos, "tka_taken_yellow", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * tkaball_alpha * f, DRAWFLAG_NORMAL);
+       else if(stat_items & TKA_BALL_TAKEN_RED)
+               drawpic_aspect_skin(pos, "tka_taken_pink", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * tkaball_alpha * f, DRAWFLAG_NORMAL);
+
+}
diff --git a/qcsrc/common/gamemodes/gamemode/tka/cl_tka.qh b/qcsrc/common/gamemodes/gamemode/tka/cl_tka.qh
new file mode 100644 (file)
index 0000000..d062456
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+
+void HUD_Mod_TeamKeepaway(vector pos, vector mySize);
diff --git a/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc b/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc
new file mode 100644 (file)
index 0000000..8337cef
--- /dev/null
@@ -0,0 +1,524 @@
+#include "sv_tka.qh"
+
+#include <common/effects/all.qh>
+
+.entity ballcarried;
+
+int autocvar_g_tka_ballcarrier_effects;
+float autocvar_g_tka_ballcarrier_damage;
+float autocvar_g_tka_ballcarrier_force;
+float autocvar_g_tka_ballcarrier_highspeed;
+float autocvar_g_tka_ballcarrier_selfdamage;
+float autocvar_g_tka_ballcarrier_selfforce;
+float autocvar_g_tka_noncarrier_damage;
+float autocvar_g_tka_noncarrier_force;
+float autocvar_g_tka_noncarrier_selfdamage;
+float autocvar_g_tka_noncarrier_selfforce;
+bool autocvar_g_tka_noncarrier_warn;
+int autocvar_g_tka_score_bckill;
+int autocvar_g_tka_score_killac;
+bool autocvar_g_tka_score_team;
+int autocvar_g_tka_score_timepoints;
+float autocvar_g_tka_score_timeinterval;
+float autocvar_g_tkaball_damageforcescale;
+int autocvar_g_tkaball_effects;
+float autocvar_g_tkaball_respawntime;
+int autocvar_g_tkaball_trail_color;
+
+bool tka_ballcarrier_waypointsprite_visible_for_player(entity this, entity player, entity view) // runs on waypoints which are attached to ballcarriers, updates once per frame
+{
+       if(view.ballcarried)
+               if(IS_SPEC(player))
+                       return false; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen
+
+       // TODO: Make the ballcarrier lack a waypointsprite whenever they have the invisibility powerup
+
+       return true;
+}
+
+void tka_EventLog(string mode, entity actor) // use an alias for easy changing and quick editing later
+{
+       if(autocvar_sv_eventlog)
+               GameLogEcho(strcat(":tka:", mode, ((actor != NULL) ? (strcat(":", ftos(actor.team), ":", ftos(actor.playerid))) : "")));
+}
+
+void tka_TouchEvent(entity this, entity toucher);
+void tka_RespawnBall(entity this) // runs whenever the ball needs to be relocated
+{
+       if(game_stopped) return;
+       vector oldballorigin = this.origin;
+
+       if(!MoveToRandomMapLocation(this, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
+       {
+               entity spot = SelectSpawnPoint(this, true);
+               setorigin(this, spot.origin);
+               this.angles = spot.angles;
+       }
+
+       makevectors(this.angles);
+       set_movetype(this, MOVETYPE_BOUNCE);
+       this.velocity = '0 0 200';
+       this.angles = '0 0 0';
+       this.effects = autocvar_g_tkaball_effects;
+       settouch(this, tka_TouchEvent);
+       setthink(this, tka_RespawnBall);
+       this.nextthink = time + autocvar_g_tkaball_respawntime;
+       navigation_dynamicgoal_set(this, NULL);
+
+       Send_Effect(EFFECT_ELECTRO_COMBO, oldballorigin, '0 0 0', 1);
+       Send_Effect(EFFECT_ELECTRO_COMBO, this.origin, '0 0 0', 1);
+
+       WaypointSprite_Spawn(WP_KaBall, 0, 0, this, '0 0 64', NULL, this.team, this, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
+       WaypointSprite_Ping(this.waypointsprite_attachedforcarrier);
+
+       sound(this, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+}
+
+void tka_TimeScoring(entity this)
+{
+       if(this.owner.ballcarried)
+       { // add points for holding the ball after a certain amount of time
+               if(autocvar_g_tka_score_timepoints)
+                       GameRules_scoring_add_team(this.owner, SCORE, autocvar_g_tka_score_timepoints);
+
+               GameRules_scoring_add(this.owner, TKA_BCTIME, (autocvar_g_tka_score_timeinterval / 1)); // interval is divided by 1 so that time always shows "seconds"
+               this.nextthink = time + autocvar_g_tka_score_timeinterval;
+       }
+}
+
+void tka_TouchEvent(entity this, entity toucher) // runs any time that the ball comes in contact with something
+{
+       if (!this || game_stopped)
+               return;
+
+       if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+       { // The ball fell off the map, respawn it since players can't get to it
+               tka_RespawnBall(this);
+               return;
+       }
+       if(IS_DEAD(toucher)) { return; }
+       if(STAT(FROZEN, toucher)) { return; }
+       if (!IS_PLAYER(toucher))
+       {  // The ball just touched an object, most likely the world
+               Send_Effect(EFFECT_BALL_SPARKS, this.origin, '0 0 0', 1);
+               sound(this, CH_TRIGGER, SND_KA_TOUCH, VOL_BASE, ATTEN_NORM);
+               return;
+       }
+       else if(this.wait > time) { return; }
+
+       // attach the ball to the player
+       this.owner = toucher;
+       toucher.ballcarried = this;
+       GameRules_scoring_vip(toucher, true);
+       setattachment(this, toucher, "");
+       setorigin(this, '0 0 0');
+
+       // make the ball invisible/unable to do anything/set up time scoring
+       this.velocity = '0 0 0';
+       set_movetype(this, MOVETYPE_NONE);
+       this.effects |= EF_NODRAW;
+       settouch(this, func_null);
+       setthink(this, tka_TimeScoring);
+       this.nextthink = time + autocvar_g_tka_score_timeinterval;
+       this.takedamage = DAMAGE_NO;
+       navigation_dynamicgoal_unset(this);
+
+       // apply effects to player
+       toucher.glow_color = autocvar_g_tkaball_trail_color;
+       toucher.glow_trail = true;
+       toucher.effects |= autocvar_g_tka_ballcarrier_effects;
+
+       // messages and sounds
+       tka_EventLog("pickup", toucher);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_KEEPAWAY_PICKUP, toucher.netname);
+       Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_CENTER, CENTER_KEEPAWAY_PICKUP, toucher.netname);
+       Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_KEEPAWAY_PICKUP_SELF);
+       sound(this.owner, CH_TRIGGER, SND_KA_PICKEDUP, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+
+       // scoring
+       GameRules_scoring_add(toucher, TKA_PICKUPS, 1);
+
+       // waypoints
+       WaypointSprite_AttachCarrier(WP_Null, toucher, RADARICON_FLAGCARRIER);
+       toucher.waypointsprite_attachedforcarrier.colormod = colormapPaletteColor(toucher.team - 1, 0);
+       toucher.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = tka_ballcarrier_waypointsprite_visible_for_player;
+       WaypointSprite_UpdateRule(toucher.waypointsprite_attachedforcarrier, toucher.team, SPRITERULE_TEAMPLAY);
+       if(toucher.team == NUM_TEAM_1)
+               WaypointSprite_UpdateSprites(toucher.waypointsprite_attachedforcarrier, WP_TkaBallCarrierRed, WP_KaBallCarrier, WP_TkaBallCarrierRed);
+       else if(toucher.team == NUM_TEAM_2)
+               WaypointSprite_UpdateSprites(toucher.waypointsprite_attachedforcarrier, WP_TkaBallCarrierBlue, WP_KaBallCarrier, WP_TkaBallCarrierBlue);
+       else if(toucher.team == NUM_TEAM_3)
+               WaypointSprite_UpdateSprites(toucher.waypointsprite_attachedforcarrier, WP_TkaBallCarrierYellow, WP_KaBallCarrier, WP_TkaBallCarrierYellow);
+       else if(toucher.team == NUM_TEAM_4)
+               WaypointSprite_UpdateSprites(toucher.waypointsprite_attachedforcarrier, WP_TkaBallCarrierPink, WP_KaBallCarrier, WP_TkaBallCarrierPink);
+       WaypointSprite_Ping(toucher.waypointsprite_attachedforcarrier);
+       WaypointSprite_Kill(this.waypointsprite_attachedforcarrier);
+}
+
+void tka_PlayerReset(entity plyr)
+{
+       plyr.ballcarried = NULL;
+       GameRules_scoring_vip(plyr, false);
+       WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
+
+       // reset the player effects
+       plyr.glow_trail = false;
+       plyr.effects &= ~autocvar_g_tka_ballcarrier_effects;
+}
+
+void tka_DropEvent(entity plyr) // runs any time that a player is supposed to lose the ball
+{
+       entity ball;
+       ball = plyr.ballcarried;
+
+       if(!ball) { return; }
+
+       // reset the ball
+       setattachment(ball, NULL, "");
+       set_movetype(ball, MOVETYPE_BOUNCE);
+       ball.wait = time + 1;
+       settouch(ball, tka_TouchEvent);
+       setthink(ball, tka_RespawnBall);
+       ball.nextthink = time + autocvar_g_tkaball_respawntime;
+       ball.takedamage = DAMAGE_YES;
+       ball.effects &= ~EF_NODRAW;
+       setorigin(ball, plyr.origin + '0 0 10');
+       ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
+       ball.owner = NULL;
+       navigation_dynamicgoal_set(ball, plyr);
+
+       // messages and sounds
+       tka_EventLog("dropped", plyr);
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_KEEPAWAY_DROPPED, plyr.netname);
+       Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_KEEPAWAY_DROPPED, plyr.netname);
+       sound(NULL, CH_TRIGGER, SND_KA_DROPPED, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+
+       // waypoints
+       WaypointSprite_Spawn(WP_KaBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
+       WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+       WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
+
+       tka_PlayerReset(plyr);
+}
+
+.bool pushable;
+
+MODEL(TKA_BALL, "models/orbs/orbblue.md3");
+
+void tka_RemoveBall()
+{
+       entity plyr = tka_ball.owner;
+       if (plyr) // it was attached
+               tka_PlayerReset(plyr);
+       else
+               WaypointSprite_DetachCarrier(tka_ball);
+       delete(tka_ball);
+       tka_ball = NULL;
+}
+
+void tka_SpawnBall()
+{
+       entity e = new(keepawayball);
+       setmodel(e, MDL_TKA_BALL);
+       setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
+       e.damageforcescale = autocvar_g_tkaball_damageforcescale;
+       e.takedamage = DAMAGE_YES;
+       e.solid = SOLID_TRIGGER;
+       set_movetype(e, MOVETYPE_BOUNCE);
+       e.glow_color = autocvar_g_tkaball_trail_color;
+       e.glow_trail = true;
+       e.flags = FL_ITEM;
+       IL_PUSH(g_items, e);
+       e.pushable = true;
+       settouch(e, tka_TouchEvent);
+       e.owner = NULL;
+       tka_ball = e;
+       navigation_dynamicgoal_init(tka_ball, false);
+
+       InitializeEntity(e, tka_RespawnBall, INITPRIO_SETLOCATION); // is this the right priority? Neh, I have no idea.. Well-- it works! So.
+}
+
+void tka_Handler_CheckBall(entity this)
+{
+       if(time < game_starttime)
+       {
+               if (tka_ball)
+                       tka_RemoveBall();
+       }
+       else
+       {
+               if (!tka_ball)
+                       tka_SpawnBall();
+       }
+
+       this.nextthink = time;
+}
+
+void tka_DelayedInit(entity this) // run at the start of a match, initiates game mode
+{
+       tka_Handler = new(tka_Handler);
+       setthink(tka_Handler, tka_Handler_CheckBall);
+       tka_Handler.nextthink = time;
+}
+
+
+// ================
+// Bot player logic
+// ================
+
+void havocbot_goalrating_tkaball(entity this, float ratingscale, vector org)
+{
+       entity ball_owner = tka_ball.owner;
+
+       if (ball_owner == this || SAME_TEAM(ball_owner, this)) // TODO: defend ball carrier?
+               return;
+
+       if (ball_owner)
+               navigation_routerating(this, ball_owner, ratingscale, 2000);
+       else
+               navigation_routerating(this, tka_ball, ratingscale, 2000);
+}
+
+void havocbot_role_tka_carrier(entity this)
+{
+       if (IS_DEAD(this))
+               return;
+
+       if (navigation_goalrating_timeout(this))
+       {
+               navigation_goalrating_start(this);
+               havocbot_goalrating_items(this, 10000, this.origin, 10000);
+               havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
+               havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
+               navigation_goalrating_end(this);
+
+               navigation_goalrating_timeout_set(this);
+       }
+
+       if (!this.ballcarried)
+       {
+               this.havocbot_role = havocbot_role_tka_collector;
+               navigation_goalrating_timeout_expire(this, 2);
+       }
+}
+
+void havocbot_role_tka_collector(entity this)
+{
+       if (IS_DEAD(this))
+               return;
+
+       if (navigation_goalrating_timeout(this))
+       {
+               navigation_goalrating_start(this);
+               havocbot_goalrating_items(this, 10000, this.origin, 10000);
+               havocbot_goalrating_enemyplayers(this, 500, this.origin, 10000);
+               havocbot_goalrating_tkaball(this, 8000, this.origin);
+               navigation_goalrating_end(this);
+
+               navigation_goalrating_timeout_set(this);
+       }
+
+       if (this.ballcarried)
+       {
+               this.havocbot_role = havocbot_role_tka_carrier;
+               navigation_goalrating_timeout_expire(this, 2);
+       }
+}
+
+
+// ==============
+// Hook Functions
+// ==============
+
+MUTATOR_HOOKFUNCTION(tka, PlayerDies)
+{
+       entity frag_attacker = M_ARGV(1, entity);
+       entity frag_target = M_ARGV(2, entity);
+
+       if(frag_attacker != frag_target && IS_PLAYER(frag_attacker) && DIFF_TEAM(frag_attacker, frag_target))
+       {
+               if(frag_target.ballcarried) { // add to amount of times killing carrier
+                       GameRules_scoring_add(frag_attacker, TKA_CARRIERKILLS, 1);
+                       if(autocvar_g_tka_score_bckill) // add bckills to the score
+                               GameRules_scoring_add_team(frag_attacker, SCORE, autocvar_g_tka_score_bckill);
+               }
+               else if(!frag_attacker.ballcarried && !(autocvar_g_tka_score_team && SAME_TEAM(tka_ball.owner, frag_attacker)))
+               {
+                       if(autocvar_g_tka_noncarrier_warn)
+                               Send_Notification(NOTIF_ONE_ONLY, frag_attacker, MSG_CENTER, CENTER_KEEPAWAY_WARN);
+               }
+
+               if(frag_attacker.ballcarried || (autocvar_g_tka_score_team && SAME_TEAM(tka_ball.owner, frag_attacker))) // add to amount of kills while ballcarrier (or if team scoring is enabled)
+                       GameRules_scoring_add_team(frag_attacker, SCORE, autocvar_g_tka_score_killac);
+       }
+
+       if(frag_target.ballcarried) { tka_DropEvent(frag_target); } // a player with the ball has died, drop it
+}
+
+MUTATOR_HOOKFUNCTION(tka, GiveFragsForKill)
+{
+       M_ARGV(2, float) = 0; // no frags counted in keepaway
+       return true; // you deceptive little bugger ;3 This needs to be true in order for this function to even count.
+}
+
+MUTATOR_HOOKFUNCTION(tka, Scores_CountFragsRemaining)
+{
+       // announce remaining frags, but only when timed scoring is off
+       return !autocvar_g_tka_score_timepoints;
+}
+
+MUTATOR_HOOKFUNCTION(tka, PlayerPreThink)
+{
+       entity player = M_ARGV(0, entity);
+
+       // clear the item used for the ball in keepaway
+       STAT(TKA_BALLSTATUS, player) &= ~(TKA_BALL_TAKEN_RED | TKA_BALL_TAKEN_BLUE | TKA_BALL_TAKEN_YELLOW | TKA_BALL_TAKEN_PINK | TKA_BALL_CARRYING | TKA_BALL_DROPPED);
+
+       // if the player has the ball, make sure they have the item for it (Used for HUD primarily)
+       if(player.ballcarried)
+               STAT(TKA_BALLSTATUS, player) |= TKA_BALL_CARRYING;
+
+       if(!tka_ball.owner)
+               STAT(TKA_BALLSTATUS, player) |= TKA_BALL_DROPPED;
+       else
+       {
+               // TODO: teamless carrier?
+               switch(tka_ball.owner.team)
+               {
+                       case NUM_TEAM_1: STAT(TKA_BALLSTATUS, player) |= TKA_BALL_TAKEN_RED; break;
+                       case NUM_TEAM_2: STAT(TKA_BALLSTATUS, player) |= TKA_BALL_TAKEN_BLUE; break;
+                       case NUM_TEAM_3: STAT(TKA_BALLSTATUS, player) |= TKA_BALL_TAKEN_YELLOW; break;
+                       case NUM_TEAM_4: STAT(TKA_BALLSTATUS, player) |= TKA_BALL_TAKEN_PINK; break;
+               }
+       }
+}
+
+MUTATOR_HOOKFUNCTION(tka, PlayerUseKey)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(MUTATOR_RETURNVALUE == 0)
+       if(player.ballcarried)
+       {
+               tka_DropEvent(player);
+               return true;
+       }
+}
+
+MUTATOR_HOOKFUNCTION(tka, Damage_Calculate) // for changing damage and force values that are applied to players in g_damage.qc
+{
+       entity frag_attacker = M_ARGV(1, entity);
+       entity frag_target = M_ARGV(2, entity);
+       float frag_damage = M_ARGV(4, float);
+       vector frag_force = M_ARGV(6, vector);
+
+       if(frag_attacker.ballcarried) // if the attacker is a ballcarrier
+       {
+               if(frag_target == frag_attacker) // damage done to yourself
+               {
+                       frag_damage *= autocvar_g_tka_ballcarrier_selfdamage;
+                       frag_force *= autocvar_g_tka_ballcarrier_selfforce;
+               }
+               else // damage done to noncarriers
+               {
+                       frag_damage *= autocvar_g_tka_ballcarrier_damage;
+                       frag_force *= autocvar_g_tka_ballcarrier_force;
+               }
+       }
+       else if (IS_PLAYER(frag_attacker) && !frag_target.ballcarried) // if the target is a noncarrier
+       {
+               if(frag_target == frag_attacker) // damage done to yourself
+               {
+                       frag_damage *= autocvar_g_tka_noncarrier_selfdamage;
+                       frag_force *= autocvar_g_tka_noncarrier_selfforce;
+               }
+               else // damage done to other noncarriers
+               {
+                       frag_damage *= autocvar_g_tka_noncarrier_damage;
+                       frag_force *= autocvar_g_tka_noncarrier_force;
+               }
+       }
+
+       M_ARGV(4, float) = frag_damage;
+       M_ARGV(6, vector) = frag_force;
+}
+
+MUTATOR_HOOKFUNCTION(tka, ClientDisconnect)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(player.ballcarried) { tka_DropEvent(player); } // a player with the ball has left the match, drop it
+}
+
+MUTATOR_HOOKFUNCTION(tka, MakePlayerObserver)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(player.ballcarried) { tka_DropEvent(player); } // a player with the ball has left the match, drop it
+}
+
+MUTATOR_HOOKFUNCTION(tka, PlayerPowerups)
+{
+       entity player = M_ARGV(0, entity);
+
+       // In the future this hook is supposed to allow me to do some extra stuff with waypointsprites and invisibility powerup
+       // So bare with me until I can fix a certain bug with tka_ballcarrier_waypointsprite_visible_for_player()
+
+       player.effects &= ~autocvar_g_tka_ballcarrier_effects;
+
+       if(player.ballcarried)
+               player.effects |= autocvar_g_tka_ballcarrier_effects;
+}
+
+
+MUTATOR_HOOKFUNCTION(tka, PlayerPhysics_UpdateStats)
+{
+       entity player = M_ARGV(0, entity);
+       // these automatically reset, no need to worry
+
+       if(player.ballcarried)
+               STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_tka_ballcarrier_highspeed;
+}
+
+MUTATOR_HOOKFUNCTION(tka, BotShouldAttack)
+{
+       entity bot = M_ARGV(0, entity);
+       entity targ = M_ARGV(1, entity);
+
+       // if neither player has ball then don't attack unless the ball is on the ground
+       if(!targ.ballcarried && !bot.ballcarried && tka_ball.owner && !(autocvar_g_tka_score_team && SAME_TEAM(tka_ball.owner, bot)))
+               return true;
+}
+
+MUTATOR_HOOKFUNCTION(tka, HavocBot_ChooseRole)
+{
+       entity bot = M_ARGV(0, entity);
+
+       if (bot.ballcarried)
+               bot.havocbot_role = havocbot_role_tka_carrier;
+       else
+               bot.havocbot_role = havocbot_role_tka_collector;
+       return true;
+}
+
+MUTATOR_HOOKFUNCTION(tka, DropSpecialItems)
+{
+       entity frag_target = M_ARGV(0, entity);
+
+       if(frag_target.ballcarried)
+               tka_DropEvent(frag_target);
+}
+
+MUTATOR_HOOKFUNCTION(tka, SpectateCopy)
+{
+       entity spectatee = M_ARGV(0, entity);
+       entity client = M_ARGV(1, entity);
+
+       STAT(TKA_BALLSTATUS, client) = STAT(TKA_BALLSTATUS, spectatee);
+}
+
+MUTATOR_HOOKFUNCTION(tka, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+{
+       M_ARGV(0, float) = tka_teams;
+       return true;
+}
diff --git a/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qh b/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qh
new file mode 100644 (file)
index 0000000..7b7236f
--- /dev/null
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <common/mutators/base.qh>
+int autocvar_g_tka_point_limit;
+int autocvar_g_tka_point_leadlimit;
+bool autocvar_g_tka_team_spawns;
+void tka_DelayedInit(entity this);
+
+int tka_teams;
+//int autocvar_g_tka_teams;
+int autocvar_g_tka_teams_override;
+
+REGISTER_MUTATOR(tka, false)
+{
+    MUTATOR_STATIC();
+       MUTATOR_ONADD
+       {
+               GameRules_teams(true);
+        GameRules_spawning_teams(autocvar_g_tka_team_spawns);
+               GameRules_limit_score(autocvar_g_tka_point_limit);
+        GameRules_limit_lead(autocvar_g_tka_point_leadlimit);
+
+        tka_teams = autocvar_g_tka_teams_override;
+        if(tka_teams < 2)
+               tka_teams = cvar("g_tka_teams"); // read the cvar directly as it gets written earlier in the same frame
+        tka_teams = BITS(bound(2, tka_teams, 4));
+           GameRules_scoring(tka_teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {
+            field(SP_TKA_PICKUPS, "pickups", 0);
+            field(SP_TKA_CARRIERKILLS, "bckills", 0);
+            field(SP_TKA_BCTIME, "bctime", SFL_SORT_PRIO_SECONDARY);
+        });
+
+               InitializeEntity(NULL, tka_DelayedInit, INITPRIO_GAMETYPE);
+       }
+       return false;
+}
+
+
+entity tka_ball;
+entity tka_Handler;
+
+void(entity this) havocbot_role_tka_carrier;
+void(entity this) havocbot_role_tka_collector;
+
+void tka_DropEvent(entity plyr);
diff --git a/qcsrc/common/gamemodes/gamemode/tka/tka.qc b/qcsrc/common/gamemodes/gamemode/tka/tka.qc
new file mode 100644 (file)
index 0000000..e0e6033
--- /dev/null
@@ -0,0 +1 @@
+#include "tka.qh"
diff --git a/qcsrc/common/gamemodes/gamemode/tka/tka.qh b/qcsrc/common/gamemodes/gamemode/tka/tka.qh
new file mode 100644 (file)
index 0000000..e8682db
--- /dev/null
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <common/gamemodes/gamemode/deathmatch/deathmatch.qh>
+#include <common/gamemodes/gamemode/keepaway/keepaway.qh>
+#include <common/mapinfo.qh>
+#if defined(CSQC)
+       #include <common/gamemodes/gamemode/tka/cl_tka.qh>
+#endif
+
+CLASS(TeamKeepaway, Gametype)
+    INIT(TeamKeepaway)
+    {
+        this.gametype_init(this, _("Team Keepaway"),"tka","g_tka",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS,"","timelimit=15 pointlimit=50 teams=2 leadlimit=0",_("Keep the ball in your team's possession to get points for kills"));
+    }
+    METHOD(TeamKeepaway, m_parse_mapinfo, bool(string k, string v))
+    {
+        if (!k) {
+            cvar_set("g_tka_teams", cvar_defstring("g_tka_teams"));
+            return true;
+        }
+        switch (k) {
+            case "teams":
+                cvar_set("g_tka_teams", v);
+                return true;
+        }
+        return false;
+    }
+    METHOD(TeamKeepaway, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter))
+    {
+        if(spawnpoints >= 8 && diameter > 4096)
+            return true;
+        return false;
+    }
+    METHOD(TeamKeepaway, m_isForcedSupported, bool(Gametype this))
+    {
+        if(cvar("g_tka_on_dm_maps"))
+        {
+            // if this is set, all DM and KA maps support TKA too
+            if(!(MapInfo_Map_supportedGametypes & this.m_flags) && ((MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH.m_flags) || (MapInfo_Map_supportedGametypes & MAPINFO_TYPE_KEEPAWAY.m_flags)))
+                return true; // TODO: references another gametype (alternatively, we could check which gamemodes are always enabled and append this if any are supported)
+        }
+        return false;
+    }
+    METHOD(TeamKeepaway, m_setTeams, void(string sa))
+    {
+        cvar_set("g_tka_teams", sa);
+    }
+#ifdef CSQC
+    ATTRIB(TeamKeepaway, m_modicons, void(vector pos, vector mySize), HUD_Mod_TeamKeepaway);
+#endif
+ENDCLASS(TeamKeepaway)
+REGISTER_GAMETYPE(TEAMKEEPAWAY, NEW(TeamKeepaway));
+
+const int TKA_BALL_TAKEN_RED                   = 1;
+const int TKA_BALL_TAKEN_BLUE                  = 2;
+const int TKA_BALL_TAKEN_YELLOW                        = 3;
+const int TKA_BALL_TAKEN_PINK                  = 4;
+const int TKA_BALL_CARRYING                            = 8;
+const int TKA_BALL_DROPPED                             = 12;
index daa5af4d51dff6d099a53f1cc13d299c94e899df..a2aad0e438fdfd60bfe6899ed161eb534a845c1b 100644 (file)
@@ -47,6 +47,11 @@ REGISTER_WAYPOINT(KeyCarrierPink, _("Key carrier"), "kh_pink_carrying", '0 1 1',
 
 REGISTER_WAYPOINT(KaBall, _("Ball"), "notify_ballpickedup", '0 1 1', 1);
 REGISTER_WAYPOINT(KaBallCarrier, _("Ball carrier"), "keepawayball_carrying", '1 0 0', 1);
+//LegendGuard adds REGISTER_WAYPOINT from Mario/team_keepaway 15-02-2021
+REGISTER_WAYPOINT(TkaBallCarrierRed, _("Ball carrier"), "tka_taken_red", '0 1 1', 1);
+REGISTER_WAYPOINT(TkaBallCarrierBlue, _("Ball carrier"), "tka_taken_blue", '0 1 1', 1);
+REGISTER_WAYPOINT(TkaBallCarrierYellow, _("Ball carrier"), "tka_taken_yellow", '0 1 1', 1);
+REGISTER_WAYPOINT(TkaBallCarrierPink, _("Ball carrier"), "tka_taken_pink", '0 1 1', 1);
 
 REGISTER_WAYPOINT(NbBall, _("Ball"), "", '0.91 0.85 0.62', 1);
 REGISTER_WAYPOINT(NbGoal, _("Goal"), "", '1 0.5 0', 1);
index 09c6995b6c3db366abe5b3da67730e7d2a10e1a6..64608a0a7ed804379f5900e5c360abf1a4a92bad 100644 (file)
@@ -110,6 +110,10 @@ REGISTER_SP(MEDAL_KILLSTREAK_15);
 
 REGISTER_SP(SV_SURVIVALS); //LegendGuard adds REGISTER_SP from Mario/survival 15-02-2021
 REGISTER_SP(SV_HUNTS);
+
+REGISTER_SP(TKA_PICKUPS); //LegendGuard adds REGISTER_SP from Mario/team_keepaway 15-02-2021
+REGISTER_SP(TKA_BCTIME);
+REGISTER_SP(TKA_CARRIERKILLS);
 #endif
 
 
index 0d17414d0563032104f32629ff22aea2ae90fea9..a38d2d7c96dc898b0c2126776ce1d84faa16f9da 100644 (file)
@@ -160,6 +160,7 @@ REGISTER_STAT(AMMUNITIONING_ORB, float) //LegendGuard registers new STAT 13-02-2
 REGISTER_STAT(AMMUNITIONING_ORB_ALPHA, float)
 REGISTER_STAT(DARK_ORB, float) //LegendGuard registers new STAT 08-02-2021
 REGISTER_STAT(DARK_ORB_ALPHA, float)
+REGISTER_STAT(TKA_BALLSTATUS, int) //LegendGuard adds STAT from Mario/team_keepaway 15-02-2021
 
 #ifdef SVQC
 float autocvar_sv_showfps = 5;
index 3ea53be5e451927bc9bc92a04758e0fb908315dd..67ee965d7d457a9b3dfd6bae1dd5ff6bee63ebf1 100644 (file)
@@ -675,6 +675,7 @@ float updateCompression()
        GAMETYPE(MAPINFO_TYPE_CA) \
        GAMETYPE(MAPINFO_TYPE_FREEZETAG) \
        GAMETYPE(MAPINFO_TYPE_KEEPAWAY) \
+       GAMETYPE(MAPINFO_TYPE_TEAMKEEPAWAY) \
        GAMETYPE(MAPINFO_TYPE_KEYHUNT) \
        GAMETYPE(MAPINFO_TYPE_LMS) \
        GAMETYPE(MAPINFO_TYPE_DOMINATION) \
@@ -685,6 +686,7 @@ float updateCompression()
        /* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
        GAMETYPE(MAPINFO_TYPE_SURVIVAL) \
        //LegendGuard adds GAMETYPE for menu from Mario/survival 15-02-2021
+       //LegendGuard adds GAMETYPE for menu from Mario/team_keepaway 15-02-2021
        /**/
 
 // hidden gametypes come last so indexing always works correctly
index d509eccf89da66807bc104cebd9105e8e8b0afff..f46194fa44c9c344b43c7206fc5ec50b11fa06fc 100644 (file)
@@ -301,6 +301,9 @@ void cvar_changes_init()
                BADCVAR("g_tdm");
                BADCVAR("g_tdm_on_dm_maps");
                BADCVAR("g_tdm_teams");
+               BADCVAR("g_tka");
+               BADCVAR("g_tka_on_dm_maps");
+               BADCVAR("g_tka_teams");
                BADCVAR("g_vip");
                BADCVAR("leadlimit");
                BADCVAR("nextmap");
@@ -310,6 +313,8 @@ void cvar_changes_init()
                BADCVAR("g_mapinfo_ignore_warnings");
                BADCVAR("g_maplist_ignore_sizes");
                BADCVAR("g_maplist_sizes_count_bots");
+               //LegendGuard adds BADCVAR(g_*) from Mario/survival 15-02-2021
+               //LegendGuard adds BADCVAR(g_*) from Mario/team_keepaway 15-02-2021
 
                // long
                BADCVAR("hostname");