Skip to content

Instantly share code, notes, and snippets.

@samisalreadytaken
Last active December 19, 2023 18:25
Show Gist options
  • Select an option

  • Save samisalreadytaken/61b86fee4023df102fa87d52c9882845 to your computer and use it in GitHub Desktop.

Select an option

Save samisalreadytaken/61b86fee4023df102fa87d52c9882845 to your computer and use it in GitHub Desktop.
//-----------------------------------------------------------------------
// github.com/samisalreadytaken
//-----------------------------------------------------------------------
//
// Melee attack regardless of weapons player is wielding
//
// +attack3 to swing
//
const ATTACK_DELAY = 0.1;
const ATTACK_INTERVAL = 0.6;
const ATTACK_RANGE = 76.0;
local m_hCrowbar;
if ( SERVER_DLL )
{
local Time = Time,
RandomFloat = RandomFloat,
RandomInt = RandomInt,
Convars = Convars,
CreateDamageInfo = CreateDamageInfo,
DestroyDamageInfo = DestroyDamageInfo,
TraceHullComplex = TraceHullComplex;
local m_flNextAttackTime = 0.0;
local ATTACK_HULL_MAX = Vector(4,4,2);
local ATTACK_HULL_MIN = Vector(4,-4,-8);
local function UnforceAttack( player )
{
player.UnforceButtons( IN.ATTACK );
}
//
// Leg model animation does not look good outside of viewmodel space,
// so just make the client swing a crowbar.
//
// Create the prop on server because animation on client is not yet possible
//
local function AnimThink( player )
{
if ( m_hCrowbar.IsSequenceFinished() )
{
m_hCrowbar.Destroy();
m_hCrowbar = null;
player.EnableButtons( IN.ATTACK | IN.ATTACK2 | IN.ATTACK3 );
local wep = player.GetActiveWeapon();
if ( wep )
{
NetProps.SetPropInt( wep, "m_bLowered", 0 );
wep.SendWeaponAnim( 173 ); // ACT_VM_IDLE
}
return -1;
}
m_hCrowbar.StudioFrameAdvance();
return 0.0;
}
local function PlaySwingAnimation( player )
{
if ( m_hCrowbar && m_hCrowbar.IsValid() )
m_hCrowbar.Destroy();
m_hCrowbar = Entities.CreateByClassname("prop_dynamic");
m_hCrowbar.SetModel("models/weapons/v_crowbar.mdl");
m_hCrowbar.SetSequence( 3 );
m_hCrowbar.ResetSequenceInfo();
player.SetContextThink( "MeleeAttack.Anim", AnimThink, 0.0 );
NetMsg.Start("MeleeAttack.Anim");
m_hCrowbar.SetTransmitState( 8 );
NetMsg.WriteEntity( m_hCrowbar );
NetMsg.Send( player, true );
}
local function TraceAttack( player )
{
local vecStart = player.EyePosition();
local viewForward = player.GetEyeForward();
local vecEnd = viewForward.Multiply( ATTACK_RANGE ).Add( vecStart );
local tr = TraceHullComplex( vecStart, vecEnd, ATTACK_HULL_MIN, ATTACK_HULL_MAX, player, MASK_SHOT_HULL, COLLISION_GROUP_NONE );
//debugoverlay.EntityBounds( tr.Entity(), 255, 0, 255, 15, 3.0 )
//debugoverlay.SweptBox( vecStart, vecEnd, ATTACK_HULL_MIN, ATTACK_HULL_MAX, player.EyeAngles(), 255, 0, 0, 2, 3.0 );
local pEnt = tr.Entity();
if ( pEnt )
{
if ( pEnt.entindex() )
{
local dmg = Convars.GetInt("sk_plr_dmg_crowbar") * 0.75;
local endpos = tr.EndPos();
local info = CreateDamageInfo( player, player, player.GetAutoaimVector( dmg * 3072. ), endpos, dmg, DMG_CLUB );
if ( pEnt.GetTakeDamage() != DAMAGE_NO )
{
pEnt.TakeDamage( info );
}
else
{
while ( (pEnt = pEnt.GetMoveParent()) && (pEnt.GetTakeDamage() != DAMAGE_NO) )
{
pEnt.TakeDamage( info );
break;
}
}
DestroyDamageInfo( info );
player.EmitSound( "Weapon_Crowbar.Melee_Hit" );
}
else
{
player.EmitSound( "Weapon_Crowbar.Melee_HitWorld" );
}
player.ViewPunch( Vector( RandomFloat(0., 1.), 0., RandomFloat(1., 2.) ) );
player.EmitSound( tr.Surface().SurfaceProps().GetSoundBulletImpact() );
}
else
{
player.ViewPunch( Vector( RandomFloat(-0.5, 0.), 0., 0.5 ) );
player.EmitSound( "Weapon_Crowbar.Single" );
}
tr.Destroy();
}
local function DoAttack( player )
{
// Don't swing while attacking
if ( player.GetButtons() & (IN.ATTACK | IN.ATTACK2) )
return;
// Don't swing if dead or driving
if ( !player.IsAlive() || player.GetVehicleEntity() )
return;
local curtime = Time();
if ( curtime < m_flNextAttackTime )
return;
m_flNextAttackTime = curtime + ATTACK_INTERVAL;
local wep = player.GetActiveWeapon();
if ( wep && wep.GetClassname() == "weapon_crowbar" )
{
player.ForceButtons( IN.ATTACK );
player.SetContextThink( "MeleeAttack", UnforceAttack, 0.001 );
}
else
{
player.DisableButtons( IN.ATTACK | IN.ATTACK2 | IN.ATTACK3 );
if ( wep )
{
NetProps.SetPropInt( wep, "m_bLowered", 1 );
wep.SendWeaponAnim( 203 ); // ACT_VM_IDLE_LOWERED
}
player.SetContextThink( "PlaySwingAnimation", PlaySwingAnimation, ATTACK_DELAY );
player.SetContextThink( "MeleeAttack", TraceAttack, ATTACK_DELAY * 2.0 );
}
}
NetMsg.Receive( "MeleeAttack", DoAttack );
}
if ( CLIENT_DLL )
{
local function AnimThink(_)
{
if ( m_hCrowbar.IsValid() )
{
local origin = MainViewOrigin()
.Subtract( MainViewForward().Multiply( 20. ) )
.Subtract( MainViewUp().Multiply( 8.0 ) )
.Add( MainViewRight().Multiply( 8.0 ) );
local angles = MainViewAngles();
angles.z = 30.0;
m_hCrowbar.SetLocalOrigin( origin );
m_hCrowbar.SetLocalAngles( angles );
return 0.0;
}
m_hCrowbar = null;
return -1;
}
NetMsg.Receive( "MeleeAttack.Anim", function()
{
m_hCrowbar = NetMsg.ReadEntity();
Entities.First().SetContextThink( "MeleeAttack.Anim", AnimThink, 0.0 );
} );
local function Attack()
{
NetMsg.Start( "MeleeAttack" );
return NetMsg.Send();
}
Convars.RegisterCommand( "+attack3", function(...)
{
Attack();
return true;
}, "", 0 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment