Skip to content

Commit

Permalink
Merge pull request #183 from Petercov/mapbase-feature/custom-weapons
Browse files Browse the repository at this point in the history
Enhanced custom weapons support
  • Loading branch information
Blixibon authored Oct 25, 2023
2 parents f4c2cb4 + d3978db commit 6915787
Show file tree
Hide file tree
Showing 21 changed files with 2,381 additions and 35 deletions.
7 changes: 7 additions & 0 deletions sp/src/game/client/c_basecombatweapon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ int C_BaseCombatWeapon::GetWorldModelIndex( void )
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
{
#ifdef MAPBASE
if (updateType == DATA_UPDATE_CREATED)
{
Precache();
}
#endif // MAPBASE

BaseClass::OnDataChanged(updateType);

CHandle< C_BaseCombatWeapon > handle = this;
Expand Down
1 change: 1 addition & 0 deletions sp/src/game/client/client_mapbase.vpc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ $Project
$File "mapbase\c_func_fake_worldportal.h"
$File "mapbase\c_point_glow.cpp"
$File "mapbase\c_vgui_text_display.cpp"
$File "mapbase\c_weapon_custom_hl2.cpp"
$File "mapbase\mapbase_autocubemap.cpp"
}

Expand Down
67 changes: 67 additions & 0 deletions sp/src/game/client/mapbase/c_weapon_custom_hl2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Client classes for Half-Life 2 based custom weapons.
//
// Author: Peter Covington ([email protected])
//
//==================================================================================//

#include "cbase.h"
#include "c_weapon__stubs.h"
#include "basehlcombatweapon_shared.h"
#include "c_basehlcombatweapon.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

class C_HLCustomWeaponMelee : public C_BaseHLBludgeonWeapon
{
public:
DECLARE_CLASS(C_HLCustomWeaponMelee, C_BaseHLBludgeonWeapon);
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();

C_HLCustomWeaponMelee();

virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
private:
char m_iszWeaponScriptName[128];
};

STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustommelee, C_HLCustomWeaponMelee);

IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponMelee, DT_HLCustomWeaponMelee, CHLCustomWeaponMelee)
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
END_RECV_TABLE();

C_HLCustomWeaponMelee::C_HLCustomWeaponMelee()
{
m_iszWeaponScriptName[0] = '\0';
}



class C_HLCustomWeaponGun : public C_BaseHLCombatWeapon
{
public:
DECLARE_CLASS(C_HLCustomWeaponGun, C_BaseHLCombatWeapon);
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();

C_HLCustomWeaponGun();

virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
private:
char m_iszWeaponScriptName[128];
};

STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustomgun, C_HLCustomWeaponGun);

IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponGun, DT_HLCustomWeaponGun, CHLCustomWeaponGun)
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
END_RECV_TABLE();

C_HLCustomWeaponGun::C_HLCustomWeaponGun()
{
m_iszWeaponScriptName[0] = '\0';
}
2 changes: 1 addition & 1 deletion sp/src/game/client/prediction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
if ( weapon )
{
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
}
}

Expand Down
181 changes: 159 additions & 22 deletions sp/src/game/server/basebludgeonweapon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon )
END_SEND_TABLE()

#ifdef MAPBASE
BEGIN_DATADESC(CBaseHLBludgeonWeapon)

DEFINE_FIELD(m_flDelayedFire, FIELD_TIME),
DEFINE_FIELD(m_bShotDelayed, FIELD_BOOLEAN),

END_DATADESC()
#endif // MAPBASE

#define BLUDGEON_HULL_DIM 16

static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM);
Expand All @@ -39,6 +48,9 @@ static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_
CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon()
{
m_bFiresUnderwater = true;
#ifdef MAPBASE
m_bShotDelayed = false;
#endif // MAPBASE
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -96,11 +108,19 @@ void CBaseHLBludgeonWeapon::ItemPostFrame( void )
#ifdef MAPBASE
if (pOwner->HasSpawnFlags( SF_PLAYER_SUPPRESS_FIRING ))
{
m_bShotDelayed = false;
WeaponIdle();
return;
}
#endif

// See if we need to fire off our secondary round
if (m_bShotDelayed)
{
if (gpGlobals->curtime > m_flDelayedFire)
DelayedAttack();
}
else
#endif
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
{
PrimaryAttack();
Expand Down Expand Up @@ -162,7 +182,12 @@ void CBaseHLBludgeonWeapon::Hit( trace_t &traceHit, Activity nHitActivity, bool
pPlayer->EyeVectors( &hitDirection, NULL, NULL );
VectorNormalize( hitDirection );

CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
#ifdef MAPBASE
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
#else
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
#endif // MAPBASE


if( pPlayer && pHitEntity->IsNPC() )
{
Expand Down Expand Up @@ -234,7 +259,7 @@ Activity CBaseHLBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hit
}


return ACT_VM_HITCENTER;
return GetPrimaryAttackActivity();
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -292,7 +317,6 @@ void CBaseHLBludgeonWeapon::ImpactEffect( trace_t &traceHit )
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
}


//------------------------------------------------------------------------------
// Purpose : Starts the swing of the weapon and determines the animation
// Input : bIsSecondary - is this a secondary attack?
Expand All @@ -315,10 +339,14 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )

Vector swingEnd = swingStart + forward * GetRange();
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
Activity nHitActivity = ACT_VM_HITCENTER;
Activity nHitActivity = GetPrimaryAttackActivity();

// Like bullets, bludgeon traces have to trace against triggers.
CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
#ifdef MAPBASE
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
#else
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
#endif // MAPBASE
triggerInfo.SetDamagePosition( traceHit.startpos );
triggerInfo.SetDamageForce( forward );
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward );
Expand Down Expand Up @@ -369,31 +397,20 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
{
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;

#ifndef MAPBASE
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();

#ifdef MAPBASE
// Sound has been moved here since we're using the other melee sounds now
WeaponSound( SINGLE );
#endif

// See if we happened to hit water
ImpactWater( swingStart, testEnd );
ImpactWater(swingStart, testEnd);
#endif // !MAPBASE
}
#ifndef MAPBASE
else
{
#ifdef MAPBASE
// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);
#endif

Hit( traceHit, nHitActivity, bIsSecondary ? true : false );
}
#endif

// Send the anim
SendWeaponAnim( nHitActivity );
Expand All @@ -409,5 +426,125 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )

#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );

if (GetHitDelay() > 0.f)
{
//Play swing sound
WeaponSound(SINGLE);

m_flDelayedFire = gpGlobals->curtime + GetHitDelay();
m_bShotDelayed = true;
}
else
{
if (traceHit.fraction == 1.0f)
{
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();

//Play swing sound
WeaponSound(SINGLE);

// See if we happened to hit water
ImpactWater(swingStart, testEnd);
}
else
{
// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);

Hit(traceHit, nHitActivity, bIsSecondary ? true : false);
}
}
#endif
}

#ifdef MAPBASE
void CBaseHLBludgeonWeapon::DelayedAttack(void)
{
m_bShotDelayed = false;

trace_t traceHit;

// Try a ray
CBasePlayer* pOwner = ToBasePlayer(GetOwner());
if (!pOwner)
return;

pOwner->RumbleEffect(RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART);

Vector swingStart = pOwner->Weapon_ShootPosition();
Vector forward;

forward = pOwner->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT, GetRange());

Vector swingEnd = swingStart + forward * GetRange();
UTIL_TraceLine(swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);

if (traceHit.fraction == 1.0)
{
float bludgeonHullRadius = 1.732f * BLUDGEON_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point

// Back off by hull "radius"
swingEnd -= forward * bludgeonHullRadius;

UTIL_TraceHull(swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
if (traceHit.fraction < 1.0 && traceHit.m_pEnt)
{
Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart;
VectorNormalize(vecToTarget);

float dot = vecToTarget.Dot(forward);

// YWB: Make sure they are sort of facing the guy at least...
if (dot < 0.70721f)
{
// Force amiss
traceHit.fraction = 1.0f;
}
else
{
ChooseIntersectionPointAndActivity(traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner);
}
}
}

if (traceHit.fraction == 1.0f)
{
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();

// See if we happened to hit water
ImpactWater(swingStart, testEnd);
}
else
{
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(GetActivity()), GetDamageType());
triggerInfo.SetDamagePosition(traceHit.startpos);
triggerInfo.SetDamageForce(forward);

// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);

Hit(traceHit, GetActivity(), false);
}
}

bool CBaseHLBludgeonWeapon::CanHolster(void)
{
if (m_bShotDelayed)
return false;

return BaseClass::CanHolster();
}
#endif // MAPBASE
Loading

0 comments on commit 6915787

Please sign in to comment.