diff --git a/cl_dll/hl/hl_weapons.cpp b/cl_dll/hl/hl_weapons.cpp index 88556f61..78d813f7 100644 --- a/cl_dll/hl/hl_weapons.cpp +++ b/cl_dll/hl/hl_weapons.cpp @@ -69,7 +69,6 @@ CTripmine g_Tripmine; CSqueak g_Snark; CDisplacer g_Displacer; CEagle g_Eagle; -CGrapple g_Grapple; CKnife g_Knife; CM249 g_M249; CPenguin g_Penguin; @@ -628,7 +627,6 @@ void HUD_InitClientWeapons( void ) HUD_PrepEntity( &g_Snark, &player ); HUD_PrepEntity( &g_Displacer, &player ); HUD_PrepEntity( &g_Eagle, &player ); - HUD_PrepEntity( &g_Grapple, &player ); HUD_PrepEntity( &g_Knife, &player ); HUD_PrepEntity( &g_M249, &player ); HUD_PrepEntity( &g_Penguin, &player ); @@ -744,9 +742,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm case WEAPON_DISPLACER: pWeapon = &g_Displacer; break; - case WEAPON_GRAPPLE: - pWeapon = &g_Grapple; - break; case WEAPON_EAGLE: pWeapon = &g_Eagle; break; diff --git a/dlls/agrunt.cpp b/dlls/agrunt.cpp index cb47ac65..d9bf491c 100644 --- a/dlls/agrunt.cpp +++ b/dlls/agrunt.cpp @@ -102,6 +102,8 @@ public: virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_LARGE; } + static const char *pAttackHitSounds[]; static const char *pAttackMissSounds[]; static const char *pAttackSounds[]; diff --git a/dlls/barnacle.cpp b/dlls/barnacle.cpp index ecc1f5d4..3ece6f6b 100644 --- a/dlls/barnacle.cpp +++ b/dlls/barnacle.cpp @@ -47,6 +47,8 @@ public: virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_FIXED; } + float m_flAltitude; float m_flCachedLength; // tongue cached length float m_flKillVictimTime; diff --git a/dlls/bigmomma.cpp b/dlls/bigmomma.cpp index 434d6134..c46838d5 100644 --- a/dlls/bigmomma.cpp +++ b/dlls/bigmomma.cpp @@ -287,6 +287,8 @@ public: virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_LARGE; } + static const char *pChildDieSounds[]; static const char *pSackSounds[]; static const char *pDeathSounds[]; diff --git a/dlls/bullsquid.h b/dlls/bullsquid.h index 37eceb72..a5490365 100644 --- a/dlls/bullsquid.h +++ b/dlls/bullsquid.h @@ -73,9 +73,11 @@ public: int Save(CSave &save); int Restore(CRestore &restore); - CUSTOM_SCHEDULES; + CUSTOM_SCHEDULES static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + BOOL m_fCanThreatDisplay;// this is so the squid only does the "I see a headcrab!" dance one time. float m_flLastHurtTime;// we keep track of this, because if something hurts a squid, it will forget about its love of headcrabs for a while. @@ -83,4 +85,4 @@ public: }; -#endif // BULLSQUID_H \ No newline at end of file +#endif // BULLSQUID_H diff --git a/dlls/cbase.h b/dlls/cbase.h index 22d8737e..28921732 100644 --- a/dlls/cbase.h +++ b/dlls/cbase.h @@ -134,6 +134,15 @@ public: CBaseEntity *operator ->(); }; +enum GrappleTarget +{ + GRAPPLE_NOT_A_TARGET = 0, + GRAPPLE_SMALL = 1, + GRAPPLE_MEDIUM = 2, + GRAPPLE_LARGE = 3, + GRAPPLE_FIXED = 4, +}; + // // Base Entity. All entity types derive from this // @@ -356,6 +365,8 @@ public: virtual BOOL FVisible( CBaseEntity *pEntity ); virtual BOOL FVisible( const Vector &vecOrigin ); + virtual int SizeForGrapple() { return GRAPPLE_NOT_A_TARGET; } + //We use this variables to store each ammo count. int ammo_9mm; int ammo_357; diff --git a/dlls/gargantua.cpp b/dlls/gargantua.cpp index f3155d7f..bdcf9dce 100644 --- a/dlls/gargantua.cpp +++ b/dlls/gargantua.cpp @@ -244,6 +244,8 @@ public: CUSTOM_SCHEDULES + virtual int SizeForGrapple() { return GRAPPLE_LARGE; } + private: static const char *pAttackHitSounds[]; static const char *pBeamAttackSounds[]; diff --git a/dlls/gearbox/grapple.cpp b/dlls/gearbox/grapple.cpp index 6cefd0c2..5d58c76b 100644 --- a/dlls/gearbox/grapple.cpp +++ b/dlls/gearbox/grapple.cpp @@ -16,710 +16,531 @@ #include "extdll.h" #include "util.h" #include "cbase.h" -#include "monsters.h" #include "weapons.h" -#include "nodes.h" -#include "player.h" #include "gamerules.h" +#include "player.h" +#include "skill.h" +#include "effects.h" +#include "customentity.h" #ifndef CLIENT_DLL #include "grapple_tonguetip.h" #endif -LINK_ENTITY_TO_CLASS(weapon_grapple, CGrapple); +LINK_ENTITY_TO_CLASS( weapon_grapple, CBarnacleGrapple ) enum bgrap_e { - BGRAP_BREATHE = 0, - BGRAP_LONGIDLE, - BGRAP_SHORTIDLE, - BGRAP_COUGH, - BGRAP_DOWN, - BGRAP_UP, - BGRAP_FIRE, - BGRAP_FIREWAITING, - BGRAP_FIREREACHED, - BGRAP_FIRETRAVEL, - BGRAP_FIRERELEASE, + BGRAPPLE_BREATHE = 0, + BGRAPPLE_LONGIDLE, + BGRAPPLE_SHORTIDLE, + BGRAPPLE_COUGH, + BGRAPPLE_DOWN, + BGRAPPLE_UP, + BGRAPPLE_FIRE, + BGRAPPLE_FIREWAITING, + BGRAPPLE_FIREREACHED, + BGRAPPLE_FIRETRAVEL, + BGRAPPLE_FIRERELEASE }; -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Spawn() +void CBarnacleGrapple::Precache( void ) { - Precache(); - m_iId = WEAPON_GRAPPLE; - SET_MODEL(ENT(pev), "models/w_bgrap.mdl"); - m_iClip = -1; - - m_pBeam = NULL; - m_pTongueTip = NULL; - m_fTipHit = FALSE; - m_fPlayPullSound = FALSE; + PRECACHE_MODEL( "models/v_bgrap.mdl" ); + PRECACHE_MODEL( "models/w_bgrap.mdl" ); + PRECACHE_MODEL( "models/p_bgrap.mdl" ); - m_iHitFlags = 0; - m_iFirestate = FIRESTATE_NONE; + PRECACHE_SOUND( "weapons/bgrapple_release.wav" ); + PRECACHE_SOUND( "weapons/bgrapple_impact.wav" ); + PRECACHE_SOUND( "weapons/bgrapple_fire.wav" ); + PRECACHE_SOUND( "weapons/bgrapple_cough.wav" ); + PRECACHE_SOUND( "weapons/bgrapple_pull.wav" ); + PRECACHE_SOUND( "weapons/bgrapple_wait.wav" ); + PRECACHE_SOUND( "weapons/alienweap_draw.wav" ); + PRECACHE_SOUND( "barnacle/bcl_chew1.wav" ); + PRECACHE_SOUND( "barnacle/bcl_chew2.wav" ); + PRECACHE_SOUND( "barnacle/bcl_chew3.wav" ); - m_flNextPullSoundTime = 0.0f; + PRECACHE_MODEL( "sprites/tongue.spr" ); - FallInit();// get ready to fall down. + UTIL_PrecacheOther( "grapple_tip" ); + m_flNextPrimaryAttack = 0; + m_flNextSecondaryAttack = 0; + m_flTimeWeaponIdle = 0; } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Precache(void) +void CBarnacleGrapple::Spawn( void ) { - PRECACHE_MODEL("models/v_bgrap.mdl"); - PRECACHE_MODEL("models/v_bgrap_tonguetip.mdl"); - - PRECACHE_MODEL("models/w_bgrap.mdl"); - PRECACHE_MODEL("models/p_bgrap.mdl"); - - PRECACHE_SOUND("weapons/alienweap_draw.wav"); - - PRECACHE_SOUND("weapons/bgrapple_cough.wav"); - PRECACHE_SOUND("weapons/bgrapple_fire.wav"); - PRECACHE_SOUND("weapons/bgrapple_impact.wav"); - PRECACHE_SOUND("weapons/bgrapple_pull.wav"); - PRECACHE_SOUND("weapons/bgrapple_release.wav"); - PRECACHE_SOUND("weapons/bgrapple_wait.wav"); + Precache(); + m_iId = WEAPON_GRAPPLE; + SET_MODEL( ENT(pev), "models/w_bgrap.mdl" ); + m_pTip = NULL; + m_bGrappling = FALSE; + m_iClip = -1; - PRECACHE_MODEL("sprites/smoke_blk.spr"); + FallInit(); } -//========================================================= -// Purpose: -//========================================================= -int CGrapple::GetItemInfo(ItemInfo *p) +int CBarnacleGrapple::GetItemInfo(ItemInfo *p) { p->pszName = STRING(pev->classname); p->pszAmmo1 = NULL; p->iMaxAmmo1 = -1; p->pszAmmo2 = NULL; p->iMaxAmmo2 = -1; - p->iMaxClip = WEAPON_GRAPPLE; + p->iMaxClip = WEAPON_NOCLIP; p->iSlot = 0; p->iPosition = 3; - p->iId = WEAPON_GRAPPLE; + p->iId = m_iId = WEAPON_GRAPPLE; p->iWeight = GRAPPLE_WEIGHT; return 1; } -//========================================================= -// Purpose: -//========================================================= -BOOL CGrapple::Deploy() +int CBarnacleGrapple::AddToPlayer( CBasePlayer* pPlayer ) { - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.9f; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.9f; - - return DefaultDeploy("models/v_bgrap.mdl", "models/p_bgrap.mdl", BGRAP_UP, "bgrap"); + if( CBasePlayerWeapon::AddToPlayer( pPlayer ) ) + { + MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev ); + WRITE_BYTE( m_iId ); + MESSAGE_END(); + return TRUE; + } + return FALSE; } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Holster(int skiplocal /* = 0 */) +BOOL CBarnacleGrapple::Deploy() { - FireRelease(); - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; - SendWeaponAnim(BGRAP_DOWN); + int r = DefaultDeploy("models/v_bgrap.mdl", "models/p_bgrap.mdl", BGRAPPLE_UP, "gauss" ); + m_flTimeWeaponIdle = gpGlobals->time + 1.1; + return r; } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::PrimaryAttack(void) +void CBarnacleGrapple::Holster( int skiplocal /* = 0 */ ) { - if (m_iFirestate != FIRESTATE_NONE) - return; + m_pPlayer->m_flNextAttack = gpGlobals->time + 0.5; - m_iFirestate = FIRESTATE_FIRE; + if( m_fireState != OFF ) + EndAttack(); - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(10, 15); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase(); + SendWeaponAnim( BGRAPPLE_DOWN ); } -//========================================================= -// Purpose: `` -//========================================================= -void CGrapple::ItemPostFrame(void) +void CBarnacleGrapple::WeaponIdle( void ) { - if (!(m_pPlayer->pev->button & IN_ATTACK)) - { - m_flLastFireTime = 0.0f; - } - - if (m_iFirestate != FIRESTATE_NONE) - { - if (m_fTipHit) - { - Pull(); - } + ResetEmptySound(); - // Check if fire is still eligible. - CheckFireEligibility(); + if( m_flTimeWeaponIdle > gpGlobals->time ) + return; - // Check if the current tip is attached to a monster or a wall. - // If the tongue tip move type is MOVETYPE_FOLLOW, then it - // implies that we are targetting a monster, so it will kill - // the monster when close enough. - CheckTargetProximity(); + if( m_fireState != OFF ) + { + EndAttack(); + return; + } - // Update the tip velocity and position. - UpdateTongueTip(); + m_bMissed = FALSE; - // Update the tongue beam. - UpdateBeam(); + const float flNextIdle = RANDOM_FLOAT( 0.0, 1.0 ); - // Update the pull sound. - UpdatePullSound(); - } + int iAnim; - if ((m_pPlayer->pev->button & IN_ATTACK) && CanAttack(m_flNextPrimaryAttack, gpGlobals->time, UseDecrement())) + if( flNextIdle <= 0.5 ) { - if ((m_iClip == 0 && pszAmmo1()) || (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()])) - { - m_fFireOnEmpty = TRUE; - } - -#ifndef CLIENT_DLL - m_pPlayer->TabulateAmmo(); -#endif - PrimaryAttack(); - m_pPlayer->pev->button &= ~IN_ATTACK; + iAnim = BGRAPPLE_LONGIDLE; + m_flTimeWeaponIdle = gpGlobals->time + 10.0; } - else if (!(m_pPlayer->pev->button & (IN_ATTACK | IN_ATTACK2))) + else if( flNextIdle > 0.95 ) { - if (m_iFirestate != FIRESTATE_NONE) - { - FireRelease(); - } - -#ifndef CLIENT_DLL - // no fire buttons down - - m_fFireOnEmpty = FALSE; - - if (!IsUseable() && m_flNextPrimaryAttack < (UseDecrement() ? 0.0 : gpGlobals->time)) - { - // weapon isn't useable, switch. - if (!(iFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && g_pGameRules->GetNextBestWeapon(m_pPlayer, this)) - { - m_flNextPrimaryAttack = (UseDecrement() ? 0.0 : gpGlobals->time) + 0.3; - return; - } - } -#endif + EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_STATIC, "weapons/bgrapple_cough.wav", VOL_NORM, ATTN_NORM, 0, PITCH_NORM ); - WeaponIdle(); - return; + iAnim = BGRAPPLE_COUGH; + m_flTimeWeaponIdle = gpGlobals->time + 4.6; } - - // catch all - if (ShouldWeaponIdle()) + else { - WeaponIdle(); + iAnim = BGRAPPLE_BREATHE; + m_flTimeWeaponIdle = gpGlobals->time + 2.566; } + + SendWeaponAnim( iAnim ); } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::WeaponIdle(void) +void CBarnacleGrapple::PrimaryAttack( void ) { - ResetEmptySound(); - - if (m_flTimeWeaponIdle > UTIL_WeaponTimeBase()) - return; - - if (m_iFirestate != FIRESTATE_NONE) + if( m_bMissed ) { - switch (m_iFirestate) - { - case FIRESTATE_FIRE: - Fire(); - break; - - case FIRESTATE_FIRE2: - Fire2(); - break; - - case FIRESTATE_WAIT: - FireWait(); - break; - - case FIRESTATE_REACH: - FireReach(); - break; - - case FIRESTATE_TRAVEL: - FireTravel(); - break; - - case FIRESTATE_RELEASE: - FireRelease(); - break; - - default: - break; - } + m_flTimeWeaponIdle = gpGlobals->time + 0.1; return; } - int iAnim; - float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1); - if (flRand <= 0.8f) - { - iAnim = BGRAP_BREATHE; - m_flTimeWeaponIdle = 2.6f; - } - else if (flRand <= 0.7f) - { - iAnim = BGRAP_LONGIDLE; - m_flTimeWeaponIdle = 10.0f; - } - else if (flRand <= 0.95) - { - iAnim = BGRAP_SHORTIDLE; - m_flTimeWeaponIdle = 1.3f; - } - else + UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle ); +#ifndef CLIENT_DLL + if( m_pTip ) { - iAnim = BGRAP_COUGH; - m_flTimeWeaponIdle = 4.6f; - - EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/bgrapple_cough.wav", 1, ATTN_NORM); - } + if( m_pTip->IsStuck() ) + { + CBaseEntity* pTarget = m_pTip->GetGrappleTarget(); - SendWeaponAnim(iAnim, UseDecrement()); -} + if( !pTarget ) + { + EndAttack(); + return; + } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Fire(void) -{ - EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/bgrapple_fire.wav", 1, ATTN_NORM); + if( m_pTip->GetGrappleType() > GRAPPLE_SMALL ) + { + m_pPlayer->pev->movetype = MOVETYPE_FLY; + m_pPlayer->pev->flags |= FL_IMMUNE_SLIME; + //Tells the physics code that the player is not on a ladder - Solokiller + } - SendWeaponAnim(BGRAP_FIRE, UseDecrement()); - m_iFirestate = FIRESTATE_FIRE2; + if( m_bMomentaryStuck ) + { + SendWeaponAnim( BGRAPPLE_FIRETRAVEL ); - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(15, 20); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.45f; -} + EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/bgrapple_impact.wav", 0.98, ATTN_NORM, 0, 125 ); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Fire2(void) -{ - // Create the tongue tip. - CreateTongueTip(); + if( pTarget->IsPlayer() ) + { + EMIT_SOUND_DYN( ENT(pTarget->pev), CHAN_WEAPON,"weapons/bgrapple_impact.wav", 0.98, ATTN_NORM, 0, 125 ); + } - // Start the pull sound. - StartPullSound(); + m_bMomentaryStuck = FALSE; + } - m_iFirestate = FIRESTATE_WAIT; + switch( m_pTip->GetGrappleType() ) + { + case GRAPPLE_NOT_A_TARGET: break; + + case GRAPPLE_SMALL: + //pTarget->BarnacleVictimGrabbed( this ); + m_pTip->pev->origin = pTarget->Center(); + + pTarget->pev->velocity = pTarget->pev->velocity + ( m_pPlayer->pev->origin - pTarget->pev->origin ); + + if( pTarget->pev->velocity.Length() > 450.0 ) + { + pTarget->pev->velocity = pTarget->pev->velocity.Normalize() * 450.0; + } + + break; + + case GRAPPLE_MEDIUM: + case GRAPPLE_LARGE: + case GRAPPLE_FIXED: + //pTarget->BarnacleVictimGrabbed( this ); + + if( m_pTip->GetGrappleType() != GRAPPLE_FIXED ) + UTIL_SetOrigin( m_pTip->pev, pTarget->Center() ); + + m_pPlayer->pev->velocity = + m_pPlayer->pev->velocity + ( m_pTip->pev->origin - m_pPlayer->pev->origin ); + + if( m_pPlayer->pev->velocity.Length() > 450.0 ) + { + m_pPlayer->pev->velocity = m_pPlayer->pev->velocity.Normalize() * 450.0; + + Vector vecPitch = UTIL_VecToAngles( m_pPlayer->pev->velocity ); + + if( (vecPitch.x > 55.0 && vecPitch.x < 205.0) || vecPitch.x < -55.0 ) + { + m_bGrappling = FALSE; + m_pPlayer->SetAnimation( PLAYER_IDLE ); + } + else + { + if (!m_bGrappling) + EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/bgrapple_pull.wav", 0.98, ATTN_NORM, 0, 125 ); + m_bGrappling = TRUE; + m_pPlayer->m_afPhysicsFlags |= PFLAG_LATCHING; + } + } + else + { + m_bGrappling = FALSE; + m_pPlayer->SetAnimation( PLAYER_IDLE ); + } + + break; + } + } - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(15, 20); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase(); -} + if( m_pTip->HasMissed() ) + { + EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/bgrapple_release.wav", 0.98, ATTN_NORM, 0, 125 ); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::FireWait(void) -{ - SendWeaponAnim(BGRAP_FIREWAITING, UseDecrement()); + EndAttack(); + return; + } + } +#endif + if( m_fireState != OFF ) + { + m_pPlayer->m_iWeaponVolume = 450; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(15, 20); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.5f; -} + if( m_flShootTime != 0.0 && gpGlobals->time > m_flShootTime ) + { + SendWeaponAnim( BGRAPPLE_FIREWAITING ); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::FireReach(void) -{ - SendWeaponAnim(BGRAP_FIREREACHED, UseDecrement()); - m_iFirestate = FIRESTATE_TRAVEL; + Vector vecPunchAngle = m_pPlayer->pev->punchangle; - // Start pulling the owner toward tongue tip. - StartPull(); + vecPunchAngle.x += 2.0; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(15, 20); - //m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.7; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase(); -} + m_pPlayer->pev->punchangle = vecPunchAngle; -//========================================================= -// Purpose: -//========================================================= -void CGrapple::FireTravel(void) -{ - SendWeaponAnim(BGRAP_FIRETRAVEL, UseDecrement()); + Fire( m_pPlayer->GetGunPosition(), gpGlobals->v_forward ); + EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/bgrapple_pull.wav", 0.98, ATTN_NORM, 0, 125 ); + m_flShootTime = 0; + } + } + else + { + m_bMomentaryStuck = TRUE; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + RANDOM_FLOAT(15, 20); - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6f; -} + SendWeaponAnim( BGRAPPLE_FIRE ); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::FireRelease(void) -{ - // Stop pull sound. - // STOP_SOUND(ENT(pev), CHAN_VOICE, "weapons/bgrapple_pull.wav"); + m_pPlayer->m_iWeaponVolume = 450; - // Play release sound. - EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/bgrapple_release.wav", 1, ATTN_NORM); + m_flTimeWeaponIdle = gpGlobals->time + 0.1; +#ifndef CLIENT_DLL + if( g_pGameRules->IsMultiplayer() ) + { + m_flShootTime = gpGlobals->time; + } + else + { + m_flShootTime = gpGlobals->time + 0.35; + } +#endif + EMIT_SOUND_DYN( ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/bgrapple_fire.wav", 0.98, ATTN_NORM, 0, 125 ); + m_fireState = CHARGE; + } - SendWeaponAnim(BGRAP_FIRERELEASE, UseDecrement()); - m_iFirestate = FIRESTATE_NONE; + if( !m_pTip ) + { + m_flNextPrimaryAttack = gpGlobals->time + 0.01; + return; + } - // Stop the pulling. - StopPull(); +#ifndef CLIENT_DLL + if( m_pTip->GetGrappleType() != GRAPPLE_FIXED && m_pTip->IsStuck() ) + { + UTIL_MakeVectors( m_pPlayer->pev->v_angle ); - // Reset pull sound. - ResetPullSound(); + Vector vecSrc = m_pPlayer->GetGunPosition(); - // Destroy the tongue tip. - DestroyTongueTip(); + Vector vecEnd = vecSrc + gpGlobals->v_forward * 16.0; - m_fTipHit = FALSE; - m_iHitFlags = 0; + TraceResult tr; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.75f; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.1; -} + UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr ); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::OnTongueTipHitSurface(const Vector& vecTarget) -{ -#ifndef CLIENT_DLL - ALERT(at_console, "Hit surface at: (%f,%f,%f).\n", vecTarget.x, vecTarget.y, vecTarget.z); -#endif - FireReach(); -} + if( tr.flFraction >= 1.0 ) + { + UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, m_pPlayer->edict(), &tr ); + if( tr.flFraction < 1.0 ) + { + CBaseEntity* pHit = Instance( tr.pHit ); +/* + if( !pHit ) + pHit = CWorld::GetInstance(); + + if( !pHit ) + { + FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer ); + } +*/ + } + } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::OnTongueTipHitEntity(CBaseEntity* pEntity) -{ + if( tr.flFraction < 1.0 ) + { + CBaseEntity* pHit = Instance( tr.pHit ); +/* + if( !pHit ) + pHit = CWorld::GetInstance(); +*/ + m_pPlayer->SetAnimation( PLAYER_ATTACK1 ); + + if( pHit ) + { + if( m_pTip ) + { + bool bValidTarget = FALSE; #ifndef CLIENT_DLL - ALERT(at_console, "Hit entity with classname %s.\n", (char*)STRING(pEntity->pev->classname)); + if( pHit->IsPlayer() ) + { + m_pTip->SetGrappleTarget( pHit ); + bValidTarget = TRUE; + } + else if( m_pTip->CheckTarget( pHit ) != GRAPPLE_NOT_A_TARGET ) + { + bValidTarget = TRUE; + } #endif - FireReach(); -} -//========================================================= -// Purpose: -//========================================================= -void CGrapple::StartPull(void) -{ + if( bValidTarget ) + { + if( m_flDamageTime + 0.5 < gpGlobals->time ) + { #ifndef CLIENT_DLL - Vector vecOrigin = m_pPlayer->pev->origin; + ClearMultiDamage(); - vecOrigin.z++; - UTIL_SetOrigin(m_pPlayer->pev, vecOrigin); + float flDamage = gSkillData.plrDmgGrapple; - m_pPlayer->pev->movetype = MOVETYPE_FLY; - m_pPlayer->pev->gravity = 0.0f; + if( g_pGameRules->IsMultiplayer() ) + { + flDamage *= 2; + } - m_pPlayer->pev->flags &= ~FL_ONGROUND; + pHit->TraceAttack( m_pPlayer->pev, flDamage, gpGlobals->v_forward, &tr, DMG_CLUB ); - m_pPlayer->m_afPhysicsFlags |= PFLAG_LATCHING; + ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev ); #endif -} - -//========================================================= -// Purpose: -//========================================================= -void CGrapple::StopPull(void) -{ -#ifndef CLIENT_DLL - m_pPlayer->pev->movetype = MOVETYPE_WALK; - m_pPlayer->pev->gravity = 1.0f; - m_pPlayer->m_afPhysicsFlags &= ~PFLAG_LATCHING; + m_flDamageTime = gpGlobals->time; + + const char* pszSample; + + switch( RANDOM_LONG( 0, 2 ) ) + { + default: + case 0: pszSample = "barnacle/bcl_chew1.wav"; break; + case 1: pszSample = "barnacle/bcl_chew2.wav"; break; + case 2: pszSample = "barnacle/bcl_chew3.wav"; break; + } + EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_VOICE, pszSample, VOL_NORM, ATTN_NORM, 0, 125 ); + } + } + } + } + } + } #endif -} - -//========================================================= -// Purpose: -//========================================================= -void CGrapple::Pull( void ) -{ -#ifndef CLIENT_DLL - - Vector vecOwnerPos, vecTipPos, vecDirToTip; - vecOwnerPos = m_pPlayer->pev->origin; - vecTipPos = m_pTongueTip->pev->origin; - vecDirToTip = (vecTipPos - vecOwnerPos).Normalize(); - m_pPlayer->pev->velocity = vecDirToTip * 300; - - m_pPlayer->m_afPhysicsFlags |= PFLAG_LATCHING; -#endif + //TODO: CTF support - Solokiller + /* + if( g_pGameRules->IsMultiplayer() && g_pGameRules->IsCTF() ) + { + m_flNextPrimaryAttack = gpGlobals->time; + } + else + */ + { + m_flNextPrimaryAttack = gpGlobals->time + 0.01; + } } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::CreateTongueTip( void ) +void CBarnacleGrapple::Fire( Vector vecOrigin, Vector vecDir ) { #ifndef CLIENT_DLL - Vector vecSrc, vecAiming, vecVel; - UTIL_MakeVectors( m_pPlayer->pev->v_angle ); + Vector vecSrc = vecOrigin; - vecSrc = m_pPlayer->GetGunPosition(); - vecSrc = vecSrc + gpGlobals->v_forward * 8; - vecSrc = vecSrc + gpGlobals->v_right * 8; - vecSrc = vecSrc + gpGlobals->v_up; + Vector vecEnd = vecSrc + vecDir * 2048.0; - vecVel = gpGlobals->v_forward * 300; - - //GetAttachment(0, vecSrc, vecAiming); - - m_pTongueTip = CGrappleTonguetip::CreateTip(pev, vecSrc, vecVel); - - CreateBeam(m_pTongueTip); -#endif - -} + TraceResult tr; -//========================================================= -// Purpose: -//========================================================= -void CGrapple::DestroyTongueTip(void) -{ -#ifndef CLIENT_DLL - DestroyBeam(); + UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, m_pPlayer->edict(), &tr ); - if (m_pTongueTip) + if( !tr.fAllSolid ) { - UTIL_Remove(m_pTongueTip); - m_pTongueTip = NULL; + CBaseEntity* pHit = Instance( tr.pHit ); +/* + if( !pHit ) + pHit = CWorld::GetInstance(); +*/ + if( pHit ) + { + UpdateEffect(); + + m_flDamageTime = gpGlobals->time; + } } #endif } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::UpdateTongueTip(void) +void CBarnacleGrapple::EndAttack( void ) { -#ifndef CLIENT_DLL - if (m_pTongueTip) - { - Vector tipVel = m_pTongueTip->pev->velocity; - Vector ownerVel = VARS(pev->owner)->velocity; + m_fireState = OFF; + SendWeaponAnim( BGRAPPLE_FIRERELEASE ); - Vector newVel; + EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/bgrapple_release.wav", 1, ATTN_NORM); - newVel.x = tipVel.x + (ownerVel.x * 0.02f); - newVel.y = tipVel.y + (ownerVel.y * 0.05f); - newVel.z = tipVel.z + (ownerVel.z * 0.01f); + EMIT_SOUND_DYN( ENT( m_pPlayer->pev ), CHAN_WEAPON, "weapons/bgrapple_pull.wav", 0.0, ATTN_NONE, SND_STOP, 100 ); - m_pTongueTip->pev->velocity = newVel; - } -#endif -} + m_flTimeWeaponIdle = gpGlobals->time + 0.9; -//========================================================= -// Purpose: -//========================================================= -void CGrapple::CreateBeam( CBaseEntity* pTongueTip ) -{ -#ifndef CLIENT_DLL - m_pBeam = CBeam::BeamCreate("sprites/smoke_blk.spr", 16); + m_flNextPrimaryAttack = gpGlobals->time + 0.01; - if (m_pBeam) - { - m_pBeam->PointsInit(pTongueTip->pev->origin, pev->origin); - m_pBeam->SetColor(255, 255, 255); - m_pBeam->SetBrightness(255); - m_pBeam->SetNoise(0); - m_pBeam->SetFrame(0); - m_pBeam->pev->rendermode = kRenderNormal; - m_pBeam->pev->renderamt = 255; - } -#endif -} + DestroyEffect(); -//========================================================= -// Purpose: -//========================================================= -void CGrapple::DestroyBeam(void) -{ -#ifndef CLIENT_DLL - if (m_pBeam) + if( m_bGrappling && m_pPlayer->IsAlive() ) { - UTIL_Remove(m_pBeam); - m_pBeam = NULL; + m_pPlayer->SetAnimation( PLAYER_IDLE ); } -#endif + + m_pPlayer->pev->movetype = MOVETYPE_WALK; + m_pPlayer->pev->flags &= ~(FL_IMMUNE_SLIME); + m_pPlayer->m_afPhysicsFlags &= ~PFLAG_LATCHING; } -//========================================================= -// Purpose: -//========================================================= -void CGrapple::UpdateBeam(void) +void CBarnacleGrapple::CreateEffect( void ) { #ifndef CLIENT_DLL - if (m_pBeam) - { - Vector vecSrc; - UTIL_MakeVectors(m_pPlayer->pev->v_angle); - - vecSrc = m_pPlayer->GetGunPosition(); - vecSrc = vecSrc + gpGlobals->v_forward * 16; - vecSrc = vecSrc + gpGlobals->v_right * 6; - vecSrc = vecSrc + gpGlobals->v_up * -8; - m_pBeam->SetStartPos(vecSrc); - m_pBeam->SetEndPos(m_pTongueTip->pev->origin); - m_pBeam->RelinkBeam(); - } -#endif -} + DestroyEffect(); -//========================================================= -// Purpose: -//========================================================= -BOOL CGrapple::CanAttack(float attack_time, float curtime, BOOL isPredicted) -{ -#if defined( CLIENT_WEAPONS ) - if (!isPredicted) -#else - if (1) -#endif - { - return (attack_time <= curtime) ? TRUE : FALSE; - } - else - { - return (attack_time <= 0.0) ? TRUE : FALSE; - } -} + m_pTip = GetClassPtr((CBarnacleGrappleTip *)NULL); + m_pTip->Spawn(); + UTIL_MakeVectors( m_pPlayer->pev->v_angle ); -void CGrapple::StartPullSound(void) -{ - m_flNextPullSoundTime = UTIL_WeaponTimeBase(); - m_fPlayPullSound = TRUE; -} + Vector vecOrigin = + m_pPlayer->GetGunPosition() + + gpGlobals->v_forward * 16.0 + + gpGlobals->v_right * 8.0 + + gpGlobals->v_up * -8.0; -void CGrapple::UpdatePullSound(void) -{ - if (!m_fPlayPullSound) - return; + Vector vecAngles = m_pPlayer->pev->v_angle; + + vecAngles.x = -vecAngles.x; + + m_pTip->SetPosition( vecOrigin, vecAngles, m_pPlayer ); - if (m_flNextPullSoundTime <= UTIL_WeaponTimeBase()) + if( !m_pBeam ) { - EMIT_SOUND(ENT(pev), CHAN_BODY, "weapons/bgrapple_pull.wav", 1, ATTN_NORM); - m_flNextPullSoundTime = UTIL_WeaponTimeBase() + 0.6f; - } -} + m_pBeam = CBeam::BeamCreate( "sprites/tongue.spr", 16 ); -void CGrapple::ResetPullSound(void) -{ - STOP_SOUND(ENT(pev), CHAN_BODY, "weapons/bgrapple_pull.wav"); - m_flNextPullSoundTime = 0.0f; - m_fPlayPullSound = FALSE; -} + m_pBeam->EntsInit( m_pTip->entindex(), m_pPlayer->entindex() ); -BOOL CGrapple::IsTongueColliding(const Vector& vecShootOrigin, const Vector& vecTipPos) -{ -#ifndef CLIENT_DLL - TraceResult tr; - UTIL_TraceLine(vecShootOrigin, vecTipPos, dont_ignore_monsters, ENT(m_pPlayer->pev), &tr); + m_pBeam->SetFlags( BEAM_FSOLID ); - if (tr.flFraction != 1.0) - { - if (m_pTongueTip->pev->movetype == MOVETYPE_FOLLOW) - { - if (tr.pHit && m_pTongueTip->pev->aiment && m_pTongueTip->pev->aiment == tr.pHit) - return FALSE; - } + m_pBeam->SetBrightness( 100.0 ); - return TRUE; - } + m_pBeam->SetEndAttachment( 1 ); - return FALSE; -#else - return TRUE; + m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY; + } #endif } -void CGrapple::CheckFireEligibility(void) +void CBarnacleGrapple::UpdateEffect( void ) { #ifndef CLIENT_DLL - // Do not check for this if the tongue is not valid. - if (!m_pTongueTip) - return; - - // Check if the tongue is through walls or if other things - // such as entities are between the owner and the tip. - if (IsTongueColliding(m_pPlayer->GetGunPosition(), m_pTongueTip->pev->origin)) - { - // Stop firing! - FireRelease(); - } + if( !m_pBeam || !m_pTip ) + CreateEffect(); #endif } -BOOL CGrapple::CheckTargetProximity(void) +void CBarnacleGrapple::DestroyEffect( void ) { + if( m_pBeam ) + { + UTIL_Remove( m_pBeam ); + m_pBeam = NULL; + } #ifndef CLIENT_DLL - // Do not check for this if the tongue is not valid. - if (!m_pTongueTip) - return FALSE; - - if (m_pTongueTip->pev->movetype == MOVETYPE_FOLLOW) + if( m_pTip ) { - // Trace a hull around to see if we hit something within 20 units. - TraceResult tr; - UTIL_TraceHull( - pev->origin, - pev->origin + VARS(pev->owner)->velocity.Normalize() * 20, - dont_ignore_monsters, - head_hull, - edict(), - &tr); - - - // Check to see if we are close enough to our target. - // In the case o a monster, attempt to get a pointer to - // the entity, gib it, release grappler fire. - edict_t* pHit = ENT(tr.pHit); - if ( pHit && - (VARS(pHit)->flags & FL_MONSTER) && - (m_pTongueTip->pev->aiment == tr.pHit)) - { - // Get a pointer to the entity. - CBaseEntity* pEnt = GetClassPtr((CBaseEntity*)VARS(tr.pHit)); - if (pEnt) - { - // Since FL_MONSTER is set, it can only be a monster entity. - ASSERT(pEnt->MyMonsterPointer() != NULL); - - // Gib monster. - ((CBaseMonster*)pEnt)->GibMonster(); - } - else - { - ALERT(at_console, "ERROR: %s attempted to reference an unlisted monster.\n", STRING(m_pTongueTip->pev->classname)); - } - - // Release fire. - FireRelease(); - } + m_pTip->Killed( NULL, GIB_NEVER ); + m_pTip = NULL; } #endif - return FALSE; } diff --git a/dlls/gearbox/grapple_tonguetip.cpp b/dlls/gearbox/grapple_tonguetip.cpp index 1c7124cf..2961d18f 100644 --- a/dlls/gearbox/grapple_tonguetip.cpp +++ b/dlls/gearbox/grapple_tonguetip.cpp @@ -23,133 +23,193 @@ #include "gamerules.h" #include "grapple_tonguetip.h" -LINK_ENTITY_TO_CLASS(grapple_tonguetip, CGrappleTonguetip); +LINK_ENTITY_TO_CLASS( grapple_tip, CBarnacleGrappleTip ) -TYPEDESCRIPTION CGrappleTonguetip::m_SaveData[] = +void CBarnacleGrappleTip::Precache() { - DEFINE_FIELD(CGrappleTonguetip, m_pMyGrappler, FIELD_CLASSPTR), -}; - -IMPLEMENT_SAVERESTORE(CGrappleTonguetip, CBaseEntity); + PRECACHE_MODEL( "models/shock_effect.mdl" ); +} -//========================================================= -// Purpose: Spawn -//========================================================= -void CGrappleTonguetip::Spawn(void) +void CBarnacleGrappleTip::Spawn() { - pev->movetype = MOVETYPE_TOSS; - pev->classname = MAKE_STRING("grapple_tonguetip"); + Precache(); + pev->movetype = MOVETYPE_FLY; pev->solid = SOLID_BBOX; - pev->rendermode = kRenderTransTexture; - pev->renderamt = 0; - pev->gravity = 0.01; - SET_MODEL(ENT(pev), "models/v_bgrap_tonguetip.mdl"); + SET_MODEL( ENT(pev), "models/shock_effect.mdl" ); - UTIL_SetSize(pev, Vector(0, 0, 0), Vector(0, 0, 0)); + UTIL_SetSize( pev, Vector(0, 0, 0), Vector(0, 0, 0) ); - SetTouch(&CGrappleTonguetip::TipTouch); -} + UTIL_SetOrigin( pev, pev->origin ); -//========================================================= -// Purpose: CreateTip -//========================================================= -CGrappleTonguetip* CGrappleTonguetip::CreateTip(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) -{ - CGrappleTonguetip* pTonguetip = GetClassPtr((CGrappleTonguetip *)NULL); - pTonguetip->Spawn(); + SetThink( &CBarnacleGrappleTip::FlyThink ); + SetTouch( &CBarnacleGrappleTip::TongueTouch ); - UTIL_SetOrigin(pTonguetip->pev, vecStart); - pTonguetip->pev->velocity = vecVelocity; - pTonguetip->pev->owner = ENT(pevOwner); - pTonguetip->m_pMyGrappler = GetClassPtr((CGrapple*)pevOwner); - pTonguetip->SetThink(&CGrappleTonguetip::FlyThink); - pTonguetip->pev->nextthink = gpGlobals->time + 0.1; + Vector vecAngles = pev->angles; - return pTonguetip; -} + vecAngles.x -= 30.0; -//========================================================= -// Purpose: FlyThink -//========================================================= -void CGrappleTonguetip::FlyThink(void) -{ - ALERT(at_console, "FlyThink\n"); + pev->angles = vecAngles; - pev->nextthink = gpGlobals->time + 0.1f; -} + UTIL_MakeVectors( pev->angles ); -//========================================================= -// Purpose: HitThink -//========================================================= -void CGrappleTonguetip::HitThink(void) -{ - ALERT(at_console, "HitThink\n"); + vecAngles.x = -( 30.0 + vecAngles.x ); - pev->nextthink = gpGlobals->time + 0.1f; -} + pev->velocity = g_vecZero; -//========================================================= -// Purpose: TipTouch -//========================================================= -void CGrappleTonguetip::TipTouch(CBaseEntity *pOther) -{ - // Do not collide with the owner. - if (ENT(pOther->pev) == pev->owner || (ENT(pOther->pev) == VARS(pev->owner)->owner)) - return; + pev->gravity = 1.0; - ALERT(at_console, "TipTouch\n"); + pev->nextthink = gpGlobals->time + 0.02; - TraceResult tr; - UTIL_TraceLine(pev->origin, pev->origin + pev->velocity * 10, dont_ignore_monsters, ENT(pev), &tr); + m_bIsStuck = FALSE; + m_bMissed = FALSE; +} - pev->velocity = Vector(0, 0, 0); +void CBarnacleGrappleTip::FlyThink() +{ + UTIL_MakeAimVectors( pev->angles ); + + pev->angles = UTIL_VecToAngles( gpGlobals->v_forward ); - int content = UTIL_PointContents(tr.vecEndPos); - int hitFlags = pOther->pev->flags; + const float flNewVel = ( ( pev->velocity.Length() * 0.8 ) + 400.0 ); - m_pMyGrappler->m_fTipHit = TRUE; - m_pMyGrappler->m_iHitFlags = hitFlags; + pev->velocity = pev->velocity * 0.2 + ( flNewVel * gpGlobals->v_forward ); - if (hitFlags & (FL_CLIENT | FL_MONSTER)) + if( !g_pGameRules->IsMultiplayer() ) { - // Set player attached flag. - if (pOther->IsPlayer()) - ((CBasePlayer*)pOther)->m_afPhysicsFlags |= PFLAG_ATTACHED; + //Note: the old grapple had a maximum velocity of 1600. - Solokiller + if( pev->velocity.Length() > 750.0 ) + { + pev->velocity = pev->velocity.Normalize() * 750.0; + } + } + else + { + //TODO: should probably clamp at sv_maxvelocity to prevent the tip from going off course. - Solokiller + if( pev->velocity.Length() > 2000.0 ) + { + pev->velocity = pev->velocity.Normalize() * 2000.0; + } + } - pev->movetype = MOVETYPE_FOLLOW; - pev->aiment = ENT(pOther->pev); + pev->nextthink = gpGlobals->time + 0.02; +} - m_pMyGrappler->OnTongueTipHitEntity(pOther); +void CBarnacleGrappleTip::OffsetThink() +{ + //Nothing +} + +void CBarnacleGrappleTip::TongueTouch( CBaseEntity* pOther ) +{ + if( !pOther ) + { + targetClass = GRAPPLE_NOT_A_TARGET; + m_bMissed = TRUE; } else { - pev->velocity = Vector(0, 0, 0); - pev->movetype = MOVETYPE_NONE; - pev->gravity = 0.0f; + if( pOther->IsPlayer() ) + { + targetClass = GRAPPLE_MEDIUM; + + m_hGrappleTarget = pOther; - m_pMyGrappler->OnTongueTipHitSurface(tr.vecEndPos); + m_bIsStuck = TRUE; + } + else + { + targetClass = CheckTarget( pOther ); + + if( targetClass != GRAPPLE_NOT_A_TARGET ) + { + m_bIsStuck = TRUE; + } + else + { + m_bMissed = TRUE; + } + } } - EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/bgrapple_impact.wav", 1, ATTN_NORM, 0, 100); + pev->velocity = g_vecZero; + + m_GrappleType = targetClass; + + SetThink( &CBarnacleGrappleTip::OffsetThink ); + pev->nextthink = gpGlobals->time + 0.02; SetTouch( NULL ); - SetThink(&CGrappleTonguetip::HitThink); - pev->nextthink = gpGlobals->time + 0.1f; } -void CGrappleTonguetip::PreRemoval(void) +int CBarnacleGrappleTip::CheckTarget( CBaseEntity* pTarget ) { - if (pev->aiment != NULL) + if( !pTarget ) + return GRAPPLE_NOT_A_TARGET; + + if( pTarget->IsPlayer() ) { - CBaseEntity* pEnt = GetClassPtr((CBaseEntity*)VARS(pev->aiment)); - if (pEnt && pEnt->IsPlayer()) - { - // Remove attached flag of the target entity. - ((CBasePlayer*)pEnt)->m_afPhysicsFlags &= ~PFLAG_ATTACHED; + m_hGrappleTarget = pTarget; + + return pTarget->SizeForGrapple(); + } + + Vector vecStart = pev->origin; + Vector vecEnd = pev->origin + pev->velocity * 1024.0; + + TraceResult tr; + + UTIL_TraceLine( vecStart, vecEnd, ignore_monsters, edict(), &tr ); + + CBaseEntity* pHit = Instance( tr.pHit ); + +/* if( !pHit ) + pHit = CWorld::GetInstance();*/ + + float rgfl1[3]; + float rgfl2[3]; + const char *pTexture; + + vecStart.CopyToArray(rgfl1); + vecEnd.CopyToArray(rgfl2); + + if (pHit) + pTexture = TRACE_TEXTURE(ENT(pHit->pev), rgfl1, rgfl2); + else + pTexture = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2); + + bool bIsFixed = false; + + if( pTexture && strnicmp( pTexture, "xeno_grapple", 12 ) == 0 ) + { + bIsFixed = true; + } + else if (pTarget->SizeForGrapple() != GRAPPLE_NOT_A_TARGET) + { + if (pTarget->SizeForGrapple() == GRAPPLE_FIXED) { + bIsFixed = true; + } else { + m_hGrappleTarget = pTarget; + m_vecOriginOffset = pev->origin - pTarget->pev->origin; + return pTarget->SizeForGrapple(); } } - CBaseEntity::PreRemoval(); -} \ No newline at end of file + if( bIsFixed ) + { + m_hGrappleTarget = pTarget; + m_vecOriginOffset = g_vecZero; + + return GRAPPLE_FIXED; + } + + return GRAPPLE_NOT_A_TARGET; +} + +void CBarnacleGrappleTip::SetPosition( Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner ) +{ + UTIL_SetOrigin( pev, vecOrigin ); + pev->angles = vecAngles; + pev->owner = pOwner->edict(); +} diff --git a/dlls/gearbox/grapple_tonguetip.h b/dlls/gearbox/grapple_tonguetip.h index 188a54df..0eb800dd 100644 --- a/dlls/gearbox/grapple_tonguetip.h +++ b/dlls/gearbox/grapple_tonguetip.h @@ -16,32 +16,47 @@ #ifndef GRAPPLE_TONGUETIP_H #define GRAPPLE_TONGUETIP_H -class CGrapple; - -// -// -// -class CGrappleTonguetip : public CBaseEntity +class CBarnacleGrappleTip : public CBaseEntity { public: -#ifndef CLIENT_DLL - virtual int Save(CSave &save); - virtual int Restore(CRestore &restore); +/* virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; -#endif +*/ + int targetClass; + void Precache(); + void Spawn(); + + void FlyThink(); + void OffsetThink(); + + void TongueTouch( CBaseEntity* pOther ); + + int CheckTarget( CBaseEntity* pTarget ); - void Spawn(void); - void FlyThink(void); - void HitThink(void); - void TipTouch(CBaseEntity* pOther); - void PreRemoval(void); + void SetPosition( Vector vecOrigin, Vector vecAngles, CBaseEntity* pOwner ); - CGrapple* m_pMyGrappler; + int GetGrappleType() const { return m_GrappleType; } + bool IsStuck() const { return m_bIsStuck; } + + bool HasMissed() const { return m_bMissed; } +#ifndef CLIENT_DLL + EHANDLE& GetGrappleTarget() { return m_hGrappleTarget; } + void SetGrappleTarget( CBaseEntity* pTarget ) + { + m_hGrappleTarget = pTarget; + } +#endif private: - static CGrappleTonguetip* CreateTip(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity); - friend class CGrapple; + int m_GrappleType; + bool m_bIsStuck; + bool m_bMissed; +#ifndef CLIENT_DLL + EHANDLE m_hGrappleTarget; +#endif + Vector m_vecOriginOffset; }; -#endif // GRAPPLE_TONGUETIP_H \ No newline at end of file +#endif // GRAPPLE_TONGUETIP_H diff --git a/dlls/gearbox/pitdrone.cpp b/dlls/gearbox/pitdrone.cpp index c95ac2a4..f9854d73 100644 --- a/dlls/gearbox/pitdrone.cpp +++ b/dlls/gearbox/pitdrone.cpp @@ -237,6 +237,8 @@ public: void GibMonster(); CUSTOM_SCHEDULES + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + float m_flLastHurtTime; float m_flNextSpitTime;// last time the PitDrone used the spit attack. float m_flNextFlinch; diff --git a/dlls/gearbox/voltigore.cpp b/dlls/gearbox/voltigore.cpp index dfaca4ca..bd3c74de 100644 --- a/dlls/gearbox/voltigore.cpp +++ b/dlls/gearbox/voltigore.cpp @@ -336,6 +336,8 @@ public: CUSTOM_SCHEDULES static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_LARGE; } + float m_flNextZapTime; // last time the voltigore used the spit attack. BOOL m_fShouldUpdateBeam; CBeam* m_pBeam[3]; @@ -1209,6 +1211,8 @@ public: void GibMonster(); Schedule_t* GetSchedule(); Schedule_t* GetScheduleOfType(int Type); + + virtual int SizeForGrapple() { return GRAPPLE_SMALL; } }; LINK_ENTITY_TO_CLASS(monster_alien_babyvoltigore, CBabyVoltigore) diff --git a/dlls/headcrab.h b/dlls/headcrab.h index 027658d7..5d4c3733 100644 --- a/dlls/headcrab.h +++ b/dlls/headcrab.h @@ -46,7 +46,9 @@ public: virtual float GetSoundVolue(void) { return 1.0; } Schedule_t* GetScheduleOfType(int Type); - CUSTOM_SCHEDULES; + CUSTOM_SCHEDULES + + virtual int SizeForGrapple() { return GRAPPLE_SMALL; } static const char *pIdleSounds[]; static const char *pAlertSounds[]; @@ -56,4 +58,4 @@ public: static const char *pBiteSounds[]; }; -#endif \ No newline at end of file +#endif diff --git a/dlls/hgrunt.h b/dlls/hgrunt.h index 4e33c36f..818f5591 100644 --- a/dlls/hgrunt.h +++ b/dlls/hgrunt.h @@ -60,9 +60,11 @@ public: virtual BOOL FOkToSpeak(void); void JustSpoke(void); - CUSTOM_SCHEDULES; + CUSTOM_SCHEDULES static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + // checking the feasibility of a grenade toss is kind of costly, so we do it every couple of seconds, // not every server frame. float m_flNextGrenadeCheck; diff --git a/dlls/houndeye.cpp b/dlls/houndeye.cpp index 940b68ea..b6b71c73 100644 --- a/dlls/houndeye.cpp +++ b/dlls/houndeye.cpp @@ -105,6 +105,8 @@ public: CUSTOM_SCHEDULES static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + int m_iSpriteTexture; BOOL m_fAsleep;// some houndeyes sleep in idle mode if this is set, the houndeye is lying down BOOL m_fDontBlink;// don't try to open/close eye if this bit is set! diff --git a/dlls/ichthyosaur.cpp b/dlls/ichthyosaur.cpp index 53f57a27..1c7329f3 100644 --- a/dlls/ichthyosaur.cpp +++ b/dlls/ichthyosaur.cpp @@ -90,6 +90,8 @@ public: float FlPitchDiff( void ); float ChangePitch( int speed ); + virtual int SizeForGrapple() { return GRAPPLE_LARGE; } + Vector m_SaveVelocity; float m_idealDist; diff --git a/dlls/islave.cpp b/dlls/islave.cpp index b516c09b..db7db97b 100644 --- a/dlls/islave.cpp +++ b/dlls/islave.cpp @@ -63,6 +63,8 @@ public: void Killed( entvars_t *pevAttacker, int iGib ); + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + void StartTask( Task_t *pTask ); Schedule_t *GetSchedule( void ); Schedule_t *GetScheduleOfType( int Type ); diff --git a/dlls/leech.cpp b/dlls/leech.cpp index 1d64eae1..d2fc193f 100644 --- a/dlls/leech.cpp +++ b/dlls/leech.cpp @@ -112,6 +112,8 @@ public: static const char *pAttackSounds[]; static const char *pAlertSounds[]; + virtual int SizeForGrapple() { return GRAPPLE_SMALL; } + private: // UNDONE: Remove unused boid vars, do group behavior float m_flTurning;// is this boid turning? diff --git a/dlls/squeakgrenade.cpp b/dlls/squeakgrenade.cpp index a7295599..ac38d5eb 100644 --- a/dlls/squeakgrenade.cpp +++ b/dlls/squeakgrenade.cpp @@ -59,6 +59,8 @@ class CSqueakGrenade : public CGrenade static TYPEDESCRIPTION m_SaveData[]; + virtual int SizeForGrapple() { return GRAPPLE_SMALL; } + static float m_flNextBounceSoundTime; // CBaseEntity *m_pTarget; diff --git a/dlls/talkmonster.h b/dlls/talkmonster.h index 36ac21a6..de438c4b 100644 --- a/dlls/talkmonster.h +++ b/dlls/talkmonster.h @@ -154,7 +154,8 @@ public: virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; - + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } + static const char *m_szFriends[TLK_CFRIENDS]; // array of friend names static float g_talkWaitTime; diff --git a/dlls/tentacle.cpp b/dlls/tentacle.cpp index ff44014d..d3b9b5e9 100644 --- a/dlls/tentacle.cpp +++ b/dlls/tentacle.cpp @@ -74,6 +74,8 @@ public: int Classify( void ); + virtual int SizeForGrapple() { return GRAPPLE_FIXED; } + int Level( float dz ); int MyLevel( void ); float MyHeight( void ); diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index b7bb1cf4..be470d33 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -371,7 +371,7 @@ void W_Precache( void ) UTIL_PrecacheOtherWeapon( "weapon_displacer" ); UTIL_PrecacheOtherWeapon( "weapon_eagle" ); UTIL_PrecacheOtherWeapon( "weapon_grapple" ); - UTIL_PrecacheOther( "grapple_tonguetip" ); + UTIL_PrecacheOther( "grapple_tip" ); UTIL_PrecacheOtherWeapon( "weapon_knife" ); UTIL_PrecacheOtherWeapon( "weapon_m249" ); UTIL_PrecacheOther( "ammo_556" ); @@ -1687,17 +1687,13 @@ TYPEDESCRIPTION CEagle::m_SaveData[] = IMPLEMENT_SAVERESTORE( CEagle, CBasePlayerWeapon ) -TYPEDESCRIPTION CGrapple::m_SaveData[] = +TYPEDESCRIPTION CBarnacleGrapple::m_SaveData[] = { - DEFINE_FIELD( CGrapple, m_iFirestate, FIELD_INTEGER ), - DEFINE_FIELD( CGrapple, m_iHitFlags, FIELD_INTEGER ), - DEFINE_FIELD( CGrapple, m_fTipHit, FIELD_BOOLEAN ), - DEFINE_FIELD( CGrapple, m_pTongueTip, FIELD_CLASSPTR ), - DEFINE_FIELD( CGrapple, m_pBeam, FIELD_CLASSPTR ), - DEFINE_FIELD( CGrapple, m_flNextPullSoundTime, FIELD_TIME ), - DEFINE_FIELD( CGrapple, m_fPlayPullSound, FIELD_BOOLEAN ), + DEFINE_FIELD( CBarnacleGrapple, m_pBeam, FIELD_CLASSPTR ), + DEFINE_FIELD( CBarnacleGrapple, m_flShootTime, FIELD_TIME ), + DEFINE_FIELD( CBarnacleGrapple, m_fireState, FIELD_INTEGER ), }; -IMPLEMENT_SAVERESTORE( CGrapple, CBasePlayerWeapon ) +IMPLEMENT_SAVERESTORE( CBarnacleGrapple, CBasePlayerWeapon ) TYPEDESCRIPTION CM249::m_SaveData[] = { diff --git a/dlls/weapons.h b/dlls/weapons.h index 84c6c907..b44278e7 100644 --- a/dlls/weapons.h +++ b/dlls/weapons.h @@ -1145,92 +1145,57 @@ private: unsigned short m_usEagle; }; -class CGrappleTonguetip; +class CBarnacleGrappleTip; -class CGrapple : public CBasePlayerWeapon +class CBarnacleGrapple : public CBasePlayerWeapon { public: - #ifndef CLIENT_DLL - int Save(CSave &save); - int Restore(CRestore &restore); + virtual int Save( CSave &save ); + virtual int Restore( CRestore &restore ); static TYPEDESCRIPTION m_SaveData[]; #endif + enum FireState + { + OFF = 0, + CHARGE = 1 + }; - void Spawn(void); - void Precache(void); + void Precache( void ); + void Spawn( void ); int iItemSlot(void) { return 1; } - int GetItemInfo(ItemInfo *p); + void EndAttack( void ); - void PrimaryAttack(void); - BOOL Deploy(void); - void Holster(int skiplocal = 0); - void WeaponIdle(void); - void ItemPostFrame(void); + int GetItemInfo(ItemInfo *p); + int AddToPlayer( CBasePlayer* pPlayer ); + BOOL Deploy(); + void Holster( int skiplocal /* = 0 */ ); + void WeaponIdle( void ); + void PrimaryAttack( void ); - virtual BOOL ShouldWeaponIdle(void) { return TRUE; } + void Fire( Vector vecOrigin, Vector vecDir ); + void CreateEffect( void ); + void UpdateEffect( void ); + void DestroyEffect( void ); virtual BOOL UseDecrement(void) { -#if defined( CLIENT_WEAPONS ) - return TRUE; -#else return FALSE; -#endif } - void Fire(void); - void FireWait(void); - void FireReach(void); - void FireTravel(void); - void FireRelease(void); - - void Fire2(void); + const char* MyWModel() { return "models/w_bgrap.mdl"; } - void OnTongueTipHitSurface( const Vector& vecTarget ); - void OnTongueTipHitEntity( CBaseEntity* pEntity ); - - void StartPull( void ); - void StopPull( void ); - void Pull( void ); - - BOOL IsTongueColliding( const Vector& vecShootOrigin, const Vector& vecTipPos ); - void CheckFireEligibility( void ); - BOOL CheckTargetProximity( void ); - - void CreateTongueTip( void ); - void DestroyTongueTip( void ); - void UpdateTongueTip( void ); - - void CreateBeam( CBaseEntity* pTongueTip ); - void DestroyBeam( void ); - void UpdateBeam( void ); - - void StartPullSound( void ); - void UpdatePullSound( void ); - void ResetPullSound( void ); +private: + CBarnacleGrappleTip* m_pTip; - BOOL CanAttack(float attack_time, float curtime, BOOL isPredicted); + CBeam* m_pBeam; - enum GRAPPLE_FIRESTATE - { - FIRESTATE_NONE = 0, - FIRESTATE_FIRE, - FIRESTATE_FIRE2, - FIRESTATE_WAIT, - FIRESTATE_REACH, - FIRESTATE_TRAVEL, - FIRESTATE_RELEASE, - }; + float m_flShootTime; + float m_flDamageTime; - int m_iFirestate; - int m_iHitFlags; - BOOL m_fTipHit; - CGrappleTonguetip* m_pTongueTip; - CBeam* m_pBeam; - float m_flNextPullSoundTime; - BOOL m_fPlayPullSound; -private: + bool m_bGrappling; + bool m_bMissed; + bool m_bMomentaryStuck; }; diff --git a/dlls/zombie.h b/dlls/zombie.h index 7c47d396..b4b258ec 100644 --- a/dlls/zombie.h +++ b/dlls/zombie.h @@ -44,4 +44,6 @@ public: virtual BOOL CheckRangeAttack1( float flDot, float flDist ) { return FALSE; } virtual BOOL CheckRangeAttack2( float flDot, float flDist ) { return FALSE; } virtual int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ); + + virtual int SizeForGrapple() { return GRAPPLE_MEDIUM; } };