diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/hl1/hl1mp_player.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/hl1/hl1mp_player.cpp')
| -rw-r--r-- | game/server/hl1/hl1mp_player.cpp | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/game/server/hl1/hl1mp_player.cpp b/game/server/hl1/hl1mp_player.cpp new file mode 100644 index 0000000..84adbfe --- /dev/null +++ b/game/server/hl1/hl1mp_player.cpp @@ -0,0 +1,636 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Multiplayer Player for HL1. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "hl1mp_player.h" +#include "client.h" +#include "team.h" + +class CTEPlayerAnimEvent : public CBaseTempEntity +{ +public: + DECLARE_CLASS( CTEPlayerAnimEvent, CBaseTempEntity ); + DECLARE_SERVERCLASS(); + + CTEPlayerAnimEvent( const char *name ) : CBaseTempEntity( name ) + { + } + + CNetworkHandle( CBasePlayer, m_hPlayer ); + CNetworkVar( int, m_iEvent ); + CNetworkVar( int, m_nData ); +}; + +IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEPlayerAnimEvent, DT_TEPlayerAnimEvent ) + SendPropEHandle( SENDINFO( m_hPlayer ) ), + SendPropInt( SENDINFO( m_iEvent ), Q_log2( PLAYERANIMEVENT_COUNT ) + 1, SPROP_UNSIGNED ), + SendPropInt( SENDINFO( m_nData ), 32 ) +END_SEND_TABLE() + +static CTEPlayerAnimEvent g_TEPlayerAnimEvent( "PlayerAnimEvent" ); + +void TE_PlayerAnimEvent( CBasePlayer *pPlayer, PlayerAnimEvent_t event, int nData ) +{ + CPVSFilter filter( pPlayer->EyePosition() ); + + // The player himself doesn't need to be sent his animation events + // unless cs_showanimstate wants to show them. +// if ( !ToolsEnabled() && ( cl_showanimstate.GetInt() == pPlayer->entindex() ) ) + { +// filter.RemoveRecipient( pPlayer ); + } + + g_TEPlayerAnimEvent.m_hPlayer = pPlayer; + g_TEPlayerAnimEvent.m_iEvent = event; + g_TEPlayerAnimEvent.m_nData = nData; + g_TEPlayerAnimEvent.Create( filter, 0 ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + +extern int gEvilImpulse101; + +LINK_ENTITY_TO_CLASS( player_mp, CHL1MP_Player ); +PRECACHE_REGISTER( player_mp ); + +IMPLEMENT_SERVERCLASS_ST( CHL1MP_Player, DT_HL1MP_PLAYER ) + SendPropExclude( "DT_BaseAnimating", "m_flPoseParameter" ), + SendPropExclude( "DT_BaseAnimating", "m_flPlaybackRate" ), + SendPropExclude( "DT_BaseAnimating", "m_nSequence" ), + SendPropExclude( "DT_BaseEntity", "m_angRotation" ), + SendPropExclude( "DT_BaseAnimatingOverlay", "overlay_vars" ), + + // cs_playeranimstate and clientside animation takes care of these on the client +// SendPropExclude( "DT_ServerAnimationData" , "m_flCycle" ), + SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), + + SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 0), 11 ), + SendPropAngle( SENDINFO_VECTORELEM(m_angEyeAngles, 1), 11 ), + + SendPropEHandle( SENDINFO( m_hRagdoll ) ), + SendPropInt( SENDINFO( m_iSpawnInterpCounter), 4 ), + SendPropInt( SENDINFO( m_iRealSequence ), 9 ), + + +// SendPropDataTable( SENDINFO_DT( m_Shared ), &REFERENCE_SEND_TABLE( DT_TFCPlayerShared ) ) +END_SEND_TABLE() + +void cc_CreatePredictionError_f() +{ + CBaseEntity *pEnt = CBaseEntity::Instance( 1 ); + pEnt->SetAbsOrigin( pEnt->GetAbsOrigin() + Vector( 63, 0, 0 ) ); +} + +ConCommand cc_CreatePredictionError( "CreatePredictionError", cc_CreatePredictionError_f, "Create a prediction error", FCVAR_CHEAT ); + +static const char * s_szModelPath = "models/player/mp/"; + +CHL1MP_Player::CHL1MP_Player() +{ + m_PlayerAnimState = CreatePlayerAnimState( this ); +// item_list = 0; + + UseClientSideAnimation(); + m_angEyeAngles.Init(); +// m_pCurStateInfo = NULL; + m_lifeState = LIFE_DEAD; // Start "dead". + + m_iSpawnInterpCounter = 0; + m_flNextModelChangeTime = 0; + m_flNextTeamChangeTime = 0; + +// SetViewOffset( TFC_PLAYER_VIEW_OFFSET ); + +// SetContextThink( &CTFCPlayer::TFCPlayerThink, gpGlobals->curtime, "TFCPlayerThink" ); +} + +CHL1MP_Player::~CHL1MP_Player() +{ + m_PlayerAnimState->Release(); +} + +void CHL1MP_Player::PostThink( void ) +{ + BaseClass::PostThink(); + + QAngle angles = GetLocalAngles(); + angles[PITCH] = 0; + SetLocalAngles( angles ); + + // Store the eye angles pitch so the client can compute its animation state correctly. + m_angEyeAngles = EyeAngles(); + + m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); +} + +void CHL1MP_Player::Spawn( void ) +{ + if ( !IsObserver() ) + { + RemoveEffects( EF_NODRAW ); + SetMoveType( MOVETYPE_WALK ); + RemoveSolidFlags( FSOLID_NOT_SOLID ); + + // if no model, force one + if ( !GetModelPtr() ) + SetModel( "models/player/mp/gordon/gordon.mdl" ); + } + + m_flNextModelChangeTime = 0; + m_flNextTeamChangeTime = 0; + + BaseClass::Spawn(); + + if ( !IsObserver() ) + { + GiveDefaultItems(); + SetPlayerModel(); + } + + m_bHasLongJump = false; + + m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; +} + +void CHL1MP_Player::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + m_PlayerAnimState->DoAnimationEvent( event, nData ); + TE_PlayerAnimEvent( this, event, nData ); // Send to any clients who can see this guy. +} + +void CHL1MP_Player::GiveDefaultItems( void ) +{ + GiveNamedItem( "weapon_crowbar" ); + GiveNamedItem( "weapon_glock" ); + + CBasePlayer::GiveAmmo( 68, "9mmRound" ); +} + +void CHL1MP_Player::UpdateOnRemove( void ) +{ + if ( m_hRagdoll ) + { + UTIL_RemoveImmediate( m_hRagdoll ); + m_hRagdoll = NULL; + } + + BaseClass::UpdateOnRemove(); +} + + +void CHL1MP_Player::DetonateSatchelCharges( void ) +{ + CBaseEntity *pSatchel = NULL; + + while ( (pSatchel = gEntList.FindEntityByClassname( pSatchel, "monster_satchel" ) ) != NULL) + { + if ( pSatchel->GetOwnerEntity() == this ) + { + pSatchel->Use( this, this, USE_ON, 0 ); + } + } +} + +void CHL1MP_Player::Event_Killed( const CTakeDamageInfo &info ) +{ + DoAnimationEvent( PLAYERANIMEVENT_DIE ); +// SetNumAnimOverlays( 0 ); + + + // Note: since we're dead, it won't draw us on the client, but we don't set EF_NODRAW + // because we still want to transmit to the clients in our PVS. + if ( !IsHLTV() ) + CreateRagdollEntity(); + + DetonateSatchelCharges(); + + BaseClass::Event_Killed( info ); + + m_lifeState = LIFE_DEAD; + RemoveEffects( EF_NODRAW ); // still draw player body +} + + +void CHL1MP_Player::SetAnimation( PLAYER_ANIM playerAnim ) +{ +// BaseClass::SetAnimation( playerAnim ); + if ( playerAnim == PLAYER_ATTACK1 ) + { + DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN ); + } + + int animDesired; + char szAnim[64]; + + float speed; + + speed = GetAbsVelocity().Length2D(); + + if (GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) + { + speed = 0; + playerAnim = PLAYER_IDLE; + } + + if ( playerAnim == PLAYER_ATTACK1 ) + { + if ( speed > 0 ) + { + playerAnim = PLAYER_WALK; + } + else + { + playerAnim = PLAYER_IDLE; + } + } + + Activity idealActivity = ACT_WALK;// TEMP!!!!! + + // This could stand to be redone. Why is playerAnim abstracted from activity? (sjb) + if (playerAnim == PLAYER_JUMP) + { + idealActivity = ACT_HOP; + } + else if (playerAnim == PLAYER_SUPERJUMP) + { + idealActivity = ACT_LEAP; + } + else if (playerAnim == PLAYER_DIE) + { + if ( m_lifeState == LIFE_ALIVE ) + { + idealActivity = ACT_DIERAGDOLL; + } + } + else if (playerAnim == PLAYER_ATTACK1) + { + if ( GetActivity() == ACT_HOVER || + GetActivity() == ACT_SWIM || + GetActivity() == ACT_HOP || + GetActivity() == ACT_LEAP || + GetActivity() == ACT_DIESIMPLE ) + { + idealActivity = GetActivity(); + } + else + { + idealActivity = ACT_RANGE_ATTACK1; + } + } + else if (playerAnim == PLAYER_IDLE || playerAnim == PLAYER_WALK) + { + if ( !( GetFlags() & FL_ONGROUND ) && (GetActivity() == ACT_HOP || GetActivity() == ACT_LEAP) ) // Still jumping + { + idealActivity = GetActivity(); + } + else if ( GetWaterLevel() > 1 ) + { + if ( speed == 0 ) + idealActivity = ACT_HOVER; + else + idealActivity = ACT_SWIM; + } + else if ( speed > 0 ) + { + idealActivity = ACT_WALK; + } + else + { + idealActivity = ACT_IDLE; + } + } + + + if (idealActivity == ACT_RANGE_ATTACK1) + { + if ( GetFlags() & FL_DUCKING ) // crouching + { + Q_strncpy( szAnim, "crouch_shoot_" ,sizeof(szAnim)); + } + else + { + Q_strncpy( szAnim, "ref_shoot_" ,sizeof(szAnim)); + } + Q_strncat( szAnim, m_szAnimExtension ,sizeof(szAnim), COPY_ALL_CHARACTERS ); + animDesired = LookupSequence( szAnim ); + if (animDesired == -1) + animDesired = 0; + + if ( GetSequence() != animDesired || !SequenceLoops() ) + { + SetCycle( 0 ); + } + + // Tracker 24588: In single player when firing own weapon this causes eye and punchangle to jitter + //if (!SequenceLoops()) + //{ + // IncrementInterpolationFrame(); + //} + + SetActivity( idealActivity ); + ResetSequence( animDesired ); + } + else if (idealActivity == ACT_IDLE) + { + if ( GetFlags() & FL_DUCKING ) + { + animDesired = LookupSequence( "crouch_idle" ); + } + else + { + animDesired = LookupSequence( "look_idle" ); + } + if (animDesired == -1) + animDesired = 0; + + SetActivity( ACT_IDLE ); + } + else if ( idealActivity == ACT_WALK ) + { + if ( GetFlags() & FL_DUCKING ) + { + animDesired = SelectWeightedSequence( ACT_CROUCH ); + SetActivity( ACT_CROUCH ); + } + else + { + animDesired = SelectWeightedSequence( ACT_RUN ); + SetActivity( ACT_RUN ); + } + + } + else + { + if ( GetActivity() == idealActivity) + return; + + SetActivity( idealActivity ); + + animDesired = SelectWeightedSequence( GetActivity() ); + + // Already using the desired animation? + if (GetSequence() == animDesired) + return; + + m_iRealSequence = animDesired; + ResetSequence( animDesired ); + SetCycle( 0 ); + return; + } + + // Already using the desired animation? + if (GetSequence() == animDesired) + return; + + m_iRealSequence = animDesired; + + //Msg( "Set animation to %d\n", animDesired ); + // Reset to first frame of desired animation + ResetSequence( animDesired ); + SetCycle( 0 ); +} + +static ConVar sv_debugweaponpickup( "sv_debugweaponpickup", "0", FCVAR_CHEAT, "Prints descriptive reasons as to why pickup did not work." ); + +// correct respawning of weapons +bool CHL1MP_Player::BumpWeapon( CBaseCombatWeapon *pWeapon ) +{ CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); + + // Can I have this weapon type? + if ( !IsAllowedToPickupWeapons() ) + { + if ( sv_debugweaponpickup.GetBool() ) + Msg("sv_debugweaponpickup: IsAllowedToPickupWeapons() returned false\n"); + + return false; + } + + if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) + { + if ( sv_debugweaponpickup.GetBool() && pOwner ) + Msg("sv_debugweaponpickup: pOwner\n"); + + if ( sv_debugweaponpickup.GetBool() && !Weapon_CanUse( pWeapon ) ) + Msg("sv_debugweaponpickup: Can't use weapon\n"); + + if ( sv_debugweaponpickup.GetBool() && !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) + Msg("sv_debugweaponpickup: Gamerules says player can't have item\n"); + + if ( gEvilImpulse101 ) + { + UTIL_Remove( pWeapon ); + } + return false; + } + + // Don't let the player fetch weapons through walls (use MASK_SOLID so that you can't pickup through windows) + if( !pWeapon->FVisible( this, MASK_SOLID ) && !(GetFlags() & FL_NOTARGET) ) + { + if ( sv_debugweaponpickup.GetBool() && !FVisible( this, MASK_SOLID ) ) + Msg("sv_debugweaponpickup: Can't fetch weapon through a wall\n"); + + if ( sv_debugweaponpickup.GetBool() && !(GetFlags() & FL_NOTARGET) ) + Msg("sv_debugweaponpickup: NoTarget\n"); + + return false; + } + + bool bOwnsWeaponAlready = !!Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()); + + if ( bOwnsWeaponAlready == true ) + { + //If we have room for the ammo, then "take" the weapon too. + if ( Weapon_EquipAmmoOnly( pWeapon ) ) + { + pWeapon->CheckRespawn(); + + UTIL_Remove( pWeapon ); + + if ( sv_debugweaponpickup.GetBool() ) + Msg("sv_debugweaponpickup: Picking up weapon\n"); + + return true; + } + else + { + if ( sv_debugweaponpickup.GetBool() ) + Msg("sv_debugweaponpickup: Owns weapon already\n"); + + return false; + } + } + + pWeapon->CheckRespawn(); + Weapon_Equip( pWeapon ); + + if ( sv_debugweaponpickup.GetBool() ) + Msg("sv_debugweaponpickup: Picking up weapon\n"); + + return true; +} + + +void CHL1MP_Player::ChangeTeam( int iTeamNum ) +{ + bool bKill = false; + + if ( g_pGameRules->IsTeamplay() == true ) + { + if ( iTeamNum != GetTeamNumber() && GetTeamNumber() != TEAM_UNASSIGNED ) + { + bKill = true; + } + } + + BaseClass::ChangeTeam( iTeamNum ); + + m_flNextTeamChangeTime = gpGlobals->curtime + 5; + + if ( g_pGameRules->IsTeamplay() == true ) + { + SetPlayerTeamModel(); + } + else + { + SetPlayerModel(); + } + + if ( bKill == true ) + { + CommitSuicide(); + } +} + +void CHL1MP_Player::SetPlayerTeamModel( void ) +{ + int iTeamNum = GetTeamNumber(); + + if ( iTeamNum <= TEAM_SPECTATOR ) + return; + + CTeam * pTeam = GetGlobalTeam( iTeamNum ); + + char szModelName[256]; + Q_snprintf( szModelName, 256, "%s%s/%s.mdl", s_szModelPath, pTeam->GetName(), pTeam->GetName() ); + + // Check to see if the model was properly precached, do not error out if not. + int i = modelinfo->GetModelIndex( szModelName ); + if ( i == -1 ) + { + Warning("Model %s does not exist.\n", szModelName ); + return; + } + + SetModel( szModelName ); + m_flNextModelChangeTime = gpGlobals->curtime + 5; +} + + +void CHL1MP_Player::SetPlayerModel( void ) +{ + char szBaseName[128]; + Q_FileBase( engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ), szBaseName, 128 ); + + // Don't let it be 'none'; default to Barney + if ( Q_stricmp( "none", szBaseName ) == 0 ) + { + Q_strcpy( szBaseName, "gordon" ); + } + + char szModelName[256]; + Q_snprintf( szModelName, 256, "%s%s/%s.mdl", s_szModelPath, szBaseName, szBaseName ); + + // Check to see if the model was properly precached, do not error out if not. + int i = modelinfo->GetModelIndex( szModelName ); + if ( i == -1 ) + { + SetModel( "models/player/mp/gordon/gordon.mdl" ); + engine->ClientCommand ( edict(), "cl_playermodel models/gordon.mdl\n" ); + return; + } + + SetModel( szModelName ); + + m_flNextModelChangeTime = gpGlobals->curtime + 5; +} + + +// -------------------------------------------------------------------------------- // +// Ragdoll entities. +// -------------------------------------------------------------------------------- // + +class CHL1MPRagdoll : public CBaseAnimatingOverlay +{ +public: + DECLARE_CLASS( CHL1MPRagdoll, CBaseAnimatingOverlay ); + DECLARE_SERVERCLASS(); + + // Transmit ragdolls to everyone. + virtual int UpdateTransmitState() + { + return SetTransmitState( FL_EDICT_ALWAYS ); + } + +public: + // In case the client has the player entity, we transmit the player index. + // In case the client doesn't have it, we transmit the player's model index, origin, and angles + // so they can create a ragdoll in the right place. + CNetworkHandle( CBaseEntity, m_hPlayer ); // networked entity handle + CNetworkVector( m_vecRagdollVelocity ); + CNetworkVector( m_vecRagdollOrigin ); +}; + +LINK_ENTITY_TO_CLASS( hl1mp_ragdoll, CHL1MPRagdoll ); + +IMPLEMENT_SERVERCLASS_ST_NOBASE( CHL1MPRagdoll, DT_HL1MPRagdoll ) + SendPropVector ( SENDINFO( m_vecRagdollOrigin), -1, SPROP_COORD ), + SendPropEHandle ( SENDINFO( m_hPlayer ) ), + SendPropModelIndex( SENDINFO( m_nModelIndex ) ), + SendPropInt ( SENDINFO( m_nForceBone), 8, 0 ), + SendPropVector ( SENDINFO( m_vecForce), -1, SPROP_NOSCALE ), + SendPropVector ( SENDINFO( m_vecRagdollVelocity ) ) +END_SEND_TABLE() + + +void CHL1MP_Player::CreateRagdollEntity( void ) +{ + if ( m_hRagdoll ) + { + UTIL_RemoveImmediate( m_hRagdoll ); + m_hRagdoll = NULL; + } + + // If we already have a ragdoll, don't make another one. + CHL1MPRagdoll *pRagdoll = dynamic_cast< CHL1MPRagdoll* >(m_hRagdoll.Get() ); + + if ( !pRagdoll ) + { + // Create a new one + pRagdoll = dynamic_cast< CHL1MPRagdoll* >( CreateEntityByName( "hl1mp_ragdoll" ) ); + } + + if ( pRagdoll ) + { + pRagdoll->m_hPlayer = this; + pRagdoll->m_vecRagdollOrigin = GetAbsOrigin(); + pRagdoll->m_vecRagdollVelocity = GetAbsVelocity(); + pRagdoll->m_nModelIndex = m_nModelIndex; + pRagdoll->m_nForceBone = m_nForceBone; + //pRagdoll->m_vecForce = m_vecTotalBulletForce; + pRagdoll->SetAbsOrigin( GetAbsOrigin() ); + + } + + m_hRagdoll = pRagdoll; +} + +void CHL1MP_Player::CreateCorpse( void ) +{ + +} + |