Skip to content

Commit 6915787

Browse files
authored
Merge pull request #183 from Petercov/mapbase-feature/custom-weapons
Enhanced custom weapons support
2 parents f4c2cb4 + d3978db commit 6915787

21 files changed

Lines changed: 2381 additions & 35 deletions

sp/src/game/client/c_basecombatweapon.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ int C_BaseCombatWeapon::GetWorldModelIndex( void )
151151
//-----------------------------------------------------------------------------
152152
void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
153153
{
154+
#ifdef MAPBASE
155+
if (updateType == DATA_UPDATE_CREATED)
156+
{
157+
Precache();
158+
}
159+
#endif // MAPBASE
160+
154161
BaseClass::OnDataChanged(updateType);
155162

156163
CHandle< C_BaseCombatWeapon > handle = this;

sp/src/game/client/client_mapbase.vpc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ $Project
6969
$File "mapbase\c_func_fake_worldportal.h"
7070
$File "mapbase\c_point_glow.cpp"
7171
$File "mapbase\c_vgui_text_display.cpp"
72+
$File "mapbase\c_weapon_custom_hl2.cpp"
7273
$File "mapbase\mapbase_autocubemap.cpp"
7374
}
7475

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
2+
//
3+
// Purpose: Client classes for Half-Life 2 based custom weapons.
4+
//
5+
// Author: Peter Covington (petercov@outlook.com)
6+
//
7+
//==================================================================================//
8+
9+
#include "cbase.h"
10+
#include "c_weapon__stubs.h"
11+
#include "basehlcombatweapon_shared.h"
12+
#include "c_basehlcombatweapon.h"
13+
14+
// memdbgon must be the last include file in a .cpp file!!!
15+
#include "tier0/memdbgon.h"
16+
17+
class C_HLCustomWeaponMelee : public C_BaseHLBludgeonWeapon
18+
{
19+
public:
20+
DECLARE_CLASS(C_HLCustomWeaponMelee, C_BaseHLBludgeonWeapon);
21+
DECLARE_CLIENTCLASS();
22+
DECLARE_PREDICTABLE();
23+
24+
C_HLCustomWeaponMelee();
25+
26+
virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
27+
private:
28+
char m_iszWeaponScriptName[128];
29+
};
30+
31+
STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustommelee, C_HLCustomWeaponMelee);
32+
33+
IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponMelee, DT_HLCustomWeaponMelee, CHLCustomWeaponMelee)
34+
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
35+
END_RECV_TABLE();
36+
37+
C_HLCustomWeaponMelee::C_HLCustomWeaponMelee()
38+
{
39+
m_iszWeaponScriptName[0] = '\0';
40+
}
41+
42+
43+
44+
class C_HLCustomWeaponGun : public C_BaseHLCombatWeapon
45+
{
46+
public:
47+
DECLARE_CLASS(C_HLCustomWeaponGun, C_BaseHLCombatWeapon);
48+
DECLARE_CLIENTCLASS();
49+
DECLARE_PREDICTABLE();
50+
51+
C_HLCustomWeaponGun();
52+
53+
virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
54+
private:
55+
char m_iszWeaponScriptName[128];
56+
};
57+
58+
STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustomgun, C_HLCustomWeaponGun);
59+
60+
IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponGun, DT_HLCustomWeaponGun, CHLCustomWeaponGun)
61+
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
62+
END_RECV_TABLE();
63+
64+
C_HLCustomWeaponGun::C_HLCustomWeaponGun()
65+
{
66+
m_iszWeaponScriptName[0] = '\0';
67+
}

sp/src/game/client/prediction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
855855
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
856856
if ( weapon )
857857
{
858-
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
858+
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
859859
}
860860
}
861861

sp/src/game/server/basebludgeonweapon.cpp

Lines changed: 159 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon )
2929
END_SEND_TABLE()
3030

31+
#ifdef MAPBASE
32+
BEGIN_DATADESC(CBaseHLBludgeonWeapon)
33+
34+
DEFINE_FIELD(m_flDelayedFire, FIELD_TIME),
35+
DEFINE_FIELD(m_bShotDelayed, FIELD_BOOLEAN),
36+
37+
END_DATADESC()
38+
#endif // MAPBASE
39+
3140
#define BLUDGEON_HULL_DIM 16
3241

3342
static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM);
@@ -39,6 +48,9 @@ static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_
3948
CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon()
4049
{
4150
m_bFiresUnderwater = true;
51+
#ifdef MAPBASE
52+
m_bShotDelayed = false;
53+
#endif // MAPBASE
4254
}
4355

4456
//-----------------------------------------------------------------------------
@@ -96,11 +108,19 @@ void CBaseHLBludgeonWeapon::ItemPostFrame( void )
96108
#ifdef MAPBASE
97109
if (pOwner->HasSpawnFlags( SF_PLAYER_SUPPRESS_FIRING ))
98110
{
111+
m_bShotDelayed = false;
99112
WeaponIdle();
100113
return;
101114
}
102-
#endif
103115

116+
// See if we need to fire off our secondary round
117+
if (m_bShotDelayed)
118+
{
119+
if (gpGlobals->curtime > m_flDelayedFire)
120+
DelayedAttack();
121+
}
122+
else
123+
#endif
104124
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
105125
{
106126
PrimaryAttack();
@@ -162,7 +182,12 @@ void CBaseHLBludgeonWeapon::Hit( trace_t &traceHit, Activity nHitActivity, bool
162182
pPlayer->EyeVectors( &hitDirection, NULL, NULL );
163183
VectorNormalize( hitDirection );
164184

165-
CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
185+
#ifdef MAPBASE
186+
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
187+
#else
188+
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
189+
#endif // MAPBASE
190+
166191

167192
if( pPlayer && pHitEntity->IsNPC() )
168193
{
@@ -234,7 +259,7 @@ Activity CBaseHLBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hit
234259
}
235260

236261

237-
return ACT_VM_HITCENTER;
262+
return GetPrimaryAttackActivity();
238263
}
239264

240265
//-----------------------------------------------------------------------------
@@ -292,7 +317,6 @@ void CBaseHLBludgeonWeapon::ImpactEffect( trace_t &traceHit )
292317
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
293318
}
294319

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

316340
Vector swingEnd = swingStart + forward * GetRange();
317341
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
318-
Activity nHitActivity = ACT_VM_HITCENTER;
342+
Activity nHitActivity = GetPrimaryAttackActivity();
319343

320344
// Like bullets, bludgeon traces have to trace against triggers.
321-
CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
345+
#ifdef MAPBASE
346+
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
347+
#else
348+
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
349+
#endif // MAPBASE
322350
triggerInfo.SetDamagePosition( traceHit.startpos );
323351
triggerInfo.SetDamageForce( forward );
324352
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward );
@@ -369,31 +397,20 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
369397
{
370398
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
371399

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

375-
#ifdef MAPBASE
376-
// Sound has been moved here since we're using the other melee sounds now
377-
WeaponSound( SINGLE );
378-
#endif
379-
380404
// See if we happened to hit water
381-
ImpactWater( swingStart, testEnd );
405+
ImpactWater(swingStart, testEnd);
406+
#endif // !MAPBASE
382407
}
408+
#ifndef MAPBASE
383409
else
384410
{
385-
#ifdef MAPBASE
386-
// Other melee sounds
387-
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
388-
WeaponSound(MELEE_HIT_WORLD);
389-
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
390-
WeaponSound(MELEE_MISS);
391-
else
392-
WeaponSound(MELEE_HIT);
393-
#endif
394-
395411
Hit( traceHit, nHitActivity, bIsSecondary ? true : false );
396412
}
413+
#endif
397414

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

410427
#ifdef MAPBASE
411428
pOwner->SetAnimation( PLAYER_ATTACK1 );
429+
430+
if (GetHitDelay() > 0.f)
431+
{
432+
//Play swing sound
433+
WeaponSound(SINGLE);
434+
435+
m_flDelayedFire = gpGlobals->curtime + GetHitDelay();
436+
m_bShotDelayed = true;
437+
}
438+
else
439+
{
440+
if (traceHit.fraction == 1.0f)
441+
{
442+
// We want to test the first swing again
443+
Vector testEnd = swingStart + forward * GetRange();
444+
445+
//Play swing sound
446+
WeaponSound(SINGLE);
447+
448+
// See if we happened to hit water
449+
ImpactWater(swingStart, testEnd);
450+
}
451+
else
452+
{
453+
// Other melee sounds
454+
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
455+
WeaponSound(MELEE_HIT_WORLD);
456+
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
457+
WeaponSound(MELEE_MISS);
458+
else
459+
WeaponSound(MELEE_HIT);
460+
461+
Hit(traceHit, nHitActivity, bIsSecondary ? true : false);
462+
}
463+
}
412464
#endif
413465
}
466+
467+
#ifdef MAPBASE
468+
void CBaseHLBludgeonWeapon::DelayedAttack(void)
469+
{
470+
m_bShotDelayed = false;
471+
472+
trace_t traceHit;
473+
474+
// Try a ray
475+
CBasePlayer* pOwner = ToBasePlayer(GetOwner());
476+
if (!pOwner)
477+
return;
478+
479+
pOwner->RumbleEffect(RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART);
480+
481+
Vector swingStart = pOwner->Weapon_ShootPosition();
482+
Vector forward;
483+
484+
forward = pOwner->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT, GetRange());
485+
486+
Vector swingEnd = swingStart + forward * GetRange();
487+
UTIL_TraceLine(swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
488+
489+
if (traceHit.fraction == 1.0)
490+
{
491+
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
492+
493+
// Back off by hull "radius"
494+
swingEnd -= forward * bludgeonHullRadius;
495+
496+
UTIL_TraceHull(swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
497+
if (traceHit.fraction < 1.0 && traceHit.m_pEnt)
498+
{
499+
Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart;
500+
VectorNormalize(vecToTarget);
501+
502+
float dot = vecToTarget.Dot(forward);
503+
504+
// YWB: Make sure they are sort of facing the guy at least...
505+
if (dot < 0.70721f)
506+
{
507+
// Force amiss
508+
traceHit.fraction = 1.0f;
509+
}
510+
else
511+
{
512+
ChooseIntersectionPointAndActivity(traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner);
513+
}
514+
}
515+
}
516+
517+
if (traceHit.fraction == 1.0f)
518+
{
519+
// We want to test the first swing again
520+
Vector testEnd = swingStart + forward * GetRange();
521+
522+
// See if we happened to hit water
523+
ImpactWater(swingStart, testEnd);
524+
}
525+
else
526+
{
527+
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(GetActivity()), GetDamageType());
528+
triggerInfo.SetDamagePosition(traceHit.startpos);
529+
triggerInfo.SetDamageForce(forward);
530+
531+
// Other melee sounds
532+
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
533+
WeaponSound(MELEE_HIT_WORLD);
534+
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
535+
WeaponSound(MELEE_MISS);
536+
else
537+
WeaponSound(MELEE_HIT);
538+
539+
Hit(traceHit, GetActivity(), false);
540+
}
541+
}
542+
543+
bool CBaseHLBludgeonWeapon::CanHolster(void)
544+
{
545+
if (m_bShotDelayed)
546+
return false;
547+
548+
return BaseClass::CanHolster();
549+
}
550+
#endif // MAPBASE

0 commit comments

Comments
 (0)