]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_minstagib.qc
3a4bbfffdc2f57bd9702655bd92934eef425c2ed
[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         Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, 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                 minstagib_stop_countdown(self);
30         else
31         {
32                 self.minstagib_needammo = TRUE;
33                 if (self.health == 5)
34                 {
35                         Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
36                         AnnounceTo(self, "terminated");
37                 }
38                 else if (self.health == 10)
39                 {
40                         Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
41                         AnnounceTo(self, "1");
42                 }
43                 else if (self.health == 20)
44                 {
45                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
46                         AnnounceTo(self, "2");
47                 }
48                 else if (self.health == 30)
49                 {
50                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
51                         AnnounceTo(self, "3");
52                 }
53                 else if (self.health == 40)
54                 {
55                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
56                         AnnounceTo(self, "4");
57                 }
58                 else if (self.health == 50)
59                 {
60                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
61                         AnnounceTo(self, "5");
62                 }
63                 else if (self.health == 60)
64                 {
65                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
66                         AnnounceTo(self, "6");
67                 }
68                 else if (self.health == 70)
69                 {
70                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
71                         AnnounceTo(self, "7");
72                 }
73                 else if (self.health == 80)
74                 {
75                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
76                         AnnounceTo(self, "8");
77                 }
78                 else if (self.health == 90)
79                 {
80                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO);
81                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
82                         AnnounceTo(self, "9");
83                 }
84                 else if (self.health == 100)
85                 {
86                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO_FIRST);
87                         Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
88                         if not(self.flags & FL_GODMODE)
89                                 AnnounceTo(self, "10");
90                 }
91         }
92         self.minstagib_nextthink = time + 1;
93 }
94
95 MUTATOR_HOOKFUNCTION(minstagib_BotShouldAttack)
96 {
97         if(checkentity.items & IT_STRENGTH)
98                 return TRUE;
99                 
100         return FALSE;
101 }
102
103 MUTATOR_HOOKFUNCTION(minstagib_MakePlayerObserver)
104 {
105         minstagib_stop_countdown(self);
106         return FALSE;
107 }
108
109 MUTATOR_HOOKFUNCTION(minstagib_PlayerSpawn)
110 {
111         self.effects |= EF_FULLBRIGHT;
112         return FALSE;
113 }
114
115 MUTATOR_HOOKFUNCTION(minstagib_PlayerPreThink)
116 {
117         minstagib_ammocheck();
118         return FALSE;
119 }
120
121 MUTATOR_HOOKFUNCTION(minstagib_PlayerPowerups)
122 {
123         if not(self.effects & EF_FULLBRIGHT)
124                 self.effects |= EF_FULLBRIGHT;
125
126         if (self.items & IT_STRENGTH)
127         {
128                 play_countdown(self.strength_finished, "misc/poweroff.wav");
129                 if (time > self.strength_finished)
130                 {
131                         self.alpha = default_player_alpha;
132                         self.exteriorweaponentity.alpha = default_weapon_alpha;
133                         self.items &~= IT_STRENGTH;
134                         Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
135                 }
136         }
137         else
138         {
139                 if (time < self.strength_finished)
140                 {
141                         self.alpha = g_minstagib_invis_alpha;
142                         self.exteriorweaponentity.alpha = g_minstagib_invis_alpha;
143                         self.items |= IT_STRENGTH;
144                         Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
145                         Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
146                 }
147         }
148
149         if (self.items & IT_INVINCIBLE)
150         {
151                 play_countdown(self.invincible_finished, "misc/poweroff.wav");
152                 if (time > self.invincible_finished)
153                 {
154                         self.items &~= IT_INVINCIBLE;
155                         Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
156                 }
157         }
158         else
159         {
160                 if (time < self.invincible_finished)
161                 {
162                         self.items |= IT_INVINCIBLE;
163                         Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
164                         Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
165                 }
166         }
167         return FALSE;
168 }
169
170 MUTATOR_HOOKFUNCTION(minstagib_PlayerPhysics)
171 {
172         if(self.items & IT_INVINCIBLE)
173                 self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_minstagib_speed_highspeed;
174                 
175         return FALSE;
176 }
177
178 MUTATOR_HOOKFUNCTION(minstagib_SplitHealthArmor)
179 {
180         damage_save = 0;
181         //damage_take = frag_damage; // frag_damage isn't even set here?!
182         
183         return FALSE;
184 }
185
186 MUTATOR_HOOKFUNCTION(minstagib_ForbidThrowing)
187 {
188         if (self.health < 1)
189                 return FALSE;
190                 
191         return TRUE;
192 }
193
194 MUTATOR_HOOKFUNCTION(minstagib_PlayStrengthSound)
195 {
196         // You shall not play!
197         return TRUE;
198 }
199
200 MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage)
201 {
202         if(autocvar_g_friendlyfire == 0 && !IsDifferentTeam(frag_target, frag_attacker) && IS_PLAYER(frag_target))
203                 frag_damage = 0;
204                 
205         if(IS_PLAYER(frag_target))
206         {
207                 if ((frag_deathtype == DEATH_FALL)  ||
208                         (frag_deathtype == DEATH_DROWN) ||
209                         (frag_deathtype == DEATH_SLIME) ||
210                         (frag_deathtype == DEATH_LAVA))
211                 {
212                         frag_damage = 0;
213                 }
214                 
215                 if (frag_target.armorvalue && (frag_deathtype == WEP_MINSTANEX) && frag_damage)
216                 {
217                         frag_target.armorvalue -= 1;
218                         Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_MINSTA_LIVES_REMAINING, frag_target.armorvalue);
219                         frag_damage = 0;
220                         frag_target.hitsound += 1;
221                         frag_attacker.hitsound += 1; // TODO change this to a future specific hitsound for armor hit
222                 }
223                 if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
224                 {
225                         frag_damage = 0;
226                         frag_mirrordamage = 0;
227                         if (frag_target != frag_attacker)
228                         {
229                                 if ((frag_target.health >= 1) && IS_PLAYER(frag_target))
230                                         Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_SECONDARY);
231                                 frag_force = '0 0 0';
232                                 // keep mirrorfrag_force
233                                 frag_attacker = frag_target;
234                         }
235                 }
236         }
237         
238         if(frag_mirrordamage > 0)
239         {
240                 // just lose extra LIVES, don't kill the player for mirror damage
241                 if(frag_attacker.armorvalue > 0)
242                 {
243                         frag_attacker.armorvalue = frag_attacker.armorvalue - 1;
244                         Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_MINSTA_LIVES_REMAINING, frag_attacker.armorvalue);
245                         frag_attacker.hitsound += 1;
246                 }
247                 frag_mirrordamage = 0;
248         }
249         
250         if(frag_target.items & IT_STRENGTH)
251                 yoda = 1;
252                 
253         return FALSE;
254 }
255
256 MUTATOR_HOOKFUNCTION(minstagib_SetStartItems)
257 {
258         start_ammo_cells = cvar("g_minstagib_ammo_start");
259         
260         g_pinata = 0; // incompatible
261         g_weapon_stay = 0; // incompatible
262         g_bloodloss = 0; // incompatible
263         start_health = 100;
264         start_armorvalue = 0;
265         WEPSET_COPY_AW(start_weapons, WEP_MINSTANEX);
266         g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
267         start_items |= IT_UNLIMITED_SUPERWEAPONS;
268
269         if (g_minstagib_invis_alpha <= 0)
270                 g_minstagib_invis_alpha = -1;
271                 
272         return FALSE;
273 }
274
275 MUTATOR_HOOKFUNCTION(minstagib_FilterItem)
276 {
277         if(self.classname == "item_cells")
278                 return TRUE; // no normal cells?
279                 
280         if(self.weapon == WEP_MINSTANEX && self.classname == "droppedweapon")
281         {
282                 self.ammo_cells = autocvar_g_minstagib_ammo_drop;
283                 return FALSE;
284         }
285         
286         if(self.weapon == WEP_ROCKET_LAUNCHER || self.weapon == WEP_NEX)
287         {
288                 entity e = spawn();
289                 setorigin(e, self.origin);
290                 entity oldself;
291                 oldself = self;
292                 self = e;
293                 spawnfunc_item_minst_cells();
294                 self = oldself;
295                 return TRUE;
296         }
297                 
298         if(self.flags & FL_POWERUP)
299                 return FALSE;
300                 
301         if(self.ammo_cells > autocvar_g_minstagib_ammo_drop && self.classname != "item_minst_cells")
302                 self.ammo_cells = autocvar_g_minstagib_ammo_drop;
303                 
304         if(self.ammo_cells && !self.weapon)
305                 return FALSE;
306                 
307         return TRUE;
308 }
309
310 MUTATOR_HOOKFUNCTION(minstagib_ItemCountdown)
311 {
312         switch(self.items)
313         {
314                 case IT_STRENGTH:   item_name = "item-invis"; item_color = '0 0 1'; break;
315                 case IT_NAILS:      item_name = "item-extralife"; item_color = '1 0 0'; break;
316                 case IT_INVINCIBLE: item_name = "item-speed"; item_color = '1 0 1'; break;
317         }
318         return FALSE;
319 }
320
321 MUTATOR_HOOKFUNCTION(minstagib_GiveItem)
322 {
323         if(giveitem.ammo_cells)
324         {
325                 // play some cool sounds ;)
326                 if (clienttype(giveplayer) == CLIENTTYPE_REAL)
327                 {
328                         if(giveplayer.health <= 5)
329                                 AnnounceTo(giveplayer, "lastsecond");
330                         else if(giveplayer.health < 50)
331                                 AnnounceTo(giveplayer, "narrowly");
332                 }
333
334                 if(giveplayer.health < 100)
335                         giveplayer.health = 100;
336                         
337                 player_pickedup = TRUE;
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 }