+ antilag_restore(it, it);
+ });
+ }
+}
+
+METHOD(Shockwave, wr_aim, void(entity thiswep, entity actor))
+{
+ if(vdist(actor.origin - actor.enemy.origin, <=, WEP_CVAR(shockwave, melee_range)))
+ { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false); }
+ else
+ { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false); }
+}
+METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+ if(fire & 1)
+ {
+ if(time >= actor.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
+ {
+ if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(shockwave, blast_animtime)))
+ {
+ W_Shockwave_Attack(actor);
+ actor.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(actor);
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
+ }
+ }
+ }
+ else if(fire & 2)
+ {
+ //if(actor.clip_load >= 0) // we are not currently reloading
+ if(!actor.crouch) // no crouchmelee please
+ if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR(shockwave, melee_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_Shockwave_Melee);
+ }
+ }
+}
+METHOD(Shockwave, wr_checkammo1, bool(entity thiswep, entity actor))
+{
+ return true; // infinite ammo
+}
+METHOD(Shockwave, wr_checkammo2, bool(entity thiswep, entity actor))
+{
+ // shockwave has infinite ammo
+ return true;
+}
+METHOD(Shockwave, wr_suicidemessage, Notification(entity thiswep))
+{
+ return WEAPON_THINKING_WITH_PORTALS;
+}
+METHOD(Shockwave, wr_killmessage, Notification(entity thiswep))
+{
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_SHOCKWAVE_MURDER_SLAP;
+ else
+ return WEAPON_SHOCKWAVE_MURDER;
+}