From: Samual Lenks Date: Tue, 7 May 2013 05:42:27 +0000 (-0400) Subject: Merge remote-tracking branch 'origin/master' into Mario/assault_mutator X-Git-Tag: xonotic-v0.7.0~59^2 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=4779c1bd8269aaca0d20e802c7e8e685602bb926 Merge remote-tracking branch 'origin/master' into Mario/assault_mutator Conflicts: qcsrc/server/cl_client.qc qcsrc/server/mutators/mutators.qh qcsrc/server/progs.src --- 4779c1bd8269aaca0d20e802c7e8e685602bb926 diff --cc qcsrc/server/attic/assault.qc index 2562dca3d,000000000..7a5662c97 mode 100644,000000..100644 --- a/qcsrc/server/attic/assault.qc +++ b/qcsrc/server/attic/assault.qc @@@ -1,376 -1,0 +1,376 @@@ +void spawnfunc_func_breakable(); +void target_objective_decrease_activate(); +.entity assault_decreaser; +.entity assault_sprite; + +void spawnfunc_info_player_attacker() { + if(!g_assault) + { + remove(self); + return; + } - self.team = COLOR_TEAM1; // red, gets swapped every round ++ self.team = NUM_TEAM_1; // red, gets swapped every round + spawnfunc_info_player_deathmatch(); +} + +void spawnfunc_info_player_defender() { + if(!g_assault) + { + remove(self); + return; + } - self.team = COLOR_TEAM2; // blue, gets swapped every round ++ self.team = NUM_TEAM_2; // blue, gets swapped every round + spawnfunc_info_player_deathmatch(); +} + +// reset this objective. Used when spawning an objective +// and when a new round starts +void assault_objective_reset() { + self.health = ASSAULT_VALUE_INACTIVE; +} + +void assault_objective_use() { + // activate objective + self.health = 100; + //print("^2Activated objective ", self.targetname, "=", etos(self), "\n"); + //print("Activator is ", activator.classname, "\n"); + + entity oldself; + oldself = self; + + for(self = world; (self = find(self, target, oldself.targetname)); ) + { + if(self.classname == "target_objective_decrease") + target_objective_decrease_activate(); + } + + self = oldself; +} + +vector target_objective_spawn_evalfunc(entity player, entity spot, vector current) +{ + if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE) + return '-1 0 0'; + return current; +} + +void spawnfunc_target_objective() { + if(!g_assault) + { + remove(self); + return; + } + self.classname = "target_objective"; + self.use = assault_objective_use; + assault_objective_reset(); + self.reset = assault_objective_reset; + self.spawn_evalfunc = target_objective_spawn_evalfunc; +} + + +// decrease the health of targeted objectives +void assault_objective_decrease_use() { + if(activator.team != assault_attacker_team) { + // wrong team triggered decrease + return; + } + + if(other.assault_sprite) + { + WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime); + if(other.classname == "func_assault_destructible") + other.sprite = world; + } + else + return; // already activated! cannot activate again! + + if(self.enemy.health < ASSAULT_VALUE_INACTIVE) + { + if(self.enemy.health - self.dmg > 0.5) + { + PlayerTeamScore_Add(activator, 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); + self.enemy.health = -1; + + entity oldself, oldactivator; + + oldself = self; + self = oldself.enemy; + if(self.message) + { + entity player; + string s; + FOR_EACH_PLAYER(player) + { + s = strcat(self.message, "\n"); + centerprint(player, s); + } + } + + oldactivator = activator; + activator = oldself; + SUB_UseTargets(); + activator = oldactivator; + self = oldself; + } + } +} + +void assault_setenemytoobjective() +{ + entity objective; + for(objective = world; (objective = find(objective, targetname, self.target)); ) { + if(objective.classname == "target_objective") { + if(self.enemy == world) + self.enemy = objective; + else + objerror("more than one objective as target - fix the map!"); + break; + } + } + + if(self.enemy == world) + objerror("no objective as target - fix the map!"); +} + +float assault_decreaser_sprite_visible(entity e) +{ + entity decreaser; + + decreaser = self.assault_decreaser; + + if(decreaser.enemy.health >= ASSAULT_VALUE_INACTIVE) + return FALSE; + + return TRUE; +} + +void target_objective_decrease_activate() +{ + entity ent, spr; + self.owner = world; + for(ent = world; (ent = find(ent, target, self.targetname)); ) + { + if(ent.assault_sprite != world) + { + WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime); + if(ent.classname == "func_assault_destructible") + ent.sprite = world; + } + + spr = WaypointSprite_SpawnFixed("", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0'); + spr.assault_decreaser = self; + spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; + spr.classname = "sprite_waypoint"; + WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY); + if(ent.classname == "func_assault_destructible") + { + WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy"); + WaypointSprite_UpdateMaxHealth(spr, ent.max_health); + WaypointSprite_UpdateHealth(spr, ent.health); + ent.sprite = spr; + } + else + WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push"); + } +} + +void target_objective_decrease_findtarget() +{ + assault_setenemytoobjective(); +} + +//============================================================================= + +void spawnfunc_target_objective_decrease() { + if(!g_assault) + { + remove(self); + return; + } + + self.classname = "target_objective_decrease"; + + if(!self.dmg) { + self.dmg = 101; + } + self.use = assault_objective_decrease_use; + self.health = ASSAULT_VALUE_INACTIVE; + self.max_health = ASSAULT_VALUE_INACTIVE; + self.enemy = world; + + InitializeEntity(self, target_objective_decrease_findtarget, INITPRIO_FINDTARGET); +} + +// destructible walls that can be used to trigger target_objective_decrease +void spawnfunc_func_assault_destructible() { + if(!g_assault) + { + remove(self); + return; + } + self.spawnflags = 3; + self.classname = "func_assault_destructible"; - if(assault_attacker_team == COLOR_TEAM1) { - self.team = COLOR_TEAM2; ++ if(assault_attacker_team == NUM_TEAM_1) { ++ self.team = NUM_TEAM_2; + } else { - self.team = COLOR_TEAM1; ++ self.team = NUM_TEAM_1; + } + spawnfunc_func_breakable(); +} + +void assault_wall_think() { + if(self.enemy.health < 0) { + self.model = ""; + self.solid = SOLID_NOT; + } else { + self.model = self.mdl; + self.solid = SOLID_BSP; + } + + self.nextthink = time + 0.2; +} + +void spawnfunc_func_assault_wall() { + if(!g_assault) + { + remove(self); + return; + } + self.classname = "func_assault_wall"; + self.mdl = self.model; + setmodel(self, self.mdl); + self.solid = SOLID_BSP; + self.think = assault_wall_think; + self.nextthink = time; + InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET); +} + + +void target_assault_roundend_reset() { + //print("round end reset\n"); + self.cnt = self.cnt + 1; // up round counter + self.winning = 0; // up round +} + +void target_assault_roundend_use() { + self.winning = 1; // round has been won by attackers +} + +void spawnfunc_target_assault_roundend() { + if(!g_assault) + { + remove(self); + return; + } + self.winning = 0; // round not yet won by attackers + self.classname = "target_assault_roundend"; + self.use = target_assault_roundend_use; + self.cnt = 0; // first round + self.reset = target_assault_roundend_reset; +} + +void assault_roundstart_use() { + + activator = self; + SUB_UseTargets(); + + +#ifdef TTURRETS_ENABLED + entity ent, oldself; + + //(Re)spawn all turrets + oldself = self; + ent = find(world, classname, "turret_main"); + while(ent) { + // Swap turret teams - if(ent.team == COLOR_TEAM1) - ent.team = COLOR_TEAM2; ++ if(ent.team == NUM_TEAM_1) ++ ent.team = NUM_TEAM_2; + else - ent.team = COLOR_TEAM1; ++ ent.team = NUM_TEAM_1; + + self = ent; + + // Dubbles as teamchange + turret_stdproc_respawn(); + + ent = find(ent, classname, "turret_main"); + } + self = oldself; +#endif + + +} + +void spawnfunc_target_assault_roundstart() { + if(!g_assault) + { + remove(self); + return; + } - assault_attacker_team = COLOR_TEAM1; ++ 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); +} + +// trigger new round +// reset objectives, toggle spawnpoints, reset triggers, ... +void vehicles_clearrturn(); +void vehicles_spawn(); +void assault_new_round() +{ + entity oldself; + //bprint("ASSAULT: new round\n"); + + oldself = self; + // Eject players from vehicles + FOR_EACH_PLAYER(self) + { + if(self.vehicle) + vehicles_exit(VHEF_RELESE); + } + + self = findchainflags(vehicle_flags, VHF_ISVEHICLE); + while(self) + { + vehicles_clearrturn(); + vehicles_spawn(); + self = self.chain; + } + + self = oldself; + + // up round counter + self.winning = self.winning + 1; + + // swap attacker/defender roles - if(assault_attacker_team == COLOR_TEAM1) { - assault_attacker_team = COLOR_TEAM2; ++ if(assault_attacker_team == NUM_TEAM_1) { ++ assault_attacker_team = NUM_TEAM_2; + } else { - assault_attacker_team = COLOR_TEAM1; ++ assault_attacker_team = NUM_TEAM_1; + } + + + entity ent; + for(ent = world; (ent = nextent(ent)); ) + { + if(clienttype(ent) == CLIENTTYPE_NOTACLIENT) + { - if(ent.team_saved == COLOR_TEAM1) - ent.team_saved = COLOR_TEAM2; - else if(ent.team_saved == COLOR_TEAM2) - ent.team_saved = COLOR_TEAM1; ++ 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; + } + } + + // reset the level with a countdown + cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60)); + ReadyRestart_force(); // sets game_starttime +} diff --cc qcsrc/server/autocvars.qh index 45e5d35fb,bfc362caf..efb9f8c17 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@@ -75,7 -75,9 +75,8 @@@ float autocvar_g_arena_maxspawned float autocvar_g_arena_point_leadlimit; float autocvar_g_arena_point_limit; float autocvar_g_arena_roundbased; + float autocvar_g_arena_round_timelimit; float autocvar_g_arena_warmup; -float autocvar_g_assault; float autocvar_g_balance_armor_blockpercent; float autocvar_g_balance_armor_limit; float autocvar_g_balance_armor_regen; diff --cc qcsrc/server/cl_client.qc index 6c05b534d,2f9c0d831..075280c26 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@@ -865,7 -808,14 +808,7 @@@ void PutClientInServer (void //stuffcmd(self, "chase_active 0"); //stuffcmd(self, "set viewsize $tmpviewsize \n"); - - if(g_assault) { - if(self.team == assault_attacker_team) - Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING); - else - Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_DEFENDING); - } -- ++ target_voicescript_clear(self); // reset fields the weapons may use diff --cc qcsrc/server/mutators/mutators.qh index 7d75706d7,9c139f0e9..dab42bd65 --- a/qcsrc/server/mutators/mutators.qh +++ b/qcsrc/server/mutators/mutators.qh @@@ -1,4 -1,5 +1,6 @@@ +MUTATOR_DECLARATION(gamemode_assault); + MUTATOR_DECLARATION(gamemode_arena); + MUTATOR_DECLARATION(gamemode_ca); MUTATOR_DECLARATION(gamemode_keyhunt); MUTATOR_DECLARATION(gamemode_freezetag); MUTATOR_DECLARATION(gamemode_keepaway); diff --cc qcsrc/server/progs.src index 271248923,28736e6cd..b3cc22dda --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@@ -27,10 -30,15 +30,16 @@@ autocvars.q constants.qh defs.qh // Should rename this, it has fields and globals + ../common/notifications.qh // must be after autocvars + ../common/deathtypes.qh // must be after notifications + mutators/base.qh mutators/mutators.qh +mutators/gamemode_assault.qh + mutators/gamemode_arena.qh + mutators/gamemode_ca.qh mutators/gamemode_ctf.qh + mutators/gamemode_domination.qh mutators/gamemode_keyhunt.qh // TODO fix this mutators/gamemode_keepaway.qh mutators/gamemode_nexball.qh @@@ -208,8 -220,10 +221,11 @@@ round_handler.q ../common/explosion_equation.qc mutators/base.qc +mutators/gamemode_assault.qc + mutators/gamemode_arena.qc + mutators/gamemode_ca.qc mutators/gamemode_ctf.qc + mutators/gamemode_domination.qc mutators/gamemode_freezetag.qc mutators/gamemode_keyhunt.qc mutators/gamemode_keepaway.qc