b972cfdec4adfa1a74a6d7ef24b4c6c7dc6b9498
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / all.qc
1 #ifndef WEAPONS_ALL_C
2 #define WEAPONS_ALL_C
3
4 #include "all.qh"
5
6 #if defined(CSQC)
7         #include "../../dpdefs/csprogsdefs.qh"
8         #include "../../client/defs.qh"
9         #include "../constants.qh"
10         #include "../stats.qh"
11         #include "../../warpzonelib/anglestransform.qh"
12         #include "../../warpzonelib/common.qh"
13         #include "../../warpzonelib/client.qh"
14         #include "../util.qh"
15         #include "../buffs.qh"
16         #include "../../client/autocvars.qh"
17         #include "../deathtypes.qh"
18         #include "../../csqcmodellib/interpolate.qh"
19         #include "../movetypes/movetypes.qh"
20         #include "../../client/main.qh"
21         #include "../../csqcmodellib/cl_model.qh"
22 #elif defined(MENUQC)
23 #elif defined(SVQC)
24         #include "../../dpdefs/progsdefs.qh"
25     #include "../../dpdefs/dpextensions.qh"
26     #include "../../warpzonelib/anglestransform.qh"
27     #include "../../warpzonelib/common.qh"
28     #include "../../warpzonelib/util_server.qh"
29     #include "../../warpzonelib/server.qh"
30     #include "../constants.qh"
31     #include "../stats.qh"
32     #include "../teams.qh"
33     #include "../util.qh"
34     #include "../buffs.qh"
35     #include "../monsters/all.qh"
36     #include "config.qh"
37     #include "../../server/weapons/csqcprojectile.qh"
38     #include "../../server/weapons/tracing.qh"
39     #include "../../server/t_items.qh"
40     #include "../../server/autocvars.qh"
41     #include "../../server/constants.qh"
42     #include "../../server/defs.qh"
43     #include "../notifications.qh"
44     #include "../deathtypes.qh"
45     #include "../../server/mutators/mutators_include.qh"
46     #include "../mapinfo.qh"
47     #include "../../server/command/common.qh"
48     #include "../../csqcmodellib/sv_model.qh"
49     #include "../../server/portals.qh"
50     #include "../../server/g_hook.qh"
51 #endif
52 #ifndef MENUQC
53 #include "calculations.qc"
54 #endif
55 #define IMPLEMENTATION
56 #include "all.inc"
57 #undef IMPLEMENTATION
58
59 // WEAPON PLUGIN SYSTEM
60
61 #if WEP_MAXCOUNT > 72
62 # error Kein Weltraum links auf dem Gerät
63 #endif
64
65 WepSet WepSet_FromWeapon(int a) {
66         a -= WEP_FIRST;
67 #if WEP_MAXCOUNT > 24
68         if(a >= 24) {
69                 a -= 24;
70 #if WEP_MAXCOUNT > 48
71                 if(a >= 24) {
72                         a -= 24;
73                         return '0 0 1' * power2of(a);
74                 }
75 #endif
76                 return '0 1 0' * power2of(a);
77         }
78 #endif
79         return '1 0 0' * power2of(a);
80 }
81 #ifdef SVQC
82 void WepSet_AddStat()
83 {
84         addstat(STAT_WEAPONS, AS_INT, weapons_x);
85 #if WEP_MAXCOUNT > 24
86         addstat(STAT_WEAPONS2, AS_INT, weapons_y);
87 #if WEP_MAXCOUNT > 48
88         addstat(STAT_WEAPONS3, AS_INT, weapons_z);
89 #endif
90 #endif
91 }
92 void WepSet_AddStat_InMap()
93 {
94         addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
95 #if WEP_MAXCOUNT > 24
96         addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
97 #if WEP_MAXCOUNT > 48
98         addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
99 #endif
100 #endif
101 }
102 void WriteWepSet(float dst, WepSet w)
103 {
104 #if WEP_MAXCOUNT > 48
105         WriteInt72_t(dst, w);
106 #elif WEP_MAXCOUNT > 24
107         WriteInt48_t(dst, w);
108 #else
109         WriteInt24_t(dst, w.x);
110 #endif
111 }
112 #endif
113 #ifdef CSQC
114 WepSet WepSet_GetFromStat()
115 {
116         WepSet w = '0 0 0';
117         w.x = getstati(STAT_WEAPONS);
118 #if WEP_MAXCOUNT > 24
119         w.y = getstati(STAT_WEAPONS2);
120 #if WEP_MAXCOUNT > 48
121         w.z = getstati(STAT_WEAPONS3);
122 #endif
123 #endif
124         return w;
125 }
126 WepSet WepSet_GetFromStat_InMap()
127 {
128         WepSet w = '0 0 0';
129         w_x = getstati(STAT_WEAPONSINMAP);
130 #if WEP_MAXCOUNT > 24
131         w_y = getstati(STAT_WEAPONSINMAP2);
132 #if WEP_MAXCOUNT > 48
133         w_z = getstati(STAT_WEAPONSINMAP3);
134 #endif
135 #endif
136         return w;
137 }
138 WepSet ReadWepSet()
139 {
140 #if WEP_MAXCOUNT > 48
141         return ReadInt72_t();
142 #elif WEP_MAXCOUNT > 24
143         return ReadInt48_t();
144 #else
145         return ReadInt24_t() * '1 0 0';
146 #endif
147 }
148 #endif
149
150 void register_weapons_done()
151 {
152         dummy_weapon_info = NEW(Weapon);
153
154         weaponorder_byid = "";
155         for (int i = WEP_MAXCOUNT - 1; i >= 0; --i)
156                 if (weapon_info[i])
157                         weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
158         weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
159 }
160 entity get_weaponinfo(int id)
161 {
162         entity w;
163         if(id < WEP_FIRST || id > WEP_LAST)
164                 return dummy_weapon_info;
165         w = weapon_info[id - 1];
166         if(w)
167                 return w;
168         return dummy_weapon_info;
169 }
170 string W_FixWeaponOrder(string order, float complete)
171 {
172         return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
173 }
174 string W_NameWeaponOrder_MapFunc(string s)
175 {
176         entity wi;
177         if(s == "0" || stof(s))
178         {
179                 wi = get_weaponinfo(stof(s));
180                 if(wi != dummy_weapon_info)
181                         return wi.netname;
182         }
183         return s;
184 }
185
186 string W_UndeprecateName(string s)
187 {
188         switch ( s )
189         {
190                 case "nex"            : return "vortex";
191                 case "rocketlauncher" : return "devastator";
192                 case "laser"          : return "blaster";
193                 case "minstanex"      : return "vaporizer";
194                 case "grenadelauncher": return "mortar";
195                 case "uzi"            : return "machinegun";
196                 default               : return s;
197         }
198 }
199 string W_NameWeaponOrder(string order)
200 {
201         return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
202 }
203 string W_NumberWeaponOrder_MapFunc(string s)
204 {
205         int i;
206         if(s == "0" || stof(s))
207                 return s;
208         s = W_UndeprecateName(s);
209         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
210                 if(s == get_weaponinfo(i).netname)
211                         return ftos(i);
212         return s;
213 }
214 string W_NumberWeaponOrder(string order)
215 {
216         return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
217 }
218
219 float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
220 string W_FixWeaponOrder_BuildImpulseList_order;
221 void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
222 {
223         float h;
224         h = W_FixWeaponOrder_BuildImpulseList_buf[i];
225         W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
226         W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
227 }
228 float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
229 {
230         entity e1, e2;
231         float d;
232         e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
233         e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
234         d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
235         if(d != 0)
236                 return -d; // high impulse first!
237         return
238                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
239                 -
240                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
241                 ; // low char index first!
242 }
243 string W_FixWeaponOrder_BuildImpulseList(string o)
244 {
245         int i;
246         W_FixWeaponOrder_BuildImpulseList_order = o;
247         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
248                 W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
249         heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
250         o = "";
251         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
252                 o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
253         W_FixWeaponOrder_BuildImpulseList_order = string_null;
254         return substring(o, 1, -1);
255 }
256
257 string W_FixWeaponOrder_AllowIncomplete(string order)
258 {
259         return W_FixWeaponOrder(order, 0);
260 }
261
262 string W_FixWeaponOrder_ForceComplete(string order)
263 {
264         if(order == "")
265                 order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
266         return W_FixWeaponOrder(order, 1);
267 }
268
269 void W_RandomWeapons(entity e, float n)
270 {
271         int i, j;
272         WepSet remaining;
273         WepSet result;
274         remaining = e.weapons;
275         result = '0 0 0';
276         for(i = 0; i < n; ++i)
277         {
278                 RandomSelection_Init();
279                 for(j = WEP_FIRST; j <= WEP_LAST; ++j)
280                         if(remaining & WepSet_FromWeapon(j))
281                                 RandomSelection_Add(world, j, string_null, 1, 1);
282                 result |= WepSet_FromWeapon(RandomSelection_chosen_float);
283                 remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
284         }
285         e.weapons = result;
286 }
287
288 string GetAmmoPicture(.int ammotype)
289 {
290         switch (ammotype)
291         {
292                 case ammo_shells:  return ITEM_Shells.m_icon;
293                 case ammo_nails:   return ITEM_Bullets.m_icon;
294                 case ammo_rockets: return ITEM_Rockets.m_icon;
295                 case ammo_cells:   return ITEM_Cells.m_icon;
296                 case ammo_plasma:  return ITEM_Plasma.m_icon;
297                 case ammo_fuel:    return ITEM_JetpackFuel.m_icon;
298                 default: return ""; // wtf, no ammo type?
299         }
300 }
301
302 #ifdef CSQC
303 .int GetAmmoFieldFromNum(int i)
304 {
305         switch(i)
306         {
307                 case 0: return ammo_shells;
308                 case 1: return ammo_nails;
309                 case 2: return ammo_rockets;
310                 case 3: return ammo_cells;
311                 case 4: return ammo_plasma;
312                 case 5: return ammo_fuel;
313                 default: return ammo_none;
314         }
315 }
316
317 int GetAmmoStat(.int ammotype)
318 {
319         switch(ammotype)
320         {
321                 case ammo_shells: return STAT_SHELLS;
322                 case ammo_nails: return STAT_NAILS;
323                 case ammo_rockets: return STAT_ROCKETS;
324                 case ammo_cells: return STAT_CELLS;
325                 case ammo_plasma: return STAT_PLASMA;
326                 case ammo_fuel: return STAT_FUEL;
327                 default: return -1;
328         }
329 }
330 #endif
331
332 string W_Sound(string w_snd)
333 {
334         #define extensions(X) X(wav) X(ogg)
335         #define tryext(ext) { if (fexists(strcat("sound/", output = strcat("weapons/", w_snd, "."#ext)))) break; }
336         string output;
337         do {
338                 extensions(tryext);
339                 #undef tryext
340                 #undef extensions
341                 output = strcat("weapons/", w_snd);
342         } while (0);
343
344 #ifdef SVQC
345         MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
346         return weapon_sound_output;
347 #else
348         return output;
349 #endif
350 }
351
352 string W_Model(string w_mdl)
353 {
354         string output = strcat("models/weapons/", w_mdl);
355 #ifdef SVQC
356         MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
357         return weapon_model_output;
358 #else
359         return output;
360 #endif
361 }
362
363 #endif