]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapons.qc
More descriptive stuff, better naming
[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 crosshair,
88         string refname,
89         string wepname)
90 {
91         entity e;
92         weapon_info[id - 1] = e = spawn();
93         e.classname = "weapon_info";
94         e.weapon = id;
95         e.weapons = bit;
96         e.weapon_func = func;
97         e.ammo_field = ammotype;
98         e.impulse = i;
99         e.spawnflags = weapontype;
100         e.bot_pickupbasevalue = pickupbasevalue;
101         e.wpcolor = clr;
102         e.mdl = modelname;
103         e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
104         e.w_crosshair = strzone(car(crosshair));
105         string s = cdr(crosshair);
106         e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
107         e.model2 = strzone(strcat("wpn-", ftos(id)));
108         e.netname = refname;
109         e.message = wepname;
110
111         #ifndef MENUQC
112         func(WR_INIT);
113         #endif
114 }
115 float w_null(float dummy)
116 {
117         return 0;
118 }
119 void register_weapons_done()
120 {
121         dummy_weapon_info = spawn();
122         dummy_weapon_info.classname = "weapon_info";
123         dummy_weapon_info.weapon = 0; // you can recognize dummies by this
124         dummy_weapon_info.weapons = '0 0 0';
125         dummy_weapon_info.netname = "";
126         dummy_weapon_info.message = "AOL CD Thrower";
127         dummy_weapon_info.weapon_func = w_null;
128         dummy_weapon_info.mdl = "";
129         dummy_weapon_info.model = "";
130         dummy_weapon_info.spawnflags = 0;
131         dummy_weapon_info.model2 = "";
132         dummy_weapon_info.impulse = -1;
133         dummy_weapon_info.bot_pickupbasevalue = 0;
134         dummy_weapon_info.ammo_field = ammo_none;
135
136         dummy_weapon_info.w_crosshair = "gfx/crosshair1";
137         dummy_weapon_info.w_crosshair_size = 1;
138
139         float i;
140         weaponorder_byid = "";
141         for(i = WEP_MAXCOUNT; i >= 1; --i)
142                 if(weapon_info[i-1])
143                         weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
144         weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
145 }
146 entity get_weaponinfo(float id)
147 {
148         entity w;
149         if(id < WEP_FIRST || id > WEP_LAST)
150                 return dummy_weapon_info;
151         w = weapon_info[id - 1];
152         if(w)
153                 return w;
154         return dummy_weapon_info;
155 }
156 string W_FixWeaponOrder(string order, float complete)
157 {
158         return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
159 }
160 string W_NameWeaponOrder_MapFunc(string s)
161 {
162         entity wi;
163         if(s == "0" || stof(s))
164         {
165                 wi = get_weaponinfo(stof(s));
166                 if(wi != dummy_weapon_info)
167                         return wi.netname;
168         }
169         return s;
170 }
171 string W_NameWeaponOrder(string order)
172 {
173         return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
174 }
175 string W_NumberWeaponOrder_MapFunc(string s)
176 {
177         float i;
178         if(s == "0" || stof(s))
179                 return s;
180         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
181                 if(s == get_weaponinfo(i).netname)
182                         return ftos(i);
183         return s;
184 }
185 string W_NumberWeaponOrder(string order)
186 {
187         return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
188 }
189
190 float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
191 string W_FixWeaponOrder_BuildImpulseList_order;
192 void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
193 {
194         float h;
195         h = W_FixWeaponOrder_BuildImpulseList_buf[i];
196         W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
197         W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
198 }
199 float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
200 {
201         entity e1, e2;
202         float d;
203         e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
204         e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
205         d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
206         if(d != 0)
207                 return -d; // high impulse first!
208         return
209                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
210                 -
211                 strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
212                 ; // low char index first!
213 }
214 string W_FixWeaponOrder_BuildImpulseList(string o)
215 {
216         float i;
217         W_FixWeaponOrder_BuildImpulseList_order = o;
218         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
219                 W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
220         heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
221         o = "";
222         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
223                 o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
224         W_FixWeaponOrder_BuildImpulseList_order = string_null;
225         return substring(o, 1, -1);
226 }
227
228 string W_FixWeaponOrder_AllowIncomplete(string order)
229 {
230         return W_FixWeaponOrder(order, 0);
231 }
232
233 string W_FixWeaponOrder_ForceComplete(string order)
234 {
235         if(order == "")
236                 order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
237         return W_FixWeaponOrder(order, 1);
238 }
239
240 void W_RandomWeapons(entity e, float n)
241 {
242         float i, j;
243         WepSet remaining;
244         WepSet result;
245         remaining = e.weapons;
246         result = '0 0 0';
247         for(i = 0; i < n; ++i)
248         {
249                 RandomSelection_Init();
250                 for(j = WEP_FIRST; j <= WEP_LAST; ++j)
251                         if(remaining & WepSet_FromWeapon(j))
252                                 RandomSelection_Add(world, j, string_null, 1, 1);
253                 result |= WepSet_FromWeapon(RandomSelection_chosen_float);
254                 remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
255         }
256         e.weapons = result;
257 }
258
259 #ifdef CSQC
260 .float GetAmmoFieldFromNum(float i)
261 {
262         switch(i)
263         {
264                 case 0: return ammo_shells;
265                 case 1: return ammo_nails;
266                 case 2: return ammo_rockets;
267                 case 3: return ammo_cells;
268                 case 4: return ammo_fuel;
269                 default: return ammo_none;
270         }
271 }
272
273 string GetAmmoPicture(.float ammotype)
274 {
275         switch(ammotype)
276         {
277                 case ammo_shells:  return "ammo_shells";
278                 case ammo_nails:   return "ammo_nails";
279                 case ammo_rockets: return "ammo_rockets";
280                 case ammo_cells:   return "ammo_cells";
281                 case ammo_fuel:    return "ammo_fuel";
282                 default: return ""; // wtf, no ammo type?
283         }
284 }
285
286 float GetAmmoStat(.float ammotype)
287 {
288         switch(ammotype)
289         {
290                 case ammo_shells: return STAT_SHELLS;
291                 case ammo_nails: return STAT_NAILS;
292                 case ammo_rockets: return STAT_ROCKETS;
293                 case ammo_cells: return STAT_CELLS;
294                 case ammo_fuel: return STAT_FUEL;
295                 default: return -1;
296         }
297 }
298 #endif