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