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