]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
new toys: start coding it, far from done
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nix.qc
1 float g_nix_with_laser;
2
3 float nix_weapon;
4 float nix_weapon_ammo;
5 float nix_nextchange;
6 float nix_nextweapon;
7 float nix_nextweapon_ammo;
8 .float nix_lastchange_id;
9 .float nix_lastinfotime;
10 .float nix_nextincr;
11
12 float NIX_CanChooseWeapon(float wpn)
13 {
14         entity e;
15         e = get_weaponinfo(wpn);
16         if(!e.weapon) // skip dummies
17                 return FALSE;
18         if(g_weaponarena)
19         {
20                 if not(WEPSET_CONTAINS_AW(g_weaponarena_weapons, wpn))
21                         return FALSE;
22         }
23         else
24         {
25                 if(wpn == WEP_LASER && g_nix_with_laser)
26                         return FALSE;
27                 if not(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         nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
41 }
42
43 void NIX_GiveCurrentWeapon()
44 {
45         float dt;
46
47         if(!nix_nextweapon)
48                 NIX_ChooseNextWeapon();
49
50         dt = ceil(nix_nextchange - time);
51
52         if(dt <= 0)
53         {
54                 nix_weapon = nix_nextweapon;
55                 nix_weapon_ammo = nix_nextweapon_ammo;
56                 nix_nextweapon = 0;
57                 if (!nix_nextchange) // no round played yet?
58                         nix_nextchange = time; // start the first round now!
59                 else
60                         nix_nextchange = time + autocvar_g_balance_nix_roundtime;
61                 //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
62         }
63
64         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
65         {
66                 self.nix_lastchange_id = nix_nextchange;
67                 if (self.items & IT_UNLIMITED_WEAPON_AMMO)
68                 {
69                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
70                                 autocvar_g_pickup_shells_max : 0;
71                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
72                                 autocvar_g_pickup_nails_max : 0;
73                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
74                                 autocvar_g_pickup_rockets_max : 0;
75                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
76                                 autocvar_g_pickup_cells_max : 0;
77                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
78                                 autocvar_g_pickup_fuel_max : 0;
79                 }
80                 else
81                 {
82                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
83                                 autocvar_g_balance_nix_ammo_shells : 0;
84                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
85                                 autocvar_g_balance_nix_ammo_nails : 0;
86                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
87                                 autocvar_g_balance_nix_ammo_rockets : 0;
88                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
89                                 autocvar_g_balance_nix_ammo_cells : 0;
90                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
91                                 autocvar_g_balance_nix_ammo_fuel : 0;
92                 }
93                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
94                 if(dt >= 1 && dt <= 5)
95                         self.nix_lastinfotime = -42;
96                 else
97                         Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^2Active weapon: ^3", W_Name(nix_weapon)), 0, 0);
98
99                 weapon_action(nix_weapon, WR_RESETPLAYER);
100
101                 // all weapons must be fully loaded when we spawn
102                 entity e;
103                 e = get_weaponinfo(nix_weapon);
104                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
105                         self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
106
107                 // nex too
108                 if(autocvar_g_balance_nex_charge)
109                 {
110                         if(autocvar_g_balance_nex_secondary_chargepool)
111                                 self.nex_chargepool_ammo = 1;
112                         self.nex_charge = autocvar_g_balance_nex_charge_start;
113                 }
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_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^3%d^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon)), 1, dt);
120         }
121
122         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
123         {
124                 if (nix_weapon_ammo & IT_SHELLS)
125                         self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells;
126                 else if (nix_weapon_ammo & IT_NAILS)
127                         self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails;
128                 else if (nix_weapon_ammo & IT_ROCKETS)
129                         self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets;
130                 else if (nix_weapon_ammo & IT_CELLS)
131                         self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells;
132                 if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
133                         self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel;
134                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
135         }
136
137         WEPSET_CLEAR_E(self);
138         if(g_nix_with_laser)
139                 WEPSET_ANDNOT_EW(self, WEP_LASER);
140         WEPSET_OR_EW(self, nix_weapon);
141
142         if(self.switchweapon != nix_weapon)
143                 if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
144                         if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
145                                 W_SwitchWeapon(nix_weapon);
146 }
147
148 void NIX_precache()
149 {
150         float i;
151         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
152                 if (NIX_CanChooseWeapon(i))
153                         weapon_action(i, WR_PRECACHE);
154 }
155
156 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
157 {
158         return 1; // no throwing in NIX
159 }
160
161 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
162 {
163         ret_string = strcat(ret_string, ":NIX");
164         return 0;
165 }
166
167 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
168 {
169         ret_string = strcat(ret_string, ", NIX");
170         return 0;
171 }
172
173 MUTATOR_HOOKFUNCTION(nix_FilterItem)
174 {
175         switch (self.items)
176         {
177                 case IT_HEALTH:
178                 case IT_5HP:
179                 case IT_25HP:
180                 case IT_ARMOR:
181                 case IT_ARMOR_SHARD:
182                         if (autocvar_g_nix_with_healtharmor)
183                                 return 0;
184                         break;
185                 case IT_STRENGTH:
186                 case IT_INVINCIBLE:
187                         if (autocvar_g_nix_with_powerups)
188                                 return 0;
189                         break;
190         }
191
192         return 1; // delete all other items
193 }
194
195 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
196 {
197         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
198                 return 1;
199         return 0;
200 }
201
202 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
203 {
204         if(!intermission_running)
205         if(self.deadflag == DEAD_NO)
206         if(self.classname == "player")
207                 NIX_GiveCurrentWeapon();
208         return 0;
209 }
210
211 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
212 {
213         self.nix_lastchange_id = -1;
214         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
215         self.items |= IT_UNLIMITED_SUPERWEAPONS;
216         return 0;
217 }
218
219 MUTATOR_DEFINITION(mutator_nix)
220 {
221         entity e;
222
223         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
224         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
225         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
226         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
227         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
228         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
229         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
230
231         MUTATOR_ONADD
232         {
233                 g_nix_with_laser = autocvar_g_nix_with_laser;
234
235                 nix_nextchange = 0;
236                 nix_nextweapon = 0;
237
238                 NIX_precache();
239         }
240
241         MUTATOR_ONREMOVE
242         {
243                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
244
245                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
246                 {
247                         e.ammo_cells = start_ammo_cells;
248                         e.ammo_shells = start_ammo_shells;
249                         e.ammo_nails = start_ammo_nails;
250                         e.ammo_rockets = start_ammo_rockets;
251                         e.ammo_fuel = start_ammo_fuel;
252                         WEPSET_COPY_EA(e, start_weapons);
253                         if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
254                                 e.switchweapon = w_getbestweapon(self);
255                 }
256         }
257
258         return 0;
259 }