1 //=============================================================================
3 /*QUAKED spawnfunc_info_player_attacker (1 0 0) (-16 -16 -24) (16 16 45) INITIAL
4 Normal attacker spawning location for Nexuiz Asssault
6 angle : direction in which player will look when spawning in the game. Does not apply to bots.
7 target : this should point to a spawnfunc_target_objective to decide when this spawning point is active.
8 nobots : when set to 1, bots will never use this spawn point to respawn in the game.
9 nohumans : when set to 1, human players will never use this spawn point to respawn in the game.
10 notfree : when set to 1, entity will not spawn in "Free for all" and "Tournament" modes.
11 notteam : when set to 1, entity will not spawn in "Teamplay" and "CTF" modes.
12 notsingle : when set to 1, entity will not spawn in Single Player mode (bot play mode).
13 -------- SPAWNFLAGS --------
14 INITIAL : makes the spawnpoint the initial place for the player to spawn at the beginning of the game.*/
15 void spawnfunc_info_player_attacker() {
16 self.team = COLOR_TEAM1; // red, gets swapped every round
17 spawnfunc_info_player_deathmatch();
20 //=============================================================================
22 /*QUAKED spawnfunc_info_player_defender (0 1 0) (-16 -16 -24) (16 16 45) INITIAL
23 Normal defender spawning location for Nexuiz Asssault
24 -------- KEYS --------
25 angle : direction in which player will look when spawning in the game. Does not apply to bots.
26 target : this should point to a spawnfunc_target_objective to decide when this spawning point is active.
27 nobots : when set to 1, bots will never use this spawn point to respawn in the game.
28 nohumans : when set to 1, human players will never use this spawn point to respawn in the game.
29 notfree : when set to 1, entity will not spawn in "Free for all" and "Tournament" modes.
30 notteam : when set to 1, entity will not spawn in "Teamplay" and "CTF" modes.
31 notsingle : when set to 1, entity will not spawn in Single Player mode (bot play mode).
32 -------- SPAWNFLAGS --------
33 INITIAL : makes the spawnpoint the initial place for the player to spawn at the beginning of the game.*/
34 void spawnfunc_info_player_defender() {
35 self.team = COLOR_TEAM2; // blue, gets swapped every round
36 spawnfunc_info_player_deathmatch();
39 // reset this objective. Used when spawning an objective
40 // and when a new round starts
41 void assault_objective_reset() {
42 self.health = ASSAULT_VALUE_INACTIVE;
45 void assault_objective_use() {
48 self.nextthink = time + 0.1;
51 void assault_objective_think() {
57 //self.effects = EF_STARDUST;
58 self.nextthink = time + 0.1;
62 //=============================================================================
64 /*QUAKED spawnfunc_target_objective (0 .5 0) (-8 -8 -8) (8 8 8)
65 Objective controller for Nexuiz Assault. When active it has 100 health. If it falls below 0 then
66 it'll trigger the next targeted entity (usually the next objective or spawnfunc_target_assault_roundend etc.)
67 -------- KEYS --------
68 targetname : point to e.g. next objective*/
69 void spawnfunc_target_objective() {
70 self.classname = "target_objective";
71 self.think = assault_objective_think;
72 self.use = assault_objective_use;
73 assault_objective_reset();
76 float assault_objective_decrease_customizeforclient() {
81 if(other.team == assault_attacker_team)
82 if(self.spawnflags == 1)
83 setmodel(self, "models/sprites/push.sp2");
85 setmodel(self, "models/sprites/destroy.sp2");
87 setmodel(self, "models/sprites/defend.sp2");
95 void assault_objective_decrease_think() {
97 local entity objective;
100 objective = find(world, targetname, self.target);
101 while(objective && found == 0) {
102 if(objective.classname == "target_objective") {
104 if(objective.health < ASSAULT_VALUE_INACTIVE) { // targeted objective is active
105 if(self.cnt == 1 && self.max_health >= ASSAULT_VALUE_INACTIVE) {
106 // decrease was fired already, but objective did recover (round reset)
109 } else { // objective isn't active
112 self.max_health = objective.health; // save current objective status for next think
116 if(!self.spawnflags) {
118 ent = find(world, target, self.targetname);
120 if(ent.classname == "func_assault_destructible")
127 self.nextthink = time + 0.2;
131 // decrease the health of targeted objectives
132 void assault_objective_decrease_use() {
139 if(activator.team != assault_attacker_team) {
140 // wrong team triggered decrease
145 ent = find(world, targetname, self.target);
147 if(ent.health > 0 && ent.health < ASSAULT_VALUE_INACTIVE)
148 ent.health = ent.health - self.dmg;
149 ent = find(ent, targetname, self.target);
155 //=============================================================================
157 /*QUAKED target_objective_decrease (0 .5 0) (-8 -8 -8) (8 8 8)
158 When triggered decreases health of the targeted spawnfunc_target_objective.
159 -------- KEYS --------
160 targetname : point to a spawnfunc_target_objective entity*/
161 void spawnfunc_target_objective_decrease() {
163 self.classname = "target_objective_decrease";
165 precache_model("models/sprites/defend.sp2");
166 precache_model("models/sprites/destroy.sp2");
167 precache_model("models/sprites/push.sp2");
172 self.cnt = 0; // not used yet
173 self.use = assault_objective_decrease_use;
174 self.mdl = "models/sprites/here.sp2";
175 self.effects = EF_NODEPTHTEST;
176 self.health = ASSAULT_VALUE_INACTIVE;
177 self.max_health = ASSAULT_VALUE_INACTIVE;
178 self.think = assault_objective_decrease_think;
179 self.customizeentityforclient = assault_objective_decrease_customizeforclient;
180 self.nextthink = time;
184 void assault_destructible_reset() {
185 self.health = self.max_health;
186 self.model = self.mdl;
187 self.solid = SOLID_BSP;
188 self.colormod = '1 1 1';
189 self.cnt = 0; // not active
197 void assault_destructible_use() {
198 self.cnt = 1; // mark active
199 self.takedamage = DAMAGE_YES;
202 void assault_destructible_destroy() {
204 self.takedamage = DAMAGE_NO;
205 self.solid = SOLID_NOT;
209 void assault_destructible_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) {
211 if(self.cnt > 0 && assault_attacker_team == attacker.team) {
212 self.health = self.health - damage;
213 if(self.health / self.max_health < 0.25)
214 self.colormod = '1 0 0';
215 else if(self.health / self.max_health < 0.375)
216 self.colormod = '1 0.25 0';
217 else if(self.health / self.max_health < 0.50)
218 self.colormod = '1 0.5 0';
219 else if(self.health / self.max_health < 0.625)
220 self.colormod = '1 0.75 0';
221 else if(self.health / self.max_health < 0.75)
222 self.colormod = '1 1 0';
224 self.colormod = '1 1 1';
227 if(self.health < 0) {
228 activator = attacker;
229 assault_destructible_destroy();
233 // destructible walls that can be used to trigger target_objective_decrease
234 void spawnfunc_func_assault_destructible() {
238 self.max_health = self.health;
240 self.cnt = 0; // not yet activated
242 self.classname = "func_assault_destructible";
243 self.mdl = self.model;
244 setmodel(self, self.mdl);
246 self.solid = SOLID_BSP;
247 self.use = assault_destructible_use;
248 self.event_damage = assault_destructible_damage;
252 void assault_wall_think() {
254 local float notvisible;
256 ent = find(world, targetname, self.target);
258 if(ent.classname == "target_objective" && ent.health < 0)
260 ent = find(ent, targetname, self.target);
265 self.solid = SOLID_NOT;
267 self.model = self.mdl;
268 self.solid = SOLID_BSP;
271 self.nextthink = time + 0.2;
274 void spawnfunc_func_assault_wall() {
275 self.classname = "func_assault_wall";
276 self.mdl = self.model;
277 setmodel(self, self.mdl);
278 self.solid = SOLID_BSP;
279 self.think = assault_wall_think;
280 self.nextthink = time;
284 void target_assault_roundend_reset() {
285 self.cnt = self.cnt + 1; // up round counter
286 self.winning = 0; // up round
289 void target_assault_roundend_use() {
290 self.winning = 1; // round has been won by attackers
293 void spawnfunc_target_assault_roundend() {
295 self.health = 300; // 5 minutes
297 cvar_set("timelimit", ftos(self.health/60));
298 self.winning = 0; // round not yet won by attackers
299 self.classname = "target_assault_roundend";
300 self.use = target_assault_roundend_use;
301 self.cnt = 0; // first round
304 void assault_roundstart_use() {
309 #ifdef TTURRETS_ENABLED
312 //(Re)spawn all turrets
314 ent = find(world, classname, "turret_main");
317 if(ent.team == COLOR_TEAM1)
318 ent.team = COLOR_TEAM2;
320 ent.team = COLOR_TEAM1;
324 // Dubbles as teamchange
325 ent.turret_spawnfunc();
327 ent = find(ent, classname, "turret_main");
334 void spawnfunc_target_assault_roundstart() {
335 assault_attacker_team = COLOR_TEAM1;
336 self.classname = "target_assault_roundstart";
337 self.use = assault_roundstart_use;
338 self.think = assault_roundstart_use;
339 self.nextthink = time + 0.1;
343 // reset objectives, toggle spawnpoints, reset triggers, ...
344 void assault_new_round() {
347 self.winning = self.winning + 1;
348 // set end time for next round
349 self.cnt = time + self.health;
351 // swap spawn point teams
353 local entity oldself;
355 // reward attackers for winning the round
356 ent = find(world, classname, "player");
358 if(ent.team == assault_attacker_team) {
359 UpdateFrags(ent, 10);
361 ent = find(ent, classname, "player");
364 // swap attacker/defender roles
365 if(assault_attacker_team == COLOR_TEAM1) {
366 assault_attacker_team = COLOR_TEAM2;
368 assault_attacker_team = COLOR_TEAM1;
371 ent = find(world, classname, "info_player_deathmatch");
376 if(self.team == COLOR_TEAM1) {
377 self.team = COLOR_TEAM2;
379 self.team = COLOR_TEAM1;
383 ent = find(ent, classname, "info_player_deathmatch");
386 // reset all objectives
387 ent = find(world, classname, "target_objective");
392 assault_objective_reset();
395 ent = find(ent, classname, "target_objective");
398 // reset round end triggers
399 ent = find(world, classname, "target_assault_roundend");
404 target_assault_roundend_reset();
407 ent = find(ent, classname, "target_assault_roundend");
410 // reset all target_object_decrease
411 ent = find(world, classname, "target_objective_decrease");
415 ent = find(ent, classname, "target_objective_decrease");
418 // reset all spawnfunc_func_assault_destructible
419 ent = find(world, classname, "func_assault_destructible");
425 if(ent.team == COLOR_TEAM1)
426 ent.team = COLOR_TEAM2;
428 ent.team = COLOR_TEAM1;
430 assault_destructible_reset();
432 ent = find(ent, classname, "func_assault_destructible");
435 ent = find(world, classname, "target_assault_roundstart");
442 ent = find(ent, classname, "target_assault_roundstart");
445 // actually restart round... how to do that?
446 ent = find(world, classname, "player");
452 ent = find(ent, classname, "player");