From 78fd790dbb8690b148bd9270934b8e918a2fbc00 Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 29 Jan 2013 23:31:43 +1100 Subject: [PATCH] Moving Domination into the mutator API --- qcsrc/server/{ => attic}/domination.qc | 0 qcsrc/server/bot/havocbot/roles.qc | 26 - qcsrc/server/cl_client.qc | 6 - qcsrc/server/g_world.qc | 3 - qcsrc/server/mutators/gamemode_domination.qc | 515 +++++++++++++++++++ qcsrc/server/mutators/gamemode_domination.qh | 23 + qcsrc/server/mutators/mutators.qh | 1 + qcsrc/server/progs.src | 4 +- qcsrc/server/scores_rules.qc | 20 - qcsrc/server/teamplay.qc | 3 +- 10 files changed, 543 insertions(+), 58 deletions(-) rename qcsrc/server/{ => attic}/domination.qc (100%) create mode 100644 qcsrc/server/mutators/gamemode_domination.qc create mode 100644 qcsrc/server/mutators/gamemode_domination.qh diff --git a/qcsrc/server/domination.qc b/qcsrc/server/attic/domination.qc similarity index 100% rename from qcsrc/server/domination.qc rename to qcsrc/server/attic/domination.qc diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc index ad3bb2367..a3078c4e4 100644 --- a/qcsrc/server/bot/havocbot/roles.qc +++ b/qcsrc/server/bot/havocbot/roles.qc @@ -203,25 +203,6 @@ void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradi // choose a role according to the situation void havocbot_role_dm(); -//DOM: -//go to best items, or control points you don't own -void havocbot_role_dom() -{ - if(self.deadflag != DEAD_NO) - return; - - if (self.bot_strategytime < time) - { - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; - navigation_goalrating_start(); - havocbot_goalrating_controlpoints(10000, self.origin, 15000); - havocbot_goalrating_items(8000, self.origin, 8000); - //havocbot_goalrating_enemyplayers(3000, self.origin, 2000); - //havocbot_goalrating_waypoints(1, self.origin, 1000); - navigation_goalrating_end(); - } -} - //DM: //go to best items void havocbot_role_dm() @@ -284,19 +265,12 @@ void havocbot_chooserole_race() self.havocbot_role = havocbot_role_race; } -void havocbot_chooserole_dom() -{ - self.havocbot_role = havocbot_role_dom; -} - void havocbot_chooserole() { dprint("choosing a role...\n"); self.bot_strategytime = 0; if (MUTATOR_CALLHOOK(HavocBot_ChooseRule)) return; - else if (g_domination) - havocbot_chooserole_dom(); else if (g_keyhunt) havocbot_chooserole_kh(); else if (g_race || g_cts) diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 165460eeb..0144fbf32 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -1381,9 +1381,6 @@ void ClientConnect (void) race_PreSpawnObserver(); - //if(g_domination) - // dom_player_join_team(self); - // identify the right forced team if(autocvar_g_campaign) { @@ -1569,9 +1566,6 @@ void ClientConnect (void) else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca send_CSQC_teamnagger(); - if (g_domination) - set_dom_state(self); - CheatInitClient(); if(!autocvar_g_campaign) diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 8d8c0328e..7912b2081 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -669,9 +669,6 @@ void spawnfunc_worldspawn (void) WaypointSprite_Init(); - //if (g_domination) - // dom_init(); - GameLogInit(); // prepare everything // NOTE for matchid: // changing the logic generating it is okay. But: diff --git a/qcsrc/server/mutators/gamemode_domination.qc b/qcsrc/server/mutators/gamemode_domination.qc new file mode 100644 index 000000000..852fb90c0 --- /dev/null +++ b/qcsrc/server/mutators/gamemode_domination.qc @@ -0,0 +1,515 @@ +void dom_EventLog(string mode, float team_before, entity actor) // use an alias for easy changing and quick editing later +{ + if(autocvar_sv_eventlog) + GameLogEcho(strcat(":dom:", mode, ":", ftos(team_before), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : ""))); +} + +void set_dom_state(entity e) +{ + e.dom_total_pps = total_pps; + e.dom_pps_red = pps_red; + e.dom_pps_blue = pps_blue; + if(c3 >= 0) + e.dom_pps_yellow = pps_yellow; + if(c4 >= 0) + e.dom_pps_pink = pps_pink; +} + +void dompoint_captured () +{ + entity head; + float old_delay, old_team, real_team; + + // now that the delay has expired, switch to the latest team to lay claim to this point + head = self.owner; + + real_team = self.cnt; + self.cnt = -1; + + dom_EventLog("taken", self.team, self.dmg_inflictor); + self.dmg_inflictor = world; + + self.goalentity = head; + self.model = head.mdl; + self.modelindex = head.dmg; + self.skin = head.skin; + + float points, wait_time; + if (autocvar_g_domination_point_amt) + points = autocvar_g_domination_point_amt; + else + points = self.frags; + if (autocvar_g_domination_point_rate) + wait_time = autocvar_g_domination_point_rate; + else + wait_time = self.wait; + + bprint("^3", head.netname, "^3", self.message); + if (points != 1) + bprint(" ^7(", ftos(points), " points every ", ftos(wait_time), " seconds)\n"); + else + bprint(" ^7(", ftos(points), " point every ", ftos(wait_time), " seconds)\n"); + + if(self.enemy.playerid == self.enemy_playerid) + PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1); + else + self.enemy = world; + + if (head.noise != "") + if(self.enemy) + sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM); + else + sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM); + if (head.noise1 != "") + play2all(head.noise1); + + self.delay = time + wait_time; + + // do trigger work + old_delay = self.delay; + old_team = self.team; + self.team = real_team; + self.delay = 0; + activator = self; + SUB_UseTargets (); + self.delay = old_delay; + self.team = old_team; + + switch(self.goalentity.team) + { + case COLOR_TEAM1: + WaypointSprite_UpdateSprites(self.sprite, "dom-red", "", ""); + break; + case COLOR_TEAM2: + WaypointSprite_UpdateSprites(self.sprite, "dom-blue", "", ""); + break; + case COLOR_TEAM3: + WaypointSprite_UpdateSprites(self.sprite, "dom-yellow", "", ""); + break; + case COLOR_TEAM4: + WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", ""); + } + + total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0; + for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; ) + { + if (autocvar_g_domination_point_amt) + points = autocvar_g_domination_point_amt; + else + points = head.frags; + if (autocvar_g_domination_point_rate) + wait_time = autocvar_g_domination_point_rate; + else + wait_time = head.wait; + switch(head.goalentity.team) + { + case COLOR_TEAM1: + pps_red += points/wait_time; + break; + case COLOR_TEAM2: + pps_blue += points/wait_time; + break; + case COLOR_TEAM3: + pps_yellow += points/wait_time; + break; + case COLOR_TEAM4: + pps_pink += points/wait_time; + } + total_pps += points/wait_time; + } + + WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0)); + WaypointSprite_Ping(self.sprite); + + self.captime = time; + + FOR_EACH_REALCLIENT(head) + set_dom_state(head); +} + +void AnimateDomPoint() +{ + if(self.pain_finished > time) + return; + self.pain_finished = time + self.t_width; + if(self.nextthink > self.pain_finished) + self.nextthink = self.pain_finished; + + self.frame = self.frame + 1; + if(self.frame > self.t_length) + self.frame = 0; +} + +void dompointthink() +{ + float fragamt; + + self.nextthink = time + 0.1; + + //self.frame = self.frame + 1; + //if(self.frame > 119) + // self.frame = 0; + AnimateDomPoint(); + + // give points + + if (gameover || self.delay > time || time < game_starttime) // game has ended, don't keep giving points + return; + + if(autocvar_g_domination_point_rate) + self.delay = time + autocvar_g_domination_point_rate; + else + self.delay = time + self.wait; + + // give credit to the team + // NOTE: this defaults to 0 + if (self.goalentity.netname != "") + { + if(autocvar_g_domination_point_amt) + fragamt = autocvar_g_domination_point_amt; + else + fragamt = self.frags; + TeamScore_AddToTeam(self.goalentity.team, ST_SCORE, fragamt); + TeamScore_AddToTeam(self.goalentity.team, ST_DOM_TICKS, fragamt); + + // give credit to the individual player, if he is still there + if (self.enemy.playerid == self.enemy_playerid) + { + PlayerScore_Add(self.enemy, SP_SCORE, fragamt); + PlayerScore_Add(self.enemy, SP_DOM_TICKS, fragamt); + } + else + self.enemy = world; + } +} + +void dompointtouch() +{ + entity head; + if (other.classname != "player") + return; + if (other.health < 1) + return; + + if(time < self.captime + 0.3) + return; + + // only valid teams can claim it + head = find(world, classname, "dom_team"); + while (head && head.team != other.team) + head = find(head, classname, "dom_team"); + if (!head || head.netname == "" || head == self.goalentity) + return; + + // delay capture + + self.team = self.goalentity.team; // this stores the PREVIOUS team! + + self.cnt = other.team; + self.owner = head; // team to switch to after the delay + self.dmg_inflictor = other; + + // self.state = 1; + // self.delay = time + cvar("g_domination_point_capturetime"); + //self.nextthink = time + cvar("g_domination_point_capturetime"); + //self.think = dompoint_captured; + + // go to neutral team in the mean time + head = find(world, classname, "dom_team"); + while (head && head.netname != "") + head = find(head, classname, "dom_team"); + if(head == world) + return; + + WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", ""); + WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1'); + WaypointSprite_Ping(self.sprite); + + self.goalentity = head; + self.model = head.mdl; + self.modelindex = head.dmg; + self.skin = head.skin; + + self.enemy = other; // individual player scoring + self.enemy_playerid = other.playerid; + dompoint_captured(); +} + +void dom_controlpoint_setup() +{ + entity head; + // find the spawnfunc_dom_team representing unclaimed points + head = find(world, classname, "dom_team"); + while(head && head.netname != "") + head = find(head, classname, "dom_team"); + if (!head) + objerror("no spawnfunc_dom_team with netname \"\" found\n"); + + // copy important properties from spawnfunc_dom_team entity + self.goalentity = head; + setmodel(self, head.mdl); // precision already set + self.skin = head.skin; + + self.cnt = -1; + + if(self.message == "") + self.message = " has captured a control point"; + + if(self.frags <= 0) + self.frags = 1; + if(self.wait <= 0) + self.wait = 5; + + float points, waittime; + if (autocvar_g_domination_point_amt) + points = autocvar_g_domination_point_amt; + else + points = self.frags; + if (autocvar_g_domination_point_rate) + waittime = autocvar_g_domination_point_rate; + else + waittime = self.wait; + + total_pps += points/waittime; + + if(!self.t_width) + self.t_width = 0.02; // frame animation rate + if(!self.t_length) + self.t_length = 239; // maximum frame + + self.think = dompointthink; + self.nextthink = time; + self.touch = dompointtouch; + self.solid = SOLID_TRIGGER; + self.flags = FL_ITEM; + setsize(self, '-32 -32 -32', '32 32 32'); + setorigin(self, self.origin + '0 0 20'); + droptofloor(); + + waypoint_spawnforitem(self); + WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1'); +} + +//go to best items, or control points you don't own +void havocbot_role_dom() +{ + if(self.deadflag != DEAD_NO) + return; + + if (self.bot_strategytime < time) + { + self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_start(); + havocbot_goalrating_controlpoints(10000, self.origin, 15000); + havocbot_goalrating_items(8000, self.origin, 8000); + //havocbot_goalrating_enemyplayers(3000, self.origin, 2000); + //havocbot_goalrating_waypoints(1, self.origin, 1000); + navigation_goalrating_end(); + } +} + +MUTATOR_HOOKFUNCTION(dom_ClientConnect) +{ + set_dom_state(self); + return FALSE; +} + +MUTATOR_HOOKFUNCTION(dom_BotRoles) +{ + self.havocbot_role = havocbot_role_dom; + return TRUE; +} + +/*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32) +Control point for Domination gameplay. +*/ +void spawnfunc_dom_controlpoint() +{ + if(!g_domination) + { + remove(self); + return; + } + self.think = dom_controlpoint_setup; + self.nextthink = time + 0.1; + self.reset = dom_controlpoint_setup; + + if(!self.scale) + self.scale = 0.6; + + self.effects = self.effects | EF_LOWPRECISION; + if (autocvar_g_domination_point_fullbright) + self.effects |= EF_FULLBRIGHT; +} + +/*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32) +Team declaration for Domination gameplay, this allows you to decide what team +names and control point models are used in your map. + +Note: If you use spawnfunc_dom_team entities you must define at least 3 and only two +can have netname set! The nameless team owns all control points at start. + +Keys: +"netname" + Name of the team (for example Red Team, Blue Team, Green Team, Yellow Team, Life, Death, etc) +"cnt" + Scoreboard color of the team (for example 4 is red and 13 is blue) +"model" + Model to use for control points owned by this team (for example + "progs/b_g_key.mdl" is a gold keycard, and "progs/b_s_key.mdl" is a silver + keycard) +"skin" + Skin of the model to use (for team skins on a single model) +"noise" + Sound to play when this team captures a point. + (this is a localized sound, like a small alarm or other effect) +"noise1" + Narrator speech to play when this team captures a point. + (this is a global sound, like "Red team has captured a control point") +*/ + +void spawnfunc_dom_team() +{ + if(!g_domination || autocvar_g_domination_teams_override >= 2) + { + remove(self); + return; + } + precache_model(self.model); + if (self.noise != "") + precache_sound(self.noise); + if (self.noise1 != "") + precache_sound(self.noise1); + self.classname = "dom_team"; + setmodel(self, self.model); // precision not needed + self.mdl = self.model; + self.dmg = self.modelindex; + self.model = ""; + self.modelindex = 0; + // this would have to be changed if used in quakeworld + if(self.cnt) + self.team = self.cnt + 1; // WHY are these different anyway? +} + +// scoreboard setup +void ScoreRules_dom() +{ + float sp_domticks, sp_score; + sp_score = sp_domticks = 0; + if(autocvar_g_domination_disable_frags) + sp_domticks = SFL_SORT_PRIO_PRIMARY; + else + sp_score = SFL_SORT_PRIO_PRIMARY; + CheckAllowedTeams(world); + ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), sp_score, sp_score, TRUE); + ScoreInfo_SetLabel_TeamScore (ST_DOM_TICKS, "ticks", sp_domticks); + ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS, "ticks", sp_domticks); + ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES, "takes", 0); + ScoreRules_basics_end(); +} + +// code from here on is just to support maps that don't have control point and team entities +void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage) +{ + entity oldself; + oldself = self; + self = spawn(); + self.classname = "dom_team"; + self.netname = teamname; + self.cnt = teamcolor; + self.model = pointmodel; + self.skin = pointskin; + self.noise = capsound; + self.noise1 = capnarration; + self.message = capmessage; + + // this code is identical to spawnfunc_dom_team + setmodel(self, self.model); // precision not needed + self.mdl = self.model; + self.dmg = self.modelindex; + self.model = ""; + self.modelindex = 0; + // this would have to be changed if used in quakeworld + self.team = self.cnt + 1; + + //eprint(self); + self = oldself; +} + +void dom_spawnpoint(vector org) +{ + entity oldself; + oldself = self; + self = spawn(); + self.classname = "dom_controlpoint"; + self.think = spawnfunc_dom_controlpoint; + self.nextthink = time; + setorigin(self, org); + spawnfunc_dom_controlpoint(); + self = oldself; +} + +// spawn some default teams if the map is not set up for domination +void dom_spawnteams() +{ + float numteams = ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override); + + dom_spawnteam("Red", COLOR_TEAM1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point"); + dom_spawnteam("Blue", COLOR_TEAM2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point"); + if(numteams > 2) + dom_spawnteam("Yellow", COLOR_TEAM3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point"); + if(numteams > 3) + dom_spawnteam("Pink", COLOR_TEAM4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point"); + dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", ""); +} + +void dom_DelayedInit() // Do this check with a delay so we can wait for teams to be set up. +{ + // if no teams are found, spawn defaults + if(find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2) + { + print("No ""dom_team"" entities found on this map, creating them anyway.\n"); + dom_spawnteams(); + } + + ScoreRules_dom(); +} + +void dom_Initialize() +{ + precache_model("models/domination/dom_red.md3"); + precache_model("models/domination/dom_blue.md3"); + precache_model("models/domination/dom_yellow.md3"); + precache_model("models/domination/dom_pink.md3"); + precache_model("models/domination/dom_unclaimed.md3"); + precache_sound("domination/claim.wav"); + + addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps); + addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red); + addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue); + if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow); + if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink); + + InitializeEntity(world, dom_DelayedInit, INITPRIO_GAMETYPE); +} + + +MUTATOR_DEFINITION(gamemode_domination) +{ + MUTATOR_HOOK(ClientConnect, dom_ClientConnect, CBC_ORDER_ANY); + MUTATOR_HOOK(HavocBot_ChooseRule, dom_BotRoles, CBC_ORDER_ANY); + + MUTATOR_ONADD + { + if(time > 1) // game loads at time 1 + error("This is a game type and it cannot be added at runtime."); + dom_Initialize(); + } + + MUTATOR_ONREMOVE + { + error("This is a game type and it cannot be removed at runtime."); + } + + return 0; +} diff --git a/qcsrc/server/mutators/gamemode_domination.qh b/qcsrc/server/mutators/gamemode_domination.qh new file mode 100644 index 000000000..a7d18530c --- /dev/null +++ b/qcsrc/server/mutators/gamemode_domination.qh @@ -0,0 +1,23 @@ +// these are needed since mutators are compiled last + +// score rule declarations +#define ST_DOM_TICKS 1 +#define SP_DOM_TICKS 4 +#define SP_DOM_TAKES 5 + +// pps: points per second +.float dom_total_pps; +.float dom_pps_red; +.float dom_pps_blue; +.float dom_pps_yellow; +.float dom_pps_pink; +float total_pps; +float pps_red; +float pps_blue; +float pps_yellow; +float pps_pink; + +// capture declarations +.float enemy_playerid; +.entity sprite; +.float captime; \ No newline at end of file diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh index 2ac6094d3..f6327a163 100644 --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@ -4,6 +4,7 @@ MUTATOR_DECLARATION(gamemode_keepaway); MUTATOR_DECLARATION(gamemode_ctf); MUTATOR_DECLARATION(gamemode_nexball); MUTATOR_DECLARATION(gamemode_onslaught); +MUTATOR_DECLARATION(gamemode_domination); MUTATOR_DECLARATION(mutator_dodging); MUTATOR_DECLARATION(mutator_invincibleprojectiles); diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 028519372..d04d5ac70 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -30,6 +30,7 @@ defs.qh // Should rename this, it has fields and globals mutators/base.qh mutators/mutators.qh mutators/gamemode_ctf.qh +mutators/gamemode_domination.qh mutators/gamemode_keyhunt.qh // TODO fix this mutators/gamemode_keepaway.qh mutators/gamemode_nexball.qh @@ -141,7 +142,7 @@ t_plats.qc antilag.qc //ctf.qc -domination.qc +//domination.qc //mode_onslaught.qc //nexball.qc g_hook.qc @@ -208,6 +209,7 @@ playerstats.qc mutators/base.qc mutators/gamemode_ctf.qc +mutators/gamemode_domination.qc mutators/gamemode_freezetag.qc mutators/gamemode_keyhunt.qc mutators/gamemode_keepaway.qc diff --git a/qcsrc/server/scores_rules.qc b/qcsrc/server/scores_rules.qc index c4021fc39..ebf133688 100644 --- a/qcsrc/server/scores_rules.qc +++ b/qcsrc/server/scores_rules.qc @@ -44,26 +44,6 @@ void ScoreRules_generic() ScoreRules_basics_end(); } -// g_domination -#define ST_DOM_TICKS 1 -#define SP_DOM_TICKS 4 -#define SP_DOM_TAKES 5 -void ScoreRules_dom() -{ - float sp_domticks, sp_score; - sp_score = sp_domticks = 0; - if(autocvar_g_domination_disable_frags) - sp_domticks = SFL_SORT_PRIO_PRIMARY; - else - sp_score = SFL_SORT_PRIO_PRIMARY; - CheckAllowedTeams(world); - ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), sp_score, sp_score, TRUE); - ScoreInfo_SetLabel_TeamScore (ST_DOM_TICKS, "ticks", sp_domticks); - ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS, "ticks", sp_domticks); - ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES, "takes", 0); - ScoreRules_basics_end(); -} - // LMS stuff #define SP_LMS_LIVES 4 #define SP_LMS_RANK 5 diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index b8f2f3ac8..1ed2f533b 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -52,7 +52,6 @@ string TeamNoName(float t) return "Neutral Team"; } -void dom_init(); void runematch_init(); void tdm_init(); void entcs_init(); @@ -134,7 +133,7 @@ void InitGameplayMode() ActivateTeamplay(); fraglimit_override = autocvar_g_domination_point_limit; leadlimit_override = autocvar_g_domination_point_leadlimit; - dom_init(); + MUTATOR_ADD(gamemode_domination); have_team_spawns = -1; // request team spawns } -- 2.39.2