void WBActionEldRemoveBlock::TraceFromSourceEntity( WBEntity* const pSourceEntity ) const { if( !pSourceEntity ) { return; } WBCompEldTransform* const pTransform = pSourceEntity->GetTransformComponent<WBCompEldTransform>(); if( !pTransform ) { return; } // TODO: If I reuse this stuff a lot in weapons and powers, wrap it up. WBCompEldCamera* const pCamera = GET_WBCOMP( pSourceEntity, EldCamera ); EldritchWorld* const pWorld = EldritchFramework::GetInstance()->GetWorld(); ASSERT( pWorld ); Vector EyeLoc = pTransform->GetLocation(); Angles EyeRot = pTransform->GetOrientation(); if( pCamera ) { EyeLoc += pCamera->GetViewTranslationOffset( WBCompEldCamera::EVM_All ); EyeRot += pCamera->GetViewOrientationOffset( WBCompEldCamera::EVM_All ); } const Vector EyeDir = EyeRot.ToVector(); const Ray TraceRay( EyeLoc, EyeDir ); CollisionInfo Info; Info.m_CollideWorld = true; Info.m_CollideEntities = true; Info.m_CollidingEntity = pSourceEntity; Info.m_UserFlags = EECF_Trace; if( pWorld->Trace( TraceRay, Info ) ) { const Vector HitLoc = Info.m_Intersection - Info.m_Plane.m_Normal * 0.1f; pWorld->RemoveVoxelAt( HitLoc ); } }
void EldritchFramework::CreateMinimapView() { PRINTF("EldritchFramework::CreateMinimapView\n"); SafeDelete(m_MinimapView); STATICHASH(EldMinimap); STATICHASH(MinimapRTWidth); const float fMinimapRTWidth = ConfigManager::GetFloat(sMinimapRTWidth, 0.0f, sEldMinimap); STATICHASH(MinimapRTHeight); const float fMinimapRTHeight = ConfigManager::GetFloat(sMinimapRTHeight, 0.0f, sEldMinimap); STATICHASH(MinimapViewDistance); const float ViewDistance = ConfigManager::GetFloat(sMinimapViewDistance, 0.0f, sEldMinimap); STATICHASH(MinimapViewPitch); const float ViewPitch = DEGREES_TO_RADIANS( ConfigManager::GetFloat(sMinimapViewPitch, 0.0f, sEldMinimap)); STATICHASH(MinimapViewFOV); const float FOV = ConfigManager::GetFloat(sMinimapViewFOV, 0.0f, sEldMinimap); STATICHASH(MinimapViewNearClip); const float NearClip = ConfigManager::GetFloat(sMinimapViewNearClip, 0.0f, sEldMinimap); STATICHASH(MinimapViewFarClip); const float FarClip = ConfigManager::GetFloat(sMinimapViewFarClip, 0.0f, sEldMinimap); const Angles EyeOrientation = Angles(ViewPitch, 0.0f, 0.0f); const Vector EyeDirection = EyeOrientation.ToVector(); const Vector EyePosition = -EyeDirection * ViewDistance; const float AspectRatio = fMinimapRTWidth / fMinimapRTHeight; m_MinimapView = new View(EyePosition, EyeOrientation, FOV, AspectRatio, NearClip, FarClip); }
/*virtual*/ void WBActionEldCheckLine::Execute() { WBAction::Execute(); STATIC_HASHED_STRING( EventOwner ); WBEntity* const pEntity = GetEntity(); WBEntity* const pOwnerEntity = GetOwner(); EldritchWorld* const pWorld = EldritchFramework::GetInstance()->GetWorld(); WBEventManager* const pEventManager = WBWorld::GetInstance()->GetEventManager(); Vector LineStart; Angles LineOrientation; GetLineTransform( LineStart, LineOrientation ); const Vector LineDirection = LineOrientation.ToVector(); CollisionInfo Info; Info.m_CollideWorld = true; Info.m_CollideEntities = true; Info.m_CollidingEntity = pOwnerEntity; Info.m_UserFlags = EECF_Trace; if( m_LineLength > 0.0f ) { const Vector LineEnd = LineStart + LineDirection * m_LineLength; const Segment TraceSegment = Segment( LineStart, LineEnd ); if( !pWorld->Trace( TraceSegment, Info ) ) { return; } } else { const Ray TraceRay = Ray( LineStart, LineDirection ); if( !pWorld->Trace( TraceRay, Info ) ) { return; } } const Vector HitLocation = Info.m_Intersection; const Vector HitNormal = Info.m_Plane.m_Normal; // Notify this entity that the line check hit that entity. if( Info.m_HitEntity ) { WB_MAKE_EVENT( OnLineCheck, pEntity ); WB_SET_AUTO( OnLineCheck, Hash, CheckTag, m_CheckTag ); WB_SET_AUTO( OnLineCheck, Entity, Checked, static_cast<WBEntity*>( Info.m_HitEntity ) ); WB_SET_AUTO( OnLineCheck, Vector, LineDirection, LineDirection ); WB_SET_AUTO( OnLineCheck, Vector, HitLocation, HitLocation ); WB_SET_AUTO( OnLineCheck, Vector, HitNormal, HitNormal ); WB_DISPATCH_EVENT( pEventManager, OnLineCheck, pEntity ); } else { const Vector HalfHitNormal = 0.5f * Info.m_Plane.m_Normal; const Vector HitVoxel = pWorld->GetVoxelCenter( HitLocation - HalfHitNormal ); WB_MAKE_EVENT( OnLineCheckMissed, pEntity ); WB_SET_AUTO( OnLineCheckMissed, Hash, CheckTag, m_CheckTag ); WB_SET_AUTO( OnLineCheckMissed, Vector, LineDirection, LineDirection ); WB_SET_AUTO( OnLineCheckMissed, Vector, HitLocation, HitLocation ); WB_SET_AUTO( OnLineCheckMissed, Vector, HitNormal, HitNormal ); WB_SET_AUTO( OnLineCheckMissed, Vector, HitVoxel, HitVoxel ); WB_DISPATCH_EVENT( pEventManager, OnLineCheckMissed, pEntity ); } }
void WBCompEldWatson::TickPrimed() { if( !EldritchGame::IsPlayerAlive() ) { // Player can't cause Watson to teleport and attack when dead return; } if( !EldritchGame::IsPlayerVisible() ) { // Player can't cause Watson to teleport and attack when invisible return; } if( !IsPlayerVulnerable( true ) ) { // Do nothing, can't attack until player is vulnerable return; } WBEntity* const pEntity = GetEntity(); DEVASSERT( pEntity ); WBEntity* const pPlayer = EldritchGame::GetPlayer(); ASSERT( pPlayer ); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); WBCompEldTransform* const pPlayerTransform = pPlayer->GetTransformComponent<WBCompEldTransform>(); ASSERT( pPlayerTransform ); const Vector PlayerLocation = pPlayerTransform->GetLocation(); const Angles PlayerOrientation = pPlayerTransform->GetOrientation(); EldritchWorld* const pWorld = GetWorld(); ASSERT( pWorld ); const Angles PlayerOrientation2D = Angles( 0.0f, 0.0f, PlayerOrientation.Yaw ); const Vector PlayerFacing2D = PlayerOrientation2D.ToVector(); WBCompEldCollision* const pCollision = GET_WBCOMP( pEntity, EldCollision ); const Vector Extents = pCollision->GetExtents(); Vector TeleportLocation = PlayerLocation - ( PlayerFacing2D * m_TeleportDist ); CollisionInfo FindSpotInfo; FindSpotInfo.m_CollideWorld = true; FindSpotInfo.m_CollideEntities = true; FindSpotInfo.m_UserFlags = EECF_EntityCollision; FindSpotInfo.m_CollidingEntity = pEntity; if( pCollision->MatchesAllCollisionFlags( EECF_BlocksEntities ) ) { // HACK: Test against all entities, since Watson is a blocking entity. FindSpotInfo.m_UserFlags |= EECF_CollideAllEntities; } if( !pWorld->FindSpot( TeleportLocation, Extents, FindSpotInfo ) ) { // Do nothing, we don't fit behind player return; } const Vector NewToPlayer2D = ( PlayerLocation - TeleportLocation ).Get2D(); const Angles NewOrientation = NewToPlayer2D.ToAngles(); pTransform->SetLocation( TeleportLocation ); pTransform->SetOrientation( NewOrientation ); WB_MAKE_EVENT( OnWatsonTeleported, GetEntity() ); WB_DISPATCH_EVENT( GetEventManager(), OnWatsonTeleported, GetEntity() ); // Need to prime again before we can do another teleport m_Primed = false; }
bool WBCompEldWatson::IsPlayerVulnerable( const bool CheckMinDistance ) const { WBEntity* const pEntity = GetEntity(); DEVASSERT( pEntity ); WBEntity* const pPlayer = EldritchGame::GetPlayer(); ASSERT( pPlayer ); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); WBCompEldTransform* const pPlayerTransform = pPlayer->GetTransformComponent<WBCompEldTransform>(); ASSERT( pPlayerTransform ); const Vector EyeLocation = pTransform->GetLocation() + Vector( 0.0f, 0.0f, m_EyeOffsetZ ); const Vector PlayerLocation = pPlayerTransform->GetLocation(); const Vector PlayerViewLocation = EldritchGame::GetPlayerViewLocation(); const Vector ToPlayer = PlayerViewLocation - EyeLocation; const float DistanceSq = ToPlayer.LengthSquared(); if( CheckMinDistance && DistanceSq < m_MinAttackDistSq ) { // Do nothing, we're already close to player. return false; } if( DistanceSq > m_MaxAttackDistSq ) { // Do nothing, we're too far from the player return false; } // Do both a 3D and 2D check. 3D check is necessary so Watson doesn't teleport // when player is looking up or down at it, and 2D is necessary so Watson doesn't // teleport when player is looking up or down *away* from it. const Angles PlayerOrientation = pPlayerTransform->GetOrientation(); const Angles PlayerOrientation2D = Angles( 0.0f, 0.0f, PlayerOrientation.Yaw ); const Vector PlayerFacing = PlayerOrientation.ToVector(); const Vector PlayerFacing2D = PlayerOrientation2D.ToVector(); const Vector ToPlayer2D = ToPlayer.Get2D(); const float CosPlayerAngle = PlayerFacing.Dot( ToPlayer ); const float CosPlayerAngle2D = PlayerFacing2D.Dot( ToPlayer2D ); if( CosPlayerAngle < 0.0f || CosPlayerAngle2D < 0.0f ) { // Do nothing, player is facing us. return false; } EldritchWorld* const pWorld = GetWorld(); ASSERT( pWorld ); CollisionInfo OcclusionInfo; OcclusionInfo.m_CollideWorld = true; OcclusionInfo.m_CollideEntities = true; OcclusionInfo.m_UserFlags = EECF_Occlusion; OcclusionInfo.m_StopAtAnyCollision = true; if( pWorld->LineCheck( EyeLocation, PlayerViewLocation, OcclusionInfo ) ) { // Do nothing, player is occluded. return false; } return true; }