]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_minstagib.qc
Fix a missing mutator hook
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_minstagib.qc
1 void spawnfunc_item_minst_cells (void) 
2 {
3         if not(g_minstagib) { remove(self); return; }
4         if not(self.ammo_cells)
5                 self.ammo_cells = autocvar_g_minstagib_ammo_drop;
6                 
7         StartItem ("models/items/a_cells.md3",
8                            "misc/itempickup.wav", 45, 0,
9                            "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
10 }
11
12 .float minstagib_nextthink;
13 .float minstagib_needammo;
14 void minstagib_stop_countdown(entity e)
15 {
16         if (!e.minstagib_needammo)
17                 return;
18         Send_CSQC_Centerprint_Generic_Expire(e, CPID_MINSTA_FINDAMMO);
19         e.minstagib_needammo = FALSE;
20 }
21 void minstagib_ammocheck(void)
22 {
23         if (time < self.minstagib_nextthink)
24                 return;
25
26         if (self.deadflag || gameover)
27                 minstagib_stop_countdown(self);
28         else if (self.ammo_cells > 0 || (self.items & IT_UNLIMITED_WEAPON_AMMO))
29         {
30                 minstagib_stop_countdown(self);
31                 if(self.health < 100)
32                         self.health = 100;
33         }
34         else
35         {
36                 self.minstagib_needammo = TRUE;
37                 if (self.health == 5)
38                 {
39                         Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
40                         AnnounceTo(self, "terminated");
41                 }
42                 else if (self.health == 10)
43                 {
44                         Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
45                         AnnounceTo(self, "1");
46                 }
47                 else if (self.health == 20)
48                 {
49                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
50                         AnnounceTo(self, "2");
51                 }
52                 else if (self.health == 30)
53                 {
54                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
55                         AnnounceTo(self, "3");
56                 }
57                 else if (self.health == 40)
58                 {
59                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
60                         AnnounceTo(self, "4");
61                 }
62                 else if (self.health == 50)
63                 {
64                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
65                         AnnounceTo(self, "5");
66                 }
67                 else if (self.health == 60)
68                 {
69                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
70                         AnnounceTo(self, "6");
71                 }
72                 else if (self.health == 70)
73                 {
74                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
75                         AnnounceTo(self, "7");
76                 }
77                 else if (self.health == 80)
78                 {
79                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
80                         AnnounceTo(self, "8");
81                 }
82                 else if (self.health == 90)
83                 {
84                         Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "^1%d^7 seconds left to find some ammo", 1, 9);
85                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
86                         AnnounceTo(self, "9");
87                 }
88                 else if (self.health == 100)
89                 {
90                         Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "get some ammo or\nyou'll be dead in ^3%d^7 seconds...", 1, 10);
91                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
92                         if not(self.flags & FL_GODMODE)
93                                 AnnounceTo(self, "10");
94                 }
95         }
96         self.minstagib_nextthink = time + 1;
97 }
98
99 MUTATOR_HOOKFUNCTION(minstagib_BotShouldAttack)
100 {
101         if(checkentity.items & IT_STRENGTH)
102                 return TRUE;
103                 
104         return FALSE;
105 }
106
107 MUTATOR_HOOKFUNCTION(minstagib_MakePlayerObserver)
108 {
109         minstagib_stop_countdown(self);
110         return FALSE;
111 }
112
113 MUTATOR_HOOKFUNCTION(minstagib_PlayerSpawn)
114 {
115         self.effects |= EF_FULLBRIGHT;
116         return FALSE;
117 }
118
119 MUTATOR_HOOKFUNCTION(minstagib_PlayerPreThink)
120 {
121         minstagib_ammocheck();
122         return FALSE;
123 }
124
125 MUTATOR_HOOKFUNCTION(minstagib_PlayerPowerups)
126 {
127         if not(self.effects & EF_FULLBRIGHT)
128                 self.effects |= EF_FULLBRIGHT;
129
130         if (self.items & IT_STRENGTH)
131         {
132                 play_countdown(self.strength_finished, "misc/poweroff.wav");
133                 if (time > self.strength_finished)
134                 {
135                         self.alpha = default_player_alpha;
136                         self.exteriorweaponentity.alpha = default_weapon_alpha;
137                         self.items &~= IT_STRENGTH;
138                         sprint(self, "^3Invisibility has worn off\n");
139                 }
140         }
141         else
142         {
143                 if (time < self.strength_finished)
144                 {
145                         self.alpha = g_minstagib_invis_alpha;
146                         self.exteriorweaponentity.alpha = g_minstagib_invis_alpha;
147                         self.items |= IT_STRENGTH;
148                         sprint(self, "^3You are invisible\n");
149                 }
150         }
151
152         if (self.items & IT_INVINCIBLE)
153         {
154                 play_countdown(self.invincible_finished, "misc/poweroff.wav");
155                 if (time > self.invincible_finished)
156                 {
157                         self.items &~= IT_INVINCIBLE;
158                         sprint(self, "^3Speed has worn off\n");
159                 }
160         }
161         else
162         {
163                 if (time < self.invincible_finished)
164                 {
165                         self.items |= IT_INVINCIBLE;
166                         sprint(self, "^3You are on speed\n");
167                 }
168         }
169         return FALSE;
170 }
171
172 MUTATOR_HOOKFUNCTION(minstagib_PlayerPhysics)
173 {
174         if(self.items & IT_INVINCIBLE)
175                 self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_minstagib_speed_highspeed;
176                 
177         return FALSE;
178 }
179
180 MUTATOR_HOOKFUNCTION(minstagib_SplitHealthArmor)
181 {
182         damage_save = 0;
183         damage_take = frag_damage;
184         
185         return FALSE;
186 }
187
188 MUTATOR_HOOKFUNCTION(minstagib_ForbidThrowing)
189 {
190         if (self.health < 1)
191                 return FALSE;
192                 
193         return TRUE;
194 }
195
196 MUTATOR_HOOKFUNCTION(minstagib_PlayStrengthSound)
197 {
198         // You shall not play!
199         return TRUE;
200 }
201
202 MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage)
203 {
204         if(autocvar_g_friendlyfire == 0)
205                 frag_damage = 0;
206                 
207         if(frag_target.classname == "player")
208         {
209                 if ((frag_deathtype == DEATH_FALL)  ||
210                         (frag_deathtype == DEATH_DROWN) ||
211                         (frag_deathtype == DEATH_SLIME) ||
212                         (frag_deathtype == DEATH_LAVA))
213                 {
214                         frag_damage = 0;
215                 }
216                 
217                 if (frag_target.armorvalue && (frag_deathtype == WEP_MINSTANEX) && frag_damage)
218                 {
219                         frag_target.armorvalue -= 1;
220                         centerprint(frag_target, strcat("^3Remaining extra lives: ",ftos(frag_target.armorvalue)));
221                         frag_damage = 0;
222                         frag_target.hitsound += 1;
223                         frag_attacker.hitsound += 1; // TODO change this to a future specific hitsound for armor hit
224                 }
225                 if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
226                 {
227                         frag_damage = 0;
228                         frag_mirrordamage = 0;
229                         if (frag_target != frag_attacker)
230                         {
231                                 if ((frag_target.health >= 1) && (frag_target.classname == "player"))
232                                         centerprint(frag_attacker, "Secondary fire inflicts no damage!");
233                                 frag_force = '0 0 0';
234                                 // keep mirrorfrag_force
235                                 frag_attacker = frag_target;
236                         }
237                 }
238         }
239         
240         if(frag_mirrordamage > 0)
241         {
242                 // just lose extra LIVES, don't kill the player for mirror damage
243                 if(frag_attacker.armorvalue > 0)
244                 {
245                         frag_attacker.armorvalue = frag_attacker.armorvalue - 1;
246                         centerprint(frag_attacker, strcat("^3Remaining extra lives: ", ftos(frag_attacker.armorvalue)));
247                         frag_attacker.hitsound += 1;
248                 }
249                 frag_mirrordamage = 0;
250         }
251         
252         if(frag_target.items & IT_STRENGTH)
253                 yoda = 1;
254                 
255         return FALSE;
256 }
257
258 MUTATOR_HOOKFUNCTION(minstagib_SetStartItems)
259 {
260         start_ammo_cells = cvar("g_minstagib_ammo_start");
261         
262         g_pinata = 0; // incompatible
263         g_weapon_stay = 0; // incompatible
264         g_bloodloss = 0; // incompatible
265         start_health = 100;
266         start_armorvalue = 0;
267         WEPSET_COPY_AW(start_weapons, WEP_MINSTANEX);
268         g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
269         start_items |= IT_UNLIMITED_SUPERWEAPONS;
270
271         if (g_minstagib_invis_alpha <= 0)
272                 g_minstagib_invis_alpha = -1;
273                 
274         return FALSE;
275 }
276
277 MUTATOR_HOOKFUNCTION(minstagib_FilterItem)
278 {
279         if(self.classname == "item_cells")
280                 return TRUE; // no normal cells?
281                 
282         if(self.weapon == WEP_MINSTANEX && self.classname == "droppedweapon")
283         {
284                 self.ammo_cells = autocvar_g_minstagib_ammo_drop;
285                 return FALSE;
286         }
287         
288         if(self.weapon == WEP_ROCKET_LAUNCHER || self.weapon == WEP_NEX)
289         {
290                 entity e = spawn();
291                 setorigin(e, self.origin);
292                 entity oldself;
293                 oldself = self;
294                 self = e;
295                 spawnfunc_item_minst_cells();
296                 self = oldself;
297                 return TRUE;
298         }
299                 
300         if(self.flags & FL_POWERUP)
301                 return FALSE;
302                 
303         if(self.ammo_cells > autocvar_g_minstagib_ammo_drop && self.classname != "item_minst_cells")
304                 self.ammo_cells = autocvar_g_minstagib_ammo_drop;
305                 
306         if(self.ammo_cells && !self.weapon)
307                 return FALSE;
308                 
309         return TRUE;
310 }
311
312 MUTATOR_HOOKFUNCTION(minstagib_ItemCountdown)
313 {
314         switch(self.items)
315         {
316                 case IT_STRENGTH:   item_name = "item-invis"; item_color = '0 0 1'; break;
317                 case IT_NAILS:      item_name = "item-extralife"; item_color = '1 0 0'; break;
318                 case IT_INVINCIBLE: item_name = "item-speed"; item_color = '1 0 1'; break;
319         }
320         return FALSE;
321 }
322
323 MUTATOR_HOOKFUNCTION(minstagib_GiveItem)
324 {
325         if(giveitem.ammo_cells)
326         {
327                 // play some cool sounds ;)
328                 if (clienttype(giveplayer) == CLIENTTYPE_REAL)
329                 {
330                         if(giveplayer.health <= 5)
331                                 AnnounceTo(giveplayer, "lastsecond");
332                         else if(giveplayer.health < 50)
333                                 AnnounceTo(giveplayer, "narrowly");
334                 }
335
336                 if(giveplayer.health < 100)
337                         giveplayer.health = 100;
338         }
339                 
340         return TRUE;
341 }
342
343 MUTATOR_HOOKFUNCTION(minstagib_BuildMutatorsString)
344 {
345         ret_string = strcat(ret_string, ":MinstaGib");
346         return FALSE;
347 }
348
349 MUTATOR_HOOKFUNCTION(minstagib_BuildMutatorsPrettyString)
350 {
351         ret_string = strcat(ret_string, ", MinstaGib");
352         return FALSE;
353 }
354
355 MUTATOR_DEFINITION(mutator_minstagib)
356 {
357         MUTATOR_HOOK(BotShouldAttack, minstagib_BotShouldAttack, CBC_ORDER_ANY);
358         MUTATOR_HOOK(PlayerPhysics, minstagib_PlayerPhysics, CBC_ORDER_ANY);
359         MUTATOR_HOOK(PlayerSpawn, minstagib_PlayerSpawn, CBC_ORDER_ANY);
360         MUTATOR_HOOK(PlayerDamage_Calculate, minstagib_PlayerDamage, CBC_ORDER_ANY);
361         MUTATOR_HOOK(PlayStrengthSound, minstagib_PlayStrengthSound, CBC_ORDER_ANY);
362         MUTATOR_HOOK(MakePlayerObserver, minstagib_MakePlayerObserver, CBC_ORDER_ANY);
363         MUTATOR_HOOK(SetStartItems, minstagib_SetStartItems, CBC_ORDER_ANY);
364         MUTATOR_HOOK(Item_GiveTo, minstagib_GiveItem, CBC_ORDER_ANY);
365         MUTATOR_HOOK(FilterItem, minstagib_FilterItem, CBC_ORDER_ANY);
366         MUTATOR_HOOK(Item_RespawnCountdown, minstagib_ItemCountdown, CBC_ORDER_ANY);
367         MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, minstagib_SplitHealthArmor, CBC_ORDER_ANY);
368         MUTATOR_HOOK(PlayerPowerups, minstagib_PlayerPowerups, CBC_ORDER_ANY);
369         MUTATOR_HOOK(ForbidThrowCurrentWeapon, minstagib_ForbidThrowing, CBC_ORDER_ANY);
370         MUTATOR_HOOK(PlayerPreThink, minstagib_PlayerPreThink, CBC_ORDER_ANY);
371         MUTATOR_HOOK(BuildMutatorsString, minstagib_BuildMutatorsString, CBC_ORDER_ANY);
372         MUTATOR_HOOK(BuildMutatorsPrettyString, minstagib_BuildMutatorsPrettyString, CBC_ORDER_ANY);
373
374         return FALSE;
375 }