]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapons.qc
Merge branch 'master' into samual/weapons
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapons.qc
1 #ifndef MENUQC
2 #include "calculations.qc"
3 #endif
4 #include "all.qh"
5
6 // WEAPON PLUGIN SYSTEM
7 entity weapon_info[WEP_MAXCOUNT];
8 entity dummy_weapon_info;
9
10 #if WEP_MAXCOUNT > 72
11 # error Kein Weltraum links auf dem Gerät
12 #endif
13
14 WepSet WepSet_FromWeapon(float a) {
15         a -= WEP_FIRST;
16 #if WEP_MAXCOUNT > 24
17         if(a >= 24) {
18                 a -= 24;
19 #if WEP_MAXCOUNT > 48
20                 if(a >= 24) {
21                         a -= 24;
22                         return '0 0 1' * power2of(a);
23                 }
24 #endif
25                 return '0 1 0' * power2of(a);
26         }
27 #endif
28         return '1 0 0' * power2of(a);
29 }
30 #ifdef SVQC
31 void WepSet_AddStat()
32 {
33         addstat(STAT_WEAPONS, AS_INT, weapons_x);
34 #if WEP_MAXCOUNT > 24
35         addstat(STAT_WEAPONS2, AS_INT, weapons_y);
36 #if WEP_MAXCOUNT > 48
37         addstat(STAT_WEAPONS3, AS_INT, weapons_z);
38 #endif
39 #endif
40 }
41 void WriteWepSet(float dst, WepSet w)
42 {
43 #if WEP_MAXCOUNT > 48
44         WriteInt72_t(dst, w);
45 #elif WEP_MAXCOUNT > 24
46         WriteInt48_t(dst, w);
47 #else
48         WriteInt24_t(dst, w_x);
49 #endif
50 }
51 #endif
52 #ifdef CSQC
53 WepSet WepSet_GetFromStat()
54 {
55         WepSet w = '0 0 0';
56         w_x = getstati(STAT_WEAPONS);
57 #if WEP_MAXCOUNT > 24
58         w_y = getstati(STAT_WEAPONS2);
59 #if WEP_MAXCOUNT > 48
60         w_z = getstati(STAT_WEAPONS3);
61 #endif
62 #endif
63         return w;
64 }
65 WepSet ReadWepSet()
66 {
67 #if WEP_MAXCOUNT > 48
68         return ReadInt72_t();
69 #elif WEP_MAXCOUNT > 24
70         return ReadInt48_t();
71 #else
72         return ReadInt24_t() * '1 0 0';
73 #endif
74 }
75 #endif
76
77 void register_weapon(
78         float id,
79         WepSet bit,
80         float(float) func,
81         .float ammotype,
82         float i,
83         float weapontype,
84         float pickupbasevalue,
85         vector clr,
86         string modelname,
87         string simplemdl,
88         string crosshair,
89         string wepimg,
90         string refname,
91         string wepname)
92 {
93         entity e;
94         weapon_info[id - 1] = e = spawn();
95         e.classname = "weapon_info";
96         e.weapon = id;
97         e.weapons = bit;
98         e.weapon_func = func;
99         e.ammo_field = ammotype;
100         e.impulse = i;
101         e.spawnflags = weapontype;
102         e.bot_pickupbasevalue = pickupbasevalue;
103         e.wpcolor = clr;
104         e.wpmodel = strzone(strcat("wpn-", ftos(id)));
105         e.mdl = modelname;
106         e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
107         e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
108         e.w_crosshair = strzone(car(crosshair));
109         string s = cdr(crosshair);
110         e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
111         e.model2 = strzone(wepimg);
112         e.netname = refname;
113         e.message = wepname;
114
115         #ifndef MENUQC
116         func(WR_INIT);
117         #endif
118 }
119 float w_null(float dummy)
120 {
121         return 0;
122 }
123 void register_weapons_done()
124 {
125         dummy_weapon_info = spawn();
126         dummy_weapon_info.classname = "weapon_info";
127         dummy_weapon_info.weapon = 0; // you can recognize dummies by this
128         dummy_weapon_info.weapons = '0 0 0';
129         dummy_weapon_info.netname = "";
130         dummy_weapon_info.message = "AOL CD Thrower";
131         dummy_weapon_info.weapon_func = w_null;
132         dummy_weapon_info.wpmodel = "";
133         dummy_weapon_info.mdl = "";
134         dummy_weapon_info.model = "";
135         dummy_weapon_info.spawnflags = 0;
136         dummy_weapon_info.impulse = -1;
137         dummy_weapon_info.bot_pickupbasevalue = 0;
138         dummy_weapon_info.ammo_field = ammo_none;
139
140         dummy_weapon_info.w_crosshair = "gfx/crosshair1";
141         dummy_weapon_info.w_crosshair_size = 1;
142         dummy_weapon_info.model2 = "";
143
144         float i;
145         weaponorder_byid = "";
146         for(i = WEP_MAXCOUNT; i >= 1; --i)
147                 if(weapon_info[i-1])
148                         weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
149         weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
150 }
151 entity get_weaponinfo(float id)
152 {
153         entity w;
154         if(id < WEP_FIRST || id > WEP_LAST)
155                 return dummy_weapon_info;
156         w = weapon_info[id - 1];
157         if(w)
158                 return w;
159         return dummy_weapon_info;
160 }
161 string W_FixWeaponOrder(string order, float complete)
162 {
163         return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
164 }
165 string W_NameWeaponOrder_MapFunc(string s)
166 {
167         entity wi;
168         if(s == "0" || stof(s))
169         {
170                 wi = get_weaponinfo(stof(s));
171                 if(wi != dummy_weapon_info)
172                         return wi.netname;
173         }
174         return s;
175 }
176 string W_NameWeaponOrder(string order)
177 {
178         return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
179 }
180 string W_NumberWeaponOrder_MapFunc(string s)
181 {
182         float i;
183         if(s == "0" || stof(s))
184                 return s;
185         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
186                 if(s == get_weaponinfo(i).netname)
187                         return ftos(i);
188         return s;
189 }
190 string W_NumberWeaponOrder(string order)
191 {
192         return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
193 }
194
195 float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
196 string W_FixWeaponOrder_BuildImpulseList_order;
197 void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
198 {
199         float h;
200         h = W_FixWeaponOrder_BuildImpulseList_buf[i];
201         W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
202         W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
203 }
204 float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
205 {
206         entity e1, e2;
207         float d;
208         e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
209         e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
210         d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
211         if(d != 0)
212                 return -d; // high impulse first!
213         return
214                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
215                 -
216                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
217                 ; // low char index first!
218 }
219 string W_FixWeaponOrder_BuildImpulseList(string o)
220 {
221         float i;
222         W_FixWeaponOrder_BuildImpulseList_order = o;
223         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
224                 W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
225         heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
226         o = "";
227         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
228                 o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
229         W_FixWeaponOrder_BuildImpulseList_order = string_null;
230         return substring(o, 1, -1);
231 }
232
233 string W_FixWeaponOrder_AllowIncomplete(string order)
234 {
235         return W_FixWeaponOrder(order, 0);
236 }
237
238 string W_FixWeaponOrder_ForceComplete(string order)
239 {
240         if(order == "")
241                 order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
242         return W_FixWeaponOrder(order, 1);
243 }
244
245 void W_RandomWeapons(entity e, float n)
246 {
247         float i, j;
248         WepSet remaining;
249         WepSet result;
250         remaining = e.weapons;
251         result = '0 0 0';
252         for(i = 0; i < n; ++i)
253         {
254                 RandomSelection_Init();
255                 for(j = WEP_FIRST; j <= WEP_LAST; ++j)
256                         if(remaining & WepSet_FromWeapon(j))
257                                 RandomSelection_Add(world, j, string_null, 1, 1);
258                 result |= WepSet_FromWeapon(RandomSelection_chosen_float);
259                 remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
260         }
261         e.weapons = result;
262 }
263
264 string GetAmmoPicture(.float ammotype)
265 {
266         switch(ammotype)
267         {
268                 case ammo_shells:  return "ammo_shells";
269                 case ammo_nails:   return "ammo_bullets";
270                 case ammo_rockets: return "ammo_rockets";
271                 case ammo_cells:   return "ammo_cells";
272                 case ammo_fuel:    return "ammo_fuel";
273                 default: return ""; // wtf, no ammo type?
274         }
275 }
276
277 #ifdef CSQC
278 .float GetAmmoFieldFromNum(float i)
279 {
280         switch(i)
281         {
282                 case 0: return ammo_shells;
283                 case 1: return ammo_nails;
284                 case 2: return ammo_rockets;
285                 case 3: return ammo_cells;
286                 case 4: return ammo_fuel;
287                 default: return ammo_none;
288         }
289 }
290
291 float GetAmmoStat(.float ammotype)
292 {
293         switch(ammotype)
294         {
295                 case ammo_shells: return STAT_SHELLS;
296                 case ammo_nails: return STAT_NAILS;
297                 case ammo_rockets: return STAT_ROCKETS;
298                 case ammo_cells: return STAT_CELLS;
299                 case ammo_fuel: return STAT_FUEL;
300                 default: return -1;
301         }
302 }
303 #endif