bool CRopeKeyframe::GetEndPointPos2( CBaseEntity *pAttached, int iAttachment, Vector &vPos ) { if( !pAttached ) return false; if ( iAttachment > 0 ) { CBaseAnimating *pAnim = pAttached->GetBaseAnimating(); if ( pAnim ) { if( !pAnim->GetAttachment( iAttachment, vPos ) ) return false; } else { return false; } } else { vPos = pAttached->GetAbsOrigin(); } return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : &vecEyeExitEndpoint - // Output : int //----------------------------------------------------------------------------- int CJeepFourWheelServerVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ) { bAllPointsBlocked = false; if ( !m_bParsedAnimations ) { // Load the entry/exit animations from the vehicle ParseEntryExitAnims(); m_bParsedAnimations = true; } CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating *>(m_pVehicle); // If we don't have the gun anymore, we want to get out using the "gun-less" animation if ( pAnimating ) { // HACK: We know the tau-cannon removed exit anim uses the first upright anim's exit details trace_t tr; Vector vehicleExitOrigin; QAngle vehicleExitAngles; // Ensure the endpoint is clear by dropping a point down from above pAnimating->GetAttachment( m_ExitAnimations[0].iAttachment, vehicleExitOrigin, vehicleExitAngles ); vehicleExitOrigin -= VEC_VIEW; Vector vecMove = Vector(0,0,64); Vector vecStart = vehicleExitOrigin + vecMove; Vector vecEnd = vehicleExitOrigin - vecMove; UTIL_TraceHull( vecStart, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); Assert( !tr.startsolid && tr.fraction < 1.0 ); m_vecCurrentExitEndPoint = vecStart + ((vecEnd - vecStart) * tr.fraction); vecEyeExitEndpoint = m_vecCurrentExitEndPoint + VEC_VIEW; m_iCurrentExitAnim = 0; return pAnimating->LookupSequence( "exit_tauremoved" ); } return BaseClass::GetExitAnimToUse( vecEyeExitEndpoint, bAllPointsBlocked ); }
void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLimit, bool defaultLocation ) { // Check for prop breakable count reset. int nPropCount = props_break_max_pieces_perframe.GetInt(); if ( nPropCount != -1 ) { if ( nFrameNumber != gpGlobals->framecount ) { nPropBreakablesPerFrameCount = 0; nFrameNumber = gpGlobals->framecount; } // Check for max breakable count for the frame. if ( nPropBreakablesPerFrameCount >= nPropCount ) return; } int iMaxBreakCount = bIgnoreGibLimit ? -1 : props_break_max_pieces.GetInt(); if ( iMaxBreakCount != -1 ) { if ( iPrecomputedBreakableCount != -1 ) { iPrecomputedBreakableCount = MIN( iMaxBreakCount, iPrecomputedBreakableCount ); } else { iPrecomputedBreakableCount = iMaxBreakCount; } } #ifdef GAME_DLL // On server limit break model creation if ( !PropBreakableCapEdictsOnCreateAll(modelindex, pPhysics, params, pEntity, iPrecomputedBreakableCount ) ) { DevMsg( "Failed to create PropBreakable: would exceed MAX_EDICTS\n" ); return; } #endif vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); if ( !pCollide ) return; int nSkin = 0; CBaseEntity *pOwnerEntity = pEntity; CBaseAnimating *pOwnerAnim = NULL; if ( pPhysics ) { pOwnerEntity = static_cast<CBaseEntity *>(pPhysics->GetGameData()); } if ( pOwnerEntity ) { pOwnerAnim = pOwnerEntity->GetBaseAnimating(); if ( pOwnerAnim ) { nSkin = pOwnerAnim->m_nSkin; } } matrix3x4_t localToWorld; CStudioHdr studioHdr; const model_t *model = modelinfo->GetModel( modelindex ); if ( model ) { studioHdr.Init( modelinfo->GetStudiomodel( model ) ); } Vector parentOrigin = vec3_origin; int parentAttachment = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; if ( parentAttachment > 0 ) { GetAttachmentLocalSpace( &studioHdr, parentAttachment-1, localToWorld ); MatrixGetColumn( localToWorld, 3, parentOrigin ); } else { AngleMatrix( vec3_angle, localToWorld ); } CUtlVector<breakmodel_t> list; BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup ); if ( list.Count() ) { for ( int i = 0; i < list.Count(); i++ ) { int modelIndex = modelinfo->GetModelIndex( list[i].modelName ); if ( modelIndex <= 0 ) continue; // Skip multiplayer pieces that should be spawning on the other dll #ifdef GAME_DLL if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() ) #else if ( gpGlobals->maxClients > 1 ) #endif { #ifdef GAME_DLL if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_CLIENTSIDE ) continue; #else if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_SERVERSIDE ) continue; #endif if ( !defaultLocation && list[i].mpBreakMode == MULTIPLAYER_BREAK_DEFAULT ) continue; } if ( ( nPropCount != -1 ) && ( nPropBreakablesPerFrameCount > nPropCount ) ) break; if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) break; matrix3x4_t matrix; AngleMatrix( params.angles, params.origin, matrix ); CStudioHdr studioHdr; const model_t *model = modelinfo->GetModel( modelIndex ); if ( model ) { studioHdr.Init( modelinfo->GetStudiomodel( model ) ); } // Increment the number of breakable props this frame. ++nPropBreakablesPerFrameCount; Vector position = vec3_origin; QAngle angles = params.angles; if ( pOwnerAnim && list[i].placementName[0] ) { if ( list[i].placementIsBone ) { int boneIndex = pOwnerAnim->LookupBone( list[i].placementName ); if ( boneIndex >= 0 ) { pOwnerAnim->GetBonePosition( boneIndex, position, angles ); AngleMatrix( angles, position, matrix ); } } else { int attachmentIndex = Studio_FindAttachment( &studioHdr, list[i].placementName ) + 1; if ( attachmentIndex > 0 ) { pOwnerAnim->GetAttachment( attachmentIndex, matrix ); MatrixAngles( matrix, angles ); } } } else { int placementIndex = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; Vector placementOrigin = parentOrigin; if ( placementIndex > 0 ) { GetAttachmentLocalSpace( &studioHdr, placementIndex-1, localToWorld ); MatrixGetColumn( localToWorld, 3, placementOrigin ); placementOrigin -= parentOrigin; } VectorTransform( list[i].offset - placementOrigin, matrix, position ); } Vector objectVelocity = params.velocity; if (pPhysics) { pPhysics->GetVelocityAtPoint( position, &objectVelocity ); } int nActualSkin = nSkin; if ( nActualSkin > studioHdr.numskinfamilies() ) nActualSkin = 0; CBaseEntity *pBreakable = NULL; #ifdef GAME_DLL if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) #endif { pBreakable = BreakModelCreateSingle( pOwnerEntity, &list[i], position, angles, objectVelocity, params.angularVelocity, nActualSkin, params ); } if ( pBreakable ) { #ifdef GAME_DLL if ( GetGibManager() ) { GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); } #endif if ( pOwnerEntity && pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) { pBreakable->AddEffects( EF_NOSHADOW ); } // If burst scale is set, this piece should 'burst' away from // the origin in addition to travelling in the wished velocity. if ( list[i].burstScale != 0.0 ) { Vector vecBurstDir = position - params.origin; // If $autocenter wasn't used, try the center of the piece if ( vecBurstDir == vec3_origin ) { vecBurstDir = pBreakable->WorldSpaceCenter() - params.origin; } VectorNormalize( vecBurstDir ); pBreakable->ApplyAbsVelocityImpulse( vecBurstDir * list[i].burstScale ); } // If this piece is supposed to be motion disabled, disable it if ( list[i].isMotionDisabled ) { IPhysicsObject *pPhysicsObject = pBreakable->VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->EnableMotion( false ); } } } } } // Then see if the propdata specifies any breakable pieces else if ( pEntity ) { IBreakableWithPropData *pBreakableInterface = dynamic_cast<IBreakableWithPropData*>(pEntity); if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) { breakmodel_t breakModel; for ( int i = 0; i < pBreakableInterface->GetBreakableCount(); i++ ) { if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) break; Q_strncpy( breakModel.modelName, g_PropDataSystem.GetRandomChunkModel(STRING(pBreakableInterface->GetBreakableModel()), pBreakableInterface->GetMaxBreakableSize()), sizeof(breakModel.modelName) ); breakModel.health = 1; breakModel.fadeTime = RandomFloat(5,10); breakModel.fadeMinDist = 0.0f; breakModel.fadeMaxDist = 0.0f; breakModel.burstScale = params.defBurstScale; breakModel.collisionGroup = COLLISION_GROUP_DEBRIS; breakModel.isRagdoll = false; breakModel.isMotionDisabled = false; breakModel.placementName[0] = 0; breakModel.placementIsBone = false; Vector vecObbSize = pEntity->CollisionProp()->OBBSize(); // Find a random point on the plane of the original's two largest axis int smallestAxis = SmallestAxis( vecObbSize ); Vector vecMins(0,0,0); Vector vecMaxs(1,1,1); vecMins[smallestAxis] = 0.5; vecMaxs[smallestAxis] = 0.5; pEntity->CollisionProp()->RandomPointInBounds( vecMins, vecMaxs, &breakModel.offset ); // Push all chunks away from the center Vector vecBurstDir = breakModel.offset - params.origin; VectorNormalize( vecBurstDir ); Vector vecVelocity = vecBurstDir * params.defBurstScale; QAngle vecAngles = pEntity->GetAbsAngles(); int iSkin = pBreakableInterface->GetBreakableSkin(); CBaseEntity *pBreakable = NULL; #ifdef GAME_DLL if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) #endif { pBreakable = BreakModelCreateSingle( pOwnerEntity, &breakModel, breakModel.offset, vecAngles, vecVelocity, vec3_origin/*params.angularVelocity*/, iSkin, params ); if ( !pBreakable ) { DevWarning( "PropBreakableCreateAll: Could not create model %s\n", breakModel.modelName ); } } if ( pBreakable ) { #ifdef GAME_DLL if ( GetGibManager() ) { GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); } #endif Vector vecBreakableObbSize = pBreakable->CollisionProp()->OBBSize(); // Try to align the gibs along the original axis matrix3x4_t matrix; AngleMatrix( vecAngles, matrix ); AlignBoxes( &matrix, vecObbSize, vecBreakableObbSize ); MatrixAngles( matrix, vecAngles ); if ( pBreakable->VPhysicsGetObject() ) { Vector pos; pBreakable->VPhysicsGetObject()->GetPosition( &pos, NULL ); pBreakable->VPhysicsGetObject()->SetPosition( pos, vecAngles, true ); } pBreakable->SetAbsAngles( vecAngles ); if ( pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) { pBreakable->AddEffects( EF_NOSHADOW ); } } } } } }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CBaseViewModel::SpawnControlPanels() { #if defined( VGUI_CONTROL_PANELS ) char buf[64]; // Destroy existing panels DestroyControlPanels(); CBaseCombatWeapon *weapon = m_hWeapon.Get(); if ( weapon == NULL ) { return; } MDLCACHE_CRITICAL_SECTION(); // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; /* if ( IsBuiltOnAttachment() ) { pEntityToSpawnOn = dynamic_cast<CBaseAnimating*>((CBaseEntity*)m_hBuiltOnEntity.Get()); if ( pEntityToSpawnOn ) { char sBuildPointLL[64]; char sBuildPointUR[64]; Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint ); Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint ); pAttachmentNameLL = sBuildPointLL; pAttachmentNameUR = sBuildPointUR; } else { pEntityToSpawnOn = this; } } */ Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; weapon->GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; weapon->GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( false ); pScreen->MakeVisibleOnlyToTeammates( false ); #ifdef INVASION_DLL pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL ); #endif pScreen->SetAttachedToViewModel( true ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } #endif }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CPlantedC4::SpawnControlPanels() { char buf[64]; // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( true ); pScreen->MakeVisibleOnlyToTeammates( false ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } }