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 turret_stdproc_respawn();
326 //ent.turret_spawnfunc();
328 ent = find(ent, classname, "turret_main");
335 void spawnfunc_target_assault_roundstart() {
336 assault_attacker_team = COLOR_TEAM1;
337 self.classname = "target_assault_roundstart";
338 self.use = assault_roundstart_use;
339 self.think = assault_roundstart_use;
340 self.nextthink = time + 0.1;
344 // reset objectives, toggle spawnpoints, reset triggers, ...
345 void assault_new_round() {
348 self.winning = self.winning + 1;
349 // set end time for next round
350 self.cnt = time + self.health;
352 // swap spawn point teams
354 local entity oldself;
356 // reward attackers for winning the round
357 ent = find(world, classname, "player");
359 if(ent.team == assault_attacker_team) {
360 UpdateFrags(ent, 10);
362 ent = find(ent, classname, "player");
365 // swap attacker/defender roles
366 if(assault_attacker_team == COLOR_TEAM1) {
367 assault_attacker_team = COLOR_TEAM2;
369 assault_attacker_team = COLOR_TEAM1;
372 ent = find(world, classname, "info_player_deathmatch");
377 if(self.team == COLOR_TEAM1) {
378 self.team = COLOR_TEAM2;
380 self.team = COLOR_TEAM1;
384 ent = find(ent, classname, "info_player_deathmatch");
387 // reset all objectives
388 ent = find(world, classname, "target_objective");
393 assault_objective_reset();
396 ent = find(ent, classname, "target_objective");
399 // reset round end triggers
400 ent = find(world, classname, "target_assault_roundend");
405 target_assault_roundend_reset();
408 ent = find(ent, classname, "target_assault_roundend");
411 // reset all target_object_decrease
412 ent = find(world, classname, "target_objective_decrease");
416 ent = find(ent, classname, "target_objective_decrease");
419 // reset all spawnfunc_func_assault_destructible
420 ent = find(world, classname, "func_assault_destructible");
426 if(ent.team == COLOR_TEAM1)
427 ent.team = COLOR_TEAM2;
429 ent.team = COLOR_TEAM1;
431 assault_destructible_reset();
433 ent = find(ent, classname, "func_assault_destructible");
436 ent = find(world, classname, "target_assault_roundstart");
443 ent = find(ent, classname, "target_assault_roundstart");
446 // actually restart round... how to do that?
447 ent = find(world, classname, "player");
453 ent = find(ent, classname, "player");