X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator%2Fgamemode_assault.qc;h=2e703d1a8c3320756d6edd1a2ab0366f8fd74e78;hb=195d267efd270e8d9ff9b4565f67d5aa4dc7681f;hp=6af1c1c4658163fcf4abd705d7df1e20110db1be;hpb=d22f17ca9ca038d46ee4c676175d2142764ba2f4;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/mutators/mutator/gamemode_assault.qc b/qcsrc/server/mutators/mutator/gamemode_assault.qc index 6af1c1c46..2e703d1a8 100644 --- a/qcsrc/server/mutators/mutator/gamemode_assault.qc +++ b/qcsrc/server/mutators/mutator/gamemode_assault.qc @@ -1,6 +1,19 @@ #include "gamemode_assault.qh" +#include + .entity sprite; +#define AS_ROUND_DELAY 5 + +IntrusiveList g_assault_destructibles; +IntrusiveList g_assault_objectivedecreasers; +IntrusiveList g_assault_objectives; +STATIC_INIT(g_assault) +{ + g_assault_destructibles = IL_NEW(); + g_assault_objectivedecreasers = IL_NEW(); + g_assault_objectives = IL_NEW(); +} // random functions void assault_objective_use(entity this, entity actor, entity trigger) @@ -52,17 +65,17 @@ void assault_objective_decrease_use(entity this, entity actor, entity trigger) { if(this.enemy.health - this.dmg > 0.5) { - PlayerTeamScore_Add(actor, SP_SCORE, ST_SCORE, this.dmg); + GameRules_scoring_add_team(actor, SCORE, this.dmg); this.enemy.health = this.enemy.health - this.dmg; } else { - PlayerTeamScore_Add(actor, SP_SCORE, ST_SCORE, this.enemy.health); - PlayerTeamScore_Add(actor, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1); + GameRules_scoring_add_team(actor, SCORE, this.enemy.health); + GameRules_scoring_add_team(actor, ASSAULT_OBJECTIVES, 1); this.enemy.health = -1; if(this.enemy.message) - FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(centerprint(it, this.enemy.message))); + FOREACH_CLIENT(IS_PLAYER(it), { centerprint(it, this.enemy.message); }); SUB_UseTargets(this.enemy, this, trigger); } @@ -105,7 +118,7 @@ void target_objective_decrease_activate(entity this) it.sprite = NULL; // TODO: just unsetting it?! } - spr = WaypointSprite_SpawnFixed(WP_Assault, 0.5 * (it.absmin + it.absmax), it, assault_sprite, RADARICON_OBJECTIVE); + spr = WaypointSprite_SpawnFixed(WP_AssaultDefend, 0.5 * (it.absmin + it.absmax), it, assault_sprite, RADARICON_OBJECTIVE); spr.assault_decreaser = this; spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; spr.classname = "sprite_waypoint"; @@ -192,24 +205,36 @@ void assault_new_round(entity this) else assault_attacker_team = NUM_TEAM_1; - FOREACH_ENTITY_FLOAT(pure_data, false, + IL_EACH(g_saved_team, !IS_CLIENT(it), { - if(IS_CLIENT(it)) - continue; - - if (it.team_saved == NUM_TEAM_1) it.team_saved = NUM_TEAM_2; - else if (it.team_saved == NUM_TEAM_2) it.team_saved = NUM_TEAM_1; + if(it.team_saved == NUM_TEAM_1) + it.team_saved = NUM_TEAM_2; + else if(it.team_saved == NUM_TEAM_2) + it.team_saved = NUM_TEAM_1; }); // reset the level with a countdown - cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60)); + cvar_set("timelimit", ftos(ceil(time - AS_ROUND_DELAY - game_starttime) / 60)); ReadyRestart_force(); // sets game_starttime } +entity as_round; +.entity ent_winning; +void as_round_think() +{ + game_stopped = false; + assault_new_round(as_round.ent_winning); + delete(as_round); + as_round = NULL; +} + // Assault winning condition: If the attackers triggered a round end (by fulfilling all objectives) // they win. Otherwise the defending team wins once the timelimit passes. int WinningCondition_Assault() { + if(as_round) + return WINNING_NO; + WinningConditionHelper(NULL); // set worldstatus int status = WINNING_NO; @@ -229,7 +254,7 @@ int WinningCondition_Assault() { if(ent.winning) // round end has been triggered by attacking team { - bprint("ASSAULT: round completed...\n"); + bprint("Assault: round completed.\n"); SetWinners(team, assault_attacker_team); TeamScore_AddToTeam(assault_attacker_team, ST_ASSAULT_OBJECTIVES, 666 - TeamScore_AddToTeam(assault_attacker_team, ST_ASSAULT_OBJECTIVES, 0)); @@ -240,7 +265,17 @@ int WinningCondition_Assault() } else { - assault_new_round(ent); + Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ASSAULT_OBJ_DESTROYED, ceil(time - game_starttime)); + as_round = new(as_round); + as_round.think = as_round_think; + as_round.ent_winning = ent; + as_round.nextthink = time + AS_ROUND_DELAY; + game_stopped = true; + + // make sure timelimit isn't hit while the game is blocked + if(autocvar_timelimit > 0) + if(time + AS_ROUND_DELAY >= game_starttime + autocvar_timelimit * 60) + cvar_set("timelimit", ftos(autocvar_timelimit + AS_ROUND_DELAY / 60)); } } } @@ -404,8 +439,8 @@ void havocbot_goalrating_ast_targets(entity this, float ratingscale) this.havocbot_attack_time = 0; - if(checkpvs(this.view_ofs,it)) - if(checkpvs(this.view_ofs,best)) + if(checkpvs(this.origin + this.view_ofs, it)) + if(checkpvs(this.origin + this.view_ofs, best)) { // dprint("increasing attack time for this target\n"); this.havocbot_attack_time = time + 2; @@ -436,7 +471,7 @@ void havocbot_role_ast_offense(entity this) if(this.havocbot_attack_time>time) return; - if (this.bot_strategytime < time) + if (navigation_goalrating_timeout(this)) { navigation_goalrating_start(this); havocbot_goalrating_enemyplayers(this, 20000, this.origin, 650); @@ -444,7 +479,7 @@ void havocbot_role_ast_offense(entity this) havocbot_goalrating_items(this, 15000, this.origin, 10000); navigation_goalrating_end(this); - this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_timeout_set(this); } } @@ -470,7 +505,7 @@ void havocbot_role_ast_defense(entity this) if(this.havocbot_attack_time>time) return; - if (this.bot_strategytime < time) + if (navigation_goalrating_timeout(this)) { navigation_goalrating_start(this); havocbot_goalrating_enemyplayers(this, 20000, this.origin, 3000); @@ -478,7 +513,7 @@ void havocbot_role_ast_defense(entity this) havocbot_goalrating_items(this, 15000, this.origin, 10000); navigation_goalrating_end(this); - this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + navigation_goalrating_timeout_set(this); } } @@ -525,11 +560,11 @@ MUTATOR_HOOKFUNCTION(as, TurretSpawn) { entity turret = M_ARGV(0, entity); - if(!turret.team || turret.team == MAX_SHOT_DISTANCE) + if(!turret.team || turret.team == FLOAT_MAX) turret.team = 5; // this gets reversed when match starts? } -MUTATOR_HOOKFUNCTION(as, VehicleSpawn) +MUTATOR_HOOKFUNCTION(as, VehicleInit) { entity veh = M_ARGV(0, entity); @@ -551,10 +586,10 @@ MUTATOR_HOOKFUNCTION(as, PlayHitsound) return (frag_victim.classname == "func_assault_destructible"); } -MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(as, TeamBalance_CheckAllowedTeams) { // assault always has 2 teams - c1 = c2 = 0; + M_ARGV(0, float) = BIT(0) | BIT(1); return true; } @@ -566,8 +601,9 @@ MUTATOR_HOOKFUNCTION(as, CheckRules_World) MUTATOR_HOOKFUNCTION(as, ReadLevelCvars) { - // no assault warmups + // incompatible warmup_stage = 0; + sv_ready_restart_after_countdown = 0; } MUTATOR_HOOKFUNCTION(as, OnEntityPreSpawn) @@ -584,15 +620,8 @@ MUTATOR_HOOKFUNCTION(as, OnEntityPreSpawn) } } -// scoreboard setup -void assault_ScoreRules() +MUTATOR_HOOKFUNCTION(as, ReadyRestart_Deny) { - int teams = 0; - teams |= BIT(0); - teams |= BIT(1); // always red vs blue - - ScoreRules_basics(teams, SFL_SORT_PRIO_SECONDARY, SFL_SORT_PRIO_SECONDARY, true); - ScoreInfo_SetLabel_TeamScore( ST_ASSAULT_OBJECTIVES, "objectives", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore(SP_ASSAULT_OBJECTIVES, "objectives", SFL_SORT_PRIO_PRIMARY); - ScoreRules_basics_end(); + // readyrestart not supported (yet) + return true; }