]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/server/assault.qc
Initial checkout of Vore Tournament 0.1.alpha.
[voretournament/voretournament.git] / data / qcsrc / server / assault.qc
1 void spawnfunc_func_breakable();\r
2 void target_objective_decrease_activate();\r
3 .entity assault_decreaser;\r
4 .entity assault_sprite;\r
5 \r
6 void spawnfunc_info_player_attacker() {\r
7         if(!g_assault)\r
8         {\r
9                 remove(self);\r
10                 return;\r
11         }\r
12         self.team = COLOR_TEAM1; // red, gets swapped every round\r
13         spawnfunc_info_player_deathmatch();\r
14 }\r
15 \r
16 void spawnfunc_info_player_defender() {\r
17         if(!g_assault)\r
18         {\r
19                 remove(self);\r
20                 return;\r
21         }\r
22         self.team = COLOR_TEAM2; // blue, gets swapped every round\r
23         spawnfunc_info_player_deathmatch();\r
24 }\r
25 \r
26 // reset this objective. Used when spawning an objective\r
27 // and when a new round starts\r
28 void assault_objective_reset() {\r
29         self.health = ASSAULT_VALUE_INACTIVE;\r
30 }\r
31 \r
32 void assault_objective_use() {\r
33         if(other.classname == "info_player_deathmatch") // a spawn, a spawn\r
34                 return;\r
35 \r
36         // activate objective\r
37         self.health = 100;\r
38         //print("^2Activated objective ", self.targetname, "=", etos(self), "\n");\r
39         //print("Activator is ", activator.classname, "\n");\r
40 \r
41         entity oldself;\r
42         oldself = self;\r
43 \r
44         for(self = world; (self = find(self, target, oldself.targetname)); )\r
45         {\r
46                 if(self.classname == "target_objective_decrease")\r
47                         target_objective_decrease_activate();\r
48         }\r
49 \r
50         self = oldself;\r
51 }\r
52 \r
53 void spawnfunc_target_objective() {\r
54         if(!g_assault)\r
55         {\r
56                 remove(self);\r
57                 return;\r
58         }\r
59         self.classname = "target_objective";\r
60         self.use = assault_objective_use;\r
61         assault_objective_reset();\r
62         self.reset = assault_objective_reset;\r
63 }\r
64 \r
65 \r
66 // decrease the health of targeted objectives\r
67 void assault_objective_decrease_use() {\r
68         if(activator.team != assault_attacker_team) {\r
69                 // wrong team triggered decrease\r
70                 return;\r
71         }\r
72 \r
73         if(other.assault_sprite.classname == "assault_decreaser_sprite")\r
74                 WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime);\r
75         else\r
76                 return; // already activated! cannot activate again!\r
77 \r
78         if(self.enemy.health < ASSAULT_VALUE_INACTIVE)\r
79         {\r
80                 if(self.enemy.health - self.dmg > 0.5)\r
81                 {\r
82                         PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.dmg);\r
83                         self.enemy.health = self.enemy.health - self.dmg;\r
84                 }\r
85                 else\r
86                 {\r
87                         PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.enemy.health);\r
88                         PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1);\r
89                         self.enemy.health = -1;\r
90 \r
91                         entity oldself, oldactivator;\r
92 \r
93                         oldself = self;\r
94                         self = oldself.enemy;\r
95                                 oldactivator = activator;\r
96                                 activator = oldself;\r
97                                         SUB_UseTargets();\r
98                                 activator = oldactivator;\r
99                         self = oldself;\r
100                 }\r
101         }\r
102 }\r
103 \r
104 void assault_setenemytoobjective()\r
105 {\r
106         local entity objective;\r
107         for(objective = world; (objective = find(objective, targetname, self.target)); ) {\r
108                 if(objective.classname == "target_objective") {\r
109                         if(self.enemy == world)\r
110                                 self.enemy = objective;\r
111                         else\r
112                                 objerror("more than one objective as target - fix the map!");\r
113                         break;\r
114                 }\r
115         }\r
116 \r
117         if(self.enemy == world)\r
118                 objerror("no objective as target - fix the map!");\r
119 }\r
120 \r
121 float assault_decreaser_sprite_visible(entity e)\r
122 {\r
123         entity decreaser;\r
124 \r
125         decreaser = self.assault_decreaser;\r
126 \r
127         if(decreaser.enemy.health >= ASSAULT_VALUE_INACTIVE)\r
128                 return FALSE;\r
129 \r
130         return TRUE;\r
131 }\r
132 \r
133 void target_objective_decrease_activate()\r
134 {\r
135         entity ent, spr;\r
136         self.owner = world;\r
137         for(ent = world; (ent = find(ent, target, self.targetname)); )\r
138         {\r
139                 if(ent.assault_sprite != world)\r
140                         WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime);\r
141 \r
142                 spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite);\r
143                 spr.assault_decreaser = self;\r
144                 spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible;\r
145                 spr.classname = "assault_decreaser_sprite";\r
146                 WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY);\r
147                 if(ent.classname == "func_assault_destructible")\r
148                         WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy");\r
149                 else\r
150                         WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push");\r
151                 WaypointSprite_UpdateTeamRadar(spr, RADARICON_OBJECTIVE, '1 0.5 0');\r
152         }\r
153 }\r
154 \r
155 void target_objective_decrease_findtarget()\r
156 {\r
157         assault_setenemytoobjective();\r
158 }\r
159 \r
160 //=============================================================================\r
161 \r
162 void spawnfunc_target_objective_decrease() {\r
163         if(!g_assault)\r
164         {\r
165                 remove(self);\r
166                 return;\r
167         }\r
168 \r
169         self.classname = "target_objective_decrease";\r
170 \r
171         if(!self.dmg) {\r
172                 self.dmg = 101;\r
173         }\r
174         self.use = assault_objective_decrease_use;\r
175         self.health = ASSAULT_VALUE_INACTIVE;\r
176         self.max_health = ASSAULT_VALUE_INACTIVE;\r
177         self.enemy = world;\r
178 \r
179         InitializeEntity(self, target_objective_decrease_findtarget, INITPRIO_FINDTARGET);\r
180 }\r
181 \r
182 // destructible walls that can be used to trigger target_objective_decrease\r
183 void spawnfunc_func_assault_destructible() {\r
184         if(!g_assault)\r
185         {\r
186                 remove(self);\r
187                 return;\r
188         }\r
189         self.spawnflags = 3;\r
190         spawnfunc_func_breakable();\r
191 }\r
192 \r
193 void assault_wall_think() {\r
194         if(self.enemy.health < 0) {\r
195                 self.model = "";\r
196                 self.solid = SOLID_NOT;\r
197         } else {\r
198                 self.model = self.mdl;\r
199                 self.solid = SOLID_BSP;\r
200         }\r
201 \r
202         self.nextthink = time + 0.2;\r
203 }\r
204 \r
205 void spawnfunc_func_assault_wall() {\r
206         if(!g_assault)\r
207         {\r
208                 remove(self);\r
209                 return;\r
210         }\r
211         self.classname = "func_assault_wall";\r
212         self.mdl = self.model;\r
213         setmodel(self, self.mdl);\r
214         self.solid = SOLID_BSP;\r
215         self.think = assault_wall_think;\r
216         self.nextthink = time;\r
217         InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET);\r
218 }\r
219 \r
220 \r
221 void target_assault_roundend_reset() {\r
222         //print("round end reset\n");\r
223         self.cnt = self.cnt + 1; // up round counter\r
224         self.winning = 0; // up round\r
225 }\r
226 \r
227 void target_assault_roundend_use() {\r
228         self.winning = 1; // round has been won by attackers\r
229 }\r
230 \r
231 void spawnfunc_target_assault_roundend() {\r
232         if(!g_assault)\r
233         {\r
234                 remove(self);\r
235                 return;\r
236         }\r
237         self.winning = 0; // round not yet won by attackers\r
238         self.classname = "target_assault_roundend";\r
239         self.use = target_assault_roundend_use;\r
240         self.cnt = 0; // first round\r
241         self.reset = target_assault_roundend_reset;\r
242 }\r
243 \r
244 void assault_roundstart_use() {\r
245 \r
246         activator = self;\r
247         SUB_UseTargets();\r
248 \r
249         /*\r
250 #ifdef TTURRETS_ENABLED\r
251 entity ent,oldself;\r
252 \r
253         //(Re)spawn all turrets\r
254         oldself = self;\r
255         ent = find(world, classname, "turret_main");\r
256         while(ent) {\r
257         // Swap turret teams\r
258         if(ent.team == COLOR_TEAM1)\r
259         ent.team = COLOR_TEAM2;\r
260         else\r
261         ent.team = COLOR_TEAM1;\r
262 \r
263         self = ent;\r
264 \r
265         // Dubbles as teamchange\r
266         turret_stdproc_respawn();\r
267         //ent.turret_spawnfunc();\r
268 \r
269         ent = find(ent, classname, "turret_main");\r
270         }\r
271         self = oldself;\r
272 #endif\r
273 */\r
274 \r
275 }\r
276 \r
277 void spawnfunc_target_assault_roundstart() {\r
278         if(!g_assault)\r
279         {\r
280                 remove(self);\r
281                 return;\r
282         }\r
283         assault_attacker_team = COLOR_TEAM1;\r
284         self.classname = "target_assault_roundstart";\r
285         self.use = assault_roundstart_use;\r
286         self.reset2 = assault_roundstart_use;\r
287         InitializeEntity(self, assault_roundstart_use, INITPRIO_FINDTARGET);\r
288 }\r
289 \r
290 // trigger new round\r
291 // reset objectives, toggle spawnpoints, reset triggers, ...\r
292 void assault_new_round() {\r
293         //bprint("ASSAULT: new round\n");\r
294 \r
295         // up round counter\r
296         self.winning = self.winning + 1;\r
297 \r
298         // swap attacker/defender roles\r
299         if(assault_attacker_team == COLOR_TEAM1) {\r
300                 assault_attacker_team = COLOR_TEAM2;\r
301         } else {\r
302                 assault_attacker_team = COLOR_TEAM1;\r
303         }\r
304 \r
305 \r
306         local entity ent;\r
307         for(ent = world; (ent = nextent(ent)); )\r
308         {\r
309                 if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)\r
310                 {\r
311                         if(ent.team_saved == COLOR_TEAM1)\r
312                                 ent.team_saved = COLOR_TEAM2;\r
313                         else if(ent.team_saved == COLOR_TEAM2)\r
314                                 ent.team_saved = COLOR_TEAM1;\r
315                 }\r
316         }\r
317 \r
318         // reset the level with a countdown\r
319         cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60));\r
320         ReadyRestartForce(); // sets game_starttime\r
321 }\r