]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/nix/nix.qc
Merge branch 'master' into TimePath/csqc_viewmodels
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / nix / nix.qc
1 #ifdef IMPLEMENTATION
2 int autocvar_g_balance_nix_ammo_cells;
3 int autocvar_g_balance_nix_ammo_plasma;
4 int autocvar_g_balance_nix_ammo_fuel;
5 int autocvar_g_balance_nix_ammo_nails;
6 int autocvar_g_balance_nix_ammo_rockets;
7 int autocvar_g_balance_nix_ammo_shells;
8 int autocvar_g_balance_nix_ammoincr_cells;
9 int autocvar_g_balance_nix_ammoincr_plasma;
10 int autocvar_g_balance_nix_ammoincr_fuel;
11 int autocvar_g_balance_nix_ammoincr_nails;
12 int autocvar_g_balance_nix_ammoincr_rockets;
13 int autocvar_g_balance_nix_ammoincr_shells;
14 float autocvar_g_balance_nix_incrtime;
15 float autocvar_g_balance_nix_roundtime;
16 bool autocvar_g_nix_with_healtharmor;
17 bool autocvar_g_nix_with_blaster;
18 bool autocvar_g_nix_with_powerups;
19 int autocvar_g_pickup_cells_max;
20 int autocvar_g_pickup_plasma_max;
21 int autocvar_g_pickup_fuel_max;
22 int autocvar_g_pickup_nails_max;
23 int autocvar_g_pickup_rockets_max;
24 int autocvar_g_pickup_shells_max;
25
26 float g_nix_with_blaster;
27 // WEAPONTODO
28 int nix_weapon;
29 float nix_nextchange;
30 float nix_nextweapon;
31 .float nix_lastchange_id;
32 .float nix_lastinfotime;
33 .float nix_nextincr;
34
35 bool NIX_CanChooseWeapon(int wpn);
36
37 REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"))
38 {
39         MUTATOR_ONADD
40         {
41                 g_nix_with_blaster = autocvar_g_nix_with_blaster;
42
43                 nix_nextchange = 0;
44                 nix_nextweapon = 0;
45
46                 for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
47                         if (NIX_CanChooseWeapon(i)) {
48                                 Weapon w = get_weaponinfo(i);
49                                 w.wr_init(w);
50                         }
51         }
52
53         MUTATOR_ONROLLBACK_OR_REMOVE
54         {
55                 // nothing to roll back
56         }
57
58         MUTATOR_ONREMOVE
59         {
60                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
61                 entity e;
62                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
63                 {
64                         e.ammo_cells = start_ammo_cells;
65                         e.ammo_plasma = start_ammo_plasma;
66                         e.ammo_shells = start_ammo_shells;
67                         e.ammo_nails = start_ammo_nails;
68                         e.ammo_rockets = start_ammo_rockets;
69                         e.ammo_fuel = start_ammo_fuel;
70                         e.weapons = start_weapons;
71                         if(!client_hasweapon(e, e.weapon, true, false))
72                                 e.switchweapon = w_getbestweapon(self);
73                 }
74         }
75
76         return 0;
77 }
78
79 bool NIX_CanChooseWeapon(int wpn)
80 {
81         entity e = get_weaponinfo(wpn);
82         if(!e.weapon) // skip dummies
83                 return false;
84         if(g_weaponarena)
85         {
86                 if(!(g_weaponarena_weapons & WepSet_FromWeapon(wpn)))
87                         return false;
88         }
89         else
90         {
91                 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
92                         return false;
93                 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
94                         return false;
95                 if (!(e.spawnflags & WEP_FLAG_NORMAL))
96                         return false;
97         }
98         return true;
99 }
100 void NIX_ChooseNextWeapon()
101 {
102         float j;
103         RandomSelection_Init();
104         for(j = WEP_FIRST; j <= WEP_LAST; ++j)
105                 if(NIX_CanChooseWeapon(j))
106                         RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
107         nix_nextweapon = RandomSelection_chosen_float;
108 }
109
110 void NIX_GiveCurrentWeapon()
111 {SELFPARAM();
112         float dt;
113
114         if(!nix_nextweapon)
115                 NIX_ChooseNextWeapon();
116
117         dt = ceil(nix_nextchange - time);
118
119         if(dt <= 0)
120         {
121                 nix_weapon = nix_nextweapon;
122                 nix_nextweapon = 0;
123                 if (!nix_nextchange) // no round played yet?
124                         nix_nextchange = time; // start the first round now!
125                 else
126                         nix_nextchange = time + autocvar_g_balance_nix_roundtime;
127                 // Weapon w = get_weaponinfo(nix_weapon);
128                 // w.wr_init(w); // forget it, too slow
129         }
130
131         // get weapon info
132         entity e = get_weaponinfo(nix_weapon);
133
134         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
135         {
136                 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
137
138                 if(self.items & IT_UNLIMITED_WEAPON_AMMO)
139                 {
140                         switch(e.ammo_field)
141                         {
142                                 case ammo_shells:  self.ammo_shells  = autocvar_g_pickup_shells_max;  break;
143                                 case ammo_nails:   self.ammo_nails   = autocvar_g_pickup_nails_max;   break;
144                                 case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
145                                 case ammo_cells:   self.ammo_cells   = autocvar_g_pickup_cells_max;   break;
146                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_pickup_plasma_max;   break;
147                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
148                         }
149                 }
150                 else
151                 {
152                         switch(e.ammo_field)
153                         {
154                                 case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
155                                 case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
156                                 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
157                                 case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
158                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_balance_nix_ammo_plasma;   break;
159                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
160                         }
161                 }
162
163                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
164                 if(dt >= 1 && dt <= 5)
165                         self.nix_lastinfotime = -42;
166                 else
167                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
168
169                 Weapon w = get_weaponinfo(nix_weapon);
170                 w.wr_resetplayer(w);
171
172                 // all weapons must be fully loaded when we spawn
173                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
174                         self.(weapon_load[nix_weapon]) = e.reloading_ammo;
175
176                 // vortex too
177                 if(WEP_CVAR(vortex, charge))
178                 {
179                         if(WEP_CVAR_SEC(vortex, chargepool))
180                                 self.vortex_chargepool_ammo = 1;
181                         self.vortex_charge = WEP_CVAR(vortex, charge_start);
182                 }
183
184                 // set last change info
185                 self.nix_lastchange_id = nix_nextchange;
186         }
187         if(self.nix_lastinfotime != dt)
188         {
189                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
190                 if(dt >= 1 && dt <= 5)
191                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
192         }
193
194         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
195         {
196                 switch(e.ammo_field)
197                 {
198                         case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
199                         case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
200                         case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
201                         case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
202                         case ammo_plasma:  self.ammo_plasma  += autocvar_g_balance_nix_ammoincr_plasma;   break;
203                         case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
204                 }
205
206                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
207         }
208
209         self.weapons = '0 0 0';
210         if(g_nix_with_blaster)
211                 self.weapons |= WEPSET(BLASTER);
212         self.weapons |= WepSet_FromWeapon(nix_weapon);
213
214         if(self.switchweapon != nix_weapon)
215                 if(!client_hasweapon(self, self.switchweapon, true, false))
216                         if(client_hasweapon(self, nix_weapon, true, false))
217                                 W_SwitchWeapon(nix_weapon);
218 }
219
220 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
221 {
222         return 1; // no throwing in NIX
223 }
224
225 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
226 {
227         ret_string = strcat(ret_string, ":NIX");
228         return 0;
229 }
230
231 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
232 {
233         ret_string = strcat(ret_string, ", NIX");
234         return 0;
235 }
236
237 MUTATOR_HOOKFUNCTION(nix, FilterItem)
238 {SELFPARAM();
239         switch (self.items)
240         {
241                 case ITEM_HealthSmall.m_itemid:
242                 case ITEM_HealthMedium.m_itemid:
243                 case ITEM_HealthLarge.m_itemid:
244                 case ITEM_HealthMega.m_itemid:
245                 case ITEM_ArmorSmall.m_itemid:
246                 case ITEM_ArmorMedium.m_itemid:
247                 case ITEM_ArmorLarge.m_itemid:
248                 case ITEM_ArmorMega.m_itemid:
249                         if (autocvar_g_nix_with_healtharmor)
250                                 return 0;
251                         break;
252                 case ITEM_Strength.m_itemid:
253                 case ITEM_Shield.m_itemid:
254                         if (autocvar_g_nix_with_powerups)
255                                 return 0;
256                         break;
257         }
258
259         return 1; // delete all other items
260 }
261
262 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
263 {SELFPARAM();
264         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
265                 return 1;
266         return 0;
267 }
268
269 MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
270 {SELFPARAM();
271         if(!intermission_running)
272         if(self.deadflag == DEAD_NO)
273         if(IS_PLAYER(self))
274                 NIX_GiveCurrentWeapon();
275         return 0;
276 }
277
278 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
279 {SELFPARAM();
280         self.nix_lastchange_id = -1;
281         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
282         self.items |= IT_UNLIMITED_SUPERWEAPONS;
283         return 0;
284 }
285
286 MUTATOR_HOOKFUNCTION(nix, SetModname, CBC_ORDER_LAST)
287 {
288         modname = "NIX";
289         return 0;
290 }
291 #endif