]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_overkill.qc
Fix some missing stuff
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_overkill.qc
1 MUTATOR_HOOKFUNCTION(ok_PlayerDamage_Calculate)
2 {
3         if(!IS_PLAYER(frag_target) || frag_target == frag_attacker)
4                 return FALSE;
5
6         if not (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
7                 return FALSE;
8
9         frag_damage = 0;
10         if(frag_target.health >= 1 && !frag_target.freezetag_frozen)
11                 Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_SECONDARY);
12
13         frag_force = '0 0 0';
14         //frag_attacker = frag_target;
15
16         return FALSE;
17 }
18
19 MUTATOR_HOOKFUNCTION(ok_BuildMutatorsString)
20 {
21         ret_string = strcat(ret_string, ":OK");
22         return FALSE;
23 }
24
25 MUTATOR_HOOKFUNCTION(ok_BuildMutatorsPrettyString)
26 {
27         ret_string = strcat(ret_string, ", Overkill");
28         return FALSE;
29 }
30
31 void ok_Item_Touch()
32 {
33         if(IS_PLAYER(other) && other.deadflag == DEAD_NO && !other.freezetag_frozen)
34         {
35                 Item_Touch();
36                 remove(self);
37         }
38 }
39
40 MUTATOR_HOOKFUNCTION(ok_PlayerDies)
41 {
42         entity oldself = self;
43         float gpi = autocvar_g_pickup_items;
44
45         self.ok_lastwep = self.weapon;
46         self.ok_deathloc = self.origin;
47         cvar_set("g_pickup_items", "1");
48         self = spawn();
49         self.noalign = TRUE;
50         spawnfunc_item_armor_small();
51         self.movetype = MOVETYPE_TOSS;
52         self.gravity = 1;
53         setorigin(self, frag_target.origin + '0 0 32');
54         self.velocity = '0 0 200' + normalize(frag_attacker.origin - self.origin) * 500;
55         self.touch = ok_Item_Touch;
56         SUB_SetFade(self, time + 5, 1);
57         self = oldself;
58         cvar_set("g_pickup_items", ftos(gpi));
59
60         return FALSE;
61 }
62
63 MUTATOR_HOOKFUNCTION(ok_ForbidThrowCurrentWeapon)
64 {
65         return TRUE;
66 }
67
68 MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
69 {
70         if(intermission_running || gameover)
71                 return FALSE;
72
73         if(self.deadflag != DEAD_NO || !IS_PLAYER(self))
74                 return FALSE;
75
76         if(self.freezetag_frozen)
77                 return FALSE;
78
79         if(self.BUTTON_ATCK2)
80                 if(self.jump_interval <= time)
81                 {
82                         self.jump_interval = time + autocvar_g_balance_laser_primary_refire * W_WeaponRateFactor();
83                         makevectors(self.v_angle);
84                         float w = self.weapon;
85                         self.weapon = WEP_LASER;
86                         W_Laser_Attack(3);
87                         self.weapon = w;
88                 }
89
90         self.BUTTON_ATCK2 = 0;
91         return FALSE;
92 }
93
94 MUTATOR_HOOKFUNCTION(ok_PlayerSpawn)
95 {
96         if(autocvar_g_overkill_spawnsystem_delay_death)
97                 self.ok_spawnsys_timer = time + autocvar_g_overkill_spawnsystem_delay_death;
98
99         if(teamplay == 0 || autocvar_g_overkill_spawnsystem == 0)
100                 return FALSE;
101
102         entity team_mate, best_mate = world;
103         vector best_spot = '0 0 0';
104         float pc = 0., best_dist = 0., dist = 0.;
105         FOR_EACH_PLAYER(team_mate)
106         {
107                 if((autocvar_g_overkill_spawnsystem_check_health != 0 && team_mate.health >= 100) || autocvar_g_overkill_spawnsystem_check_health == 0)
108                         if(team_mate.deadflag == DEAD_NO)
109                                 if(team_mate.ok_spawnsys_timer < time)
110                                         if(team_mate.team == self.team && (g_ctf || g_tdm || g_keyhunt))
111                                                 if(team_mate != self)
112                                                 {
113                                                         tracebox(team_mate.origin, PL_MIN, PL_MAX, team_mate.origin - '0 0 100', MOVE_WORLDONLY, team_mate);
114                                                         if(trace_fraction != 1.0)
115                                                                 if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
116                                                                 {
117                                                                         pc = pointcontents(trace_endpos + '0 0 1');
118                                                                         if(pc == CONTENT_EMPTY)
119                                                                         {
120                                                                                 if(vlen(team_mate.velocity) > 5)
121                                                                                         fixedmakevectors(vectoangles(team_mate.velocity));
122                                                                                 else
123                                                                                         fixedmakevectors(team_mate.angles);
124
125                                                                                 for(pc = 0; pc != 5; ++pc) // test 5 diffrent spots close to mate
126                                                                                 {
127                                                                                         switch(pc)
128                                                                                         {
129                                                                                         case 0:
130                                                                                                 tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 128, MOVE_NORMAL, team_mate);
131                                                                                                 break;
132                                                                                         case 1:
133                                                                                                 tracebox(team_mate.origin , PL_MIN, PL_MAX,team_mate.origin - v_right * 128 , MOVE_NORMAL, team_mate);
134                                                                                                 break;
135                                                                                         case 2:
136                                                                                                 tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
137                                                                                                 break;
138                                                                                         case 3:
139                                                                                                 tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
140                                                                                                 break;
141                                                                                         case 4:
142                                                                                                 tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_forward * 128, MOVE_NORMAL, team_mate);
143                                                                                                 break;
144                                                                                         }
145
146                                                                                         if(trace_fraction == 1.0)
147                                                                                         {
148                                                                                                 traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NORMAL, team_mate);
149                                                                                                 if(trace_fraction != 1.0)
150                                                                                                 {
151                                                                                                         if(autocvar_g_overkill_spawnsystem_close2death)
152                                                                                                         {
153                                                                                                                 dist = vlen(trace_endpos - self.ok_deathloc);
154                                                                                                                 if(dist < best_dist || best_dist == 0)
155                                                                                                                 {
156                                                                                                                         best_dist = dist;
157                                                                                                                         best_spot = trace_endpos;
158                                                                                                                         best_mate = team_mate;
159                                                                                                                 }
160                                                                                                         }
161                                                                                                         else
162                                                                                                         {
163                                                                                                                 setorigin(self, trace_endpos);
164                                                                                                                 self.angles = team_mate.angles;
165                                                                                                                 team_mate.ok_spawnsys_timer = time + autocvar_g_overkill_spawnsystem_delay;
166                                                                                                                 return FALSE;
167                                                                                                         }
168                                                                                                 }
169                                                                                         }
170                                                                                 }
171                                                                         }
172                                                                 }
173                                                 }
174         }
175
176         if(autocvar_g_overkill_spawnsystem_close2death)
177                 if(best_dist)
178                 {
179                         setorigin(self, best_spot);
180                         self.angles = best_mate.angles;
181                         best_mate.ok_spawnsys_timer = time + autocvar_g_overkill_spawnsystem_delay;
182                 }
183
184         return 0;
185 }
186
187 void start_hmg()
188 {
189         float gpi = autocvar_g_pickup_items;
190         cvar_set("g_pickup_items", "1");
191         self.classname = "weapon_hmg";
192         //self.weapons = WEP_HMG;
193         //self.flags |= FL_POWERUP;
194         self.respawntime = autocvar_g_overkill_superguns_respawn_time;
195         setmodel(self, "models/weapons/g_ok_hmg.md3");
196         spawnfunc_weapon_hmg();
197
198         cvar_set("g_pickup_items", ftos(gpi));
199 }
200
201 void start_rpc()
202 {
203         float gpi = autocvar_g_pickup_items;
204         cvar_set("g_pickup_items", "1");
205         self.classname = "weapon_rpc";
206         self.respawntime = autocvar_g_overkill_superguns_respawn_time;
207         //self.weapons = WEP_RPC;
208         //self.flags |= FL_POWERUP;
209         setmodel(self, "models/weapons/g_ok_rl.md3");
210         spawnfunc_weapon_rpc();
211         cvar_set("g_pickup_items", ftos(gpi));
212 }
213
214 void start_mh_anyway()
215 {
216         cvar_set("g_pickup_items", "1");
217         self.classname = "item_health_mega";
218         spawnfunc_item_health_mega();
219         cvar_set("g_pickup_items", "0");
220 }
221
222 void start_ma_anyway()
223 {
224         cvar_set("g_pickup_items", "1");
225         self.classname = "item_armor_large";
226         spawnfunc_item_armor_large();
227         cvar_set("g_pickup_items", "0");
228 }
229
230 MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
231 {
232         if(autocvar_g_powerups != 0)
233         if(autocvar_g_overkill_powerups_replace)
234         if(self.classname == "item_strength")
235         {
236                 entity wep = spawn();
237                 setorigin(wep, self.origin);
238                 wep.think = start_hmg;
239                 wep.nextthink = time + 0.1;
240                 return TRUE;
241         }
242
243         if(autocvar_g_powerups != 0)
244         if(autocvar_g_overkill_powerups_replace)
245         if(self.classname == "item_invincible")
246         {
247                 entity wep = spawn();
248                 setorigin(wep, self.origin);
249                 wep.think = start_rpc;
250                 wep.nextthink = time + 0.1;
251                 return TRUE;
252         }
253
254         return FALSE;
255 }
256
257 MUTATOR_HOOKFUNCTION(ok_ItemRemove)
258 {
259         switch(self.items)
260         {
261                 case IT_HEALTH: return !(autocvar_g_overkill_100h_anyway);
262                 case IT_ARMOR: return !(autocvar_g_overkill_100a_anyway);
263         }
264         
265         return TRUE;
266 }
267
268 MUTATOR_HOOKFUNCTION(ok_SetModname)
269 {
270         modname = "Overkill";
271         return TRUE;
272 }
273
274 MUTATOR_HOOKFUNCTION(ok_StartItems)
275 {
276         start_items |= IT_UNLIMITED_WEAPON_AMMO;
277         start_weapons = (WEPSET_UZI | WEPSET_NEX | WEPSET_SHOTGUN);
278
279         start_ammo_nails = start_ammo_cells = start_ammo_shells = start_ammo_rockets =
280         warmup_start_ammo_nails = warmup_start_ammo_cells = warmup_start_ammo_shells = warmup_start_ammo_rockets = autocvar_g_overkill_ammo_start;
281
282         return FALSE;
283 }
284
285 void ok_Initialize()
286 {
287         precache_all_playermodels("models/ok_player/*.dpm");
288
289         precache_model("models/weapons/h_ok_rl.iqm");
290         precache_model("models/weapons/v_ok_rl.md3");
291         precache_model("models/weapons/g_ok_rl.md3");
292         precache_model("models/weapons/ok_rocket.md3");
293
294         precache_model("models/weapons/h_ok_mg.iqm");
295         precache_model("models/weapons/v_ok_mg.md3");
296         precache_model("models/weapons/g_ok_mg.md3");
297
298         precache_model("models/weapons/h_ok_hmg.iqm");
299         precache_model("models/weapons/v_ok_hmg.md3");
300         precache_model("models/weapons/g_ok_hmg.md3");
301
302         precache_model("models/weapons/h_ok_shotgun.iqm");
303         precache_model("models/weapons/v_ok_shotgun.md3");
304         precache_model("models/weapons/g_ok_shotgun.md3");
305
306         precache_model("models/weapons/h_ok_sniper.iqm");
307         precache_model("models/weapons/v_ok_sniper.md3");
308         precache_model("models/weapons/g_ok_sniper.md3");
309
310         w_uzi(WR_PRECACHE);
311         w_nex(WR_PRECACHE);
312         w_shotgun(WR_PRECACHE);
313         w_laser(WR_PRECACHE);
314
315         (get_weaponinfo(WEP_RPC)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
316         (get_weaponinfo(WEP_HMG)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
317
318         (get_weaponinfo(WEP_SHOTGUN)).mdl = "ok_shotgun";
319         (get_weaponinfo(WEP_UZI)).mdl = "ok_mg";
320         (get_weaponinfo(WEP_NEX)).mdl = "ok_sniper";
321
322         string s;
323         float fh = fopen("overkill.cfg", FILE_READ);
324         if(fh >= 0)
325         {
326                 while((s = fgets(fh)))
327                 {
328                         tokenize_console(s);
329                         if not(argv(0) == "" || argv(1) == "//" || argv(1) == "")
330                                 cvar_settemp(argv(0), argv(1));
331                 }
332                 fclose(fh);
333         }
334         else
335                 dprint("^1Mutator Overkill: WARNING! overkill.cfg NOT found, things will be strange!\n");
336 }
337
338 MUTATOR_DEFINITION(mutator_overkill)
339 {
340         MUTATOR_HOOK(ForbidThrowCurrentWeapon, ok_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
341         MUTATOR_HOOK(BuildMutatorsString, ok_BuildMutatorsString, CBC_ORDER_ANY);
342         MUTATOR_HOOK(BuildMutatorsPrettyString, ok_BuildMutatorsPrettyString, CBC_ORDER_ANY);
343         MUTATOR_HOOK(PlayerPreThink, ok_PlayerPreThink, CBC_ORDER_LAST);
344         MUTATOR_HOOK(PlayerSpawn, ok_PlayerSpawn, CBC_ORDER_LAST);
345         MUTATOR_HOOK(PlayerDamage_Calculate, ok_PlayerDamage_Calculate, CBC_ORDER_LAST);
346         MUTATOR_HOOK(PlayerDies, ok_PlayerDies, CBC_ORDER_ANY);
347         MUTATOR_HOOK(OnEntityPreSpawn, ok_OnEntityPreSpawn, CBC_ORDER_ANY);
348         MUTATOR_HOOK(SetModname, ok_SetModname, CBC_ORDER_ANY);
349         MUTATOR_HOOK(FilterItem, ok_ItemRemove, CBC_ORDER_ANY);
350         MUTATOR_HOOK(SetStartItems, ok_StartItems, CBC_ORDER_ANY);
351
352         MUTATOR_ONADD
353         {
354                 ok_Initialize();
355         }
356
357         MUTATOR_ONREMOVE
358         {
359                 (get_weaponinfo(WEP_RPC)).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
360                 (get_weaponinfo(WEP_HMG)).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
361         }
362
363         return FALSE;
364 }