]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/w_mortar.qc
On second thought, undo all that shit... this system is WAYYY too hacky to
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / w_mortar.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(
3 /* WEP_##id  */ MORTAR,
4 /* function  */ W_Mortar,
5 /* ammotype  */ ammo_rockets,
6 /* impulse   */ 4,
7 /* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
8 /* rating    */ BOT_PICKUP_RATING_MID,
9 /* color     */ '1 0 0',
10 /* modelname */ "gl",
11 /* simplemdl */ "foobar",
12 /* crosshair */ "gfx/crosshairgrenadelauncher 0.7",
13 /* refname   */ "grenadelauncher",
14 /* wepname   */ _("Mortar")
15 );
16
17 #define MORTAR_SETTINGS(w_cvar,w_prop) MORTAR_SETTINGS_LIST(w_cvar, w_prop, MORTAR, mortar)
18 #define MORTAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
19         w_cvar(id, sn, BOTH, ammo) \
20         w_cvar(id, sn, BOTH, animtime) \
21         w_cvar(id, sn, NONE, bouncefactor) \
22         w_cvar(id, sn, NONE, bouncestop) \
23         w_cvar(id, sn, BOTH, damage) \
24         w_cvar(id, sn, BOTH, damageforcescale) \
25         w_cvar(id, sn, BOTH, edgedamage) \
26         w_cvar(id, sn, BOTH, force) \
27         w_cvar(id, sn, BOTH, health) \
28         w_cvar(id, sn, BOTH, lifetime) \
29         w_cvar(id, sn, SEC,  lifetime_bounce) \
30         w_cvar(id, sn, BOTH, lifetime_stick) \
31         w_cvar(id, sn, BOTH, radius) \
32         w_cvar(id, sn, BOTH, refire) \
33         w_cvar(id, sn, SEC,  remote_detonateprimary) \
34         w_cvar(id, sn, PRI,  remote_minbouncecnt) \
35         w_cvar(id, sn, BOTH, speed) \
36         w_cvar(id, sn, BOTH, speed_up) \
37         w_cvar(id, sn, BOTH, speed_z) \
38         w_cvar(id, sn, BOTH, spread) \
39         w_cvar(id, sn, BOTH, type) \
40         w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
41         w_prop(id, sn, float,  reloading_time, reload_time) \
42         w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
43         w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
44         w_prop(id, sn, string, weaponreplace, weaponreplace) \
45         w_prop(id, sn, float,  weaponstart, weaponstart) \
46         w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride)
47
48 #ifdef SVQC
49 MORTAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
50 .float gl_detonate_later;
51 .float gl_bouncecnt;
52 #endif
53 #else
54 #ifdef SVQC
55
56 void spawnfunc_weapon_mortar() { weapon_defaultspawnfunc(WEP_MORTAR); }
57 void spawnfunc_weapon_grenadelauncher() { spawnfunc_weapon_mortar(); }
58
59 void W_Mortar_Grenade_Explode()
60 {
61         if(other.takedamage == DAMAGE_AIM)
62                 if(IS_PLAYER(other))
63                         if(DIFF_TEAM(self.realowner, other))
64                                 if(other.deadflag == DEAD_NO)
65                                         if(IsFlying(other))
66                                                 Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
67
68         self.event_damage = func_null;
69         self.takedamage = DAMAGE_NO;
70
71         if(self.movetype == MOVETYPE_NONE)
72                 self.velocity = self.oldvelocity;
73
74         RadiusDamage (self, self.realowner, WEP_CVAR_PRI(mortar, damage), WEP_CVAR_PRI(mortar, edgedamage), WEP_CVAR_PRI(mortar, radius), world, world, WEP_CVAR_PRI(mortar, force), self.projectiledeathtype, other);
75
76         remove (self);
77 }
78
79 void W_Mortar_Grenade_Explode2()
80 {
81         if(other.takedamage == DAMAGE_AIM)
82                 if(IS_PLAYER(other))
83                         if(DIFF_TEAM(self.realowner, other))
84                                 if(other.deadflag == DEAD_NO)
85                                         if(IsFlying(other))
86                                                 Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
87
88         self.event_damage = func_null;
89         self.takedamage = DAMAGE_NO;
90
91         if(self.movetype == MOVETYPE_NONE)
92                 self.velocity = self.oldvelocity;
93
94         RadiusDamage (self, self.realowner, WEP_CVAR_SEC(mortar, damage), WEP_CVAR_SEC(mortar, edgedamage), WEP_CVAR_SEC(mortar, radius), world, world, WEP_CVAR_SEC(mortar, force), self.projectiledeathtype, other);
95
96         remove (self);
97 }
98
99
100 void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
101 {
102         if (self.health <= 0)
103                 return;
104                 
105         if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
106                 return; // g_projectiles_damage says to halt
107                 
108         self.health = self.health - damage;
109         
110         if (self.health <= 0)
111                 W_PrepareExplosionByDamage(attacker, self.use);
112 }
113
114 void W_Mortar_Grenade_Think1()
115 {
116         self.nextthink = time;
117         if (time > self.cnt)
118         {
119                 other = world;
120                 self.projectiledeathtype |= HITTYPE_BOUNCE;
121                 W_Mortar_Grenade_Explode();
122                 return;
123         }
124         if(self.gl_detonate_later && self.gl_bouncecnt >= WEP_CVAR_PRI(mortar, remote_minbouncecnt))
125                 W_Mortar_Grenade_Explode();
126 }
127
128 void W_Mortar_Grenade_Touch1()
129 {
130         PROJECTILE_TOUCH;
131         if (other.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
132         {
133                 self.use ();
134         }
135         else if (WEP_CVAR_PRI(mortar, type) == 1) // bounce
136         {
137                 float r;
138                 r = random() * 6;
139                 if(r < 1)
140                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
141                 else if(r < 2)
142                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
143                 else if(r < 3)
144                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
145                 else if(r < 4)
146                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
147                 else if(r < 5)
148                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
149                 else
150                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
151                 pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
152                 self.projectiledeathtype |= HITTYPE_BOUNCE;
153                 self.gl_bouncecnt += 1;
154         }
155         else if(WEP_CVAR_PRI(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
156         {
157                 spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
158
159                 // let it stick whereever it is
160                 self.oldvelocity = self.velocity;
161                 self.velocity = '0 0 0';
162                 self.movetype = MOVETYPE_NONE; // also disables gravity
163                 self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
164                 UpdateCSQCProjectile(self);
165
166                 // do not respond to any more touches
167                 self.solid = SOLID_NOT;
168
169                 self.nextthink = min(self.nextthink, time + WEP_CVAR_PRI(mortar, lifetime_stick));
170         }
171 }
172
173 void W_Mortar_Grenade_Touch2()
174 {
175         PROJECTILE_TOUCH;
176         if (other.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
177         {
178                 self.use ();
179         }
180         else if (WEP_CVAR_SEC(mortar, type) == 1) // bounce
181         {
182                 float r;
183                 r = random() * 6;
184                 if(r < 1)
185                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
186                 else if(r < 2)
187                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
188                 else if(r < 3)
189                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
190                 else if(r < 4)
191                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
192                 else if(r < 5)
193                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
194                 else
195                         spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
196                 pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
197                 self.projectiledeathtype |= HITTYPE_BOUNCE;
198                 self.gl_bouncecnt += 1;
199                 
200                 if (WEP_CVAR_SEC(mortar, lifetime_bounce) && self.gl_bouncecnt == 1)
201                         self.nextthink = time + WEP_CVAR_SEC(mortar, lifetime_bounce);
202                         
203         }
204         else if(WEP_CVAR_SEC(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
205         {
206                 spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
207
208                 // let it stick whereever it is
209                 self.oldvelocity = self.velocity;
210                 self.velocity = '0 0 0';
211                 self.movetype = MOVETYPE_NONE; // also disables gravity
212                 self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
213                 UpdateCSQCProjectile(self);
214
215                 // do not respond to any more touches
216                 self.solid = SOLID_NOT;
217
218                 self.nextthink = min(self.nextthink, time + WEP_CVAR_SEC(mortar, lifetime_stick));
219         }
220 }
221
222 void W_Mortar_Attack()
223 {
224         entity gren;
225
226         W_DecreaseAmmo(WEP_CVAR_PRI(mortar, ammo));
227
228         W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
229         w_shotdir = v_forward; // no TrueAim for grenades please
230
231         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
232
233         gren = spawn ();
234         gren.owner = gren.realowner = self;
235         gren.classname = "grenade";
236         gren.bot_dodge = TRUE;
237         gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage);
238         gren.movetype = MOVETYPE_BOUNCE;
239         gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
240         gren.bouncestop = WEP_CVAR(mortar, bouncestop);
241         PROJECTILE_MAKETRIGGER(gren);
242         gren.projectiledeathtype = WEP_MORTAR;
243         setorigin(gren, w_shotorg);
244         setsize(gren, '-3 -3 -3', '3 3 3');
245
246         gren.cnt = time + WEP_CVAR_PRI(mortar, lifetime);
247         gren.nextthink = time;
248         gren.think = W_Mortar_Grenade_Think1;
249         gren.use = W_Mortar_Grenade_Explode;
250         gren.touch = W_Mortar_Grenade_Touch1;
251
252         gren.takedamage = DAMAGE_YES;
253         gren.health = WEP_CVAR_PRI(mortar, health);
254         gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale);
255         gren.event_damage = W_Mortar_Grenade_Damage;
256         gren.damagedbycontents = TRUE;
257         gren.missile_flags = MIF_SPLASH | MIF_ARC;
258         W_SetupProjVelocity_UP_PRI(gren, mortar);
259
260         gren.angles = vectoangles (gren.velocity);
261         gren.flags = FL_PROJECTILE;
262
263         if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2)
264                 CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
265         else
266                 CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
267
268         other = gren; MUTATOR_CALLHOOK(EditProjectile);
269 }
270
271 void W_Mortar_Attack2()
272 {
273         entity gren;
274
275         W_DecreaseAmmo(WEP_CVAR_SEC(mortar, ammo));
276
277         W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
278         w_shotdir = v_forward; // no TrueAim for grenades please
279
280         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
281
282         gren = spawn ();
283         gren.owner = gren.realowner = self;
284         gren.classname = "grenade";
285         gren.bot_dodge = TRUE;
286         gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage);
287         gren.movetype = MOVETYPE_BOUNCE;
288         gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
289         gren.bouncestop = WEP_CVAR(mortar, bouncestop);
290         PROJECTILE_MAKETRIGGER(gren);
291         gren.projectiledeathtype = WEP_MORTAR | HITTYPE_SECONDARY;
292         setorigin(gren, w_shotorg);
293         setsize(gren, '-3 -3 -3', '3 3 3');
294
295         gren.nextthink = time + WEP_CVAR_SEC(mortar, lifetime);
296         gren.think = adaptor_think2use_hittype_splash;
297         gren.use = W_Mortar_Grenade_Explode2;
298         gren.touch = W_Mortar_Grenade_Touch2;
299
300         gren.takedamage = DAMAGE_YES;
301         gren.health = WEP_CVAR_SEC(mortar, health);
302         gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale);
303         gren.event_damage = W_Mortar_Grenade_Damage;
304         gren.damagedbycontents = TRUE;
305         gren.missile_flags = MIF_SPLASH | MIF_ARC;
306         W_SetupProjVelocity_UP_SEC(gren, mortar);
307
308         gren.angles = vectoangles (gren.velocity);
309         gren.flags = FL_PROJECTILE;
310
311         if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2)
312                 CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
313         else
314                 CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
315
316         other = gren; MUTATOR_CALLHOOK(EditProjectile);
317 }
318
319 .float bot_secondary_grenademooth;
320 float W_Mortar(float req)
321 {
322         entity nade;
323         float nadefound;
324         float ammo_amount;
325         switch(req)
326         {
327                 case WR_AIM:
328                 {
329                         self.BUTTON_ATCK = FALSE;
330                         self.BUTTON_ATCK2 = FALSE;
331                         if (self.bot_secondary_grenademooth == 0) // WEAPONTODO: merge this into using WEP_CVAR_BOTH
332                         {
333                                 if(bot_aim(WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), TRUE))
334                                 {
335                                         self.BUTTON_ATCK = TRUE;
336                                         if(random() < 0.01) self.bot_secondary_grenademooth = 1;
337                                 }
338                         }
339                         else
340                         {
341                                 if(bot_aim(WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), TRUE))
342                                 {
343                                         self.BUTTON_ATCK2 = TRUE;
344                                         if(random() < 0.02) self.bot_secondary_grenademooth = 0;
345                                 }
346                         }
347                         
348                         return TRUE;
349                 }
350                 /*case WR_CALCINFO:
351                 {
352                         wepinfo_pri_refire = max3(sys_frametime, WEP_CVAR_PRI(mortar, refire), WEP_CVAR_PRI(mortar, animtime));
353                         wepinfo_pri_dps = (WEP_CVAR_PRI(mortar, damage) * (1 / wepinfo_pri_refire));
354                         wepinfo_pri_speed = (1 / max(1, (10000 / max(1, WEP_CVAR_PRI(mortar, speed)))));
355
356                         // for the range calculation, closer to 1 is better
357                         wepinfo_pri_range_max = 2000 * wepinfo_pri_speed;
358                         wepinfo_pri_range = wepinfo_pri_speed * WEP_CVAR_PRI(mortar, 
359                         
360                         wepinfo_sec_refire = max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime));
361                         wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / wepinfo_sec_refire));
362                         
363                         wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime))));
364                         wepinfo_ter_dps = 0;
365                         */
366                 case WR_THINK:
367                 {
368                         if(autocvar_g_balance_mortar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) // forced reload
369                                 WEP_ACTION(self.weapon, WR_RELOAD);
370                         else if (self.BUTTON_ATCK)
371                         {
372                                 if (weapon_prepareattack(0, WEP_CVAR_PRI(mortar, refire)))
373                                 {
374                                         W_Mortar_Attack();
375                                         weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
376                                 }
377                         }
378                         else if (self.BUTTON_ATCK2)
379                         {
380                                 if(WEP_CVAR_SEC(mortar, remote_detonateprimary))
381                                 {
382                                         nadefound = 0;
383                                         for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
384                                         {
385                                                 if(!nade.gl_detonate_later)
386                                                 {
387                                                         nade.gl_detonate_later = TRUE;
388                                                         nadefound = 1;
389                                                 }
390                                         }
391                                         if(nadefound)
392                                                 sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
393                                 }
394                                 else if (weapon_prepareattack(1, WEP_CVAR_SEC(mortar, refire)))
395                                 {
396                                         W_Mortar_Attack2();
397                                         weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
398                                 }
399                         }
400                         
401                         return TRUE;
402                 }
403                 case WR_INIT:
404                 {
405                         precache_model ("models/weapons/g_gl.md3");
406                         precache_model ("models/weapons/v_gl.md3");
407                         precache_model ("models/weapons/h_gl.iqm");
408                         precache_sound ("weapons/grenade_bounce1.wav");
409                         precache_sound ("weapons/grenade_bounce2.wav");
410                         precache_sound ("weapons/grenade_bounce3.wav");
411                         precache_sound ("weapons/grenade_bounce4.wav");
412                         precache_sound ("weapons/grenade_bounce5.wav");
413                         precache_sound ("weapons/grenade_bounce6.wav");
414                         precache_sound ("weapons/grenade_stick.wav");
415                         precache_sound ("weapons/grenade_fire.wav");
416                         MORTAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
417                         return TRUE;
418                 }
419                 case WR_CHECKAMMO1:
420                 {
421                         ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
422                         ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_PRI(mortar, ammo);
423                         return ammo_amount;
424                 }
425                 case WR_CHECKAMMO2:
426                 {
427                         ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
428                         ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_SEC(mortar, ammo);
429                         return ammo_amount;
430                 }
431                 case WR_CONFIG:
432                 {
433                         MORTAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
434                         return TRUE;
435                 }
436                 case WR_RELOAD:
437                 {
438                         W_Reload(min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), "weapons/reload.wav"); // WEAPONTODO
439                         return TRUE;
440                 }
441                 case WR_SUICIDEMESSAGE:
442                 {
443                         if(w_deathtype & HITTYPE_SECONDARY)
444                                 return WEAPON_MORTAR_SUICIDE_BOUNCE;
445                         else
446                                 return WEAPON_MORTAR_SUICIDE_EXPLODE;
447                 }
448                 case WR_KILLMESSAGE:
449                 {
450                         if(w_deathtype & HITTYPE_SECONDARY)
451                                 return WEAPON_MORTAR_MURDER_BOUNCE;
452                         else
453                                 return WEAPON_MORTAR_MURDER_EXPLODE;
454                 }
455         }
456         return TRUE;
457 }
458 #endif
459 #ifdef CSQC
460 float W_Mortar(float req)
461 {
462         switch(req)
463         {
464                 case WR_IMPACTEFFECT:
465                 {
466                         vector org2;
467                         org2 = w_org + w_backoff * 12;
468                         pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
469                         if(!w_issilent)
470                                 sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
471                                 
472                         return TRUE;
473                 }
474                 case WR_INIT:
475                 {
476                         precache_sound("weapons/grenade_impact.wav");
477                         return TRUE;
478                 }
479                 case WR_ZOOMRETICLE:
480                 {
481                         // no weapon specific image for this weapon
482                         return FALSE;
483                 }
484         }
485         return TRUE;
486 }
487 #endif
488 #endif