//----------------------------------------------------------------------------- // Purpose: only called for local player //----------------------------------------------------------------------------- void C_TFWeaponBuilder::Redraw() { if ( m_iValidBuildPoseParam >= 0 ) { CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); if ( !pOwner ) return; // Assuming here that our model is the same as our viewmodel's model! CBaseViewModel *pViewModel = pOwner->GetViewModel(0); if ( pViewModel ) { float flPoseParamValue = pViewModel->GetPoseParameter( m_iValidBuildPoseParam ); C_BaseObject *pObj = m_hObjectBeingBuilt.Get(); if ( pObj && pObj->WasLastPlacementPosValid() ) { // pose param approach 1.0 flPoseParamValue = Approach( 1.0, flPoseParamValue, 3.0 * gpGlobals->frametime ); } else { // pose param approach 0.0 flPoseParamValue = Approach( 0.0, flPoseParamValue, 1.5 * gpGlobals->frametime ); } pViewModel->SetPoseParameter( m_iValidBuildPoseParam, flPoseParamValue ); } } BaseClass::Redraw(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CWarsWeapon::IsWeaponVisible( void ) { CBaseViewModel *vm = NULL; CUnitBase *pUnit; CBasePlayer *pOwner = NULL; if( GetOwner() ) { pUnit = GetOwner()->MyUnitPointer(); if( pUnit && pUnit->GetCommander() ) { pOwner = ToBasePlayer( pUnit->GetCommander() ); } } if ( pOwner ) { vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm ) return ( !vm->IsEffectActive(EF_NODRAW) ); } return BaseClass::IsWeaponVisible(); }
//----------------------------------------------------------------------------- // Purpose: Handle grenade detonate in-air (even when no ammo is left) //----------------------------------------------------------------------------- void CWeaponAR2::ItemPostFrame( void ) { // See if we need to fire off our secondary round if ( m_bShotDelayed && gpGlobals->curtime > m_flDelayedFire ) { DelayedAttack(); } // Update our pose parameter for the vents CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner ) { CBaseViewModel *pVM = pOwner->GetViewModel(); if ( pVM ) { if ( m_nVentPose == -1 ) { m_nVentPose = pVM->LookupPoseParameter( "VentPoses" ); } float flVentPose = RemapValClamped( m_nShotsFired, 0, 5, 0.0f, 1.0f ); pVM->SetPoseParameter( m_nVentPose, flVentPose ); } } BaseClass::ItemPostFrame(); }
//----------------------------------------------------------------------------- // Purpose: Show/hide weapon and corresponding view model if any // Input : visible - //----------------------------------------------------------------------------- void CWarsWeapon::SetWeaponVisible( bool visible ) { CBaseViewModel *vm = NULL; CUnitBase *pUnit; if( GetOwner() ) { pUnit = GetOwner()->MyUnitPointer(); if( pUnit && pUnit->GetCommander() ) { CBasePlayer *pOwner = ToBasePlayer( pUnit->GetCommander() ); if ( pOwner ) { vm = pOwner->GetViewModel( m_nViewModelIndex ); } } } if ( vm ) { if ( visible ) { vm->RemoveEffects( EF_NODRAW ); } else { vm->AddEffects( EF_NODRAW ); } } BaseClass::SetWeaponVisible( visible ); }
//----------------------------------------------------------------------------- // Purpose: Show/hide weapon and corresponding view model if any // Input : visible - //----------------------------------------------------------------------------- void CTFWeaponInvis::SetWeaponVisible( bool visible ) { CBaseViewModel *vm = NULL; CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner ) { vm = pOwner->GetViewModel( m_nViewModelIndex ); } if ( visible ) { RemoveEffects( EF_NODRAW ); if ( vm ) { vm->RemoveEffects( EF_NODRAW ); } } else { AddEffects( EF_NODRAW ); if ( vm ) { vm->AddEffects( EF_NODRAW ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponCrossbow::DoLoadEffect( void ) { SetSkin( BOLT_SKIN_GLOW ); CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; CBaseViewModel *pViewModel = pOwner->GetViewModel(); if ( pViewModel == NULL ) return; CEffectData data; data.m_nEntIndex = pViewModel->entindex(); data.m_nAttachmentIndex = 1; DispatchEffect( "CrossbowLoad", data ); CSprite *pBlast = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE2, GetAbsOrigin(), false ); if ( pBlast ) { pBlast->SetAttachment( pOwner->GetViewModel(), 1 ); pBlast->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); pBlast->SetBrightness( 128 ); pBlast->SetScale( 0.2f ); pBlast->FadeOutFromSpawn(); } }
//----------------------------------------------------------------------------- // Purpose: // Input : iActivity - //----------------------------------------------------------------------------- void CWarsWeapon::SendViewModelAnim( int nSequence ) { #if defined( CLIENT_DLL ) if ( !IsPredicted() ) { return; } #endif if ( nSequence < 0 ) return; CBasePlayer *pOwner = ToBasePlayer( GetCommander() ); if ( pOwner == NULL ) { BaseClass::SendViewModelAnim( nSequence ); return; } CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm == NULL ) { return; } SetViewModel(); Assert( vm->ViewModelIndex() == m_nViewModelIndex ); vm->SendViewModelMatchingSequence( nSequence ); }
void CHL2MP_Player::PostThink( void ) { BaseClass::PostThink(); if ( GetFlags() & FL_DUCKING ) { SetCollisionBounds( VEC_CROUCH_TRACE_MIN, VEC_CROUCH_TRACE_MAX ); } m_PlayerAnimState.Update(); // Store the eye angles pitch so the client can compute its animation state correctly. m_angEyeAngles = EyeAngles(); QAngle angles = GetLocalAngles(); angles[PITCH] = 0; SetLocalAngles( angles ); if (!IsDead()) { if (m_afButtonReleased & IN_KICK && m_flNextKickAttack < gpGlobals->curtime /* && m_flNextKickAttack < gpGlobals->curtime && !m_bIsKicking*/) { KickAttack(); m_bIsKicking = true; } } CBaseCombatWeapon *pWeapon = this->GetActiveWeapon(); if (pWeapon != NULL) { if (m_afButtonPressed & IN_IRONSIGHT) { pWeapon->EnableIronsights(); } else if (m_afButtonReleased & IN_IRONSIGHT) { pWeapon->DisableIronsights(); } } if (!IsDead()) { if (m_flNextKickAttack < gpGlobals->curtime) { m_bIsKicking = false; CBaseViewModel *vm = GetViewModel(1); if (vm) { int idealSequence = vm->SelectWeightedSequence(ACT_VM_IDLE); if (idealSequence >= 0) { vm->SendViewModelMatchingSequence(idealSequence); } } } } }
int CCitadelEnergyCore::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { CBaseViewModel *pViewModel = IsViewModelMoveParent( this ); if ( pViewModel ) { return pViewModel->ShouldTransmit( pInfo ); } return BaseClass::ShouldTransmit( pInfo ); }
void CBasePlayer::CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles) { for ( int i = 0; i < MAX_VIEWMODELS; i++ ) { CBaseViewModel *vm = GetViewModel( i ); if ( !vm ) continue; vm->CalcViewModelView( this, eyeOrigin, eyeAngles ); } }
void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut ) { CBaseViewModel *model = (CBaseViewModel *)pStruct; if (pData->m_Value.m_Int != model->GetSequence()) { MDLCACHE_CRITICAL_SECTION(); model->SetSequence(pData->m_Value.m_Int); model->m_flAnimTime = gpGlobals->curtime; model->SetCycle(0); } }
void CBasePlayer::DoMuzzleFlash() { for ( int i = 0; i < MAX_VIEWMODELS; i++ ) { CBaseViewModel *vm = GetViewModel( i ); if ( !vm ) continue; vm->DoMuzzleFlash(); } BaseClass::DoMuzzleFlash(); }
void CBaseCombatWeapon::Operator_FrameUpdate( CBaseCombatCharacter *pOperator ) { StudioFrameAdvance( ); // animate if ( IsSequenceFinished() ) { if ( SequenceLoops() ) { // animation does loop, which means we're playing subtle idle. Might need to fidget. int iSequence = SelectWeightedSequence( GetActivity() ); if ( iSequence != ACTIVITY_NOT_AVAILABLE ) { ResetSequence( iSequence ); // Set to new anim (if it's there) } } #if 0 else { // animation that just ended doesn't loop! That means we just finished a fidget // and should return to our heaviest weighted idle (the subtle one) SelectHeaviestSequence( GetActivity() ); } #endif } CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm == NULL ) return; // HACK: Player weapon and view model often use the same mdl, which results // in duplicate anim events. For now, let the view model handle the events // if they're the same, which is the preferred behavior in general. CStudioHdr *w_hdr = GetModelPtr(); CStudioHdr *v_hdr = vm->GetModelPtr(); if ( w_hdr->GetRenderHdr() != v_hdr->GetRenderHdr() ) { // Animation events are passed back to the weapon's owner/operator DispatchAnimEvents( pOperator ); } // Update and dispatch the viewmodel events if ( vm != NULL ) { vm->StudioFrameAdvance(); vm->DispatchAnimEvents( this ); } }
//----------------------------------------------------------------------------- // Purpose: Sets HL2 specific defaults. //----------------------------------------------------------------------------- void CHL2MP_Player::Spawn(void) { m_flNextModelChangeTime = 0.0f; m_flNextTeamChangeTime = 0.0f; PickDefaultSpawnTeam(); BaseClass::Spawn(); if ( !IsObserver() ) { pl.deadflag = false; RemoveSolidFlags( FSOLID_NOT_SOLID ); RemoveEffects( EF_NODRAW ); GiveDefaultItems(); } SetNumAnimOverlays( 3 ); ResetAnimation(); m_nRenderFX = kRenderNormal; m_Local.m_iHideHUD = 0; AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. m_impactEnergyScale = HL2MPPLAYER_PHYSDAMAGE_SCALE; if ( HL2MPRules()->IsIntermission() ) { AddFlag( FL_FROZEN ); } else { RemoveFlag( FL_FROZEN ); } m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; m_Local.m_bDucked = false; SetPlayerUnderwater(false); m_bReady = false; m_flNextKickAttack = gpGlobals->curtime; CBaseViewModel *Leg = GetViewModel(1); Leg->SetWeaponModel("models/weapons/v_kick.mdl", NULL); }
void CSDKPlayer::DoMuzzleFlash() { #ifdef CLIENT_DLL if (prediction->InPrediction() && !prediction->IsFirstTimePredicted()) return; C_SDKPlayer* pLocalPlayer = C_SDKPlayer::GetLocalSDKPlayer(); C_WeaponSDKBase* pActiveWeapon = GetActiveSDKWeapon(); if (pLocalPlayer) { if (pLocalPlayer == this && !::input->CAM_IsThirdPerson() || pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE && pLocalPlayer->GetObserverTarget() == this) { for ( int i = 0; i < MAX_VIEWMODELS; i++ ) { CBaseViewModel *vm = GetViewModel( i ); if ( !vm ) continue; vm->DoMuzzleFlash(); } } else if (pActiveWeapon) { // Force world model so the attachments work. pActiveWeapon->SetModelIndex( pActiveWeapon->GetWorldModelIndex() ); switch (pActiveWeapon->GetWeaponType()) { case WT_PISTOL: default: pActiveWeapon->ParticleProp()->Create( "muzzleflash_pistol", PATTACH_POINT_FOLLOW, "muzzle" ); break; case WT_SMG: pActiveWeapon->ParticleProp()->Create( "muzzleflash_smg", PATTACH_POINT_FOLLOW, "muzzle" ); break; case WT_RIFLE: pActiveWeapon->ParticleProp()->Create( "muzzleflash_rifle", PATTACH_POINT_FOLLOW, "muzzle" ); break; case WT_SHOTGUN: pActiveWeapon->ParticleProp()->Create( "muzzleflash_shotgun", PATTACH_POINT_FOLLOW, "muzzle" ); break; } } } #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponCrossbow::DoLoadEffect() { SetSkin(BOLT_SKIN_GLOW); CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( !pOwner ) return; CEffectData data; data.m_nAttachmentIndex = 1; #ifdef GAME_DLL data.m_nEntIndex = entindex(); CPASFilter filter(data.m_vOrigin); filter.RemoveRecipient(pOwner); te->DispatchEffect(filter, 0.0, data.m_vOrigin, "CrossbowLoad", data); #else CBaseViewModel *pViewModel = pOwner->GetViewModel(); if ( pViewModel != NULL ) { if ( ::input->CAM_IsThirdPerson() ) data.m_hEntity = pViewModel->GetRefEHandle(); else data.m_hEntity = GetRefEHandle(); DispatchEffect("CrossbowLoad", data); } #endif //Tony; switched this up, always attach it to the weapon, not the view model!! #ifndef CLIENT_DLL CSprite *pBlast = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE2, GetAbsOrigin(), false ); if ( pBlast ) { pBlast->SetAttachment(this, 1); pBlast->SetTransparency(kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); pBlast->SetBrightness(128); pBlast->SetScale(0.2f); pBlast->FadeOutFromSpawn(); } #endif }
void CTFBonesaw::UpdateChargePoseParam( void ) { CTFPlayer *pOwner = GetTFPlayerOwner(); if ( !pOwner ) return; CWeaponMedigun *pMedigun = pOwner->GetMedigun(); if ( pMedigun ) { SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm ) vm->SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); } }
static void RecvProxy_Weapon( const CRecvProxyData *pData, void *pStruct, void *pOut ) { CBaseViewModel *pViewModel = ((CBaseViewModel*)pStruct); CBaseCombatWeapon *pOldWeapon = pViewModel->GetOwningWeapon(); // Chain through to the default recieve proxy ... RecvProxy_IntToEHandle( pData, pStruct, pOut ); // ... and reset our cycle index if the server is switching weapons on us CBaseCombatWeapon *pNewWeapon = pViewModel->GetOwningWeapon(); if ( pNewWeapon != pOldWeapon ) { // Restart animation at frame 0 pViewModel->SetCycle( 0 ); pViewModel->m_flAnimTime = gpGlobals->curtime; } }
//----------------------------------------------------------------------------- // Purpose: // Input : skinNum - //----------------------------------------------------------------------------- void CWeaponGrapple::SetSkin(int skinNum) { CBasePlayer *pOwner = ToBasePlayer(GetOwner()); if (pOwner == NULL) return; CBaseViewModel *pViewModel = pOwner->GetViewModel(); if (pViewModel == NULL) return; #ifndef CLIENT_DLL pViewModel->m_nSkin = skinNum; #else pViewModel->SetSkin(skinNum); #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponCrossbow::DoLoadEffect( void ) { SetSkin( BOLT_SKIN_GLOW ); CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; //Tony; change this up a bit; on the server, dispatch an effect but don't send it to the client who fires //on the client, create an effect either in the view model, or on the world model if first person. CEffectData data; data.m_nAttachmentIndex = 1; data.m_vOrigin = pOwner->GetAbsOrigin(); CPASFilter filter( data.m_vOrigin ); #ifdef GAME_DLL filter.RemoveRecipient( pOwner ); data.m_nEntIndex = entindex(); #else CBaseViewModel *pViewModel = pOwner->GetViewModel(); if ( ShouldDrawUsingViewModel() && pViewModel != NULL ) data.m_hEntity = pViewModel->GetRefEHandle(); else data.m_hEntity = GetRefEHandle(); #endif DispatchEffect( "CrossbowLoad", data, filter ); #ifndef CLIENT_DLL CSprite *pBlast = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE2, GetAbsOrigin(), false ); if ( pBlast ) { pBlast->SetAttachment( this, 1 ); pBlast->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); pBlast->SetBrightness( 128 ); pBlast->SetScale( 0.2f ); pBlast->FadeOutFromSpawn(); } #endif }
float CWarsWeapon::GetViewModelSequenceDuration() { CBasePlayer *pOwner = ToBasePlayer( GetCommander() ); if ( pOwner == NULL ) { return BaseClass::GetViewModelSequenceDuration( ); } CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm == NULL ) { Assert( false ); return 0; } SetViewModel(); Assert( vm->ViewModelIndex() == m_nViewModelIndex ); return vm->SequenceDuration(); }
int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { // Certain entities like sprites and ropes are strewn throughout the level and they rarely change. // For these entities, it's more efficient to transmit them once and then always leave them on // the client. Otherwise, the server will have to send big bursts of data with the entity states // as they come in and out of the PVS. if ( GetMoveParent() ) { CBaseViewModel *pViewModel = ToBaseViewModel( GetMoveParent() ); if ( pViewModel ) { return pViewModel->ShouldTransmit( pInfo ); } } return FL_EDICT_ALWAYS; }
void CBaseCombatWeapon::Operator_FrameUpdate( CBaseCombatCharacter *pOperator ) { StudioFrameAdvance( ); // animate if ( IsSequenceFinished() ) { if ( SequenceLoops() ) { // animation does loop, which means we're playing subtle idle. Might need to fidget. int iSequence = SelectWeightedSequence( GetActivity() ); if ( iSequence != ACTIVITY_NOT_AVAILABLE ) { ResetSequence( iSequence ); // Set to new anim (if it's there) } } #if 0 else { // animation that just ended doesn't loop! That means we just finished a fidget // and should return to our heaviest weighted idle (the subtle one) SelectHeaviestSequence( GetActivity() ); } #endif } // Animation events are passed back to the weapon's owner/operator DispatchAnimEvents( pOperator ); // Update and dispatch the viewmodel events CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) return; CBaseViewModel *vm = pOwner->GetViewModel(); if ( vm != NULL ) { vm->StudioFrameAdvance(); vm->DispatchAnimEvents( this ); } }
//----------------------------------------------------------------------------- // Purpose: Override base class so player can reset autoaim // Input : // Output : //----------------------------------------------------------------------------- bool CBasePlayer::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex /*=0*/ ) { CBaseCombatWeapon *pLastWeapon = GetActiveWeapon(); if ( BaseClass::Weapon_Switch( pWeapon, viewmodelindex )) { if ( pLastWeapon && Weapon_ShouldSetLast( pLastWeapon, GetActiveWeapon() ) ) { Weapon_SetLast( pLastWeapon->GetLastWeapon() ); } CBaseViewModel *pViewModel = GetViewModel( viewmodelindex ); Assert( pViewModel ); if ( pViewModel ) pViewModel->RemoveEffects( EF_NODRAW ); ResetAutoaim( ); return true; } return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWarsWeapon::SetViewModel() { CUnitBase *pUnit; CHL2WarsPlayer *pOwner; pUnit = GetOwner()->MyUnitPointer(); if ( pUnit ) { pOwner = pUnit->GetCommander(); if( pOwner ) { CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm == NULL ) return; Assert( vm->ViewModelIndex() == m_nViewModelIndex ); vm->SetWeaponModel( GetViewModel( m_nViewModelIndex ), this ); } } BaseClass::SetViewModel(); }
bool CWarsWeapon::IsViewModelSequenceFinished( void ) { // These are not valid activities and always complete immediately if ( GetActivity() == ACT_RESET || GetActivity() == ACT_INVALID ) return true; CBasePlayer *pOwner = ToBasePlayer( GetCommander() ); if ( pOwner == NULL ) { return BaseClass::IsViewModelSequenceFinished( ); } CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm == NULL ) { Assert( false ); return false; } return vm->IsSequenceFinished(); }
void CC4::UpdateShieldState( void ) { //ADRIANTODO CCSPlayer *pPlayer = GetPlayerOwner(); if ( !pPlayer ) return; if ( pPlayer->HasShield() ) { pPlayer->SetShieldDrawnState( false ); CBaseViewModel *pVM = pPlayer->GetViewModel( 1 ); if ( pVM ) { pVM->AddEffects( EF_NODRAW ); } //pPlayer->SetHitBoxSet( 3 ); } else BaseClass::UpdateShieldState(); }
void CWarsWeapon::Operator_FrameUpdate( CBaseCombatCharacter *pOperator ) { BaseClass::Operator_FrameUpdate( pOperator ); if( GetCommander() ) { CBaseViewModel *vm = GetCommander()->GetViewModel( m_nViewModelIndex ); if ( vm != NULL ) { #ifndef CLIENT_DLL vm->StudioFrameAdvance(); vm->DispatchAnimEvents( this ); #else //if( vm->ShouldPredict() ) // vm->StudioFrameAdvance(); #endif // CLIENT_DLL } } }
//----------------------------------------------------------------------------- // Purpose: // // //----------------------------------------------------------------------------- void CWeaponBrickbat::DrawAmmo( void ) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); // ------------------------------------------- // Make sure I have ammo of the current type // ------------------------------------------- int counter = 0; while (m_nAmmoCount[m_iCurrentAmmoType] <=0) { m_iCurrentAmmoType = ((++m_iCurrentAmmoType)%NUM_BRICKBAT_AMMO_TYPES); counter++; // ---------------------------------------------------- // No ammo of any types so drop the weapon and destroy // ---------------------------------------------------- if (counter >= NUM_BRICKBAT_AMMO_TYPES) { pOwner->Weapon_Drop( this, NULL, NULL ); UTIL_Remove(this); return; } } SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel); CBaseViewModel *vm = pOwner->GetViewModel(); if ( vm ) { vm->SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel ); } //Msg("Drawing %s...\n",BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName); m_bNeedDraw = false; SendWeaponAnim(ACT_VM_DRAW); // Don't fire again until fire animation has completed float flSequenceEndTime = gpGlobals->curtime + SequenceDuration(); pOwner->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime; }
void CEntHost::CreateHands( int index, int parent ) { Assert( IsPlayer() ); Assert( index >= 1 && index < MAX_VIEWMODELS ); if ( !IsPlayer() ) return; if ( !GetPlayer()->GetViewModel( parent ) ) return; if ( !GetHandsModel( index ) ) return; CBaseViewModel *hands = GetPlayer()->GetViewModel( index ); CBaseViewModel *vm = GetPlayer()->GetViewModel( parent ); // Ya existe, actualizamos el modelo if ( hands ) { hands->SetModel( GetHandsModel( index ) ); return; } hands = (CBaseViewModel *)CreateEntityByName( "predicted_viewmodel" ); if ( hands ) { hands->SetAbsOrigin( GetAbsOrigin() ); hands->SetOwner( GetPlayer() ); hands->SetIndex( index ); DispatchSpawn( hands ); hands->SetModel( GetHandsModel( index ) ); hands->SetOwnerViewModel( vm ); hands->SetOwnerEntity( GetPlayer() ); hands->AddEffects( EF_NODRAW ); GetPlayer()->m_hViewModel.Set( index, hands ); } }