X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator%2Fgamemode_assault.qc;h=c2d5ed3b905771ec30d5d98e141e9c9a59acdf9e;hb=a07691e754aa071189c034693af3476777d86720;hp=68d23f4860c55485a9b12fc8f03b1b3e4cfd17a4;hpb=c1385b1eb134e4c40239273511fd63b97ff51815;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 68d23f486..c2d5ed3b9 100644 --- a/qcsrc/server/mutators/mutator/gamemode_assault.qc +++ b/qcsrc/server/mutators/mutator/gamemode_assault.qc @@ -1,7 +1,9 @@ +#include "gamemode_assault.qh" #ifndef GAMEMODE_ASSAULT_H #define GAMEMODE_ASSAULT_H void assault_ScoreRules(); +void ActivateTeamplay(); REGISTER_MUTATOR(as, false) { @@ -43,46 +45,44 @@ const int HAVOCBOT_AST_ROLE_OFFENSE = 4; .int havocbot_role_flags; .float havocbot_attack_time; -.void() havocbot_role; -.void() havocbot_previous_role; +.void(entity this) havocbot_role; +.void(entity this) havocbot_previous_role; -void() havocbot_role_ast_defense; -void() havocbot_role_ast_offense; +void(entity this) havocbot_role_ast_defense; +void(entity this) havocbot_role_ast_offense; .entity havocbot_ast_target; void(entity bot) havocbot_ast_reset_role; -void(float ratingscale, vector org, float sradius) havocbot_goalrating_items; -void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers; +void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_items; +void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers; // scoreboard stuff const float ST_ASSAULT_OBJECTIVES = 1; const float SP_ASSAULT_OBJECTIVES = 4; // predefined spawnfuncs -void target_objective_decrease_activate(); +void target_objective_decrease_activate(entity this); #endif #ifdef IMPLEMENTATION .entity sprite; // random functions -void assault_objective_use() -{SELFPARAM(); +void assault_objective_use(entity this, entity actor, entity trigger) +{ // activate objective - self.health = 100; - //print("^2Activated objective ", self.targetname, "=", etos(self), "\n"); - //print("Activator is ", activator.classname, "\n"); + this.health = 100; + //print("^2Activated objective ", this.targetname, "=", etos(this), "\n"); + //print("Activator is ", actor.classname, "\n"); for (entity e = world; (e = find(e, target, this.targetname)); ) { if (e.classname == "target_objective_decrease") { - WITH(entity, self, e, target_objective_decrease_activate()); + target_objective_decrease_activate(e); } } - - setself(this); } vector target_objective_spawn_evalfunc(entity player, entity spot, vector current) @@ -100,9 +100,9 @@ void assault_objective_reset(entity this) } // decrease the health of targeted objectives -void assault_objective_decrease_use() -{SELFPARAM(); - if(activator.team != assault_attacker_team) +void assault_objective_decrease_use(entity this, entity actor, entity trigger) +{ + if(actor.team != assault_attacker_team) { // wrong team triggered decrease return; @@ -121,27 +121,19 @@ void assault_objective_decrease_use() { if(self.enemy.health - self.dmg > 0.5) { - PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.dmg); + PlayerTeamScore_Add(actor, SP_SCORE, ST_SCORE, self.dmg); self.enemy.health = self.enemy.health - self.dmg; } else { - PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.enemy.health); - PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1); + PlayerTeamScore_Add(actor, SP_SCORE, ST_SCORE, self.enemy.health); + PlayerTeamScore_Add(actor, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1); self.enemy.health = -1; - entity oldactivator, head; - - setself(this.enemy); - if(self.message) - FOR_EACH_PLAYER(head) - centerprint(head, self.message); + if(this.enemy.message) + FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(centerprint(it, this.enemy.message))); - oldactivator = activator; - activator = this; - SUB_UseTargets(); - activator = oldactivator; - setself(this); + SUB_UseTargets(this.enemy, this, trigger); } } } @@ -177,11 +169,11 @@ float assault_decreaser_sprite_visible(entity e) return true; } -void target_objective_decrease_activate() -{SELFPARAM(); +void target_objective_decrease_activate(entity this) +{ entity ent, spr; - self.owner = world; - for(ent = world; (ent = find(ent, target, self.targetname)); ) + this.owner = world; + for(ent = world; (ent = find(ent, target, this.targetname)); ) { if(ent.assault_sprite != world) { @@ -191,7 +183,7 @@ void target_objective_decrease_activate() } spr = WaypointSprite_SpawnFixed(WP_Assault, 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE); - spr.assault_decreaser = self; + spr.assault_decreaser = this; spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; spr.classname = "sprite_waypoint"; WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY); @@ -219,27 +211,26 @@ void target_assault_roundend_reset(entity this) this.winning = false; // up round } -void target_assault_roundend_use() -{SELFPARAM(); - self.winning = 1; // round has been won by attackers +void target_assault_roundend_use(entity this, entity actor, entity trigger) +{ + this.winning = 1; // round has been won by attackers } -void assault_roundstart_use() -{SELFPARAM(); - activator = self; - SUB_UseTargets(); +void assault_roundstart_use(entity this, entity actor, entity trigger) +{ + SUB_UseTargets(this, this, trigger); //(Re)spawn all turrets - for(entity ent = NULL; (ent = find(ent, classname, "turret_main")); ) { + FOREACH_ENTITY_CLASS("turret_main", true, LAMBDA( // Swap turret teams - if(ent.team == NUM_TEAM_1) - ent.team = NUM_TEAM_2; + if(it.team == NUM_TEAM_1) + it.team = NUM_TEAM_2; else - ent.team = NUM_TEAM_1; + it.team = NUM_TEAM_1; // Dubbles as teamchange - WITH(entity, self, ent, turret_respawn()); - } + WITHSELF(it, turret_respawn()); + )); } void assault_wall_think() @@ -267,21 +258,13 @@ void assault_new_round() //bprint("ASSAULT: new round\n"); // Eject players from vehicles - entity e; - FOR_EACH_PLAYER(e) - { - if(e.vehicle) - { - WITH(entity, self, e, vehicles_exit(VHEF_RELEASE)); - } - } - - for (entity e_ = findchainflags(vehicle_flags, VHF_ISVEHICLE); e_; e_ = e_.chain) - { - setself(e_); + FOREACH_CLIENT(IS_PLAYER(it) && it.vehicle, WITHSELF(it, vehicles_exit(VHEF_RELEASE))); + + FOREACH_ENTITY_FLAGS(vehicle_flags, VHF_ISVEHICLE, LAMBDA( + setself(it); vehicles_clearreturn(self); vehicles_spawn(); - } + )); setself(this); @@ -294,21 +277,57 @@ void assault_new_round() else assault_attacker_team = NUM_TEAM_1; + FOREACH_ENTITY(IS_NOT_A_CLIENT(it), LAMBDA( + 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)); + ReadyRestart_force(); // sets game_starttime +} + +// 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() +{ + SELFPARAM(); + WinningConditionHelper(); // set worldstatus + + int status = WINNING_NO; + // as the timelimit has not yet passed just assume the defending team will win + if(assault_attacker_team == NUM_TEAM_1) + { + SetWinners(team, NUM_TEAM_2); + } + else + { + SetWinners(team, NUM_TEAM_1); + } + entity ent; - for(ent = world; (ent = nextent(ent)); ) + ent = find(world, classname, "target_assault_roundend"); + if(ent) { - if(clienttype(ent) == CLIENTTYPE_NOTACLIENT) + if(ent.winning) // round end has been triggered by attacking team { - if(ent.team_saved == NUM_TEAM_1) - ent.team_saved = NUM_TEAM_2; - else if(ent.team_saved == NUM_TEAM_2) - ent.team_saved = NUM_TEAM_1; + 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)); + + if(ent.cnt == 1 || autocvar_g_campaign) // this was the second round + { + status = WINNING_YES; + } + else + { + WITHSELF(ent, assault_new_round()); + } } } - // reset the level with a countdown - cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60)); - ReadyRestart_force(); // sets game_starttime + return status; } // spawnfuncs @@ -333,7 +352,7 @@ spawnfunc(target_objective) if (!g_assault) { remove(this); return; } this.classname = "target_objective"; - this.use = assault_objective_use; + this.use1 = assault_objective_use; this.reset = assault_objective_reset; this.reset(this); this.spawn_evalfunc = target_objective_spawn_evalfunc; @@ -348,7 +367,7 @@ spawnfunc(target_objective_decrease) if(!self.dmg) self.dmg = 101; - self.use = assault_objective_decrease_use; + self.use1 = assault_objective_decrease_use; self.health = ASSAULT_VALUE_INACTIVE; self.max_health = ASSAULT_VALUE_INACTIVE; self.enemy = world; @@ -392,7 +411,7 @@ spawnfunc(target_assault_roundend) self.winning = 0; // round not yet won by attackers self.classname = "target_assault_roundend"; - self.use = target_assault_roundend_use; + self.use1 = target_assault_roundend_use; self.cnt = 0; // first round self.reset = target_assault_roundend_reset; } @@ -403,14 +422,14 @@ spawnfunc(target_assault_roundstart) assault_attacker_team = NUM_TEAM_1; self.classname = "target_assault_roundstart"; - self.use = assault_roundstart_use; - self.reset2 = assault_roundstart_use; - InitializeEntity(self, assault_roundstart_use, INITPRIO_FINDTARGET); + self.use1 = assault_roundstart_use; + self.reset2 = adaptor_think2use; + InitializeEntity(self, adaptor_think2use, INITPRIO_FINDTARGET); } // legacy bot code -void havocbot_goalrating_ast_targets(float ratingscale) -{SELFPARAM(); +void havocbot_goalrating_ast_targets(entity this, float ratingscale) +{ entity ad, best, wp, tod; float radius, found, bestvalue; vector p; @@ -480,115 +499,115 @@ void havocbot_goalrating_ast_targets(float ratingscale) // te_lightning2(world, '0 0 0', best.origin); // te_knightspike(best.origin); - navigation_routerating(best, ratingscale, 4000); + navigation_routerating(this, best, ratingscale, 4000); best.cnt += 1; - self.havocbot_attack_time = 0; + this.havocbot_attack_time = 0; - if(checkpvs(self.view_ofs,ad)) - if(checkpvs(self.view_ofs,best)) + if(checkpvs(this.view_ofs,ad)) + if(checkpvs(this.view_ofs,best)) { // dprint("increasing attack time for this target\n"); - self.havocbot_attack_time = time + 2; + this.havocbot_attack_time = time + 2; } } } } -void havocbot_role_ast_offense() -{SELFPARAM(); - if(self.deadflag != DEAD_NO) +void havocbot_role_ast_offense(entity this) +{ + if(IS_DEAD(this)) { - self.havocbot_attack_time = 0; - havocbot_ast_reset_role(self); + this.havocbot_attack_time = 0; + havocbot_ast_reset_role(this); return; } // Set the role timeout if necessary - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 120; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 120; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ast_reset_role(self); + havocbot_ast_reset_role(this); return; } - if(self.havocbot_attack_time>time) + if(this.havocbot_attack_time>time) return; - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { - navigation_goalrating_start(); - havocbot_goalrating_enemyplayers(20000, self.origin, 650); - havocbot_goalrating_ast_targets(20000); - havocbot_goalrating_items(15000, self.origin, 10000); - navigation_goalrating_end(); + navigation_goalrating_start(this); + havocbot_goalrating_enemyplayers(this, 20000, this.origin, 650); + havocbot_goalrating_ast_targets(this, 20000); + havocbot_goalrating_items(this, 15000, this.origin, 10000); + navigation_goalrating_end(this); - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; } } -void havocbot_role_ast_defense() -{SELFPARAM(); - if(self.deadflag != DEAD_NO) +void havocbot_role_ast_defense(entity this) +{ + if(IS_DEAD(this)) { - self.havocbot_attack_time = 0; - havocbot_ast_reset_role(self); + this.havocbot_attack_time = 0; + havocbot_ast_reset_role(this); return; } // Set the role timeout if necessary - if (!self.havocbot_role_timeout) - self.havocbot_role_timeout = time + 120; + if (!this.havocbot_role_timeout) + this.havocbot_role_timeout = time + 120; - if (time > self.havocbot_role_timeout) + if (time > this.havocbot_role_timeout) { - havocbot_ast_reset_role(self); + havocbot_ast_reset_role(this); return; } - if(self.havocbot_attack_time>time) + if(this.havocbot_attack_time>time) return; - if (self.bot_strategytime < time) + if (this.bot_strategytime < time) { - navigation_goalrating_start(); - havocbot_goalrating_enemyplayers(20000, self.origin, 3000); - havocbot_goalrating_ast_targets(20000); - havocbot_goalrating_items(15000, self.origin, 10000); - navigation_goalrating_end(); + navigation_goalrating_start(this); + havocbot_goalrating_enemyplayers(this, 20000, this.origin, 3000); + havocbot_goalrating_ast_targets(this, 20000); + havocbot_goalrating_items(this, 15000, this.origin, 10000); + navigation_goalrating_end(this); - self.bot_strategytime = time + autocvar_bot_ai_strategyinterval; + this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; } } -void havocbot_role_ast_setrole(entity bot, float role) +void havocbot_role_ast_setrole(entity this, float role) { switch(role) { case HAVOCBOT_AST_ROLE_DEFENSE: - bot.havocbot_role = havocbot_role_ast_defense; - bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_DEFENSE; - bot.havocbot_role_timeout = 0; + this.havocbot_role = havocbot_role_ast_defense; + this.havocbot_role_flags = HAVOCBOT_AST_ROLE_DEFENSE; + this.havocbot_role_timeout = 0; break; case HAVOCBOT_AST_ROLE_OFFENSE: - bot.havocbot_role = havocbot_role_ast_offense; - bot.havocbot_role_flags = HAVOCBOT_AST_ROLE_OFFENSE; - bot.havocbot_role_timeout = 0; + this.havocbot_role = havocbot_role_ast_offense; + this.havocbot_role_flags = HAVOCBOT_AST_ROLE_OFFENSE; + this.havocbot_role_timeout = 0; break; } } -void havocbot_ast_reset_role(entity bot) -{SELFPARAM(); - if(self.deadflag != DEAD_NO) +void havocbot_ast_reset_role(entity this) +{ + if(IS_DEAD(this)) return; - if(bot.team == assault_attacker_team) - havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_OFFENSE); + if(this.team == assault_attacker_team) + havocbot_role_ast_setrole(this, HAVOCBOT_AST_ROLE_OFFENSE); else - havocbot_role_ast_setrole(bot, HAVOCBOT_AST_ROLE_DEFENSE); + havocbot_role_ast_setrole(this, HAVOCBOT_AST_ROLE_DEFENSE); } // mutator hooks @@ -650,6 +669,7 @@ MUTATOR_HOOKFUNCTION(as, ReadLevelCvars) MUTATOR_HOOKFUNCTION(as, OnEntityPreSpawn) { + SELFPARAM(); switch(self.classname) { case "info_player_team1":