1 void spawnfunc_func_breakable();
2 void target_objective_decrease_activate();
3 .entity assault_decreaser;
4 .entity assault_sprite;
6 void spawnfunc_info_player_attacker() {
12 self.team = COLOR_TEAM1; // red, gets swapped every round
13 spawnfunc_info_player_deathmatch();
16 void spawnfunc_info_player_defender() {
22 self.team = COLOR_TEAM2; // blue, gets swapped every round
23 spawnfunc_info_player_deathmatch();
26 // reset this objective. Used when spawning an objective
27 // and when a new round starts
28 void assault_objective_reset() {
29 self.health = ASSAULT_VALUE_INACTIVE;
32 void assault_objective_use() {
35 //print("^2Activated objective ", self.targetname, "=", etos(self), "\n");
36 //print("Activator is ", activator.classname, "\n");
41 for(self = world; (self = find(self, target, oldself.targetname)); )
43 if(self.classname == "target_objective_decrease")
44 target_objective_decrease_activate();
50 vector target_objective_spawn_evalfunc(entity player, entity spot, vector current)
52 if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE)
57 void spawnfunc_target_objective() {
63 self.classname = "target_objective";
64 self.use = assault_objective_use;
65 assault_objective_reset();
66 self.reset = assault_objective_reset;
67 self.spawn_evalfunc = target_objective_spawn_evalfunc;
71 // decrease the health of targeted objectives
72 void assault_objective_decrease_use() {
73 if(activator.team != assault_attacker_team) {
74 // wrong team triggered decrease
78 if(other.assault_sprite)
80 WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime);
81 if(other.classname == "func_assault_destructible")
85 return; // already activated! cannot activate again!
87 if(self.enemy.health < ASSAULT_VALUE_INACTIVE)
89 if(self.enemy.health - self.dmg > 0.5)
91 PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.dmg);
92 self.enemy.health = self.enemy.health - self.dmg;
96 PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.enemy.health);
97 PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1);
98 self.enemy.health = -1;
100 entity oldself, oldactivator;
103 self = oldself.enemy;
108 FOR_EACH_PLAYER(player)
110 s = strcat(self.message, "\n");
111 centerprint(player, s);
115 oldactivator = activator;
118 activator = oldactivator;
124 void assault_setenemytoobjective()
127 for(objective = world; (objective = find(objective, targetname, self.target)); ) {
128 if(objective.classname == "target_objective") {
129 if(self.enemy == world)
130 self.enemy = objective;
132 objerror("more than one objective as target - fix the map!");
137 if(self.enemy == world)
138 objerror("no objective as target - fix the map!");
141 float assault_decreaser_sprite_visible(entity e)
145 decreaser = self.assault_decreaser;
147 if(decreaser.enemy.health >= ASSAULT_VALUE_INACTIVE)
153 void target_objective_decrease_activate()
157 for(ent = world; (ent = find(ent, target, self.targetname)); )
159 if(ent.assault_sprite != world)
161 WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime);
162 if(ent.classname == "func_assault_destructible")
166 spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0');
167 spr.assault_decreaser = self;
168 spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible;
169 spr.classname = "sprite_waypoint";
170 WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY);
171 if(ent.classname == "func_assault_destructible")
173 WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy");
174 WaypointSprite_UpdateMaxHealth(spr, ent.max_health);
175 WaypointSprite_UpdateHealth(spr, ent.health);
179 WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push");
183 void target_objective_decrease_findtarget()
185 assault_setenemytoobjective();
188 //=============================================================================
190 void spawnfunc_target_objective_decrease() {
197 self.classname = "target_objective_decrease";
202 self.use = assault_objective_decrease_use;
203 self.health = ASSAULT_VALUE_INACTIVE;
204 self.max_health = ASSAULT_VALUE_INACTIVE;
207 InitializeEntity(self, target_objective_decrease_findtarget, INITPRIO_FINDTARGET);
210 // destructible walls that can be used to trigger target_objective_decrease
211 void spawnfunc_func_assault_destructible() {
218 self.classname = "func_assault_destructible";
219 if(assault_attacker_team == COLOR_TEAM1) {
220 self.team = COLOR_TEAM2;
222 self.team = COLOR_TEAM1;
224 spawnfunc_func_breakable();
227 void assault_wall_think() {
228 if(self.enemy.health < 0) {
230 self.solid = SOLID_NOT;
232 self.model = self.mdl;
233 self.solid = SOLID_BSP;
236 self.nextthink = time + 0.2;
239 void spawnfunc_func_assault_wall() {
245 self.classname = "func_assault_wall";
246 self.mdl = self.model;
247 setmodel(self, self.mdl);
248 self.solid = SOLID_BSP;
249 self.think = assault_wall_think;
250 self.nextthink = time;
251 InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET);
255 void target_assault_roundend_reset() {
256 //print("round end reset\n");
257 self.cnt = self.cnt + 1; // up round counter
258 self.winning = 0; // up round
261 void target_assault_roundend_use() {
262 self.winning = 1; // round has been won by attackers
265 void spawnfunc_target_assault_roundend() {
271 self.winning = 0; // round not yet won by attackers
272 self.classname = "target_assault_roundend";
273 self.use = target_assault_roundend_use;
274 self.cnt = 0; // first round
275 self.reset = target_assault_roundend_reset;
278 void assault_roundstart_use() {
284 #ifdef TTURRETS_ENABLED
287 //(Re)spawn all turrets
289 ent = find(world, classname, "turret_main");
292 if(ent.team == COLOR_TEAM1)
293 ent.team = COLOR_TEAM2;
295 ent.team = COLOR_TEAM1;
299 // Dubbles as teamchange
300 turret_stdproc_respawn();
302 ent = find(ent, classname, "turret_main");
310 void spawnfunc_target_assault_roundstart() {
316 assault_attacker_team = COLOR_TEAM1;
317 self.classname = "target_assault_roundstart";
318 self.use = assault_roundstart_use;
319 self.reset2 = assault_roundstart_use;
320 InitializeEntity(self, assault_roundstart_use, INITPRIO_FINDTARGET);
324 // reset objectives, toggle spawnpoints, reset triggers, ...
325 void vehicles_clearrturn();
326 void vehicles_spawn();
327 void assault_new_round()
330 //bprint("ASSAULT: new round\n");
333 // Eject players from vehicles
334 FOR_EACH_PLAYER(self)
337 vehicles_exit(VHEF_RELESE);
340 self = findchainflags(vehicle_flags, VHF_ISVEHICLE);
343 vehicles_clearrturn();
351 self.winning = self.winning + 1;
353 // swap attacker/defender roles
354 if(assault_attacker_team == COLOR_TEAM1) {
355 assault_attacker_team = COLOR_TEAM2;
357 assault_attacker_team = COLOR_TEAM1;
362 for(ent = world; (ent = nextent(ent)); )
364 if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
366 if(ent.team_saved == COLOR_TEAM1)
367 ent.team_saved = COLOR_TEAM2;
368 else if(ent.team_saved == COLOR_TEAM2)
369 ent.team_saved = COLOR_TEAM1;
373 // reset the level with a countdown
374 cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60));
375 ReadyRestart_force(); // sets game_starttime