]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapons.qc
feef90e42d7ee0b1f2da028a441c09c55026f9ea
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapons.qc
1 #if defined(CSQC)
2         #include "../../dpdefs/csprogsdefs.qh"
3         #include "../../client/defs.qh"
4         #include "../constants.qh"
5         #include "../stats.qh"
6         #include "../../warpzonelib/anglestransform.qh"
7         #include "../../warpzonelib/mathlib.qh"
8         #include "../../warpzonelib/common.qh"
9         #include "../../warpzonelib/client.qh"
10         #include "../util.qh"
11         #include "../buffs.qh"
12         #include "weapons.qh"
13         #include "../../client/autocvars.qh"
14         #include "../deathtypes.qh"
15         #include "../../csqcmodellib/interpolate.qh"
16         #include "../../client/movetypes.qh"
17         #include "../../client/main.qh"
18         #include "../../csqcmodellib/cl_model.qh"
19 #elif defined(MENUQC)
20 #elif defined(SVQC)
21         #include "../../dpdefs/progsdefs.qh"
22     #include "../../dpdefs/dpextensions.qh"
23     #include "../../server/sys-post.qh"
24     #include "../../warpzonelib/anglestransform.qh"
25     #include "../../warpzonelib/mathlib.qh"
26     #include "../../warpzonelib/common.qh"
27     #include "../../warpzonelib/util_server.qh"
28     #include "../../warpzonelib/server.qh"
29     #include "../constants.qh"
30     #include "../stats.qh"
31     #include "../teams.qh"
32     #include "../util.qh"
33     #include "../buffs.qh"
34     #include "../monsters/monsters.qh"
35     #include "config.qh"
36     #include "weapons.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 #include "all.qh"
56
57 // WEAPON PLUGIN SYSTEM
58 entity weapon_info[WEP_MAXCOUNT];
59 entity dummy_weapon_info;
60
61 #if WEP_MAXCOUNT > 72
62 # error Kein Weltraum links auf dem Gerät
63 #endif
64
65 WepSet WepSet_FromWeapon(float 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 WriteWepSet(float dst, WepSet w)
93 {
94 #if WEP_MAXCOUNT > 48
95         WriteInt72_t(dst, w);
96 #elif WEP_MAXCOUNT > 24
97         WriteInt48_t(dst, w);
98 #else
99         WriteInt24_t(dst, w.x);
100 #endif
101 }
102 #endif
103 #ifdef CSQC
104 WepSet WepSet_GetFromStat()
105 {
106         WepSet w = '0 0 0';
107         w_x = getstati(STAT_WEAPONS);
108 #if WEP_MAXCOUNT > 24
109         w_y = getstati(STAT_WEAPONS2);
110 #if WEP_MAXCOUNT > 48
111         w_z = getstati(STAT_WEAPONS3);
112 #endif
113 #endif
114         return w;
115 }
116 WepSet ReadWepSet()
117 {
118 #if WEP_MAXCOUNT > 48
119         return ReadInt72_t();
120 #elif WEP_MAXCOUNT > 24
121         return ReadInt48_t();
122 #else
123         return ReadInt24_t() * '1 0 0';
124 #endif
125 }
126 #endif
127
128 void register_weapon(
129         int id,
130         WepSet bit,
131         float(float) func,
132         .float ammotype,
133         float i,
134         float weapontype,
135         float pickupbasevalue,
136         vector clr,
137         string modelname,
138         string simplemdl,
139         string crosshair,
140         string wepimg,
141         string refname,
142         string wepname)
143 {
144         entity e;
145         weapon_info[id - 1] = e = spawn();
146         e.classname = "weapon_info";
147         e.weapon = id;
148         e.weapons = bit;
149         e.weapon_func = func;
150         e.ammo_field = ammotype;
151         e.impulse = i;
152         e.spawnflags = weapontype;
153         e.bot_pickupbasevalue = pickupbasevalue;
154         e.wpcolor = clr;
155         e.wpmodel = strzone(strcat("wpn-", ftos(id)));
156         e.mdl = modelname;
157         e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
158         e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
159         e.w_crosshair = strzone(car(crosshair));
160         string s = cdr(crosshair);
161         e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
162         e.model2 = strzone(wepimg);
163         e.netname = refname;
164         e.message = wepname;
165
166         #ifndef MENUQC
167         func(WR_INIT);
168         #endif
169 }
170 float w_null(float dummy)
171 {
172         return 0;
173 }
174 void register_weapons_done()
175 {
176         dummy_weapon_info = spawn();
177         dummy_weapon_info.classname = "weapon_info";
178         dummy_weapon_info.weapon = 0; // you can recognize dummies by this
179         dummy_weapon_info.weapons = '0 0 0';
180         dummy_weapon_info.netname = "";
181         dummy_weapon_info.message = "AOL CD Thrower";
182         dummy_weapon_info.weapon_func = w_null;
183         dummy_weapon_info.wpmodel = "";
184         dummy_weapon_info.mdl = "";
185         dummy_weapon_info.model = "";
186         dummy_weapon_info.spawnflags = 0;
187         dummy_weapon_info.impulse = -1;
188         dummy_weapon_info.bot_pickupbasevalue = 0;
189         dummy_weapon_info.ammo_field = ammo_none;
190
191         dummy_weapon_info.w_crosshair = "gfx/crosshair1";
192         dummy_weapon_info.w_crosshair_size = 1;
193         dummy_weapon_info.model2 = "";
194
195         float i;
196         weaponorder_byid = "";
197         for(i = WEP_MAXCOUNT; i >= 1; --i)
198                 if(weapon_info[i-1])
199                         weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
200         weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
201 }
202 entity get_weaponinfo(int id)
203 {
204         entity w;
205         if(id < WEP_FIRST || id > WEP_LAST)
206                 return dummy_weapon_info;
207         w = weapon_info[id - 1];
208         if(w)
209                 return w;
210         return dummy_weapon_info;
211 }
212 string W_FixWeaponOrder(string order, float complete)
213 {
214         return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
215 }
216 string W_NameWeaponOrder_MapFunc(string s)
217 {
218         entity wi;
219         if(s == "0" || stof(s))
220         {
221                 wi = get_weaponinfo(stof(s));
222                 if(wi != dummy_weapon_info)
223                         return wi.netname;
224         }
225         return s;
226 }
227
228 string W_UndeprecateName(string s)
229 {
230         switch ( s )
231         {
232                 case "nex"            : return "vortex";
233                 case "rocketlauncher" : return "devastator"; 
234                 case "laser"          : return "blaster";
235                 case "minstanex"      : return "vaporizer";
236                 case "grenadelauncher": return "mortar";
237                 case "uzi"            : return "machinegun";
238                 default               : return s;
239         }
240 }
241 string W_NameWeaponOrder(string order)
242 {
243         return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
244 }
245 string W_NumberWeaponOrder_MapFunc(string s)
246 {
247         float i;
248         if(s == "0" || stof(s))
249                 return s;
250         s = W_UndeprecateName(s);
251         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
252                 if(s == get_weaponinfo(i).netname)
253                         return ftos(i);
254         return s;
255 }
256 string W_NumberWeaponOrder(string order)
257 {
258         return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
259 }
260
261 float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
262 string W_FixWeaponOrder_BuildImpulseList_order;
263 void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
264 {
265         float h;
266         h = W_FixWeaponOrder_BuildImpulseList_buf[i];
267         W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
268         W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
269 }
270 float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int j, entity pass)
271 {
272         entity e1, e2;
273         float d;
274         e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
275         e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
276         d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
277         if(d != 0)
278                 return -d; // high impulse first!
279         return
280                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
281                 -
282                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
283                 ; // low char index first!
284 }
285 string W_FixWeaponOrder_BuildImpulseList(string o)
286 {
287         int i;
288         W_FixWeaponOrder_BuildImpulseList_order = o;
289         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
290                 W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
291         heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
292         o = "";
293         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
294                 o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
295         W_FixWeaponOrder_BuildImpulseList_order = string_null;
296         return substring(o, 1, -1);
297 }
298
299 string W_FixWeaponOrder_AllowIncomplete(string order)
300 {
301         return W_FixWeaponOrder(order, 0);
302 }
303
304 string W_FixWeaponOrder_ForceComplete(string order)
305 {
306         if(order == "")
307                 order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
308         return W_FixWeaponOrder(order, 1);
309 }
310
311 void W_RandomWeapons(entity e, float n)
312 {
313         float i, j;
314         WepSet remaining;
315         WepSet result;
316         remaining = e.weapons;
317         result = '0 0 0';
318         for(i = 0; i < n; ++i)
319         {
320                 RandomSelection_Init();
321                 for(j = WEP_FIRST; j <= WEP_LAST; ++j)
322                         if(remaining & WepSet_FromWeapon(j))
323                                 RandomSelection_Add(world, j, string_null, 1, 1);
324                 result |= WepSet_FromWeapon(RandomSelection_chosen_float);
325                 remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
326         }
327         e.weapons = result;
328 }
329
330 string GetAmmoPicture(.float ammotype)
331 {
332         switch(ammotype)
333         {
334                 case ammo_shells:  return "ammo_shells";
335                 case ammo_nails:   return "ammo_bullets";
336                 case ammo_rockets: return "ammo_rockets";
337                 case ammo_cells:   return "ammo_cells";
338                 case ammo_plasma:  return "ammo_cells";
339                 case ammo_fuel:    return "ammo_fuel";
340                 default: return ""; // wtf, no ammo type?
341         }
342 }
343
344 #ifdef CSQC
345 .float GetAmmoFieldFromNum(float i)
346 {
347         switch(i)
348         {
349                 case 0: return ammo_shells;
350                 case 1: return ammo_nails;
351                 case 2: return ammo_rockets;
352                 case 3: return ammo_cells;
353                 case 4: return ammo_plasma;
354                 case 5: return ammo_fuel;
355                 default: return ammo_none;
356         }
357 }
358
359 float GetAmmoStat(.float ammotype)
360 {
361         switch(ammotype)
362         {
363                 case ammo_shells: return STAT_SHELLS;
364                 case ammo_nails: return STAT_NAILS;
365                 case ammo_rockets: return STAT_ROCKETS;
366                 case ammo_cells: return STAT_CELLS;
367                 case ammo_plasma: return STAT_PLASMA;
368                 case ammo_fuel: return STAT_FUEL;
369                 default: return -1;
370         }
371 }
372 #endif