From: Mario Date: Sun, 22 Dec 2013 21:24:59 +0000 (+1100) Subject: Round-based domination X-Git-Tag: xonotic-v0.8.0~160^2~4 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=03395aaac54532968ff57b985a1f9cf12473b1b0;p=xonotic%2Fxonotic-data.pk3dir.git Round-based domination --- diff --git a/gamemodes.cfg b/gamemodes.cfg index feed7488b..e20ba928d 100644 --- a/gamemodes.cfg +++ b/gamemodes.cfg @@ -247,6 +247,10 @@ set g_domination_point_fullbright 0 "domination point fullbright" set g_domination_point_rate 0 "override: how often to give those points" set g_domination_point_capturetime 0.1 "how long it takes to capture a point (given no interference)" set g_domination_point_glow 0 "domination point glow (warning, slow)" +set g_domination_roundbased 0 "enable round-based domination (capture all control points to win the round)" +set g_domination_roundbased_point_limit 5 "capture limit in round-based domination mode" +set g_domination_round_timelimit 120 +set g_domination_warmup 5 //set g_domination_balance_team_points 1 "# of points received is based on team sizes" diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 55d16953f..e539dfe8c 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -194,11 +194,11 @@ const float STAT_FROZEN = 104; const float STAT_REVIVE_PROGRESS = 105; // domination -const float STAT_DOM_TOTAL_PPS = 100; -const float STAT_DOM_PPS_RED = 101; -const float STAT_DOM_PPS_BLUE = 102; +const float STAT_DOM_TOTAL_PPS = 99; +const float STAT_DOM_PPS_RED = 100; +const float STAT_DOM_PPS_BLUE = 101; +const float STAT_DOM_PPS_YELLOW = 102; const float STAT_DOM_PPS_PINK = 103; -const float STAT_DOM_PPS_YELLOW = 104; //const float STAT_SPIDERBOT_AIM 53 // compressShotOrigin //const float STAT_SPIDERBOT_TARGET 54 // compressShotOrigin diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh index 6c602219b..781fa92ed 100644 --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@ -418,6 +418,8 @@ void Send_Notification_WOCOVA( MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VOID, 2, 1, "s1 s2loc spree_lost", "s1", "notify_void", _("^BG%s^K1 was in the wrong place%s%s"), "") \ MULTITEAM_INFO(1, INFO_DEATH_TEAMKILL_, 4, 3, 1, "s1 s2 s3loc spree_end", "s2 s1", "notify_teamkill_%s", _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DOMINATION_CAPTURE, 2, 0, "s1 s2", "", "", _("^BG%s^BG%s"), "") \ + MSG_INFO_NOTIF(1, INFO_DOMINATION_CAPTURE_TIME, 2, 2, "s1 s2 f1 f2", "", "", _("^BG%s^BG%s^BG (%s points every %s seconds)"), "") \ MSG_INFO_NOTIF(1, INFO_FREEZETAG_FREEZE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was frozen by ^BG%s"), "") \ MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED, 2, 0, "s1 s2", "", "", _("^BG%s^K3 was revived by ^BG%s"), "") \ MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED_FALL, 1, 0, "s1", "", "", _("^BG%s^K3 was revived by falling"), "") \ diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 19187a39d..b49cc14c6 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -797,6 +797,10 @@ float autocvar_g_domination_disable_frags; float autocvar_g_domination_point_amt; float autocvar_g_domination_point_fullbright; float autocvar_g_domination_point_leadlimit; +float autocvar_g_domination_roundbased; +float autocvar_g_domination_roundbased_point_limit; +float autocvar_g_domination_round_timelimit; +float autocvar_g_domination_warmup; #define autocvar_g_domination_point_limit cvar("g_domination_point_limit") float autocvar_g_domination_point_rate; float autocvar_g_domination_teams_override; diff --git a/qcsrc/server/mutators/gamemode_domination.qc b/qcsrc/server/mutators/gamemode_domination.qc index 89e6fe485..8ea089eaa 100644 --- a/qcsrc/server/mutators/gamemode_domination.qc +++ b/qcsrc/server/mutators/gamemode_domination.qc @@ -9,9 +9,9 @@ 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) + if(domination_teams >= 3) e.dom_pps_yellow = pps_yellow; - if(c4 >= 0) + if(domination_teams >= 4) e.dom_pps_pink = pps_pink; } @@ -45,11 +45,10 @@ void dompoint_captured () 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"); + if(domination_roundbased) + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_DOMINATION_CAPTURE, head.netname, self.message); else - bprint(" ^7(", ftos(points), " point every ", ftos(wait_time), " seconds)\n"); + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_DOMINATION_CAPTURE_TIME, head.netname, self.message, points, wait_time); if(self.enemy.playerid == self.enemy_playerid) PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1); @@ -110,6 +109,7 @@ void dompoint_captured () break; case NUM_TEAM_4: pps_pink += points/wait_time; + break; } total_pps += points/wait_time; } @@ -159,6 +159,7 @@ void dompointthink() // give credit to the team // NOTE: this defaults to 0 + if (!domination_roundbased) if (self.goalentity.netname != "") { if(autocvar_g_domination_point_amt) @@ -187,6 +188,9 @@ void dompointtouch() if (other.health < 1) return; + if(round_handler_IsActive() && !round_handler_IsRoundStarted()) + return; + if(time < self.captime + 0.3) return; @@ -286,6 +290,94 @@ void dom_controlpoint_setup() WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1'); } +float total_controlpoints, redowned, blueowned, yellowowned, pinkowned; +void Domination_count_controlpoints() +{ + entity e; + total_controlpoints = redowned = blueowned = yellowowned = pinkowned = 0; + for(e = world; (e = find(e, classname, "dom_controlpoint")) != world; ) + { + ++total_controlpoints; + redowned += (e.goalentity.team == NUM_TEAM_1); + blueowned += (e.goalentity.team == NUM_TEAM_2); + yellowowned += (e.goalentity.team == NUM_TEAM_3); + pinkowned += (e.goalentity.team == NUM_TEAM_4); + } +} + +float Domination_GetWinnerTeam() +{ + float winner_team = 0; + if(redowned == total_controlpoints) + winner_team = NUM_TEAM_1; + if(blueowned == total_controlpoints) + { + if(winner_team) return 0; + winner_team = NUM_TEAM_2; + } + if(yellowowned == total_controlpoints) + { + if(winner_team) return 0; + winner_team = NUM_TEAM_3; + } + if(pinkowned == total_controlpoints) + { + if(winner_team) return 0; + winner_team = NUM_TEAM_4; + } + if(winner_team) + return winner_team; + return -1; // no control points left? +} + +#define DOM_OWNED_CONTROLPOINTS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0)) +#define DOM_OWNED_CONTROLPOINTS_OK() (DOM_OWNED_CONTROLPOINTS() < total_controlpoints) +float Domination_CheckWinner() +{ + if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0) + { + Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_OVER); + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_OVER); + round_handler_Init(5, autocvar_g_domination_warmup, autocvar_g_domination_round_timelimit); + return 1; + } + + Domination_count_controlpoints(); + + float winner_team = Domination_GetWinnerTeam(); + + if(winner_team == -1) + return 0; + + if(winner_team > 0) + { + Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner_team, CENTER_ROUND_TEAM_WIN_)); + Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner_team, INFO_ROUND_TEAM_WIN_)); + TeamScore_AddToTeam(winner_team, ST_DOM_CAPS, +1); + } + else if(winner_team == -1) + { + Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED); + Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED); + } + + round_handler_Init(5, autocvar_g_domination_warmup, autocvar_g_domination_round_timelimit); + + return 1; +} + +float Domination_CheckPlayers() +{ + return 1; +} + +void Domination_RoundStart() +{ + entity e; + FOR_EACH_PLAYER(e) + e.player_blocked = 0; +} + //go to best items, or control points you don't own void havocbot_role_dom() { @@ -304,6 +396,26 @@ void havocbot_role_dom() } } +MUTATOR_HOOKFUNCTION(dom_ResetMap) +{ + FOR_EACH_PLAYER(self) + { + PutClientInServer(); + self.player_blocked = 1; + } + return 1; +} + +MUTATOR_HOOKFUNCTION(dom_PlayerSpawn) +{ + if(domination_roundbased) + if(!round_handler_IsRoundStarted()) + self.player_blocked = 1; + else + self.player_blocked = 0; + return FALSE; +} + MUTATOR_HOOKFUNCTION(dom_ClientConnect) { set_dom_state(self); @@ -390,18 +502,28 @@ void spawnfunc_dom_team() // 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; + if(domination_roundbased) + { + ScoreRules_basics(domination_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(); + } 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(); + { + 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(domination_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(); + } } // code from here on is just to support maps that don't have control point and team entities @@ -448,13 +570,11 @@ void dom_spawnpoint(vector org) // 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", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point"); dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point"); - if(numteams > 2) + if(domination_teams >= 3) dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point"); - if(numteams > 3) + if(domination_teams >= 4) dom_spawnteam("Pink", NUM_TEAM_4-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, "", "", ""); } @@ -468,7 +588,15 @@ void dom_DelayedInit() // Do this check with a delay so we can wait for teams to dom_spawnteams(); } + domination_roundbased = autocvar_g_domination_roundbased; + ScoreRules_dom(); + + if(domination_roundbased) + { + round_handler_Spawn(Domination_CheckPlayers, Domination_CheckWinner, Domination_RoundStart); + round_handler_Init(5, autocvar_g_domination_warmup, autocvar_g_domination_round_timelimit); + } } void dom_Initialize() @@ -480,11 +608,14 @@ void dom_Initialize() precache_model("models/domination/dom_unclaimed.md3"); precache_sound("domination/claim.wav"); + domination_teams = ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override); + domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2); + 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); + if(domination_teams >= 3) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow); + if(domination_teams >= 4) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink); InitializeEntity(world, dom_DelayedInit, INITPRIO_GAMETYPE); } @@ -492,6 +623,8 @@ void dom_Initialize() MUTATOR_DEFINITION(gamemode_domination) { + MUTATOR_HOOK(reset_map_players, dom_ResetMap, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerSpawn, dom_PlayerSpawn, CBC_ORDER_ANY); MUTATOR_HOOK(ClientConnect, dom_ClientConnect, CBC_ORDER_ANY); MUTATOR_HOOK(HavocBot_ChooseRule, dom_BotRoles, CBC_ORDER_ANY); diff --git a/qcsrc/server/mutators/gamemode_domination.qh b/qcsrc/server/mutators/gamemode_domination.qh index a7d18530c..6b5b334e4 100644 --- a/qcsrc/server/mutators/gamemode_domination.qh +++ b/qcsrc/server/mutators/gamemode_domination.qh @@ -4,6 +4,8 @@ #define ST_DOM_TICKS 1 #define SP_DOM_TICKS 4 #define SP_DOM_TAKES 5 +#define ST_DOM_CAPS 1 +#define SP_DOM_CAPS 4 // pps: points per second .float dom_total_pps; @@ -20,4 +22,8 @@ float pps_pink; // capture declarations .float enemy_playerid; .entity sprite; -.float captime; \ No newline at end of file +.float captime; + +// misc globals +float domination_roundbased; +float domination_teams; diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index 5185b2c61..7f353dd65 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -94,6 +94,10 @@ void InitGameplayMode() fraglimit_override = autocvar_g_domination_point_limit; leadlimit_override = autocvar_g_domination_point_leadlimit; MUTATOR_ADD(gamemode_domination); + + if(autocvar_g_domination_roundbased && autocvar_g_domination_roundbased_point_limit) + fraglimit_override = autocvar_g_domination_roundbased_point_limit; + have_team_spawns = -1; // request team spawns }