]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator/gamemode_domination.qc
GameRules: encapsulate scoring
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator / gamemode_domination.qc
index 6bbbaee999abca13352a492bcbeae66168dd09aa..be38553c9588bcd4ba1bfd79042432f79aebd583 100644 (file)
@@ -1,70 +1,4 @@
 #include "gamemode_domination.qh"
-#ifndef GAMEMODE_DOMINATION_H
-#define GAMEMODE_DOMINATION_H
-
-#define autocvar_g_domination_point_limit cvar("g_domination_point_limit")
-bool autocvar_g_domination_roundbased;
-int autocvar_g_domination_roundbased_point_limit;
-int autocvar_g_domination_point_leadlimit;
-
-void dom_Initialize();
-
-REGISTER_MUTATOR(dom, false)
-{
-       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();
-
-               int fraglimit_override = autocvar_g_domination_point_limit;
-               if (autocvar_g_domination_roundbased && autocvar_g_domination_roundbased_point_limit)
-                       fraglimit_override = autocvar_g_domination_roundbased_point_limit;
-
-               ActivateTeamplay();
-               SetLimits(fraglimit_override, autocvar_g_domination_point_leadlimit, autocvar_timelimit_override, -1);
-               have_team_spawns = -1; // request team spawns
-       }
-
-       MUTATOR_ONREMOVE
-       {
-               LOG_INFO("This is a game type and it cannot be removed at runtime.");
-               return -1;
-       }
-
-       return 0;
-}
-
-// score rule declarations
-const float ST_DOM_TICKS = 1;
-const float SP_DOM_TICKS = 4;
-const float SP_DOM_TAKES = 5;
-const float ST_DOM_CAPS = 1;
-const float SP_DOM_CAPS = 4;
-
-// pps: points per second
-.float dom_total_pps = _STAT(DOM_TOTAL_PPS);
-.float dom_pps_red = _STAT(DOM_PPS_RED);
-.float dom_pps_blue = _STAT(DOM_PPS_BLUE);
-.float dom_pps_yellow = _STAT(DOM_PPS_YELLOW);
-.float dom_pps_pink = _STAT(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;
-
-// misc globals
-float domination_roundbased;
-float domination_teams;
-#endif
-
-#ifdef IMPLEMENTATION
 
 #include <server/teamplay.qh>
 
@@ -130,7 +64,7 @@ void dompoint_captured(entity this)
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_DOMINATION_CAPTURE_TIME, head.netname, this.message, points, wait_time);
 
        if(this.enemy.playerid == this.enemy_playerid)
-               PlayerScore_Add(this.enemy, SP_DOM_TAKES, 1);
+               GameRules_scoring_add(this.enemy, DOM_TAKES, 1);
        else
                this.enemy = NULL;
 
@@ -165,7 +99,8 @@ void dompoint_captured(entity this)
        WaypointSprite_UpdateSprites(this.sprite, msg, WP_Null, WP_Null);
 
        total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
-       FOREACH_ENTITY_CLASS("dom_controlpoint", true, LAMBDA(
+       IL_EACH(g_dompoints, true,
+       {
                if (autocvar_g_domination_point_amt)
                        points = autocvar_g_domination_point_amt;
                else
@@ -182,14 +117,14 @@ void dompoint_captured(entity this)
                        case NUM_TEAM_4: pps_pink += points/wait_time; break;
                }
                total_pps += points/wait_time;
-       ));
+       });
 
        WaypointSprite_UpdateTeamRadar(this.sprite, RADARICON_DOMPOINT, colormapPaletteColor(this.goalentity.team - 1, 0));
        WaypointSprite_Ping(this.sprite);
 
        this.captime = time;
 
-       FOREACH_CLIENT(IS_REAL_CLIENT(it), LAMBDA(set_dom_state(it)));
+       FOREACH_CLIENT(IS_REAL_CLIENT(it), { set_dom_state(it); });
 }
 
 void AnimateDomPoint(entity this)
@@ -218,7 +153,7 @@ void dompointthink(entity this)
 
        // give points
 
-       if (gameover || this.delay > time || time < game_starttime)     // game has ended, don't keep giving points
+       if (game_stopped || this.delay > time || time < game_starttime) // game has ended, don't keep giving points
                return;
 
        if(autocvar_g_domination_point_rate)
@@ -241,19 +176,19 @@ void dompointthink(entity this)
                // give credit to the individual player, if he is still there
                if (this.enemy.playerid == this.enemy_playerid)
                {
-                       PlayerScore_Add(this.enemy, SP_SCORE, fragamt);
-                       PlayerScore_Add(this.enemy, SP_DOM_TICKS, fragamt);
+                       GameRules_scoring_add(this.enemy, SCORE, fragamt);
+                       GameRules_scoring_add(this.enemy, DOM_TICKS, fragamt);
                }
                else
                        this.enemy = NULL;
        }
 }
 
-void dompointtouch(entity this)
+void dompointtouch(entity this, entity toucher)
 {
-       if (!IS_PLAYER(other))
+       if (!IS_PLAYER(toucher))
                return;
-       if (other.health < 1)
+       if (toucher.health < 1)
                return;
 
        if(round_handler_IsActive() && !round_handler_IsRoundStarted())
@@ -264,7 +199,7 @@ void dompointtouch(entity this)
 
        // only valid teams can claim it
        entity head = find(NULL, classname, "dom_team");
-       while (head && head.team != other.team)
+       while (head && head.team != toucher.team)
                head = find(head, classname, "dom_team");
        if (!head || head.netname == "" || head == this.goalentity)
                return;
@@ -273,9 +208,9 @@ void dompointtouch(entity this)
 
        this.team = this.goalentity.team; // this stores the PREVIOUS team!
 
-       this.cnt = other.team;
+       this.cnt = toucher.team;
        this.owner = head; // team to switch to after the delay
-       this.dmg_inflictor = other;
+       this.dmg_inflictor = toucher;
 
        // this.state = 1;
        // this.delay = time + cvar("g_domination_point_capturetime");
@@ -298,8 +233,8 @@ void dompointtouch(entity this)
        this.modelindex = head.dmg;
        this.skin = head.skin;
 
-       this.enemy = other; // individual player scoring
-       this.enemy_playerid = other.playerid;
+       this.enemy = toucher; // individual player scoring
+       this.enemy_playerid = toucher.playerid;
        dompoint_captured(this);
 }
 
@@ -349,6 +284,8 @@ void dom_controlpoint_setup(entity this)
        this.nextthink = time;
        settouch(this, dompointtouch);
        this.solid = SOLID_TRIGGER;
+       if(!this.flags & FL_ITEM)
+               IL_PUSH(g_items, this);
        this.flags = FL_ITEM;
        setsize(this, '-32 -32 -32', '32 32 32');
        setorigin(this, this.origin + '0 0 20');
@@ -362,7 +299,7 @@ float total_controlpoints;
 void Domination_count_controlpoints()
 {
        total_controlpoints = redowned = blueowned = yellowowned = pinkowned = 0;
-       FOREACH_ENTITY_CLASS("dom_controlpoint", true,
+       IL_EACH(g_dompoints, true,
        {
                ++total_controlpoints;
                redowned += (it.goalentity.team == NUM_TEAM_1);
@@ -405,6 +342,8 @@ float Domination_CheckWinner()
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER);
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER);
+
+               game_stopped = true;
                round_handler_Init(5, autocvar_g_domination_warmup, autocvar_g_domination_round_timelimit);
                return 1;
        }
@@ -428,6 +367,7 @@ float Domination_CheckWinner()
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED);
        }
 
+       game_stopped = true;
        round_handler_Init(5, autocvar_g_domination_warmup, autocvar_g_domination_round_timelimit);
 
        return 1;
@@ -440,10 +380,23 @@ float Domination_CheckPlayers()
 
 void Domination_RoundStart()
 {
-       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(it.player_blocked = false));
+       FOREACH_CLIENT(IS_PLAYER(it), { it.player_blocked = false; });
 }
 
 //go to best items, or control points you don't own
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius)
+{
+       IL_EACH(g_dompoints, vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius),
+       {
+               if(it.cnt > -1) // this is just being fought
+                       navigation_routerating(this, it, ratingscale, 5000);
+               else if(it.goalentity.cnt == 0) // unclaimed
+                       navigation_routerating(this, it, ratingscale * 0.5, 5000);
+               else if(it.goalentity.team != this.team) // other team's point
+                       navigation_routerating(this, it, ratingscale * 0.2, 5000);
+       });
+}
+
 void havocbot_role_dom(entity this)
 {
        if(IS_DEAD(this))
@@ -456,12 +409,12 @@ void havocbot_role_dom(entity this)
                havocbot_goalrating_controlpoints(this, 10000, this.origin, 15000);
                havocbot_goalrating_items(this, 8000, this.origin, 8000);
                //havocbot_goalrating_enemyplayers(this, 3000, this.origin, 2000);
-               //havocbot_goalrating_waypoints(1, this.origin, 1000);
+               havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
                navigation_goalrating_end(this);
        }
 }
 
-MUTATOR_HOOKFUNCTION(dom, GetTeamCount)
+MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams)
 {
        // fallback?
        M_ARGV(0, float) = domination_teams;
@@ -492,13 +445,13 @@ MUTATOR_HOOKFUNCTION(dom, GetTeamCount)
 MUTATOR_HOOKFUNCTION(dom, reset_map_players)
 {
        total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
-       FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
+       FOREACH_CLIENT(IS_PLAYER(it), {
                PutClientInServer(it);
                if(domination_roundbased)
                        it.player_blocked = 1;
                if(IS_REAL_CLIENT(it))
                        set_dom_state(it);
-       ));
+       });
        return true;
 }
 
@@ -535,7 +488,7 @@ spawnfunc(dom_controlpoint)
 {
        if(!g_domination)
        {
-               remove(this);
+               delete(this);
                return;
        }
        setthink(this, dom_controlpoint_setup);
@@ -548,6 +501,8 @@ spawnfunc(dom_controlpoint)
        this.effects = this.effects | EF_LOWPRECISION;
        if (autocvar_g_domination_point_fullbright)
                this.effects |= EF_FULLBRIGHT;
+
+       IL_PUSH(g_dompoints, this);
 }
 
 /*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
@@ -580,7 +535,7 @@ spawnfunc(dom_team)
 {
        if(!g_domination || autocvar_g_domination_teams_override >= 2)
        {
-               remove(this);
+               delete(this);
                return;
        }
        precache_model(this.model);
@@ -600,14 +555,14 @@ spawnfunc(dom_team)
 }
 
 // scoreboard setup
-void ScoreRules_dom(float teams)
+void ScoreRules_dom(int teams)
 {
        if(domination_roundbased)
        {
-               ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, 0, true);
-               ScoreInfo_SetLabel_TeamScore  (ST_DOM_CAPS, "caps", SFL_SORT_PRIO_PRIMARY);
-               ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES, "takes", 0);
-               ScoreRules_basics_end();
+           GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, 0, {
+            field_team(ST_DOM_CAPS, "caps", SFL_SORT_PRIO_PRIMARY);
+            field(SP_DOM_TAKES, "takes", 0);
+           });
        }
        else
        {
@@ -617,11 +572,11 @@ void ScoreRules_dom(float teams)
                        sp_domticks = SFL_SORT_PRIO_PRIMARY;
                else
                        sp_score = SFL_SORT_PRIO_PRIMARY;
-               ScoreRules_basics(teams, 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();
+               GameRules_scoring(teams, sp_score, sp_score, {
+            field_team(ST_DOM_TICKS, "ticks", sp_domticks);
+            field(SP_DOM_TICKS, "ticks", sp_domticks);
+            field(SP_DOM_TAKES, "takes", 0);
+               });
        }
 }
 
@@ -678,13 +633,23 @@ void dom_DelayedInit(entity this) // Do this check with a delay so we can wait f
        // if no teams are found, spawn defaults
        if(find(NULL, classname, "dom_team") == NULL || autocvar_g_domination_teams_override >= 2)
        {
-               LOG_TRACE("No \"dom_team\" entities found on this map, creating them anyway.\n");
-               domination_teams = bound(2, ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override), 4);
+               LOG_TRACE("No \"dom_team\" entities found on this map, creating them anyway.");
+               domination_teams = autocvar_g_domination_teams_override;
+               if (domination_teams < 2)
+                       domination_teams = autocvar_g_domination_default_teams;
+               domination_teams = bound(2, domination_teams, 4);
                dom_spawnteams(domination_teams);
        }
 
        CheckAllowedTeams(NULL);
-       domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
+       //domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
+
+       int teams = 0;
+       if(c1 >= 0) teams |= BIT(0);
+       if(c2 >= 0) teams |= BIT(1);
+       if(c3 >= 0) teams |= BIT(2);
+       if(c4 >= 0) teams |= BIT(3);
+       domination_teams = teams;
 
        domination_roundbased = autocvar_g_domination_roundbased;
 
@@ -702,5 +667,3 @@ void dom_Initialize()
        g_domination = true;
        InitializeEntity(NULL, dom_DelayedInit, INITPRIO_GAMETYPE);
 }
-
-#endif