/*virtual*/ void WBCompEldSensorMarkup::PollTick(const float DeltaTime) const { Unused(DeltaTime); const Array<WBCompEldMarkup*>* pMarkupComponents = WBComponentArrays::GetComponents<WBCompEldMarkup>(); if (!pMarkupComponents) { return; } WBEntity* const pEntity = GetEntity(); DEVASSERT(pEntity); WBCompRodinKnowledge* const pKnowledge = GET_WBCOMP(pEntity, RodinKnowledge); ASSERT(pKnowledge); WBCompEldTransform* const pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); const Vector CurrentLocation = pTransform->GetLocation(); const float RadiusSq = Square(m_Radius); const uint NumMarkups = pMarkupComponents->Size(); for (uint MarkupIndex = 0; MarkupIndex < NumMarkups; ++MarkupIndex) { WBCompEldMarkup* const pMarkup = (*pMarkupComponents)[MarkupIndex]; ASSERT(pMarkup); // Only consider the desired type of markup if (pMarkup->GetMarkup() != m_Markup) { continue; } WBEntity* const pMarkupEntity = pMarkup->GetEntity(); ASSERT(pMarkupEntity); WBCompEldTransform* const pMarkupTransform = pMarkupEntity->GetTransformComponent<WBCompEldTransform>(); // Distance check const float DistanceSq = (pMarkupTransform->GetLocation() - CurrentLocation).LengthSquared(); if (DistanceSq > RadiusSq) { continue; } // Update knowledge with this patrol WBCompRodinKnowledge::TKnowledge& Knowledge = pKnowledge->UpdateEntity(pMarkupEntity); STATIC_HASHED_STRING(DistanceSq); Knowledge.SetFloat(sDistanceSq, DistanceSq); STATIC_HASHED_STRING(LastKnownLocation); Knowledge.SetVector(sLastKnownLocation, pMarkupTransform->GetLocation()); ASSERT(!pMarkupTransform->GetLocation().IsZero()); STATIC_HASHED_STRING(KnowledgeType); Knowledge.SetHash(sKnowledgeType, m_Markup); } }
void WBCompEldAnchor::SetAnchor() { EldritchWorld* const pWorld = GetWorld(); ASSERT( pWorld ); WBEntity* const pEntity = GetEntity(); DEVASSERT( pEntity ); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); const Angles Orientation = pTransform->GetOrientation(); const Matrix RotationMatrix = Orientation.ToMatrix(); const Vector AnchorVector = m_AnchorDirection * RotationMatrix; const Vector StartLocation = pTransform->GetLocation(); const Ray TraceRay = Ray( StartLocation, AnchorVector ); CollisionInfo Info; Info.m_CollideWorld = true; Info.m_CollideEntities = true; Info.m_CollidingEntity = pEntity; Info.m_UserFlags = EECF_CollideAsEntity | EECF_CollideStaticEntities; if( pWorld->Trace( TraceRay, Info ) ) { m_AnchorPoint = Info.m_Intersection + AnchorVector * 0.1f; ASSERT( pWorld->PointCheck( m_AnchorPoint, Info ) ); // Since hard-coded 0.1 might break for thin surfaces. m_IsAnchored = true; } }
void Mesh::CopyAnimationsFrom(Mesh* const pMesh) { DEVASSERT(pMesh); DEVASSERT(pMesh->m_Bones); if (m_Bones != pMesh->m_Bones) { SafeRelease(m_Bones); m_Bones = pMesh->m_Bones; m_Bones->AddReference(); } }
/*virtual*/ void WBCompEldThinkerPatrol::Tick(float DeltaTime) { XTRACE_FUNCTION; Unused(DeltaTime); WBEntity* const pEntity = GetEntity(); DEVASSERT(pEntity); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); WBCompRodinKnowledge* const pKnowledge = GET_WBCOMP(pEntity, RodinKnowledge); ASSERT(pKnowledge); WBCompRodinBlackboard* const pBlackboard = GET_WBCOMP(pEntity, RodinBlackboard); ASSERT(pBlackboard); const Vector CurrentLocation = pTransform->GetLocation(); // Select the furthest patrol point that we know about. WBEntity* pFurthestPatrol = nullptr; float FurthestDistSq = -1.0f; const WBCompRodinKnowledge::TKnowledgeMap& KnowledgeMap = pKnowledge->GetKnowledgeMap(); FOR_EACH_MAP(KnowledgeIter, KnowledgeMap, WBEntityRef, WBCompRodinKnowledge::TKnowledge) { WBEntity* pKnowledgeEntity = KnowledgeIter.GetKey().Get(); const WBCompRodinKnowledge::TKnowledge& Knowledge = KnowledgeIter.GetValue(); if (!pKnowledgeEntity) { continue; } // Filter out knowledge entities that aren't patrol markup. STATIC_HASHED_STRING(KnowledgeType); STATIC_HASHED_STRING(Patrol); if (Knowledge.GetHash(sKnowledgeType) != sPatrol) { continue; } WBCompEldTransform* const pKnowledgeTransform = pKnowledgeEntity->GetTransformComponent<WBCompEldTransform>(); ASSERT(pKnowledgeTransform); const float DistSq = (pKnowledgeTransform->GetLocation() - CurrentLocation).LengthSquared(); if (DistSq > FurthestDistSq) { FurthestDistSq = DistSq; pFurthestPatrol = pKnowledgeEntity; } }
/*virtual*/ void WBActionEldDamageWorld::Execute() { WBAction::Execute(); STATIC_HASHED_STRING( EventOwner ); WBEntity* const pEntity = WBActionStack::Top().GetEntity( sEventOwner ); DEVASSERT( pEntity ); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); EldritchWorld* const pWorld = EldritchFramework::GetInstance()->GetWorld(); ASSERT( pWorld ); pWorld->RemoveVoxelsAt( pTransform->GetLocation(), m_Radius ); }
void AnimEventEldExecuteAction::Call( Mesh* pMesh, Animation* pAnimation ) { Unused( pMesh ); Unused( pAnimation ); EldritchMesh* const pEldritchMesh = static_cast<EldritchMesh*>( pMesh ); WBEntity* const pEntity = WBCompOwner::GetTopmostOwner( pEldritchMesh->GetEntity() ); DEVASSERT( pEntity ); WBEvent OnAnimEventEvent; STATIC_HASHED_STRING( OnAnimEvent ); OnAnimEventEvent.SetEventName( sOnAnimEvent ); pEntity->AddContextToEvent( OnAnimEventEvent ); const uint NumActions = m_Actions.Size(); for( uint ActionIndex = 0; ActionIndex < NumActions; ++ActionIndex ) { WBAction* const pAction = m_Actions[ ActionIndex ]; ASSERT( pAction ); WBActionStack::Push( OnAnimEventEvent ); pAction->Execute(); WBActionStack::Pop(); } }
/*virtual*/ void WBCompEldMesh::Tick(float DeltaTime) { XTRACE_FUNCTION; UpdateMesh(DeltaTime); // Add pseudo root motion. Hack from Couriers. if (m_Mesh && m_Mesh->IsAnimated()) { Vector AnimationVelocity; Angles AnimationRotationalVelocity; GetAnimationVelocity(AnimationVelocity, AnimationRotationalVelocity); if (AnimationVelocity.LengthSquared() > 0.0f || !AnimationRotationalVelocity.IsZero()) { WBCompEldTransform* pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); // Kill velocity in direction of movement. if (AnimationVelocity.LengthSquared() > 0.0f) { Plane MovementPlane(AnimationVelocity.GetNormalized(), 0.0f); pTransform->SetVelocity( MovementPlane.ProjectVector(pTransform->GetVelocity())); } pTransform->ApplyImpulse(AnimationVelocity); pTransform->ApplyRotationalImpulse(AnimationRotationalVelocity); } } }
void WBCompEldPickup::GiveItemTo(WBEntity* const pEntity) const { // Because Pickup is now unfortunately doubling as a Purchaseable. // This is such a hack. // TODO: Make a separate Purchaseable component. if (m_GiveItemDef == "") { // OnObtained is fired whether purchased, stolen, or given WB_MAKE_EVENT(OnObtained, GetEntity()); WB_SET_AUTO(OnObtained, Entity, Buyer, pEntity); WB_DISPATCH_EVENT(GetEventManager(), OnObtained, GetEntity()); return; } DEVASSERT(pEntity); WBCompEldInventory* const pInventory = GET_WBCOMP(pEntity, EldInventory); ASSERT(pInventory); WBEntity* const pGivenEntity = WBWorld::GetInstance()->CreateEntity(m_GiveItemDef); ASSERT(pGivenEntity); pInventory->AddItem(pGivenEntity); WB_MAKE_EVENT(OnItemGiven, GetEntity()); WB_SET_AUTO(OnItemGiven, Entity, GivenTo, pEntity); WB_DISPATCH_EVENT(GetEventManager(), OnItemGiven, GetEntity()); GetEntity()->Destroy(); }
void Mesh::AddAnimationListener(const SAnimationListener& AnimationListener) { DEVASSERT(IsAnimated()); if (IsAnimated()) { m_AnimationState.AddAnimationListener(AnimationListener); } }
void AnimationState::Tick(float DeltaTime) { SAnimationLayer* pLayer = GetAnimationLayer(); DEVASSERT(pLayer); if (!pLayer->m_Animation) { return; } const float OldTime = pLayer->m_Time; const float LayerDeltaTime = DeltaTime * pLayer->m_PlayRate; if (pLayer->m_EndBehavior == EAEB_Stop && !pLayer->m_Stopped) { pLayer->m_Time += LayerDeltaTime; const float NonLoopingLength = pLayer->m_Animation->GetNonLoopingLengthSeconds(); if (pLayer->m_Time >= NonLoopingLength) { pLayer->m_Stopped = true; pLayer->m_Time = NonLoopingLength; // Notify any listeners that the animation has finished FOR_EACH_LIST(NotifyIter, m_AnimationListeners, SAnimationListener) { SAnimationListener& AnimationListener = *NotifyIter; if (AnimationListener.m_NotifyFinishedFunc) { AnimationListener.m_NotifyFinishedFunc( AnimationListener.m_Void, m_Mesh, pLayer->m_Animation, false); } }
WBEntity* WBScene::GetFirstEntityByComponent( const HashedString& ComponentName ) const { WBEntity* RetVal = NULL; BEGIN_ITERATING_ENTITIES; FOR_EACH_MAP( EntityIter, m_Entities, uint, SEntityRef ) { const SEntityRef& EntityRef = EntityIter.GetValue(); WBEntity* const pEntity = EntityRef.m_Entity; DEVASSERT( pEntity ); if( EntityRef.m_Removed || pEntity->IsDestroyed() ) { continue; } if( pEntity->GetComponent( ComponentName ) ) { RetVal = pEntity; break; } } END_ITERATING_ENTITIES; return RetVal; }
void WBScene::Tick() { PROFILE_FUNCTION; // Delete any destroyed entities this scene owns BEGIN_ITERATING_ENTITIES; FOR_EACH_MAP( EntityIter, m_Entities, uint, SEntityRef ) { const SEntityRef& EntityRef = EntityIter.GetValue(); WBEntity* const pEntity = EntityRef.m_Entity; DEVASSERT( pEntity ); if( !EntityRef.m_Removed && pEntity->IsDestroyed() ) { SafeDeleteNoNull( pEntity ); } } END_ITERATING_ENTITIES; // Deferred removal of entities for( uint HandleIndex = 0; HandleIndex < m_DeferredRemoveHandles.Size(); ++HandleIndex ) { const uint Handle = m_DeferredRemoveHandles[ HandleIndex ]; RemoveEntity( Handle ); } m_DeferredRemoveHandles.Clear(); }
void WBScene::GetEntitiesByRadius(Array<WBEntity*>& OutEntities, const Vector& Location, const float Radius) const { const float RadiusSquared = Square(Radius); BEGIN_ITERATING_ENTITIES; FOR_EACH_MAP(EntityIter, m_Entities, uint, SEntityRef) { const SEntityRef& EntityRef = EntityIter.GetValue(); WBEntity* const pEntity = EntityRef.m_Entity; DEVASSERT(pEntity); if (EntityRef.m_Removed || pEntity->IsDestroyed()) { continue; } WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); if (!pTransform) { continue; } const Vector Offset = Location - pTransform->GetLocation(); if (Offset.LengthSquared() <= RadiusSquared) { OutEntities.PushBack(pEntity); } } END_ITERATING_ENTITIES; }
void Mesh::StopAnimation() { DEVASSERT(IsAnimated()); if (IsAnimated()) { m_AnimationState.StopAnimation(); } }
void WBCompEldSensorTheft::HandleTheft(WBEntity* const pThief) const { WBCompEldTransform* const pTransform = pThief->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); WBCompRodinKnowledge* const pKnowledge = GET_WBCOMP(GetEntity(), RodinKnowledge); ASSERT(pKnowledge); WBCompRodinKnowledge::TKnowledge& Knowledge = pKnowledge->UpdateEntity(pThief); STATIC_HASHED_STRING(NeverExpire); Knowledge.SetBool(sNeverExpire, true); STATIC_HASHED_STRING(RegardAsHostile); Knowledge.SetBool(sRegardAsHostile, true); STATIC_HASHED_STRING(LastKnownLocation); Knowledge.SetVector(sLastKnownLocation, pTransform->GetLocation()); ASSERT(!pTransform->GetLocation().IsZero()); STATIC_HASHED_STRING(KnowledgeType); STATIC_HASHED_STRING(Target); Knowledge.SetHash(sKnowledgeType, sTarget); }
/*virtual*/ void SoundInstanceCommon::Tick3D() { DEBUGASSERT(GetSound()->GetIs3D()); const Sound3DListener* const pListener = Get3DListener(); DEVASSERT(pListener); Vector DirectionToSound; float DistanceToSound; float OneOverDistanceToSound; const Vector SoundLocation = GetLocation(); const Vector OffsetToSound = SoundLocation - pListener->GetLocation(); OffsetToSound.GetNormalized(DirectionToSound, DistanceToSound, OneOverDistanceToSound); const float FalloffRadius = m_Sound->GetFalloffDistance(); const float MinimumAttenuation = m_Sound->GetMinimumAttenuation(); DEVASSERT(FalloffRadius > 0.0f); // Set pan based on distance and direction. const float PanBias = m_Sound->GetBiasedPan(DistanceToSound); const float PanCosTheta = pListener->GetRight().Dot(DirectionToSound); // This is a little bit of fakery; further attenuate sounds behind the // listener. const float Surround = pListener->GetForward().Dot(DirectionToSound); float RearAttenuation = Saturate((-Surround * PanBias)); RearAttenuation = 1.0f - (RearAttenuation * m_Sound->GetRearAttenuation()); // Set attenuation based on distance and rear attenuation m_Attenuation = FalloffRadius / (FalloffRadius + DistanceToSound); m_Attenuation *= RearAttenuation; if (m_Attenuation >= MinimumAttenuation) { pListener->ModifyAttenuation(this, m_Attenuation); } if (m_Attenuation < MinimumAttenuation) { m_Attenuation = 0.0f; } else { // Don't bother setting the pan unless we'll hear it! const float PanPow = SignedPow(PanCosTheta, m_Sound->GetPanPower()); const float Pan = PanPow * PanBias; SetPan(Pan); } }
AABB WBCompEldFrobbable::GetBound() const { WBCompEldTransform* const pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); return AABB::CreateFromCenterAndExtents( pTransform->GetLocation() + m_BoundOffset, m_BoundExtents); }
Animation* Mesh::GetAnimation(const SimpleString& Name) const { DEVASSERT(IsAnimated()); if (IsAnimated()) { return m_Bones->GetAnimation(Name); } return nullptr; }
/*virtual*/ void WBCompEldSensorVision::DebugRender() const { WBCompEldTransform* const pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); const Vector EyeLocation = pTransform->GetLocation() + Vector( 0.0f, 0.0f, m_EyeOffsetZ ); GetFramework()->GetRenderer()->DEBUGDrawCross( EyeLocation, 0.5f, ARGB_TO_COLOR( 255, 255, 0, 0 ) ); }
Mesh* RendererCommon::Print(const SimpleString& UTF8String, const Font* const pFont, const SRect& Bounds, unsigned int Flags) { DEVASSERT(pFont); Mesh* StringMesh = pFont->Print(UTF8String, Bounds, Flags); StringMesh->SetMaterialFlags(MAT_HUD); StringMesh->SetMaterialDefinition("Material_HUD", this); return StringMesh; }
const Animation* Mesh::GetPlayingAnimation() const { DEVASSERT(IsAnimated()); if (IsAnimated()) { return m_AnimationState.GetPlayingAnimation(); } else { return nullptr; } }
void WBCompEldPickup::AcceptPaymentFrom(WBEntity* const pEntity) const { DEVASSERT(pEntity); WBCompEldWallet* const pWallet = GET_WBCOMP(pEntity, EldWallet); ASSERT(pWallet); ASSERT(pWallet->GetMoney() >= m_Price); pWallet->RemoveMoney(m_Price); }
/*static*/ Vector EldritchGame::GetPlayerLocation() { WBEntity* const pPlayer = GetPlayer(); ASSERT( pPlayer ); WBCompEldTransform* const pTransform = pPlayer->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); return pTransform->GetLocation(); }
void Mesh::SetAnimation(int AnimationIndex, AnimationState::SPlayAnimationParams& PlayParams) { DEVASSERT(IsAnimated()); if (IsAnimated()) { PlayParams.m_SuppressAnimEvents = true; m_AnimationState.PlayAnimation(m_Bones->GetAnimation(AnimationIndex), PlayParams); } }
void Mesh::PlayAnimation(const HashedString& AnimationName, AnimationState::SPlayAnimationParams& PlayParams) { DEVASSERT(IsAnimated()); if (IsAnimated()) { PlayParams.m_SuppressAnimEvents = false; m_AnimationState.PlayAnimation(m_Bones->GetAnimation(AnimationName), PlayParams); } }
/*virtual*/ void WBCompEldFrobbable::DebugRender() const { WBCompEldTransform* const pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); const Vector Location = pTransform->GetLocation() + m_BoundOffset; GetFramework()->GetRenderer()->DEBUGDrawBox(Location - m_BoundExtents, Location + m_BoundExtents, ARGB_TO_COLOR(255, 255, 128, 0)); }
// This is a bit hackity. Maybe consider a better way, but I'm deep in other AI // stuff now. Vector WBCompEldVisible::GetVisibleLocation() const { WBEntity* const pEntity = GetEntity(); DEVASSERT(pEntity); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); Vector VisibleLocation = pTransform->GetLocation(); WBCompEldCamera* const pCamera = GET_WBCOMP(pEntity, EldCamera); if (pCamera) { // *Don't* trace to lean location. VisibleLocation += pCamera->GetViewTranslationOffset(WBCompEldCamera::EVM_OffsetZ); } return VisibleLocation; }
void WBCompEldMesh::GetAnimationVelocity(Vector& OutVelocity, Angles& OutRotationalVelocity) { ASSERT(m_Mesh); WBCompEldTransform* pTransform = GetEntity()->GetTransformComponent<WBCompEldTransform>(); DEVASSERT(pTransform); m_Mesh->GetAnimationVelocity(OutVelocity, OutRotationalVelocity); OutVelocity = OutVelocity.RotateBy(pTransform->GetOrientation()); }
// Copied from WBActionEldSpawnEntity::GetSpawnTransform. For reals, unify this stuff somewhere. void WBActionEldCheckLine::GetLineTransform( Vector& OutLocation, Angles& OutOrientation ) const { WBEntity* const pEntity = GetOwner(); DEVASSERT( pEntity ); WBCompEldTransform* const pTransform = pEntity->GetTransformComponent<WBCompEldTransform>(); DEVASSERT( pTransform ); WBCompEldCamera* const pCamera = GET_WBCOMP( pEntity, EldCamera ); WBCompEldHeadTracker* const pHeadTracker = GET_WBCOMP( pEntity, EldHeadTracker ); // Get location { if( pHeadTracker ) { OutLocation = pHeadTracker->GetEyesLocation(); } else { OutLocation = pTransform->GetLocation(); if( pCamera ) { OutLocation += pCamera->GetViewTranslationOffset( WBCompEldCamera::EVM_All ); } } } // Get orientation { if( pHeadTracker ) { OutOrientation = pHeadTracker->GetLookDirection().ToAngles(); } else { OutOrientation = pTransform->GetOrientation(); if( pCamera ) { OutOrientation += pCamera->GetViewOrientationOffset( WBCompEldCamera::EVM_All ); } } } }
void WBActionEldGiveItem::GiveItemTo(const SimpleString& ItemDef, WBEntity* const pEntity) const { DEVASSERT(pEntity); WBCompEldInventory* const pInventory = GET_WBCOMP(pEntity, EldInventory); ASSERT(pInventory); WBEntity* const pGivenEntity = WBWorld::GetInstance()->CreateEntity(ItemDef); ASSERT(pGivenEntity); pInventory->AddItem(pGivenEntity); }