//----------------------------------------------------------------------------- // Purpose: // Input : *pszModelName - // vecOrigin - // vecForceDir - // vecAngularImp - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool C_Gib::InitializeGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float flLifetime ) { if ( InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false ) { Release(); return false; } SetAbsOrigin( vecOrigin ); SetCollisionGroup( COLLISION_GROUP_DEBRIS ); solid_t tmpSolid; PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); m_pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &tmpSolid ); if ( m_pPhysicsObject ) { float flForce = m_pPhysicsObject->GetMass(); vecForceDir *= flForce; m_pPhysicsObject->ApplyForceOffset( vecForceDir, GetAbsOrigin() ); m_pPhysicsObject->SetCallbackFlags( m_pPhysicsObject->GetCallbackFlags() | CALLBACK_GLOBAL_TOUCH | CALLBACK_GLOBAL_TOUCH_STATIC ); } else { // failed to create a physics object Release(); return false; } SetNextClientThink( gpGlobals->curtime + flLifetime ); return true; }
void CBeam::OnDataChanged( DataUpdateType_t updateType ) { MarkMessageReceived(); // Make sure that the correct model is referenced for this entity SetModelPointer( modelinfo->GetModel( GetModelIndex() ) ); // Convert weapon world models to viewmodels if they're weapons being carried by the local player for (int i=0;i<MAX_BEAM_ENTS;i++) { C_BaseEntity *pEnt = m_hAttachEntity[i].Get(); if ( pEnt ) { C_BaseCombatWeapon *pWpn = dynamic_cast<C_BaseCombatWeapon *>(pEnt); if ( pWpn && pWpn->IsCarriedByLocalPlayer() ) { C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() ); C_BaseViewModel *pViewModel = player ? player->GetViewModel( 0 ) : NULL; if ( pViewModel ) { // Get the viewmodel and use it instead m_hAttachEntity.Set( i, pViewModel ); } } } } // Compute the bounds here... Vector mins, maxs; ComputeBounds( mins, maxs ); SetCollisionBounds( mins, maxs ); }
bool CPhysBox::CreateVPhysics() { solid_t tmpSolid; PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); if ( m_massScale > 0 ) { float mass = tmpSolid.params.mass * m_massScale; mass = clamp( mass, 0.5, 1e6 ); tmpSolid.params.mass = mass; } PhysSolidOverride( tmpSolid, m_iszOverrideScript ); IPhysicsObject *pPhysics = VPhysicsInitNormal( GetSolid(), GetSolidFlags(), true, &tmpSolid ); if ( m_damageType == 1 ) { PhysSetGameFlags( pPhysics, FVPHYSICS_DMG_SLICE ); } // Wake it up if not asleep if ( !HasSpawnFlags(SF_PHYSBOX_ASLEEP) ) { VPhysicsGetObject()->Wake(); } if ( HasSpawnFlags(SF_PHYSBOX_MOTIONDISABLED) || m_damageToEnableMotion > 0 ) { VPhysicsGetObject()->EnableMotion( false ); } // only send data when physics moves this object NetworkStateManualMode( true ); return true; }
//----------------------------------------------------------------------------- // tool recording //----------------------------------------------------------------------------- void C_BaseCombatWeapon::GetToolRecordingState( KeyValues *msg ) { if ( !ToolsEnabled() ) return; int nModelIndex = GetModelIndex(); int nWorldModelIndex = GetWorldModelIndex(); if ( nModelIndex != nWorldModelIndex ) { SetModelIndex( nWorldModelIndex ); } BaseClass::GetToolRecordingState( msg ); if ( m_iState == WEAPON_NOT_CARRIED ) { BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" ); pBaseEntity->m_nOwner = -1; } else { msg->SetInt( "worldmodel", 1 ); if ( m_iState == WEAPON_IS_ACTIVE ) { BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" ); pBaseEntity->m_bVisible = true; } } if ( nModelIndex != nWorldModelIndex ) { SetModelIndex( nModelIndex ); } }
/*VOID CEntitySA::SetModelAlpha ( int iAlpha ) { this->internalInterface->ModelClump->SetAlpha(iAlpha); }*/ VOID CEntitySA::SetPosition(float fX, float fY, float fZ) { DEBUG_TRACE("VOID CEntitySA::SetPosition(float fX, float fY, float fZ)"); CVector * vecPos; if ( m_pInterface->Placeable.matrix ) { vecPos = &m_pInterface->Placeable.matrix->vPos; } else { vecPos = &m_pInterface->Placeable.m_transform.m_translate; } if ( vecPos ) { vecPos->fX = fX; vecPos->fY = fY; vecPos->fZ = fZ; } WORD wModelID = GetModelIndex(); if ( wModelID == 537 || wModelID == 538 || wModelID == 569 || wModelID == 570 || wModelID == 590 || wModelID == 449 ) { // If it's a train, recalculate its rail position parameter (does not affect derailed state) DWORD dwThis = (DWORD) m_pInterface; DWORD dwFunc = FUNC_CVehicle_RecalcOnRailDistance; _asm { mov ecx, dwThis call dwFunc } }
//========================================================= // Tracking Hornet hit something //========================================================= void CNPC_Hornet::TrackTouch ( CBaseEntity *pOther ) { if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) { return; } if ( pOther == GetOwnerEntity() || pOther->GetModelIndex() == GetModelIndex() ) {// bumped into the guy that shot it. //SetSolid( SOLID_NOT ); return; } int nRelationship = IRelationType( pOther ); if ( (nRelationship == D_FR || nRelationship == D_NU || nRelationship == D_LI) ) { // hit something we don't want to hurt, so turn around. Vector vecVel = GetAbsVelocity(); VectorNormalize( vecVel ); vecVel.x *= -1; vecVel.y *= -1; SetAbsOrigin( GetAbsOrigin() + vecVel * 4 ); // bounce the hornet off a bit. SetAbsVelocity( vecVel * m_flFlySpeed ); return; } DieTouch( pOther ); }
void CNPC_Tentacle::HitTouch( CBaseEntity *pOther ) { if (m_flHitTime > gpGlobals->curtime) return; // only look at the ones where the player hit me if( pOther == NULL || pOther->GetModelIndex() == GetModelIndex() || ( pOther->GetSolidFlags() & FSOLID_TRIGGER ) ) return; //Right now the BoneFollower will always be hit in box 0, and //will pass that to us. Make *any* touch by the physics objects a kill //as the ragdoll only covers the top portion of the tentacle. if ( pOther->m_takedamage ) { CTakeDamageInfo info( this, this, m_iHitDmg, DMG_CLUB ); Vector vDamageForce = pOther->GetAbsOrigin() - GetAbsOrigin(); VectorNormalize( vDamageForce ); CalculateMeleeDamageForce( &info, vDamageForce, pOther->GetAbsOrigin() ); pOther->TakeDamage( info ); m_flHitTime = gpGlobals->curtime + 0.5; } }
void CRagdollProp::OnRestore() { // rebuild element 0 since it isn't saved // NOTE: This breaks the rules - the pointer needs to get fixed in Restore() m_ragdoll.list[0].pObject = VPhysicsGetObject(); m_ragdoll.list[0].parentIndex = -1; m_ragdoll.list[0].originParentSpace.Init(); BaseClass::OnRestore(); if ( !m_ragdoll.listCount ) return; // JAY: Reset collision relationships RagdollSetupCollisions( m_ragdoll, modelinfo->GetVCollide( GetModelIndex() ), GetModelIndex() ); VPhysicsUpdate( VPhysicsGetObject() ); }
void C_PhysPropClientside::Spawn() { // Initialize damage modifiers. Must be done before baseclass spawn. m_flDmgModBullet = 1.0; m_flDmgModClub = 1.0; m_flDmgModExplosive = 1.0; BaseClass::Spawn(); // we don't really precache models here, just checking how many we have: m_iNumBreakableChunks = PropBreakablePrecacheAll( GetModelIndex() ); ParsePropData(); // If we have no custom breakable chunks, see if we're breaking into generic ones if ( !m_iNumBreakableChunks ) { if ( GetBreakableModel() != NULL_STRING && GetBreakableCount() ) { m_iNumBreakableChunks = GetBreakableCount(); } } // Setup takedamage based upon the health we parsed earlier if ( m_iHealth == 0 ) { m_takedamage = DAMAGE_NO; } else { m_takedamage = DAMAGE_YES; } }
//========================================================= // hornets will never get mad at each other, no matter who the owner is. //========================================================= Disposition_t CNPC_Hornet::IRelationType( CBaseEntity *pTarget ) { if ( pTarget->GetModelIndex() == GetModelIndex() ) { return D_NU; } return BaseClass::IRelationType( pTarget ); }
CStudioHdr *C_ServerRagdoll::OnNewModel( void ) { CStudioHdr *hdr = BaseClass::OnNewModel(); if ( !m_elementCount ) { vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); if ( !pCollide ) { const char *pszName = modelinfo->GetModelName( modelinfo->GetModel( GetModelIndex() ) ); Msg( "*** ERROR: C_ServerRagdoll::InitModel: %s missing vcollide data ***\n", (pszName) ? pszName : "<null>" ); m_elementCount = 0; } else m_elementCount = RagdollExtractBoneIndices( m_boneIndex, hdr, pCollide ); m_iv_ragPos.SetMaxCount( m_elementCount ); m_iv_ragAngles.SetMaxCount( m_elementCount ); } return hdr; }
// This creates a vphysics object with a shadow controller that follows the AI IPhysicsObject *C_RagdollShadow::VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation ) { studiohdr_t *hdr = GetModelPtr(); if ( !hdr ) { return NULL; } // If this entity already has a physics object, then it should have been deleted prior to making this call. Assert(!m_pPhysicsObject); // make sure m_vecOrigin / m_vecAngles are correct const Vector &origin = GetAbsOrigin(); QAngle angles = GetAbsAngles(); IPhysicsObject *pPhysicsObject = NULL; if ( GetSolid() == SOLID_BBOX ) { const char *pSurfaceProps = "flesh"; if ( GetModelIndex() && modelinfo->GetModelType( GetModel() ) == mod_studio ) { pSurfaceProps = Studio_GetDefaultSurfaceProps( hdr ); } angles = vec3_angle; CPhysCollide *pCollide = PhysCreateBbox( WorldAlignMins(), WorldAlignMaxs() ); if ( !pCollide ) return NULL; pPhysicsObject = PhysModelCreateCustom( this, pCollide, origin, angles, pSurfaceProps ); } else { pPhysicsObject = PhysModelCreateRagdoll( this, GetModelIndex(), origin, angles ); } VPhysicsSetObject( pPhysicsObject ); pPhysicsObject->SetShadow( Vector(1e4,1e4,1e4), AngularImpulse(1e4,1e4,1e4), allowPhysicsMovement, allowPhysicsRotation ); pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 ); // PhysAddShadow( this ); return pPhysicsObject; }
void CWeaponCycler::Spawn( ) { SetSolid( SOLID_BBOX ); AddSolidFlags( FSOLID_NOT_STANDABLE ); SetMoveType( MOVETYPE_NONE ); PrecacheModel( STRING( GetModelName() ) ); SetModel( STRING( GetModelName() ) ); m_iszModel = GetModelName(); m_iModel = GetModelIndex(); UTIL_SetSize(this, Vector(-16, -16, 0), Vector(16, 16, 16)); SetTouch( &CWeaponCycler::DefaultTouch ); }
//----------------------------------------------------------------------------- // Purpose: // Input : bnewentity - //----------------------------------------------------------------------------- void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType ) { BaseClass::OnDataChanged(updateType); CHandle< C_BaseCombatWeapon > handle = this; // If it's being carried by the *local* player, on the first update, // find the registered weapon for this ID C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); C_BaseCombatCharacter *pOwner = GetOwner(); // check if weapon is carried by local player bool bIsLocalPlayer = pPlayer && pPlayer == pOwner; if ( bIsLocalPlayer && ShouldDrawLocalPlayerViewModel() ) // TODO: figure out the purpose of the ShouldDrawLocalPlayer() test. { // If I was just picked up, or created & immediately carried, add myself to this client's list of weapons if ( (m_iState != WEAPON_NOT_CARRIED ) && (m_iOldState == WEAPON_NOT_CARRIED) ) { // Tell the HUD this weapon's been picked up if ( ShouldDrawPickup() ) { CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection(); if ( pHudSelection ) { pHudSelection->OnWeaponPickup( this ); } pPlayer->EmitSound( "Player.PickupWeapon" ); } } } else // weapon carried by other player or not at all { int overrideModelIndex = CalcOverrideModelIndex(); if( overrideModelIndex != -1 && overrideModelIndex != GetModelIndex() ) { SetModelIndex( overrideModelIndex ); } } if ( updateType == DATA_UPDATE_CREATED ) { UpdateVisibility(); } m_iOldState = m_iState; m_bJustRestored = false; }
bool CBoneFollower::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) { vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); Assert( pCollide && pCollide->solidCount > m_solidIndex ); UTIL_ClearTrace( trace ); physcollision->TraceBox( ray, pCollide->solids[m_solidIndex], GetAbsOrigin(), GetAbsAngles(), &trace ); if ( trace.fraction >= 1 ) return false; return true; }
//----------------------------------------------------------------------------- // Purpose: Sets HL1specific defaults. //----------------------------------------------------------------------------- void CHL1_Player::Spawn(void) { SetModel( "models/player.mdl" ); g_ulModelIndexPlayer = GetModelIndex(); BaseClass::Spawn(); // // Our player movement speed is set once here. This will override the cl_xxxx // cvars unless they are set to be lower than this. // SetMaxSpeed( 320 ); SetFOV( 90 ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPhysicsCannister::Explode( CBaseEntity *pAttacker ) { // don't recurse m_takedamage = 0; Deactivate(); Vector velocity; AngularImpulse angVelocity; IPhysicsObject *pPhysics = VPhysicsGetObject(); pPhysics->GetVelocity( &velocity, &angVelocity ); PropBreakableCreateAll( GetModelIndex(), pPhysics, GetAbsOrigin(), GetAbsAngles(), velocity, angVelocity, 1.0, 20, COLLISION_GROUP_DEBRIS ); ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), pAttacker, m_damage, 0, true ); UTIL_Remove( this ); }
bool CFuncBrush::CreateVPhysics( void ) { IPhysicsObject *pPhys = VPhysicsInitShadow( false, false ); if ( pPhys ) { int contents = modelinfo->GetModelContents( GetModelIndex() ); if ( ! (contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) ) { // leave the physics shadow there in case it has crap constrained to it // but disable collisions with it pPhys->EnableCollisions( false ); } } return true; }
void CCyclerSprite::Spawn( void ) { SetSolidType( SOLID_SLIDEBOX ); SetMoveType( MOVETYPE_NONE ); SetTakeDamageMode( DAMAGE_YES ); GetEffects().ClearAll(); SetFrame( 0 ); SetNextThink( gpGlobals->time + 0.1 ); m_animate = 1; m_lastTime = gpGlobals->time; PRECACHE_MODEL( GetModelName() ); SetModel( GetModelName() ); m_maxFrame = ( float ) MODEL_FRAMES( GetModelIndex() ) - 1; }
bool CBoneFollower::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) { vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); Assert( pCollide && pCollide->solidCount > m_solidIndex ); UTIL_ClearTrace( trace ); physcollision->TraceBox( ray, pCollide->solids[m_solidIndex], GetAbsOrigin(), GetAbsAngles(), &trace ); if ( trace.fraction >= 1 ) return false; // return owner as trace hit trace.m_pEnt = GetOwnerEntity(); trace.hitgroup = m_hitGroup; trace.physicsbone = m_physicsBone; return true; }
int C_ServerRagdoll::InternalDrawModel( int flags ) { if ( vcollide_wireframe.GetBool() ) { vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); IMaterial *pWireframe = materials->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER); matrix3x4_t matrix; for ( int i = 0; i < m_elementCount; i++ ) { static color32 debugColor = {0,255,255,0}; AngleMatrix( m_ragAngles[i], m_ragPos[i], matrix ); engine->DebugDrawPhysCollide( pCollide->solids[i], pWireframe, matrix, debugColor ); } } return BaseClass::InternalDrawModel( flags ); }
vcollide_t *CModelInfo::GetVCollide( const model_t *model ) const { if ( !model ) return NULL; if ( model->type == mod_studio ) { return Mod_VCollide( const_cast<model_t *>(model) ); } int i = GetModelIndex( model->name ); if ( i >= 0 ) { return GetVCollide( i ); } return NULL; }
void C_PhysPropClientside::Break() { m_takedamage = DAMAGE_NO; IPhysicsObject *pPhysics = VPhysicsGetObject(); Vector velocity; AngularImpulse angVelocity; Vector origin; QAngle angles; AddSolidFlags( FSOLID_NOT_SOLID ); if ( pPhysics ) { pPhysics->GetVelocity( &velocity, &angVelocity ); pPhysics->GetPosition( &origin, &angles ); pPhysics->RecheckCollisionFilter(); } else { velocity = GetAbsVelocity(); QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); origin = GetAbsOrigin(); angles = GetAbsAngles(); } breakablepropparams_t params( origin, angles, velocity, angVelocity ); params.impactEnergyScale = m_impactEnergyScale; params.defCollisionGroup = GetCollisionGroup(); if ( params.defCollisionGroup == COLLISION_GROUP_NONE ) { // don't automatically make anything COLLISION_GROUP_NONE or it will // collide with debris being ejected by breaking params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; } // no damage/damage force? set a burst of 100 for some movement params.defBurstScale = 100; // spwan break chunks PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, false ); Release(); // destroy object }
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll ) { SetCollisionGroup( collisionGroup ); if ( collisionGroup == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetThink( &CRagdollProp::SetDebrisThink ); SetNextThink( gpGlobals->curtime + 5 ); } SetMoveType( MOVETYPE_VPHYSICS ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); m_takedamage = DAMAGE_EVENTS_ONLY; ragdollparams_t params; params.pGameData = static_cast<void *>( static_cast<CBaseEntity *>(this) ); params.pCollide = modelinfo->GetVCollide( GetModelIndex() ); params.pStudioHdr = GetModelPtr(); params.forceVector = forceVector; params.forceBoneIndex = forceBone; params.forcePosition = forcePos; params.pPrevBones = pPrevBones; params.pCurrentBones = pBoneToWorld; params.boneDt = dt; params.jointFrictionScale = 1.0; RagdollCreate( m_ragdoll, params, physcollision, physenv, physprops ); if ( activateRagdoll ) { RagdollActivate( m_ragdoll ); } for ( int i = 0; i < m_ragdoll.listCount; i++ ) { UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); } VPhysicsSetObject( m_ragdoll.list[0].pObject ); CalcRagdollSize(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPhysMagnet::Spawn( void ) { Precache(); SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_VPHYSICS ); SetModel( STRING( GetModelName() ) ); m_takedamage = DAMAGE_EVENTS_ONLY; solid_t tmpSolid; PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); if ( m_massScale > 0 ) { float mass = tmpSolid.params.mass * m_massScale; mass = clamp( mass, 0.5, 1e6 ); tmpSolid.params.mass = mass; } PhysSolidOverride( tmpSolid, m_iszOverrideScript ); VPhysicsInitNormal( GetSolid(), GetSolidFlags(), true, &tmpSolid ); // Wake it up if not asleep if ( !HasSpawnFlags(SF_MAGNET_ASLEEP) ) { VPhysicsGetObject()->Wake(); } if ( HasSpawnFlags(SF_MAGNET_MOTIONDISABLED) ) { VPhysicsGetObject()->EnableMotion( false ); } m_bActive = true; m_pConstraintGroup = NULL; m_flTotalMass = 0; m_flNextSuckTime = 0; BaseClass::Spawn(); }
bool CRagdollProp::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) { Vector origin = 0.5*(GetAbsMins() + GetAbsMaxs()); Vector size = 0.5*(GetAbsMaxs()-GetAbsMins()); if ( ray.m_IsRay ) { return BaseClass::TestCollision( ray, mask, trace ); } studiohdr_t *pStudioHdr = GetModelPtr( ); if (!pStudioHdr) return false; vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); // Just iterate all of the elements and trace the box against each one. // NOTE: This is pretty expensive for small/dense characters trace_t tr; for ( int i = 0; i < m_ragdoll.listCount; i++ ) { physcollision->TraceBox( ray, pCollide->solids[i], m_ragPos[i], m_ragAngles[i], &tr ); if ( tr.fraction < trace.fraction ) { trace = tr; } } if ( trace.fraction >= 1 ) { return false; } return true; }
//----------------------------------------------------------------------------- // Purpose: Draws the object //----------------------------------------------------------------------------- int C_NPC_Barnacle::InternalDrawModel( int flags ) { if ( !GetModel() ) return 0; // Make sure hdr is valid for drawing if ( !GetModelPtr() ) return 0; // UNDONE: With a bit of work on the model->world transform, we can probably // move the frustum culling into the client DLL entirely. Then TestVisibility() // can just return true/false and only be called when frustumcull is set. if ( flags & STUDIO_FRUSTUMCULL ) { switch ( TestVisibility() ) { // not visible, don't draw case VIS_NOT_VISIBLE: return 0; // definitely visible, disable engine check case VIS_IS_VISIBLE: flags &= ~STUDIO_FRUSTUMCULL; break; default: case VIS_USE_ENGINE: break; } } Vector vecMins, vecMaxs; GetRenderBounds( vecMins, vecMaxs ); int drawn = modelrender->DrawModel( flags, this, GetModelInstance(), index, GetModel(), GetAbsOrigin(), GetAbsAngles(), GetSequence(), m_nSkin, m_nBody, m_nHitboxSet, &GetAbsMins(), &GetAbsMaxs() ); if ( vcollide_wireframe.GetBool() ) { if ( IsRagdoll() ) { m_pRagdoll->DrawWireframe(); } else { vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); if ( pCollide && pCollide->solidCount == 1 ) { static color32 debugColor = {0,255,255,0}; matrix3x4_t matrix; AngleMatrix( GetAbsAngles(), GetAbsOrigin(), matrix ); engine->DebugDrawPhysCollide( pCollide->solids[0], NULL, matrix, debugColor ); } } } return drawn; }
void C_NEORagdoll::CreateNEORagdoll() { // First, initialize all our data. If we have the player's entity on our client, // then we can make ourselves start out exactly where the player is. C_NEOPlayer *pPlayer = dynamic_cast<C_NEOPlayer*>(m_hPlayer.Get()); if ( pPlayer && !pPlayer->IsDormant() ) { pPlayer->SnatchModelInstance( this ); VarMapping_t *varMap = GetVarMapping(); // Copy all the interpolated vars from the player entity. // The entity uses the interpolated history to get bone velocity. bool bRemotePlayer = (pPlayer != C_BasePlayer::GetLocalPlayer()); if ( bRemotePlayer ) { Interp_Copy( pPlayer ); SetAbsAngles( pPlayer->GetRenderAngles() ); GetRotationInterpolator().Reset(); m_flAnimTime = pPlayer->m_flAnimTime; SetSequence( pPlayer->GetSequence() ); m_flPlaybackRate = pPlayer->GetPlaybackRate(); } else { // This is the local player, so set them in a default // pose and slam their velocity, angles and origin SetAbsOrigin( m_vecRagdollOrigin ); SetAbsAngles( pPlayer->GetRenderAngles() ); SetAbsVelocity( m_vecRagdollVelocity ); int iSeq = LookupSequence( "walk_lower" ); if ( iSeq == -1 ) { Assert( false ); // missing walk_lower? iSeq = 0; } SetSequence( iSeq ); // walk_lower, basic pose SetCycle( 0.0 ); Interp_Reset( varMap ); pPlayer->m_bIsOnDeathScreen = true; // Only these were added pPlayer->m_fRagdollCreationTime = gpGlobals->curtime; } } else { // overwrite network origin so later interpolation will // use this position SetNetworkOrigin( m_vecRagdollOrigin ); SetAbsOrigin( m_vecRagdollOrigin ); SetAbsVelocity( m_vecRagdollVelocity ); Interp_Reset( GetVarMapping() ); } SetModelByIndex( GetModelIndex() ); // Make us a ragdoll.. m_nRenderFX = kRenderFxRagdoll; matrix3x4_t boneDelta0[ MAXSTUDIOBONES ]; matrix3x4_t boneDelta1[ MAXSTUDIOBONES ]; matrix3x4_t currentBones[ MAXSTUDIOBONES ]; const float boneDt = 0.05f; if ( pPlayer && !pPlayer->IsDormant() ) { pPlayer->GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); } else { GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); } InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); }
void CSnark::SuperBounceTouch( CBaseEntity *pOther ) { float flpitch; trace_t tr = CBaseEntity::GetTouchTrace( ); // don't hit the guy that launched this grenade if ( m_hOwner && ( pOther == m_hOwner ) ) return; // at least until we've bounced once m_hOwner = NULL; QAngle angles = GetAbsAngles(); angles.x = 0; angles.z = 0; SetAbsAngles( angles ); // avoid bouncing too much if ( m_flNextHit > gpGlobals->curtime) return; // higher pitch as squeeker gets closer to detonation time flpitch = 155.0 - 60.0 * ( ( m_flDie - gpGlobals->curtime ) / SQUEEK_DETONATE_DELAY ); if ( pOther->m_takedamage && m_flNextAttack < gpGlobals->curtime ) { // attack! // make sure it's me who has touched them if ( tr.m_pEnt == pOther ) { // and it's not another squeakgrenade if ( tr.m_pEnt->GetModelIndex() != GetModelIndex() ) { // ALERT( at_console, "hit enemy\n"); ClearMultiDamage(); Vector vecForward; AngleVectors( GetAbsAngles(), &vecForward ); if ( m_hOwner != NULL ) { CTakeDamageInfo info( this, m_hOwner, sk_snark_dmg_bite.GetFloat(), DMG_SLASH ); CalculateMeleeDamageForce( &info, vecForward, tr.endpos ); pOther->DispatchTraceAttack( info, vecForward, &tr ); } else { CTakeDamageInfo info( this, this, sk_snark_dmg_bite.GetFloat(), DMG_SLASH ); CalculateMeleeDamageForce( &info, vecForward, tr.endpos ); pOther->DispatchTraceAttack( info, vecForward, &tr ); } ApplyMultiDamage(); SetDamage( GetDamage() + sk_snark_dmg_pop.GetFloat() ); // add more explosion damage // m_flDie += 2.0; // add more life // make bite sound CPASAttenuationFilter filter( this ); enginesound->EmitSound( filter, entindex(), CHAN_WEAPON, "squeek/sqk_deploy1.wav", 1, ATTN_NORM, 0, (int)flpitch ); m_flNextAttack = gpGlobals->curtime + 0.5; } } else { // ALERT( at_console, "been hit\n"); } } m_flNextHit = gpGlobals->curtime + 0.1; m_flNextHunt = gpGlobals->curtime; if ( g_pGameRules->IsMultiplayer() ) { // in multiplayer, we limit how often snarks can make their bounce sounds to prevent overflows. if ( gpGlobals->curtime < m_flNextBounceSoundTime ) { // too soon! return; } } if ( !( GetFlags() & FL_ONGROUND ) ) { // play bounce sound CPASAttenuationFilter filter2( this ); switch ( random->RandomInt( 0, 2 ) ) { case 0: enginesound->EmitSound( filter2, entindex(), CHAN_VOICE, "squeek/sqk_hunt1.wav", 1, ATTN_NORM, 0, (int)flpitch ); break; case 1: enginesound->EmitSound( filter2, entindex(), CHAN_VOICE, "squeek/sqk_hunt2.wav", 1, ATTN_NORM, 0, (int)flpitch ); break; case 2: enginesound->EmitSound( filter2, entindex(), CHAN_VOICE, "squeek/sqk_hunt3.wav", 1, ATTN_NORM, 0, (int)flpitch ); break; } CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 256, 0.25 ); } else { // skittering sound CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 100, 0.1 ); } m_flNextBounceSoundTime = gpGlobals->curtime + 0.5;// half second. }
bool C_PhysPropClientside::Initialize() { if ( InitializeAsClientEntity( STRING(GetModelName()), RENDER_GROUP_OPAQUE_ENTITY ) == false ) { return false; } const model_t *mod = GetModel(); if ( mod ) { Vector mins, maxs; modelinfo->GetModelBounds( mod, mins, maxs ); SetCollisionBounds( mins, maxs ); } solid_t tmpSolid; // Create the object in the physics system if ( !PhysModelParseSolid( tmpSolid, this, GetModelIndex() ) ) { DevMsg("C_PhysPropClientside::Initialize: PhysModelParseSolid failed for entity %i.\n", GetModelIndex() ); return false; } else { m_pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, m_spawnflags & SF_PHYSPROP_START_ASLEEP, &tmpSolid ); if ( !m_pPhysicsObject ) { // failed to create a physics object DevMsg(" C_PhysPropClientside::Initialize: VPhysicsInitNormal() failed for %s.\n", STRING(GetModelName()) ); return false; } } // We want touch calls when we hit the world unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); if ( m_spawnflags & SF_PHYSPROP_MOTIONDISABLED ) { m_pPhysicsObject->EnableMotion( false ); } Spawn(); // loads breakable & prop data if ( m_iPhysicsMode == PHYSICS_MULTIPLAYER_AUTODETECT ) { m_iPhysicsMode = GetAutoMultiplayerPhysicsMode( CollisionProp()->OBBSize(), m_pPhysicsObject->GetMass() ); } if ( m_spawnflags & SF_PHYSPROP_FORCE_SERVER_SIDE ) { // forced to be server-side by map maker return false; } if ( m_iPhysicsMode != PHYSICS_MULTIPLAYER_CLIENTSIDE ) { // spawn only clientside entities return false; } else { if ( engine->IsInEditMode() ) { // don't spawn in map edit mode return false; } } if ( m_fadeMinDist < 0 ) { // start fading out at 75% of r_propsmaxdist m_fadeMaxDist = r_propsmaxdist.GetFloat(); m_fadeMinDist = r_propsmaxdist.GetFloat() * 0.75f; } // player can push it away SetCollisionGroup( COLLISION_GROUP_PUSHAWAY ); UpdatePartitionListEntry(); CollisionProp()->UpdatePartition(); SetBlocksLOS( false ); // this should be a small object // Set up shadows; do it here so that objects can change shadowcasting state CreateShadow(); UpdateVisibility(); SetNextClientThink( CLIENT_THINK_NEVER ); return true; }