void CASW_Boomer_Blob::DoExplosion( ) { // scorch the ground trace_t tr; UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -80 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); if ( m_bMaster ) { if ( ( tr.m_pEnt != GetWorldEntity() ) || ( tr.hitbox != 0 ) ) { // non-world needs smaller decals if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) { UTIL_DecalTrace( &tr, "SmallScorch" ); } } else { UTIL_DecalTrace( &tr, "Scorch" ); } UTIL_ASW_ScreenShake( GetAbsOrigin(), 7.0f, 45.0f, 0.5f, 150, SHAKE_START ); } // explosion effects DispatchParticleEffect( "boomer_drop_explosion", GetAbsOrigin(), Vector( m_DmgRadius, 0.0f, 0.0f ), QAngle( 0.0f, 0.0f, 0.0f ) ); EmitSound( "ASW_Boomer_Grenade.Explode" ); // damage to nearby things ASWGameRules()->RadiusDamage( CTakeDamageInfo( this, m_hFirer.Get(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); }
QPixmap CCharactereGraphic::Draw() { CCharactereWorld* charWorld = static_cast<CCharactereWorld*> (GetWorldEntity()); if (charWorld->IsDead()) return QPixmap(); return _pixmap; }
CBaseEntity *GetEntityFromMouseCommand( int idx ) { if( idx == -1 || idx >= MAX_EDICTS ) return NULL; if( idx == 0 ) return GetWorldEntity(); return UTIL_EntityByIndex( idx ); }
//----------------------------------------------------------------------------- // Class factory methods //----------------------------------------------------------------------------- bool CSoundEnt::InitSoundEnt() { ///!!!LATER - do we want a sound ent in deathmatch? (sjb) g_pSoundEnt = (CSoundEnt*)CBaseEntity::Create( "soundent", vec3_origin, vec3_angle, GetWorldEntity() ); if ( !g_pSoundEnt ) { Warning( "**COULD NOT CREATE SOUNDENT**\n" ); return false; } g_pSoundEnt->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); return true; }
void CGrenadeAR2::Detonate(void) { if (!m_bIsLive) { return; } m_bIsLive = false; m_takedamage = DAMAGE_NO; if(m_hSmokeTrail) { UTIL_Remove(m_hSmokeTrail); m_hSmokeTrail = NULL; } CPASFilter filter( GetAbsOrigin() ); te->Explosion( filter, 0.0, &GetAbsOrigin(), g_sModelIndexFireball, 2.0, 15, TE_EXPLFLAG_NONE, m_DmgRadius, m_flDamage ); Vector vecForward = GetAbsVelocity(); VectorNormalize(vecForward); trace_t tr; UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) { // non-world needs smaller decals if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) { UTIL_DecalTrace( &tr, "SmallScorch" ); } } else { UTIL_DecalTrace( &tr, "Scorch" ); } UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); RadiusDamage ( CTakeDamageInfo( this, GetThrower(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); UTIL_Remove( this ); }
void CGrenadeMP5::Detonate(void) { if (!m_bIsLive) { return; } m_bIsLive = false; m_takedamage = DAMAGE_NO; CPASFilter filter( GetAbsOrigin() ); te->Explosion( filter, 0.0, &GetAbsOrigin(), GetWaterLevel() == 0 ? g_sModelIndexFireball : g_sModelIndexWExplosion, (m_flDamage - 50) * .60, 15, TE_EXPLFLAG_NONE, m_DmgRadius, m_flDamage ); trace_t tr; tr = CBaseEntity::GetTouchTrace(); if ( (tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0) ) { // non-world needs smaller decals UTIL_DecalTrace( &tr, "SmallScorch"); } else { UTIL_DecalTrace( &tr, "Scorch" ); } CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 ); RadiusDamage ( CTakeDamageInfo( this, GetThrower(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_flDamage * 2.5, CLASS_NONE, NULL ); CPASAttenuationFilter filter2( this ); EmitSound( filter2, entindex(), "GrenadeMP5.Detonate" ); if ( GetWaterLevel() == 0 ) { int sparkCount = random->RandomInt( 0,3 ); QAngle angles; VectorAngles( tr.plane.normal, angles ); for ( int i = 0; i < sparkCount; i++ ) Create( "spark_shower", GetAbsOrigin(), angles, NULL ); } UTIL_Remove( this ); }
Vector GetRandomSpot() { CWorld *pEnt = GetWorldEntity(); if ( pEnt ) { Vector vMin, vMax; pEnt->GetWorldBounds( vMin, vMax ); return Vector( RandomFloat( vMin.x, vMax.x ), RandomFloat( vMin.y, vMax.y ), RandomFloat( vMin.z, vMax.z ) ); } else { return Vector( 0, 0, 0 ); } }
void CASW_Barrel_Explosive::DoExplosion() { // scorch the ground trace_t tr; UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -80 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) { // non-world needs smaller decals if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) { UTIL_DecalTrace( &tr, "SmallScorch" ); } } else { UTIL_DecalTrace( &tr, "Scorch" ); } UTIL_ASW_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); // explosion effects Vector vecExplosionPos = GetAbsOrigin(); CPASFilter filter( vecExplosionPos ); UserMessageBegin( filter, "ASWBarrelExplosion" ); WRITE_FLOAT( vecExplosionPos.x ); WRITE_FLOAT( vecExplosionPos.y ); WRITE_FLOAT( vecExplosionPos.z ); WRITE_FLOAT( 160.0f ); MessageEnd(); EmitSound( "ASWBarrel.Explode" ); // damage to nearby things CTakeDamageInfo info( this, ( m_hAttacker.Get() ? m_hAttacker.Get() : this ), m_iExplosionDamage, DMG_BLAST ); info.SetDamageCustom( DAMAGE_FLAG_HALF_FALLOFF ); ASWGameRules()->RadiusDamage( info, GetAbsOrigin(), 160.0f, CLASS_NONE, NULL ); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMapData_Server::GetMapBounds( Vector &vecMins, Vector &vecMaxs ) { CWorld *pWorld = static_cast<CWorld*>( GetWorldEntity() ); if ( pWorld ) { // Get the world bounds. pWorld->GetWorldBounds( vecMins, vecMaxs ); // Backward compatability... if ( ( vecMins.LengthSqr() == 0.0f ) && ( vecMaxs.LengthSqr() == 0.0f ) ) { vecMins.Init( -6500.0f, -6500.0f, -6500.0f ); vecMaxs.Init( 6500.0f, 6500.0f, 6500.0f ); } } else { Assert( 0 ); vecMins.Init( 0.0f, 0.0f, 0.0f ); vecMaxs.Init( 1.0f, 1.0f, 1.0f ); } }
void CASW_Laser_Mine::Explode( bool bRemove ) { // scorch the ground trace_t tr; UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -80 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) { // non-world needs smaller decals if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) { UTIL_DecalTrace( &tr, "SmallScorch" ); } } else { UTIL_DecalTrace( &tr, "Scorch" ); } UTIL_ASW_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); UTIL_ASW_GrenadeExplosion( GetAbsOrigin(), m_flDamageRadius ); EmitSound( "ASW_Laser_Mine.Explode" ); // damage to nearby things CTakeDamageInfo info( this, GetOwnerEntity(), m_flDamage, DMG_BLAST ); info.SetWeapon( m_hCreatorWeapon ); ASWGameRules()->RadiusDamage( info, GetAbsOrigin(), m_flDamageRadius, CLASS_NONE, NULL ); if ( bRemove ) { UTIL_Remove( this ); } }
float CalculateObjectStress( IPhysicsObject *pObject, CBaseEntity *pInputOwnerEntity, vphysics_objectstress_t *pOutput ) { CUtlVector< CBaseEntity * > pObjectList; CUtlVector< Vector > objectForce; bool hasLargeObject = false; // add a slot for static objects pObjectList.AddToTail( NULL ); objectForce.AddToTail( vec3_origin ); // add a slot for friendly objects pObjectList.AddToTail( NULL ); objectForce.AddToTail( vec3_origin ); CBaseCombatCharacter *pBCC = pInputOwnerEntity->MyCombatCharacterPointer(); IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); float objMass = pObject->GetMass(); while ( pSnapshot->IsValid() ) { float force = pSnapshot->GetNormalForce(); if ( force > 0.0f ) { IPhysicsObject *pOther = pSnapshot->GetObject(1); CBaseEntity *pOtherEntity = static_cast<CBaseEntity *>(pOther->GetGameData()); if ( !pOtherEntity ) { // object was just deleted, but we still have a contact point this frame... // just assume it came from the world. pOtherEntity = GetWorldEntity(); } CBaseEntity *pOtherOwner = pOtherEntity; if ( pOtherEntity->GetOwnerEntity() ) { pOtherOwner = pOtherEntity->GetOwnerEntity(); } int outIndex = 0; if ( !pOther->IsMoveable() ) { outIndex = 0; } // NavIgnored objects are often being pushed by a friendly else if ( pBCC && (pBCC->IRelationType( pOtherOwner ) == D_LI || pOtherEntity->IsNavIgnored()) ) { outIndex = 1; } // player held objects do no stress else if ( pOther->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) { outIndex = 1; } else { if ( pOther->GetMass() >= VPHYSICS_LARGE_OBJECT_MASS ) { if ( pInputOwnerEntity->GetGroundEntity() != pOtherEntity) { hasLargeObject = true; } } // moveable, non-friendly // aggregate contacts over each object to avoid greater stress in multiple contact cases // NOTE: Contacts should be in order, so this shouldn't ever search, but just in case outIndex = pObjectList.Count(); for ( int i = pObjectList.Count()-1; i >= 2; --i ) { if ( pObjectList[i] == pOtherOwner ) { outIndex = i; break; } } if ( outIndex == pObjectList.Count() ) { pObjectList.AddToTail( pOtherOwner ); objectForce.AddToTail( vec3_origin ); } } if ( outIndex != 0 && pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && !IsPhysicallyControlled(pOtherEntity, pOther) ) { // UNDONE: Test this! This is to remove any shadow/shadow stress. The game should handle this with blocked/damage force = 0.0f; } Vector normal; pSnapshot->GetSurfaceNormal( normal ); objectForce[outIndex] += normal * force; } pSnapshot->NextFrictionData(); } pObject->DestroyFrictionSnapshot( pSnapshot ); pSnapshot = NULL; // clear out all friendly force objectForce[1].Init(); float sum = 0; Vector negativeForce = vec3_origin; Vector positiveForce = vec3_origin; Assert( pObjectList.Count() == objectForce.Count() ); for ( int objectIndex = pObjectList.Count()-1; objectIndex >= 0; --objectIndex ) { sum += objectForce[objectIndex].Length(); for ( int i = 0; i < 3; i++ ) { if ( objectForce[objectIndex][i] < 0 ) { negativeForce[i] -= objectForce[objectIndex][i]; } else { positiveForce[i] += objectForce[objectIndex][i]; } } } // "external" stress is two way (something pushes on the object and something else pushes back) // so the set of minimum values per component are the projections of the two-way force // "internal" stress is one way (the object is pushing against something OR something pushing back) // the momentum must have come from inside the object (gravity, controller, etc) Vector internalForce = vec3_origin; Vector externalForce = vec3_origin; for ( int i = 0; i < 3; i++ ) { if ( negativeForce[i] < positiveForce[i] ) { internalForce[i] = positiveForce[i] - negativeForce[i]; externalForce[i] = negativeForce[i]; } else { internalForce[i] = negativeForce[i] - positiveForce[i]; externalForce[i] = positiveForce[i]; } } // sum is kg in / s Vector gravVector; physenv->GetGravity( &gravVector ); float gravity = gravVector.Length(); if ( pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && pObject->IsMoveable() ) { Vector lastVel; lastVel.Init(); if ( pObject->GetShadowController() ) { pObject->GetShadowController()->GetLastImpulse( &lastVel ); } else { if ( ( pObject->GetCallbackFlags() & CALLBACK_IS_PLAYER_CONTROLLER ) ) { CBasePlayer *pPlayer = ToBasePlayer( pInputOwnerEntity ); IPhysicsPlayerController *pController = pPlayer ? pPlayer->GetPhysicsController() : NULL; if ( pController ) { pController->GetLastImpulse( &lastVel ); } } } // Work in progress... // Peek into the controller for this object. Look at the input velocity and make sure it's all // accounted for in the computed stress. If not, redistribute external to internal as it's // probably being reflected in a way we can't measure here. float inputLen = lastVel.Length() * (1.0f / physenv->GetSimulationTimestep()) * objMass; if ( inputLen > 0.0f ) { float internalLen = internalForce.Length(); if ( internalLen < inputLen ) { float ratio = internalLen / inputLen; Vector delta = internalForce * (1.0f - ratio); internalForce += delta; float deltaLen = delta.Length(); sum -= deltaLen; float extLen = VectorNormalize(externalForce) - deltaLen; if ( extLen < 0 ) { extLen = 0; } externalForce *= extLen; } } } float invGravity = gravity; if ( invGravity <= 0 ) { invGravity = 1.0f; } else { invGravity = 1.0f / invGravity; } sum *= invGravity; internalForce *= invGravity; externalForce *= invGravity; if ( !pObject->IsMoveable() ) { // the above algorithm will see almost all force as internal if the object is not moveable // (it doesn't push on anything else, so nothing is reciprocated) // exceptions for friction of a single other object with multiple contact points on this object // But the game wants to see it all as external because obviously the object can't move, so it can't have // internal stress externalForce = internalForce; internalForce.Init(); if ( !pObject->IsStatic() ) { sum += objMass; } } else { // assume object is at rest if ( sum > objMass ) { sum = objMass + (sum-objMass) * 0.5; } } if ( pOutput ) { pOutput->exertedStress = internalForce.Length(); pOutput->receivedStress = externalForce.Length(); pOutput->hasNonStaticStress = pObjectList.Count() > 2 ? true : false; pOutput->hasLargeObjectContact = hasLargeObject; } // sum is now kg return sum; }
//----------------------------------------------------------------------------- // Purpose: Input handler for showing the message and/or playing the sound. //----------------------------------------------------------------------------- void CEnvInstructorHint::InputShowHint( inputdata_t &inputdata ) { static int s_InstructorServerHintEventCreate = 0; IGameEvent * event = gameeventmanager->CreateEvent( "instructor_server_hint_create", false, &s_InstructorServerHintEventCreate ); if ( event ) { CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, m_iszHintTargetEntity ); if( pTargetEntity == NULL && !m_bStatic ) pTargetEntity = inputdata.pActivator; if( pTargetEntity == NULL ) pTargetEntity = GetWorldEntity(); char szColorString[128]; Q_snprintf( szColorString, sizeof( szColorString ), "%.3d,%.3d,%.3d", m_Color.r, m_Color.g, m_Color.b ); int iFlags = 0; iFlags |= (m_iPulseOption == 0) ? 0 : (LOCATOR_ICON_FX_PULSE_SLOW << (m_iPulseOption - 1)); iFlags |= (m_iAlphaOption == 0) ? 0 : (LOCATOR_ICON_FX_ALPHA_SLOW << (m_iAlphaOption - 1)); iFlags |= (m_iShakeOption == 0) ? 0 : (LOCATOR_ICON_FX_SHAKE_NARROW << (m_iShakeOption - 1)); iFlags |= m_bStatic ? LOCATOR_ICON_FX_STATIC : 0; CBasePlayer *pActivator = NULL; bool bFilterByActivator = m_bLocalPlayerOnly; #ifdef INFESTED_DLL CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>( inputdata.pActivator ); if ( pMarine ) { pActivator = pMarine->GetCommander(); } #else if ( inputdata.value.StringID() != NULL_STRING ) { CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.String() ); pActivator = dynamic_cast<CBasePlayer*>( pTarget ); if ( pActivator ) { bFilterByActivator = true; } } else { if ( GameRules()->IsMultiplayer() == false ) { pActivator = UTIL_GetLocalPlayer(); } else { Warning( "Failed to play server side instructor hint: no player specified for hint\n" ); Assert( 0 ); } } #endif const char *pActivatorCaption = m_iszActivatorCaption.ToCStr(); if ( !pActivatorCaption || pActivatorCaption[ 0 ] == '\0' ) { pActivatorCaption = m_iszCaption.ToCStr(); } event->SetString( "hint_name", GetEntityName().ToCStr() ); event->SetString( "hint_replace_key", m_iszReplace_Key.ToCStr() ); event->SetInt( "hint_target", pTargetEntity->entindex() ); event->SetInt( "hint_activator_userid", ( pActivator ? pActivator->GetUserID() : 0 ) ); event->SetInt( "hint_timeout", m_iTimeout ); event->SetString( "hint_icon_onscreen", m_iszIcon_Onscreen.ToCStr() ); event->SetString( "hint_icon_offscreen", m_iszIcon_Offscreen.ToCStr() ); event->SetString( "hint_caption", m_iszCaption.ToCStr() ); event->SetString( "hint_activator_caption", pActivatorCaption ); event->SetString( "hint_color", szColorString ); event->SetFloat( "hint_icon_offset", m_fIconOffset ); event->SetFloat( "hint_range", m_fRange ); event->SetInt( "hint_flags", iFlags ); event->SetString( "hint_binding", m_iszBinding.ToCStr() ); event->SetBool( "hint_allow_nodraw_target", m_bAllowNoDrawTarget ); event->SetBool( "hint_nooffscreen", m_bNoOffscreen ); event->SetBool( "hint_forcecaption", m_bForceCaption ); event->SetBool( "hint_local_player_only", bFilterByActivator ); gameeventmanager->FireEvent( event ); } }
bp::object PyGetWorldEntity() { return GetWorldEntity()->GetPyHandle(); }
void CASW_Grenade_PRifle::Detonate() { if ( !ASWGameResource() ) return; m_takedamage = DAMAGE_NO; CPASFilter filter( GetAbsOrigin() ); Vector vecForward = GetAbsVelocity(); VectorNormalize(vecForward); trace_t tr; Vector vecDir = -vecForward; //te->GaussExplosion( filter, 0.0, //GetAbsOrigin(), vecDir, 0 ); CEffectData data; data.m_vOrigin = GetAbsOrigin(); DispatchEffect( "aswstunexplo", data ); EmitSound("ASW_Weapon_PRifle.StunGrenadeExplosion"); UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) { // non-world needs smaller decals if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) { UTIL_DecalTrace( &tr, "SmallScorch" ); } } else { UTIL_DecalTrace( &tr, "Scorch" ); } UTIL_ASW_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); int nPreviousStunnedAliens = ASWGameResource()->m_iElectroStunnedAliens; // do just 1 damage... CTakeDamageInfo info( this, GetOwnerEntity(), 1, DMG_SHOCK ); info.SetWeapon( m_hCreatorWeapon ); RadiusDamage ( info , GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); // count as a shot fired CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(GetOwnerEntity()); if ( pMarine && pMarine->GetMarineResource() ) { CASW_Marine_Resource *pMR = pMarine->GetMarineResource(); pMR->UsedWeapon(NULL, 1); int nAliensStunned = ASWGameResource()->m_iElectroStunnedAliens - nPreviousStunnedAliens; if ( nAliensStunned >= 6 && pMR->IsInhabited() && pMR->GetCommander() ) { pMR->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_STUN_GRENADE ); pMR->m_bStunGrenadeMedal = true; } } UTIL_Remove( this ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CObjectResupply::CalculatePlacement( CBaseTFPlayer *pPlayer ) { trace_t tr; Vector vecAiming; // Get an aim vector. Don't use GetAimVector() because we don't want autoaiming. Vector vecSrc = pPlayer->Weapon_ShootPosition( ); pPlayer->EyeVectors( &vecAiming ); Vector vecTarget; VectorMA( vecSrc, 90, vecAiming, vecTarget ); m_vecBuildOrigin = vecTarget; // Angle it towards me Vector vecForward = pPlayer->WorldSpaceCenter() - m_vecBuildOrigin; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Is there something to attach to? // Use my bounding box, not the build box, so I fit to the wall UTIL_TraceLine( vecSrc, vecTarget, MASK_SOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr); //UTIL_TraceHull( vecSrc, vecTarget, WorldAlignMins(), WorldAlignMaxs(), MASK_SOLID, pPlayer, TFCOLLISION_GROUP_OBJECT, &tr ); m_vecBuildOrigin = tr.endpos; bool bTryToPlaceGroundVersion = false; if ( tr.allsolid || (tr.fraction == 1.0) ) { bTryToPlaceGroundVersion = true; } else { // Make sure we're planting on the world CBaseEntity *pEntity = tr.m_pEnt; if ( pEntity != GetWorldEntity() ) { bTryToPlaceGroundVersion = true; } } // Make sure the wall we've touched is vertical if ( !bTryToPlaceGroundVersion && fabs(tr.plane.normal.z) > 0.3 ) { bTryToPlaceGroundVersion = true; } // Aborting? if ( bTryToPlaceGroundVersion ) { // We couldn't find a wall, so try and place a ground version instead if ( GetTeamNumber() == TEAM_HUMANS ) { SetModel( RESUPPLY_GROUND_MODEL_HUMAN ); } else { SetModel( RESUPPLY_GROUND_MODEL ); } UTIL_SetSize(this, RESUPPLY_GROUND_MINS, RESUPPLY_GROUND_MAXS); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); return BaseClass::CalculatePlacement( pPlayer ); } SetupAttachedVersion(); m_vecBuildMins = WorldAlignMins() - Vector( 4,4,0 ); m_vecBuildMaxs = WorldAlignMaxs() + Vector( 4,4,0 ); // Set the angles vecForward = tr.plane.normal; SetLocalAngles( QAngle( 0, UTIL_VecToYaw( vecForward ), 0 ) ); // Trace back from the corners Vector vecMins, vecMaxs, vecModelMins, vecModelMaxs; const model_t *pModel = GetModel(); modelinfo->GetModelBounds( pModel, vecModelMins, vecModelMaxs ); // Check the four build points Vector vecPointCheck = (vecForward * 32); Vector vecUp = Vector(0,0,1); Vector vecRight; CrossProduct( vecUp, vecForward, vecRight ); float flWidth = fabs(vecModelMaxs.y - vecModelMins.y) * 0.5; float flHeight = fabs(vecModelMaxs.z - vecModelMins.z) * 0.5; bool bResult = true; if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin + (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) + (vecUp * flHeight), vecPointCheck ); } if ( bResult ) { bResult = CheckBuildPoint( m_vecBuildOrigin - (vecRight * flWidth) - (vecUp * flHeight), vecPointCheck ); } AttemptToFindPower(); return bResult; }