]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
Merge remote-tracking branch 'origin/master' into samual/weapons
[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_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_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
78                         }
79                 }
80                 else
81                 {
82                         switch(e.ammo_field)
83                         {
84                                 case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
85                                 case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
86                                 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
87                                 case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
88                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
89                         }
90                 }
91
92                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
93                 if(dt >= 1 && dt <= 5)
94                         self.nix_lastinfotime = -42;
95                 else
96                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
97
98                 WEP_ACTION(nix_weapon, WR_RESETPLAYER);
99
100                 // all weapons must be fully loaded when we spawn
101                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
102                         self.(weapon_load[nix_weapon]) = e.reloading_ammo;
103
104                 // nex too
105                 if(WEP_CVAR(vortex, charge))
106                 {
107                         if(WEP_CVAR_SEC(vortex, chargepool))
108                                 self.vortex_chargepool_ammo = 1;
109                         self.vortex_charge = WEP_CVAR(vortex, charge_start);
110                 }
111
112                 // set last change info
113                 self.nix_lastchange_id = nix_nextchange;
114         }
115         if(self.nix_lastinfotime != dt)
116         {
117                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
118                 if(dt >= 1 && dt <= 5)
119                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
120         }
121
122         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
123         {
124                 switch(e.ammo_field)
125                 {
126                         case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
127                         case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
128                         case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
129                         case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
130                         case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
131                 }
132
133                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
134         }
135
136         self.weapons = '0 0 0';
137         if(g_nix_with_laser)
138                 self.weapons &= ~WEPSET_BLASTER;
139         self.weapons |= WepSet_FromWeapon(nix_weapon);
140
141         if(self.switchweapon != nix_weapon)
142                 if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
143                         if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
144                                 W_SwitchWeapon(nix_weapon);
145 }
146
147 void NIX_precache()
148 {
149         float i;
150         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
151                 if (NIX_CanChooseWeapon(i))
152                         WEP_ACTION(i, WR_INIT);
153 }
154
155 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
156 {
157         return 1; // no throwing in NIX
158 }
159
160 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
161 {
162         ret_string = strcat(ret_string, ":NIX");
163         return 0;
164 }
165
166 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
167 {
168         ret_string = strcat(ret_string, ", NIX");
169         return 0;
170 }
171
172 MUTATOR_HOOKFUNCTION(nix_FilterItem)
173 {
174         switch (self.items)
175         {
176                 case IT_HEALTH:
177                 case IT_5HP:
178                 case IT_25HP:
179                 case IT_ARMOR:
180                 case IT_ARMOR_SHARD:
181                         if (autocvar_g_nix_with_healtharmor)
182                                 return 0;
183                         break;
184                 case IT_STRENGTH:
185                 case IT_INVINCIBLE:
186                         if (autocvar_g_nix_with_powerups)
187                                 return 0;
188                         break;
189         }
190
191         return 1; // delete all other items
192 }
193
194 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
195 {
196         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
197                 return 1;
198         return 0;
199 }
200
201 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
202 {
203         if(!intermission_running)
204         if(self.deadflag == DEAD_NO)
205         if(IS_PLAYER(self))
206                 NIX_GiveCurrentWeapon();
207         return 0;
208 }
209
210 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
211 {
212         self.nix_lastchange_id = -1;
213         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
214         self.items |= IT_UNLIMITED_SUPERWEAPONS;
215         return 0;
216 }
217
218 MUTATOR_HOOKFUNCTION(nix_SetModname)
219 {
220         modname = "NIX";
221         return 0;
222 }
223
224 MUTATOR_DEFINITION(mutator_nix)
225 {
226         entity e;
227
228         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
229         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
230         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
231         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
232         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
233         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
234         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
235         MUTATOR_HOOK(SetModname, nix_SetModname, CBC_ORDER_LAST);
236
237         MUTATOR_ONADD
238         {
239                 g_nix_with_laser = autocvar_g_nix_with_laser;
240
241                 nix_nextchange = 0;
242                 nix_nextweapon = 0;
243
244                 NIX_precache();
245         }
246
247         MUTATOR_ONROLLBACK_OR_REMOVE
248         {
249                 // nothing to roll back
250         }
251
252         MUTATOR_ONREMOVE
253         {
254                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
255
256                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
257                 {
258                         e.ammo_cells = start_ammo_cells;
259                         e.ammo_shells = start_ammo_shells;
260                         e.ammo_nails = start_ammo_nails;
261                         e.ammo_rockets = start_ammo_rockets;
262                         e.ammo_fuel = start_ammo_fuel;
263                         e.weapons = start_weapons;
264                         if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
265                                 e.switchweapon = w_getbestweapon(self);
266                 }
267         }
268
269         return 0;
270 }