]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/all.qh
Player usable vehicle attack
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / all.qh
1 #ifndef WEAPONS_ALL_H
2 #define WEAPONS_ALL_H
3
4 #ifndef MENUQC
5 #include "calculations.qh"
6 #endif
7
8 #include "../util.qh"
9 #ifdef SVQC
10 #include "../../server/bot/aim.qh"
11 #endif
12 const int MAX_SHOT_DISTANCE = 32768;
13
14 // weapon pickup ratings for bot logic
15 const int BOT_PICKUP_RATING_LOW  =  2500;
16 const int BOT_PICKUP_RATING_MID  =  5000;
17 const int BOT_PICKUP_RATING_HIGH = 10000;
18
19 // weapon flags
20 const int WEP_TYPE_OTHER          =  0x00; // not for damaging people
21 const int WEP_TYPE_SPLASH         =  0x01; // splash damage
22 const int WEP_TYPE_HITSCAN        =  0x02; // hitscan
23 const int WEP_TYPEMASK            =  0x0F;
24 const int WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
25 const int WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
26 const int WEP_FLAG_HIDDEN         =  0x40; // hides from menu
27 const int WEP_FLAG_RELOADABLE     =  0x80; // can has reload
28 const int WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
29 const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
30
31 // weapon requests
32 const int WR_SETUP          =  1; // (SERVER) setup weapon data
33 .bool(entity this) wr_setup;
34 const int WR_THINK          =  2; // (SERVER) logic to run every frame
35 .bool(entity this) wr_think;
36 const int WR_CHECKAMMO1     =  3; // (SERVER) checks ammo for weapon primary
37 .bool(entity this) wr_checkammo1;
38 const int WR_CHECKAMMO2     =  4; // (SERVER) checks ammo for weapon second
39 .bool(entity this) wr_checkammo2;
40 const int WR_AIM            =  5; // (SERVER) runs bot aiming code for this weapon
41 .bool(entity this) wr_aim;
42 const int WR_INIT           =  6; // (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties
43 .bool(entity this) wr_init;
44 const int WR_SUICIDEMESSAGE =  7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
45 .bool(entity this) wr_suicidemessage;
46 const int WR_KILLMESSAGE    =  8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
47 .bool(entity this) wr_killmessage;
48 const int WR_RELOAD         =  9; // (SERVER) handles reloading for weapon
49 .bool(entity this) wr_reload;
50 const int WR_RESETPLAYER    = 10; // (SERVER) clears fields that the weapon may use
51 .bool(entity this) wr_resetplayer;
52 const int WR_IMPACTEFFECT   = 11; // (CLIENT) impact effect for weapon explosion
53 .bool(entity this) wr_impacteffect;
54 const int WR_PLAYERDEATH    = 12; // (SERVER) called whenever a player dies
55 .bool(entity this) wr_playerdeath;
56 const int WR_GONETHINK      = 13; // (SERVER) logic to run when weapon is lost
57 .bool(entity this) wr_gonethink;
58 const int WR_CONFIG         = 14; // (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
59 .bool(entity this) wr_config;
60 const int WR_ZOOMRETICLE    = 15; // (CLIENT) weapon specific zoom reticle
61 .bool(entity this) wr_zoomreticle;
62 const int WR_DROP           = 16; // (SERVER) the weapon is dropped
63 .bool(entity this) wr_drop;
64 const int WR_PICKUP         = 17; // (SERVER) a weapon is picked up
65 .bool(entity this) wr_pickup;
66
67 bool w_new(entity this, int req) {
68     if (req == WR_SETUP) return this.wr_setup ? this.wr_setup(this) : false;
69     if (req == WR_THINK) return this.wr_think ? this.wr_think(this) : false;
70     if (req == WR_CHECKAMMO1) return this.wr_checkammo1 ? this.wr_checkammo1(this) : false;
71     if (req == WR_CHECKAMMO2) return this.wr_checkammo2 ? this.wr_checkammo2(this) : false;
72     if (req == WR_AIM) return this.wr_aim ? this.wr_aim(this) : false;
73     if (req == WR_INIT) return this.wr_init ? this.wr_init(this) : false;
74     if (req == WR_SUICIDEMESSAGE) return this.wr_suicidemessage ? this.wr_suicidemessage(this) : false;
75     if (req == WR_KILLMESSAGE) return this.wr_killmessage ? this.wr_killmessage(this) : false;
76     if (req == WR_RELOAD) return this.wr_reload ? this.wr_reload(this) : false;
77     if (req == WR_RESETPLAYER) return this.wr_resetplayer ? this.wr_resetplayer(this) : false;
78     if (req == WR_IMPACTEFFECT) return this.wr_impacteffect ? this.wr_impacteffect(this) : false;
79     if (req == WR_PLAYERDEATH) return this.wr_playerdeath ? this.wr_playerdeath(this) : false;
80     if (req == WR_GONETHINK) return this.wr_gonethink ? this.wr_gonethink(this) : false;
81     if (req == WR_CONFIG) return this.wr_config ? this.wr_config(this) : false;
82     if (req == WR_ZOOMRETICLE) return this.wr_zoomreticle ? this.wr_zoomreticle(this) : false;
83     if (req == WR_DROP) return this.wr_drop ? this.wr_drop(this) : false;
84     if (req == WR_PICKUP) return this.wr_pickup ? this.wr_pickup(this) : false;
85     return false;
86 }
87
88 // variables:
89 string weaponorder_byid;
90
91 // weapon sets
92 typedef vector WepSet;
93 WepSet WepSet_FromWeapon(int a);
94 #ifdef SVQC
95 void WepSet_AddStat();
96 void WepSet_AddStat_InMap();
97 void WriteWepSet(float dest, WepSet w);
98 #endif
99 #ifdef CSQC
100 WepSet WepSet_GetFromStat();
101 WepSet WepSet_GetFromStat_InMap();
102 WepSet ReadWepSet();
103 #endif
104
105 // weapon name macros
106 const int WEP_FIRST = 1;
107 #define WEP_MAXCOUNT 32 // Increase as needed. Can be up to 72.
108 int WEP_COUNT;
109 #define WEP_LAST (WEP_FIRST + WEP_COUNT - 1)
110 WepSet WEPSET_ALL;
111 WepSet WEPSET_SUPERWEAPONS;
112
113 // functions:
114 entity get_weaponinfo(int id);
115 string W_FixWeaponOrder(string order, float complete);
116 string W_UndeprecateName(string s);
117 string W_NameWeaponOrder(string order);
118 string W_NumberWeaponOrder(string order);
119 string W_FixWeaponOrder_BuildImpulseList(string o);
120 string W_FixWeaponOrder_AllowIncomplete(string order);
121 string W_FixWeaponOrder_ForceComplete(string order);
122 void W_RandomWeapons(entity e, float n);
123
124 string GetAmmoPicture(.int ammotype);
125
126 #ifdef CSQC
127 .int GetAmmoFieldFromNum(int i);
128 int GetAmmoStat(.int ammotype);
129 #endif
130
131 string W_Sound(string w_snd);
132 string W_Model(string w_mdl);
133
134 // ammo types
135 .int ammo_shells;
136 .int ammo_nails;
137 .int ammo_rockets;
138 .int ammo_cells;
139 .int ammo_plasma;
140 .int ammo_fuel;
141 .int ammo_none;
142
143 // other useful macros
144 #define WEP_ACTION(wpn,wrequest) wpn.weapon_func(wpn, wrequest)
145 #define _WEP_ACTION(wpn,wrequest) WEP_ACTION(get_weaponinfo(wpn), wrequest)
146 #define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
147 #define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
148
149
150 // ======================
151 //  Configuration Macros
152 // ======================
153
154 // create cvars for weapon settings
155 #define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
156
157 #define WEP_ADD_CVAR_PRI(wepname,name) WEP_ADD_CVAR_NONE(wepname, primary_##name)
158 #define WEP_ADD_CVAR_SEC(wepname,name) WEP_ADD_CVAR_NONE(wepname, secondary_##name)
159 #define WEP_ADD_CVAR_BOTH(wepname,name) \
160         WEP_ADD_CVAR_PRI(wepname, name) \
161         WEP_ADD_CVAR_SEC(wepname, name)
162
163 #define WEP_ADD_CVAR(wepid,wepname,mode,name) WEP_ADD_CVAR_##mode(wepname, name)
164
165 // create properties for weapon settings
166 #define WEP_ADD_PROP(wepid,wepname,type,prop,name) \
167         .type prop; \
168         [[last]] type autocvar_g_balance_##wepname##_##name;
169
170 // read cvars from weapon settings
171 #define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name
172 #define WEP_CVAR_PRI(wepname,name) WEP_CVAR(wepname, primary_##name)
173 #define WEP_CVAR_SEC(wepname,name) WEP_CVAR(wepname, secondary_##name)
174 #define WEP_CVAR_BOTH(wepname,isprimary,name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name))
175
176 // set initialization values for weapon settings
177 #define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
178 #define WEP_SET_PROP(wepid,wepname,type,prop,name) WEP_##wepid.prop = autocvar_g_balance_##wepname##_##name;
179
180
181 // =====================
182 //  Weapon Registration
183 // =====================
184
185 /** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
186 CLASS(Weapon, Object)
187         ATTRIB(Weapon, m_id, int, 0)
188     /**
189      * M: WEP_id    : WEP_...
190      * you can recognize dummies when this == 0
191      */
192     ATTRIB(Weapon, weapon, int, 0);
193     /** A: WEPSET_id : WEPSET_... */
194     ATTRIB(Weapon, weapons, WepSet, '0 0 0');
195     /** M: function  : w_... */
196     ATTRIB(Weapon, weapon_func, bool(entity thiswep, int req), w_new);
197     /** M: ammotype  : main ammo field */
198     ATTRIB(Weapon, ammo_field, .int, ammo_none);
199     /** M: impulse   : weapon impulse */
200     ATTRIB(Weapon, impulse, int, -1);
201     /** M: flags     : WEPSPAWNFLAG_... combined */
202     ATTRIB(Weapon, spawnflags, int, 0);
203     /** M: rating    : bot weapon priority */
204     ATTRIB(Weapon, bot_pickupbasevalue, float, 0);
205     /** M: color     : waypointsprite color */
206     ATTRIB(Weapon, wpcolor, vector, '0 0 0');
207     /** A: wpn-id    : wpn- sprite name */
208     ATTRIB(Weapon, wpmodel, string, "");
209     /** M: modelname : name of model (without g_ v_ or h_ prefixes) */
210     ATTRIB(Weapon, mdl, string, "");
211     /** A: modelname : full path to g_ model */
212     ATTRIB(Weapon, model, string, "");
213     /** M: simplemdl : simpleitems weapon model/image */
214     ATTRIB(Weapon, w_simplemdl, string, "foobar");
215     /** M: crosshair : per-weapon crosshair: "CrosshairImage Size" */
216     ATTRIB(Weapon, w_crosshair, string, "gfx/crosshair1");
217     /** A: crosshair : per-weapon crosshair size (argument two of "crosshair" field) */
218     ATTRIB(Weapon, w_crosshair_size, float, 1);
219     /** M: wepimg    : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
220     ATTRIB(Weapon, model2, string, "");
221     /** M: refname   : reference name name */
222     ATTRIB(Weapon, netname, string, "");
223     /** M: wepname   : human readable name */
224     ATTRIB(Weapon, message, string, "AOL CD Thrower");
225
226         METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
227                 returns(this.message, this.model2 ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.model2) : string_null);
228         }
229
230         CONSTRUCTOR(Weapon,
231                 bool(entity this, int req) function,
232                 .int ammotype,
233                 int i,
234                 int weapontype,
235                 float pickupbasevalue,
236                 vector clr,
237                 string modelname,
238                 string simplemdl,
239                 string crosshair,
240                 string wepimg,
241                 string refname,
242                 string wepname
243         ) {
244                 CONSTRUCT(Weapon);
245                 this.weapon_func = function;
246                 this.ammo_field = ammotype;
247                 this.impulse = i;
248                 this.spawnflags = weapontype;
249                 this.bot_pickupbasevalue = pickupbasevalue;
250                 this.wpcolor = clr;
251                 this.mdl = modelname;
252                 this.model = strzone(W_Model(strcat("g_", modelname, ".md3")));
253                 this.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
254                 this.w_crosshair = strzone(car(crosshair));
255                 string s = cdr(crosshair);
256                 this.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
257                 this.model2 = strzone(wepimg);
258                 this.netname = refname;
259                 this.message = wepname;
260         }
261         void register_weapon(entity this, int id, WepSet bit)
262         {
263                 this.classname = "weapon_info";
264                 this.weapon = id;
265                 this.weapons = bit;
266                 this.wpmodel = strzone(strcat("wpn-", ftos(id)));
267                 #ifdef CSQC
268                 this.weapon_func(this, WR_INIT);
269                 #endif
270         }
271 ENDCLASS(Weapon)
272
273 void RegisterWeapons();
274 REGISTER_REGISTRY(RegisterWeapons)
275 entity weapon_info[WEP_MAXCOUNT], weapon_info_first, weapon_info_last;
276 entity dummy_weapon_info;
277
278 #define REGISTER_WEAPON(...) EVAL(OVERLOAD(REGISTER_WEAPON, __VA_ARGS__))
279
280 #define REGISTER_WEAPON_2(id, inst) \
281         WepSet WEPSET_##id; \
282         REGISTER(RegisterWeapons, WEP, weapon_info, WEP_COUNT, id, m_id, inst) { \
283                 this.m_id++; \
284                 WEPSET_ALL |= (WEPSET_##id = WepSet_FromWeapon(this.m_id)); \
285                 if ((this.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= WEPSET_##id; \
286                 register_weapon(this, this.m_id, WEPSET_##id); \
287         } \
288         REGISTER_INIT(WEP, id)
289
290 #define _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
291         REGISTER_WEAPON_2(id, NEW(Weapon, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname))
292
293 #ifndef MENUQC
294         #define REGISTER_WEAPON_13(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
295         bool function(entity this, int); \
296         _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
297 #else
298         #define REGISTER_WEAPON_13(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
299                 _REGISTER_WEAPON(id, w_new,   ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
300 #endif
301
302 #include "all.inc"
303
304 #undef WEP_ADD_CVAR_MO_PRI
305 #undef WEP_ADD_CVAR_MO_SEC
306 #undef WEP_ADD_CVAR_MO_BOTH
307 #undef WEP_ADD_CVAR_MO_NONE
308 #undef WEP_ADD_CVAR
309 #undef WEP_ADD_PROP
310 void register_weapons_done();
311 ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done)
312 #endif