1 //=============================================================================
3 /*QUAKED 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 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 info_player_attacker() {
16 info_player_deathmatch();
17 self.team = COLOR_TEAM1; // red, gets swapped every round
20 //=============================================================================
22 /*QUAKED 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 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 info_player_defender() {
35 info_player_deathmatch();
36 self.team = COLOR_TEAM2; // blue, gets swapped every round
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 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 target_assault_roundend etc.)
67 -------- KEYS --------
68 targetname : point to e.g. next objective*/
69 void 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() {
137 if(activator.team != assault_attacker_team)
141 ent = find(world, targetname, self.target);
143 if(ent.health > 0 && ent.health < ASSAULT_VALUE_INACTIVE)
144 ent.health = ent.health - self.dmg;
145 ent = find(ent, targetname, self.target);
151 //=============================================================================
153 /*QUAKED target_objective_decrease (0 .5 0) (-8 -8 -8) (8 8 8)
154 When triggered decreases health of the targeted target_objective.
155 -------- KEYS --------
156 targetname : point to a target_objective entity*/
157 void target_objective_decrease() {
159 self.classname = "target_objective_decrease";
161 precache_model("models/sprites/defend.sp2");
162 precache_model("models/sprites/destroy.sp2");
163 precache_model("models/sprites/push.sp2");
168 self.cnt = 0; // not used yet
169 self.use = assault_objective_decrease_use;
170 self.mdl = "models/sprites/here.sp2";
171 self.effects = EF_NODEPTHTEST;
172 self.health = ASSAULT_VALUE_INACTIVE;
173 self.max_health = ASSAULT_VALUE_INACTIVE;
174 self.think = assault_objective_decrease_think;
175 self.customizeentityforclient = assault_objective_decrease_customizeforclient;
176 self.nextthink = time;
180 void assault_destructible_reset() {
181 self.health = self.max_health;
182 self.model = self.mdl;
183 self.solid = SOLID_BSP;
184 self.colormod = '1 1 1';
185 self.cnt = 0; // not active
193 void assault_destructible_use() {
194 self.cnt = 1; // mark active
195 self.takedamage = DAMAGE_YES;
198 void assault_destructible_destroy() {
200 self.takedamage = DAMAGE_NO;
201 self.solid = SOLID_NOT;
206 void assault_destructible_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) {
208 if(self.cnt > 0 && assault_attacker_team == attacker.team) {
209 self.health = self.health - damage;
210 if(self.health / self.max_health < 0.25)
211 self.colormod = '1 0 0';
212 else if(self.health / self.max_health < 0.375)
213 self.colormod = '1 0.25 0';
214 else if(self.health / self.max_health < 0.50)
215 self.colormod = '1 0.5 0';
216 else if(self.health / self.max_health < 0.625)
217 self.colormod = '1 0.75 0';
218 else if(self.health / self.max_health < 0.75)
219 self.colormod = '1 1 0';
221 self.colormod = '1 1 1';
224 if(self.health < 0) {
225 activator = attacker;
226 assault_destructible_destroy();
230 // destructible walls that can be used to trigger target_objective_decrease
231 void func_assault_destructible() {
235 self.max_health = self.health;
237 self.cnt = 0; // not yet activated
239 self.classname = "func_assault_destructible";
240 self.mdl = self.model;
241 setmodel(self, self.mdl);
243 self.solid = SOLID_BSP;
244 self.use = assault_destructible_use;
245 self.event_damage = assault_destructible_damage;
249 void assault_wall_think() {
251 local float notvisible;
253 ent = find(world, targetname, self.target);
255 if(ent.classname == "target_objective" && ent.health < 0)
257 ent = find(ent, targetname, self.target);
262 self.solid = SOLID_NOT;
264 self.model = self.mdl;
265 self.solid = SOLID_BSP;
268 self.nextthink = time + 0.2;
271 void func_assault_wall() {
272 self.classname = "func_assault_wall";
273 self.mdl = self.model;
274 setmodel(self, self.mdl);
275 self.solid = SOLID_BSP;
276 self.think = assault_wall_think;
277 self.nextthink = time;
281 void target_assault_roundend_reset() {
282 self.cnt = self.cnt + 1; // up round counter
283 self.winning = 0; // up round
286 void target_assault_roundend_use() {
287 self.winning = 1; // round has been won by attackers
290 void target_assault_roundend() {
292 self.health = 300; // 5 minutes
294 cvar_set("timelimit", ftos(self.health/60));
295 self.winning = 0; // round not yet won by attackers
296 self.classname = "target_assault_roundend";
297 self.use = target_assault_roundend_use;
298 self.cnt = 0; // first round
301 void assault_roundstart_use() {
306 void target_assault_roundstart() {
307 assault_attacker_team = COLOR_TEAM1;
308 self.classname = "target_assault_roundstart";
309 self.use = assault_roundstart_use;
310 self.think = assault_roundstart_use;
311 self.nextthink = time + 0.1;
315 // reset objectives, toggle spawnpoints, reset triggers, ...
316 void assault_new_round() {
319 self.winning = self.winning + 1;
320 // set end time for next round
321 self.cnt = time + self.health;
323 // swap spawn point teams
325 local entity oldself;
327 // reward attackers for winning the round
328 ent = find(world, classname, "player");
330 if(ent.team == assault_attacker_team) {
331 UpdateFrags(ent, 10);
333 ent = find(ent, classname, "player");
336 // swap attacker/defender roles
337 if(assault_attacker_team == COLOR_TEAM1) {
338 assault_attacker_team = COLOR_TEAM2;
340 assault_attacker_team = COLOR_TEAM1;
343 ent = find(world, classname, "info_player_deathmatch");
348 if(self.team == COLOR_TEAM1) {
349 self.team = COLOR_TEAM2;
351 self.team = COLOR_TEAM1;
355 ent = find(ent, classname, "info_player_deathmatch");
358 // reset all objectives
359 ent = find(world, classname, "target_objective");
364 assault_objective_reset();
367 ent = find(ent, classname, "target_objective");
370 // reset round end triggers
371 ent = find(world, classname, "target_assault_roundend");
376 target_assault_roundend_reset();
379 ent = find(ent, classname, "target_assault_roundend");
382 // reset all target_object_decrease
383 ent = find(world, classname, "target_objective_decrease");
387 ent = find(ent, classname, "target_objective_decrease");
390 // reset all func_assault_destructible
391 ent = find(world, classname, "func_assault_destructible");
396 assault_destructible_reset();
398 ent = find(ent, classname, "func_assault_destructible");
401 ent = find(world, classname, "target_assault_roundstart");
408 ent = find(ent, classname, "target_assault_roundstart");
411 // actually restart round... how to do that?
412 ent = find(world, classname, "player");
418 ent = find(ent, classname, "player");