X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fweapon%2Fshotgun.qc;h=234aaadaf635daf3cbd48d7b69a39fa92582209e;hb=92749b51e06f4fd2a89d7593a9db7500818ad2fd;hp=d61a2521dd2894f87e61c620e6d902cc650baa7b;hpb=28305c2245f99ca5ae21ea8858e05c6bb0a2000b;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/weapons/weapon/shotgun.qc b/qcsrc/common/weapons/weapon/shotgun.qc index d61a2521d..234aaadaf 100644 --- a/qcsrc/common/weapons/weapon/shotgun.qc +++ b/qcsrc/common/weapons/weapon/shotgun.qc @@ -1,67 +1,71 @@ #ifndef IMPLEMENTATION -REGISTER_WEAPON( -/* WEP_##id */ SHOTGUN, -/* function */ W_Shotgun, -/* ammotype */ ammo_shells, -/* impulse */ 2, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_LOW, -/* color */ '0.5 0.25 0', -/* modelname */ "shotgun", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairshotgun 0.65", -/* wepimg */ "weaponshotgun", -/* refname */ "shotgun", -/* wepname */ _("Shotgun") -); - -#define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun) -#define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, PRI, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, PRI, bullets) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, PRI, solidpenetration) \ - w_cvar(id, sn, PRI, spread) \ - w_cvar(id, sn, NONE, secondary) \ - w_cvar(id, sn, SEC, melee_time) \ - w_cvar(id, sn, SEC, melee_no_doubleslap) \ - w_cvar(id, sn, SEC, melee_traces) \ - w_cvar(id, sn, SEC, melee_swing_up) \ - w_cvar(id, sn, SEC, melee_swing_side) \ - w_cvar(id, sn, SEC, melee_nonplayerdamage) \ - w_cvar(id, sn, SEC, melee_multihit) \ - w_cvar(id, sn, SEC, melee_delay) \ - w_cvar(id, sn, SEC, melee_range) \ - w_cvar(id, sn, SEC, alt_animtime) \ - w_cvar(id, sn, SEC, alt_refire) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) +CLASS(Shotgun, Weapon) +/* ammotype */ ATTRIB(Shotgun, ammo_field, .int, ammo_shells) +/* impulse */ ATTRIB(Shotgun, impulse, int, 2) +/* flags */ ATTRIB(Shotgun, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN); +/* rating */ ATTRIB(Shotgun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW); +/* color */ ATTRIB(Shotgun, wpcolor, vector, '0.5 0.25 0'); +/* modelname */ ATTRIB(Shotgun, mdl, string, "shotgun"); +#ifndef MENUQC +/* model */ ATTRIB(Shotgun, m_model, Model, MDL_SHOTGUN_ITEM); #endif +/* crosshair */ ATTRIB(Shotgun, w_crosshair, string, "gfx/crosshairshotgun"); +/* crosshair */ ATTRIB(Shotgun, w_crosshair_size, float, 0.65); +/* wepimg */ ATTRIB(Shotgun, model2, string, "weaponshotgun"); +/* refname */ ATTRIB(Shotgun, netname, string, "shotgun"); +/* wepname */ ATTRIB(Shotgun, m_name, string, _("Shotgun")); + +#define X(BEGIN, P, END, class, prefix) \ + BEGIN(class) \ + P(class, prefix, alt_animtime, float, SEC) \ + P(class, prefix, alt_refire, float, SEC) \ + P(class, prefix, ammo, float, PRI) \ + P(class, prefix, animtime, float, BOTH) \ + P(class, prefix, bullets, float, PRI) \ + P(class, prefix, damage, float, BOTH) \ + P(class, prefix, force, float, BOTH) \ + P(class, prefix, melee_delay, float, SEC) \ + P(class, prefix, melee_multihit, float, SEC) \ + P(class, prefix, melee_nonplayerdamage, float, SEC) \ + P(class, prefix, melee_no_doubleslap, float, SEC) \ + P(class, prefix, melee_range, float, SEC) \ + P(class, prefix, melee_swing_side, float, SEC) \ + P(class, prefix, melee_swing_up, float, SEC) \ + P(class, prefix, melee_time, float, SEC) \ + P(class, prefix, melee_traces, float, SEC) \ + P(class, prefix, refire, float, BOTH) \ + P(class, prefix, reload_ammo, float, NONE) \ + P(class, prefix, reload_time, float, NONE) \ + P(class, prefix, secondary, float, NONE) \ + P(class, prefix, solidpenetration, float, PRI) \ + P(class, prefix, spread, float, PRI) \ + P(class, prefix, switchdelay_drop, float, NONE) \ + P(class, prefix, switchdelay_raise, float, NONE) \ + P(class, prefix, weaponreplace, string,NONE) \ + P(class, prefix, weaponstartoverride, float, NONE) \ + P(class, prefix, weaponstart, float, NONE) \ + P(class, prefix, weaponthrowable, float, NONE) \ + END() + W_PROPS(X, Shotgun, shotgun) +#undef X + +ENDCLASS(Shotgun) +REGISTER_WEAPON(SHOTGUN, shotgun, NEW(Shotgun)); + + #endif #ifdef IMPLEMENTATION #ifdef SVQC -void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); } +spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(this, WEP_SHOTGUN); } -void W_Shotgun_Attack(float isprimary) +void W_Shotgun_Attack(Weapon thiswep, float isprimary) {SELFPARAM(); float sc; entity flash; - W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo)); + W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(shotgun, ammo)); - W_SetupShot(self, true, 5, W_Sound("shotgun_fire"), ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets)); + W_SetupShot(self, true, 5, SND(SHOTGUN_FIRE), ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets)); for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1) fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0); @@ -74,16 +78,16 @@ void W_Shotgun_Attack(float isprimary) // muzzle flash for 1st person view flash = spawn(); - setmodel(flash, "models/uziflash.md3"); // precision set below - flash.think = SUB_Remove; + setmodel(flash, MDL_SHOTGUN_MUZZLEFLASH); // precision set below + flash.think = SUB_Remove_self; flash.nextthink = time + 0.06; flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - W_AttachToShotorg(flash, '5 0 0'); + W_AttachToShotorg(self, flash, '5 0 0'); } .float swing_prev; .entity swing_alreadyhit; -void W_Shotgun_Melee_Think(void) +void W_Shotgun_Melee_Think() {SELFPARAM(); // declarations float i, f, swing, swing_factor, swing_damage, meleetime, is_player; @@ -104,7 +108,7 @@ void W_Shotgun_Melee_Think(void) f = ((1 - swing) * WEP_CVAR_SEC(shotgun, melee_traces)); // check to see if we can still continue, otherwise give up now - if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap)) + if(IS_DEAD(self.realowner) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap)) { remove(self); return; @@ -120,7 +124,7 @@ void W_Shotgun_Melee_Think(void) + (v_up * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_up)) + (v_right * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_side))); - WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, false, self, ANTILAG_LATENCY(self.realowner)); + WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, false, self.realowner, ANTILAG_LATENCY(self.realowner)); // draw lightning beams for debugging //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); @@ -179,214 +183,160 @@ void W_Shotgun_Melee_Think(void) } } -void W_Shotgun_Attack2(void) -{SELFPARAM(); - sound(self, CH_WEAPON_A, W_Sound("shotgun_melee"), VOL_BASE, ATTEN_NORM); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready); +void W_Shotgun_Attack2(Weapon thiswep, entity actor, .entity weaponentity, int fire) +{ + sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready); - entity meleetemp; - meleetemp = spawn(); - meleetemp.realowner = self; + entity meleetemp = new_pure(meleetemp); + meleetemp.realowner = actor; meleetemp.think = W_Shotgun_Melee_Think; meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor(); - W_SetupShot_Range(self, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range)); + W_SetupShot_Range(actor, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range)); } // alternate secondary weapon frames -void W_Shotgun_Attack3_Frame2() -{SELFPARAM(); - if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2)) - if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) +void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire) +{ + if (!thiswep.wr_checkammo2(thiswep)) + if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO)) { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); + W_SwitchWeapon_Force(actor, w_getbestweapon(actor)); + w_ready(thiswep, actor, weaponentity, fire); return; } - sound(self, CH_WEAPON_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); // kill previous sound - W_Shotgun_Attack(true); // actually is secondary, but we trick the last shot into playing full reload sound - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready); + sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound + W_Shotgun_Attack(WEP_SHOTGUN, true); // actually is secondary, but we trick the last shot into playing full reload sound + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready); } -void W_Shotgun_Attack3_Frame1() -{SELFPARAM(); - if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2)) - if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) +void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire) +{ + if (!thiswep.wr_checkammo2(thiswep)) + if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO)) { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); + W_SwitchWeapon_Force(actor, w_getbestweapon(actor)); + w_ready(thiswep, actor, weaponentity, fire); return; } - W_Shotgun_Attack(false); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2); + W_Shotgun_Attack(WEP_SHOTGUN, false); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2); } .float shotgun_primarytime; -float W_Shotgun(float req) -{SELFPARAM(); - float ammo_amount; - switch(req) - { - case WR_AIM: - { - if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range)) - self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false); - else - self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false); - - return true; - } - case WR_THINK: - { - if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload - { - // don't force reload an empty shotgun if its melee attack is active - if(WEP_CVAR(shotgun, secondary) < 2) - WEP_ACTION(self.weapon, WR_RELOAD); - } - else - { - if(self.BUTTON_ATCK) - { - if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime))) - { - W_Shotgun_Attack(true); - self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready); - } - } - } - else if(self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary) == 2) - { - if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary - { - if(weapon_prepareattack(0, WEP_CVAR_SEC(shotgun, alt_animtime))) - { - W_Shotgun_Attack(false); - self.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1); - } - } - } - } - if(self.clip_load >= 0) // we are not currently reloading - if(!self.crouch) // no crouchmelee please - if(WEP_CVAR(shotgun, secondary) == 1) - if((self.BUTTON_ATCK && self.WEP_AMMO(SHOTGUN) <= 0 && !(self.items & IT_UNLIMITED_WEAPON_AMMO)) || self.BUTTON_ATCK2) - if(weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire))) - { - // attempt forcing playback of the anim by switching to another anim (that we never play) here... - weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2); - } - - return true; - } - case WR_INIT: - { - precache_model("models/uziflash.md3"); - precache_model(W_Model("g_shotgun.md3")); - precache_model(W_Model("v_shotgun.md3")); - precache_model(W_Model("h_shotgun.iqm")); - precache_sound("misc/itempickup.wav"); - precache_sound(W_Sound("shotgun_fire")); - precache_sound(W_Sound("shotgun_melee")); - SHOTGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP); - return true; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - return true; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo); - ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(IS_BOT_CLIENT(self)) - if(vlen(self.origin-self.enemy.origin) > WEP_CVAR_SEC(shotgun, melee_range)) - return false; // bots cannot use secondary out of range (fixes constant melee when out of ammo) - switch(WEP_CVAR(shotgun, secondary)) - { - case 1: return true; // melee does not use ammo - case 2: // secondary triple shot - { - ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo); - ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo); - return ammo_amount; - } - default: return false; // secondary unavailable - } - } - case WR_CONFIG: - { - SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS); - return true; - } - case WR_RELOAD: - { - W_Reload(WEP_CVAR_PRI(shotgun, ammo), W_Sound("reload")); // WEAPONTODO - return true; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_SHOTGUN_MURDER_SLAP; - else - return WEAPON_SHOTGUN_MURDER; - } - } - return false; +METHOD(Shotgun, wr_aim, void(entity thiswep)) +{ + if(vdist(self.origin - self.enemy.origin, <=, WEP_CVAR_SEC(shotgun, melee_range))) + PHYS_INPUT_BUTTON_ATCK2(self) = bot_aim(1000000, 0, 0.001, false); + else + PHYS_INPUT_BUTTON_ATCK(self) = bot_aim(1000000, 0, 0.001, false); +} +METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) +{ + if(WEP_CVAR(shotgun, reload_ammo) && actor.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload + { + // don't force reload an empty shotgun if its melee attack is active + if(WEP_CVAR(shotgun, secondary) < 2) { + thiswep.wr_reload(thiswep, actor, weaponentity); + } + } + else + { + if(fire & 1) + { + if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary + { + if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(shotgun, animtime))) + { + W_Shotgun_Attack(thiswep, true); + actor.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready); + } + } + } + else if((fire & 2) && WEP_CVAR(shotgun, secondary) == 2) + { + if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary + { + if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(shotgun, alt_animtime))) + { + W_Shotgun_Attack(thiswep, false); + actor.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1); + } + } + } + } + if(actor.clip_load >= 0) // we are not currently reloading + if(!actor.crouch) // no crouchmelee please + if(WEP_CVAR(shotgun, secondary) == 1) + if(((fire & 1) && actor.(thiswep.ammo_field) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2)) + if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire))) + { + // attempt forcing playback of the anim by switching to another anim (that we never play) here... + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, W_Shotgun_Attack2); + } +} +METHOD(Shotgun, wr_setup, void(entity thiswep)) +{ + self.ammo_field = ammo_none; +} +METHOD(Shotgun, wr_checkammo1, bool(entity thiswep)) +{ + float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo); + ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo); + return ammo_amount; +} +METHOD(Shotgun, wr_checkammo2, bool(entity thiswep)) +{ + if(IS_BOT_CLIENT(self)) + if(vdist(self.origin - self.enemy.origin, >, WEP_CVAR_SEC(shotgun, melee_range))) + return false; // bots cannot use secondary out of range (fixes constant melee when out of ammo) + switch(WEP_CVAR(shotgun, secondary)) + { + case 1: return true; // melee does not use ammo + case 2: // secondary triple shot + { + float ammo_amount = self.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo); + ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo); + return ammo_amount; + } + default: return false; // secondary unavailable + } +} +METHOD(Shotgun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity)) +{ + W_Reload(self, WEP_CVAR_PRI(shotgun, ammo), SND(RELOAD)); // WEAPONTODO } +METHOD(Shotgun, wr_suicidemessage, Notification(entity thiswep)) +{ + return WEAPON_THINKING_WITH_PORTALS; +} +METHOD(Shotgun, wr_killmessage, Notification(entity thiswep)) +{ + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_SHOTGUN_MURDER_SLAP; + else + return WEAPON_SHOTGUN_MURDER; +} + #endif #ifdef CSQC .float prevric; -float W_Shotgun(float req) -{SELFPARAM(); - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum(EFFECT_SHOTGUN_IMPACT), org2, w_backoff * 1000, 1); - if(!w_issilent && time - self.prevric > 0.25) - { - if(w_random < 0.0165) - sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_NORM); - else if(w_random < 0.033) - sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTEN_NORM); - else if(w_random < 0.05) - sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTEN_NORM); - self.prevric = time; - } - return true; - } - case WR_INIT: - { - precache_sound(W_Sound("ric1")); - precache_sound(W_Sound("ric2")); - precache_sound(W_Sound("ric3")); - return true; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return false; - } - } - return false; +METHOD(Shotgun, wr_impacteffect, void(entity thiswep)) +{ + vector org2 = w_org + w_backoff * 2; + pointparticles(EFFECT_SHOTGUN_IMPACT, org2, w_backoff * 1000, 1); + if(!w_issilent && time - self.prevric > 0.25) + { + if(w_random < 0.05) + sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM); + self.prevric = time; + } } + #endif #endif