Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpRangeManager.cpp
Show All 15 Lines | |||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "simulation2/system/Component.h" | #include "simulation2/system/Component.h" | ||||
#include "ICmpRangeManager.h" | #include "ICmpRangeManager.h" | ||||
#include "ICmpTerrain.h" | #include "ICmpTerrain.h" | ||||
#include "simulation2/system/EntityMap.h" | |||||
#include "simulation2/MessageTypes.h" | #include "simulation2/MessageTypes.h" | ||||
#include "simulation2/components/ICmpFogging.h" | #include "simulation2/components/ICmpFogging.h" | ||||
#include "simulation2/components/ICmpMirage.h" | #include "simulation2/components/ICmpMirage.h" | ||||
#include "simulation2/components/ICmpOwnership.h" | #include "simulation2/components/ICmpOwnership.h" | ||||
#include "simulation2/components/ICmpPosition.h" | #include "simulation2/components/ICmpPosition.h" | ||||
#include "simulation2/components/ICmpObstructionManager.h" | #include "simulation2/components/ICmpObstructionManager.h" | ||||
#include "simulation2/components/ICmpTerritoryManager.h" | #include "simulation2/components/ICmpTerritoryManager.h" | ||||
#include "simulation2/components/ICmpVisibility.h" | #include "simulation2/components/ICmpVisibility.h" | ||||
#include "simulation2/components/ICmpVision.h" | #include "simulation2/components/ICmpVision.h" | ||||
#include "simulation2/components/ICmpWaterManager.h" | #include "simulation2/components/ICmpWaterManager.h" | ||||
#include "simulation2/helpers/MapEdgeTiles.h" | #include "simulation2/helpers/MapEdgeTiles.h" | ||||
#include "simulation2/helpers/Render.h" | #include "simulation2/helpers/Render.h" | ||||
#include "simulation2/helpers/SparseFlatMap.h" | |||||
#include "simulation2/helpers/Spatial.h" | #include "simulation2/helpers/Spatial.h" | ||||
#include "graphics/Overlay.h" | #include "graphics/Overlay.h" | ||||
#include "graphics/Terrain.h" | #include "graphics/Terrain.h" | ||||
#include "lib/timer.h" | #include "lib/timer.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "renderer/Scene.h" | #include "renderer/Scene.h" | ||||
▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | void operator()(S& serialize, const char* UNUSED(name), EntityData& value) | ||||
serialize.NumberU32_Unbounded("visibilities", value.visibilities); | serialize.NumberU32_Unbounded("visibilities", value.visibilities); | ||||
serialize.NumberU32_Unbounded("size", value.size); | serialize.NumberU32_Unbounded("size", value.size); | ||||
serialize.NumberU16_Unbounded("vision sharing", value.visionSharing); | serialize.NumberU16_Unbounded("vision sharing", value.visionSharing); | ||||
serialize.NumberI8_Unbounded("owner", value.owner); | serialize.NumberI8_Unbounded("owner", value.owner); | ||||
serialize.NumberU8_Unbounded("flags", value.flags); | serialize.NumberU8_Unbounded("flags", value.flags); | ||||
} | } | ||||
}; | }; | ||||
using EntityMap = SparseFlatMap<entity_id_t, EntityData>; | |||||
using EntityIdDataPair = EntityMap::value_type; | |||||
/** | /** | ||||
* Functor for sorting entities by distance from a source point. | * Functor for sorting entities by distance from a source point. | ||||
* It must only be passed entities that are in 'entities' | * It must only be passed entities that are in 'entities' | ||||
* and are currently in the world. | * and are currently in the world. | ||||
*/ | */ | ||||
struct EntityDistanceOrdering | struct EntityDistanceOrdering | ||||
{ | { | ||||
EntityDistanceOrdering(const EntityMap<EntityData>& entities, const CFixedVector2D& source) : | EntityDistanceOrdering(const EntityMap& entities, const CFixedVector2D& source) : | ||||
m_EntityData(entities), m_Source(source) | m_EntityData(entities), m_Source(source) | ||||
{ | { | ||||
} | } | ||||
bool operator()(entity_id_t a, entity_id_t b) const | bool operator()(entity_id_t a, entity_id_t b) const | ||||
{ | { | ||||
const EntityData& da = m_EntityData.find(a)->second; | const EntityData& da = m_EntityData.find(a)->second; | ||||
const EntityData& db = m_EntityData.find(b)->second; | const EntityData& db = m_EntityData.find(b)->second; | ||||
CFixedVector2D vecA = CFixedVector2D(da.x, da.z) - m_Source; | CFixedVector2D vecA = CFixedVector2D(da.x, da.z) - m_Source; | ||||
CFixedVector2D vecB = CFixedVector2D(db.x, db.z) - m_Source; | CFixedVector2D vecB = CFixedVector2D(db.x, db.z) - m_Source; | ||||
return (vecA.CompareLength(vecB) < 0); | return (vecA.CompareLength(vecB) < 0); | ||||
} | } | ||||
const EntityMap<EntityData>& m_EntityData; | const EntityMap& m_EntityData; | ||||
CFixedVector2D m_Source; | CFixedVector2D m_Source; | ||||
private: | private: | ||||
EntityDistanceOrdering& operator=(const EntityDistanceOrdering&); | EntityDistanceOrdering& operator=(const EntityDistanceOrdering&); | ||||
}; | }; | ||||
/** | /** | ||||
* Range manager implementation. | * Range manager implementation. | ||||
Show All 35 Lines | public: | ||||
entity_pos_t m_WorldX0; | entity_pos_t m_WorldX0; | ||||
entity_pos_t m_WorldZ0; | entity_pos_t m_WorldZ0; | ||||
entity_pos_t m_WorldX1; | entity_pos_t m_WorldX1; | ||||
entity_pos_t m_WorldZ1; | entity_pos_t m_WorldZ1; | ||||
// Range query state: | // Range query state: | ||||
tag_t m_QueryNext; // next allocated id | tag_t m_QueryNext; // next allocated id | ||||
std::map<tag_t, Query> m_Queries; | std::map<tag_t, Query> m_Queries; | ||||
EntityMap<EntityData> m_EntityData; | EntityMap m_EntityData; | ||||
FastSpatialSubdivision m_Subdivision; // spatial index of m_EntityData | FastSpatialSubdivision m_Subdivision; // spatial index of m_EntityData | ||||
std::vector<entity_id_t> m_SubdivisionResults; | std::vector<entity_id_t> m_SubdivisionResults; | ||||
// LOS state: | // LOS state: | ||||
static const player_id_t MAX_LOS_PLAYER_ID = 16; | static const player_id_t MAX_LOS_PLAYER_ID = 16; | ||||
std::vector<bool> m_LosRevealAll; | std::vector<bool> m_LosRevealAll; | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | public: | ||||
{ | { | ||||
serialize.NumberFixed_Unbounded("world x0", m_WorldX0); | serialize.NumberFixed_Unbounded("world x0", m_WorldX0); | ||||
serialize.NumberFixed_Unbounded("world z0", m_WorldZ0); | serialize.NumberFixed_Unbounded("world z0", m_WorldZ0); | ||||
serialize.NumberFixed_Unbounded("world x1", m_WorldX1); | serialize.NumberFixed_Unbounded("world x1", m_WorldX1); | ||||
serialize.NumberFixed_Unbounded("world z1", m_WorldZ1); | serialize.NumberFixed_Unbounded("world z1", m_WorldZ1); | ||||
serialize.NumberU32_Unbounded("query next", m_QueryNext); | serialize.NumberU32_Unbounded("query next", m_QueryNext); | ||||
SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries, GetSimContext()); | SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries, GetSimContext()); | ||||
SerializeEntityMap<SerializeEntityData>()(serialize, "entity data", m_EntityData); | SerializeSparseFlatMap<SerializeEntityData>()(serialize, "entity data", m_EntityData); | ||||
SerializeVector<SerializeBool>()(serialize, "los reveal all", m_LosRevealAll); | SerializeVector<SerializeBool>()(serialize, "los reveal all", m_LosRevealAll); | ||||
serialize.Bool("los circular", m_LosCircular); | serialize.Bool("los circular", m_LosCircular); | ||||
serialize.NumberI32_Unbounded("terrain verts per side", m_TerrainVerticesPerSide); | serialize.NumberI32_Unbounded("terrain verts per side", m_TerrainVerticesPerSide); | ||||
serialize.Bool("global visibility update", m_GlobalVisibilityUpdate); | serialize.Bool("global visibility update", m_GlobalVisibilityUpdate); | ||||
SerializeVector<SerializeU8_Unbounded>()(serialize, "global player visibility update", m_GlobalPlayerVisibilityUpdate); | SerializeVector<SerializeU8_Unbounded>()(serialize, "global player visibility update", m_GlobalPlayerVisibilityUpdate); | ||||
SerializeRepetitiveVector<SerializeU16_Unbounded>()(serialize, "dirty visibility", m_DirtyVisibility); | SerializeRepetitiveVector<SerializeU16_Unbounded>()(serialize, "dirty visibility", m_DirtyVisibility); | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | case MT_Create: | ||||
entdata.SetFlag<FlagMasks::RetainInFog>(cmpVisibility->GetRetainInFog()); | entdata.SetFlag<FlagMasks::RetainInFog>(cmpVisibility->GetRetainInFog()); | ||||
// Store the size | // Store the size | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), ent); | CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), ent); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
entdata.size = cmpObstruction->GetSize().ToInt_RoundToInfinity(); | entdata.size = cmpObstruction->GetSize().ToInt_RoundToInfinity(); | ||||
// Remember this entity | // Remember this entity | ||||
m_EntityData.insert(ent, entdata); | m_EntityData.insert_or_assign(ent, entdata); | ||||
break; | break; | ||||
} | } | ||||
case MT_PositionChanged: | case MT_PositionChanged: | ||||
{ | { | ||||
const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg); | const CMessagePositionChanged& msgData = static_cast<const CMessagePositionChanged&> (msg); | ||||
entity_id_t ent = msgData.entity; | entity_id_t ent = msgData.entity; | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// Ignore if we're not already tracking this entity | // Ignore if we're not already tracking this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
break; | break; | ||||
if (msgData.inWorld) | if (msgData.inWorld) | ||||
{ | { | ||||
if (it->second.HasFlag<FlagMasks::InWorld>()) | if (it->second.HasFlag<FlagMasks::InWorld>()) | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | case MT_PositionChanged: | ||||
break; | break; | ||||
} | } | ||||
case MT_OwnershipChanged: | case MT_OwnershipChanged: | ||||
{ | { | ||||
const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); | const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); | ||||
entity_id_t ent = msgData.entity; | entity_id_t ent = msgData.entity; | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// Ignore if we're not already tracking this entity | // Ignore if we're not already tracking this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
break; | break; | ||||
if (it->second.HasFlag<FlagMasks::InWorld>()) | if (it->second.HasFlag<FlagMasks::InWorld>()) | ||||
{ | { | ||||
// Entity vision is taken into account in VisionSharingChanged | // Entity vision is taken into account in VisionSharingChanged | ||||
Show All 17 Lines | case MT_OwnershipChanged: | ||||
break; | break; | ||||
} | } | ||||
case MT_Destroy: | case MT_Destroy: | ||||
{ | { | ||||
const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg); | const CMessageDestroy& msgData = static_cast<const CMessageDestroy&> (msg); | ||||
entity_id_t ent = msgData.entity; | entity_id_t ent = msgData.entity; | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// Ignore if we're not already tracking this entity | // Ignore if we're not already tracking this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
break; | break; | ||||
if (it->second.HasFlag<FlagMasks::InWorld>()) | if (it->second.HasFlag<FlagMasks::InWorld>()) | ||||
{ | { | ||||
m_Subdivision.Remove(ent, CFixedVector2D(it->second.x, it->second.z), it->second.size); | m_Subdivision.Remove(ent, CFixedVector2D(it->second.x, it->second.z), it->second.size); | ||||
RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent); | RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent); | ||||
} | } | ||||
// This will be called after Ownership's OnDestroy, so ownership will be set | // This will be called after Ownership's OnDestroy, so ownership will be set | ||||
// to -1 already and we don't have to do a LosRemove here | // to -1 already and we don't have to do a LosRemove here | ||||
ENSURE(it->second.owner == -1); | ENSURE(it->second.owner == -1); | ||||
m_EntityData.erase(it); | m_EntityData.erase(it); | ||||
break; | break; | ||||
} | } | ||||
case MT_VisionRangeChanged: | case MT_VisionRangeChanged: | ||||
{ | { | ||||
const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg); | const CMessageVisionRangeChanged& msgData = static_cast<const CMessageVisionRangeChanged&> (msg); | ||||
entity_id_t ent = msgData.entity; | entity_id_t ent = msgData.entity; | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// Ignore if we're not already tracking this entity | // Ignore if we're not already tracking this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
break; | break; | ||||
CmpPtr<ICmpVision> cmpVision(GetSimContext(), ent); | CmpPtr<ICmpVision> cmpVision(GetSimContext(), ent); | ||||
if (!cmpVision) | if (!cmpVision) | ||||
break; | break; | ||||
Show All 23 Lines | case MT_VisionRangeChanged: | ||||
break; | break; | ||||
} | } | ||||
case MT_VisionSharingChanged: | case MT_VisionSharingChanged: | ||||
{ | { | ||||
const CMessageVisionSharingChanged& msgData = static_cast<const CMessageVisionSharingChanged&> (msg); | const CMessageVisionSharingChanged& msgData = static_cast<const CMessageVisionSharingChanged&> (msg); | ||||
entity_id_t ent = msgData.entity; | entity_id_t ent = msgData.entity; | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// Ignore if we're not already tracking this entity | // Ignore if we're not already tracking this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
break; | break; | ||||
ENSURE(msgData.player > 0 && msgData.player < MAX_LOS_PLAYER_ID+1); | ENSURE(msgData.player > 0 && msgData.player < MAX_LOS_PLAYER_ID+1); | ||||
u16 visionChanged = CalcVisionSharingMask(msgData.player); | u16 visionChanged = CalcVisionSharingMask(msgData.player); | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | if (!m_Deserializing) | ||||
m_DirtyVisibility.clear(); | m_DirtyVisibility.clear(); | ||||
m_DirtyVisibility.resize(m_LosTilesPerSide*m_LosTilesPerSide); | m_DirtyVisibility.resize(m_LosTilesPerSide*m_LosTilesPerSide); | ||||
} | } | ||||
ENSURE(m_DirtyVisibility.size() == (size_t)(m_LosTilesPerSide*m_LosTilesPerSide)); | ENSURE(m_DirtyVisibility.size() == (size_t)(m_LosTilesPerSide*m_LosTilesPerSide)); | ||||
m_LosTiles.clear(); | m_LosTiles.clear(); | ||||
m_LosTiles.resize(m_LosTilesPerSide*m_LosTilesPerSide); | m_LosTiles.resize(m_LosTilesPerSide*m_LosTilesPerSide); | ||||
for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) | for (const EntityIdDataPair& data : m_EntityData) | ||||
if (it->second.HasFlag<FlagMasks::InWorld>()) | if (data.second.HasFlag<FlagMasks::InWorld>()) | ||||
{ | { | ||||
if (it->second.HasFlag<FlagMasks::SharedVision>()) | if (data.second.HasFlag<FlagMasks::SharedVision>()) | ||||
SharingLosAdd(it->second.visionSharing, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z)); | SharingLosAdd(data.second.visionSharing, data.second.visionRange, CFixedVector2D(data.second.x, data.second.z)); | ||||
else | else | ||||
LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z)); | LosAdd(data.second.owner, data.second.visionRange, CFixedVector2D(data.second.x, data.second.z)); | ||||
AddToTile(PosToLosTilesHelper(it->second.x, it->second.z), it->first); | AddToTile(PosToLosTilesHelper(data.second.x, data.second.z), data.first); | ||||
if (it->second.HasFlag<FlagMasks::RevealShore>()) | if (data.second.HasFlag<FlagMasks::RevealShore>()) | ||||
RevealShore(it->second.owner, true); | RevealShore(data.second.owner, true); | ||||
} | } | ||||
m_TotalInworldVertices = 0; | m_TotalInworldVertices = 0; | ||||
for (ssize_t j = 0; j < m_TerrainVerticesPerSide; ++j) | for (ssize_t j = 0; j < m_TerrainVerticesPerSide; ++j) | ||||
for (ssize_t i = 0; i < m_TerrainVerticesPerSide; ++i) | for (ssize_t i = 0; i < m_TerrainVerticesPerSide; ++i) | ||||
{ | { | ||||
if (LosIsOffWorld(i,j)) | if (LosIsOffWorld(i,j)) | ||||
m_LosStateRevealed[i + j*m_TerrainVerticesPerSide] = 0; | m_LosStateRevealed[i + j*m_TerrainVerticesPerSide] = 0; | ||||
else | else | ||||
{ | { | ||||
m_LosStateRevealed[i + j*m_TerrainVerticesPerSide] = 0xFFFFFFFFu; | m_LosStateRevealed[i + j*m_TerrainVerticesPerSide] = 0xFFFFFFFFu; | ||||
m_TotalInworldVertices++; | m_TotalInworldVertices++; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void ResetSubdivisions(entity_pos_t x1, entity_pos_t z1) | void ResetSubdivisions(entity_pos_t x1, entity_pos_t z1) | ||||
{ | { | ||||
m_Subdivision.Reset(x1, z1); | m_Subdivision.Reset(x1, z1); | ||||
for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) | for (const EntityIdDataPair& data : m_EntityData) | ||||
if (it->second.HasFlag<FlagMasks::InWorld>()) | if (data.second.HasFlag<FlagMasks::InWorld>()) | ||||
m_Subdivision.Add(it->first, CFixedVector2D(it->second.x, it->second.z), it->second.size); | m_Subdivision.Add(data.first, CFixedVector2D(data.second.x, data.second.z), data.second.size); | ||||
} | } | ||||
virtual tag_t CreateActiveQuery(entity_id_t source, | virtual tag_t CreateActiveQuery(entity_id_t source, | ||||
entity_pos_t minRange, entity_pos_t maxRange, | entity_pos_t minRange, entity_pos_t maxRange, | ||||
const std::vector<int>& owners, int requiredInterface, u8 flags) | const std::vector<int>& owners, int requiredInterface, u8 flags) | ||||
{ | { | ||||
tag_t id = m_QueryNext++; | tag_t id = m_QueryNext++; | ||||
m_Queries[id] = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, flags); | m_Queries[id] = ConstructQuery(source, minRange, maxRange, owners, requiredInterface, flags); | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | public: | ||||
{ | { | ||||
return GetEntitiesByMask(~1); // bit 0 for owner=-1 | return GetEntitiesByMask(~1); // bit 0 for owner=-1 | ||||
} | } | ||||
std::vector<entity_id_t> GetEntitiesByMask(u32 ownerMask) const | std::vector<entity_id_t> GetEntitiesByMask(u32 ownerMask) const | ||||
{ | { | ||||
std::vector<entity_id_t> entities; | std::vector<entity_id_t> entities; | ||||
for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) | for (const EntityIdDataPair& data : m_EntityData) | ||||
{ | { | ||||
// Check owner and add to list if it matches | // Check owner and add to list if it matches | ||||
if (CalcOwnerMask(it->second.owner) & ownerMask) | if (CalcOwnerMask(data.second.owner) & ownerMask) | ||||
entities.push_back(it->first); | entities.push_back(data.first); | ||||
} | } | ||||
return entities; | return entities; | ||||
} | } | ||||
virtual void SetDebugOverlay(bool enabled) | virtual void SetDebugOverlay(bool enabled) | ||||
{ | { | ||||
m_DebugOverlayEnabled = enabled; | m_DebugOverlayEnabled = enabled; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | public: | ||||
* Returns a list of distinct entity IDs that match the given query, sorted by ID. | * Returns a list of distinct entity IDs that match the given query, sorted by ID. | ||||
*/ | */ | ||||
void PerformQuery(const Query& q, std::vector<entity_id_t>& r, CFixedVector2D pos) | void PerformQuery(const Query& q, std::vector<entity_id_t>& r, CFixedVector2D pos) | ||||
{ | { | ||||
// Special case: range -1.0 means check all entities ignoring distance | // Special case: range -1.0 means check all entities ignoring distance | ||||
if (q.maxRange == entity_pos_t::FromInt(-1)) | if (q.maxRange == entity_pos_t::FromInt(-1)) | ||||
{ | { | ||||
for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) | for (const EntityIdDataPair& data : m_EntityData) | ||||
{ | { | ||||
if (!TestEntityQuery(q, it->first, it->second)) | if (!TestEntityQuery(q, data.first, data.second)) | ||||
continue; | continue; | ||||
r.push_back(it->first); | r.push_back(data.first); | ||||
} | } | ||||
} | } | ||||
// Not the entire world, so check a parabolic range, or a regular range | // Not the entire world, so check a parabolic range, or a regular range | ||||
else if (q.parabolic) | else if (q.parabolic) | ||||
{ | { | ||||
// elevationBonus is part of the 3D position, as the source is really that much heigher | // elevationBonus is part of the 3D position, as the source is really that much heigher | ||||
CmpPtr<ICmpPosition> cmpSourcePosition(q.source); | CmpPtr<ICmpPosition> cmpSourcePosition(q.source); | ||||
CFixedVector3D pos3d = cmpSourcePosition->GetPosition()+ | CFixedVector3D pos3d = cmpSourcePosition->GetPosition()+ | ||||
CFixedVector3D(entity_pos_t::Zero(), q.elevationBonus, entity_pos_t::Zero()) ; | CFixedVector3D(entity_pos_t::Zero(), q.elevationBonus, entity_pos_t::Zero()) ; | ||||
// Get a quick list of entities that are potentially in range, with a cutoff of 2*maxRange | // Get a quick list of entities that are potentially in range, with a cutoff of 2*maxRange | ||||
m_SubdivisionResults.clear(); | m_SubdivisionResults.clear(); | ||||
m_Subdivision.GetNear(m_SubdivisionResults, pos, q.maxRange * 2); | m_Subdivision.GetNear(m_SubdivisionResults, pos, q.maxRange * 2); | ||||
for (size_t i = 0; i < m_SubdivisionResults.size(); ++i) | for (size_t i = 0; i < m_SubdivisionResults.size(); ++i) | ||||
{ | { | ||||
EntityMap<EntityData>::const_iterator it = m_EntityData.find(m_SubdivisionResults[i]); | EntityMap::const_iterator it = m_EntityData.find(m_SubdivisionResults[i]); | ||||
ENSURE(it != m_EntityData.end()); | ENSURE(it != m_EntityData.end()); | ||||
if (!TestEntityQuery(q, it->first, it->second)) | if (!TestEntityQuery(q, it->first, it->second)) | ||||
continue; | continue; | ||||
CmpPtr<ICmpPosition> cmpSecondPosition(GetSimContext(), m_SubdivisionResults[i]); | CmpPtr<ICmpPosition> cmpSecondPosition(GetSimContext(), m_SubdivisionResults[i]); | ||||
if (!cmpSecondPosition || !cmpSecondPosition->IsInWorld()) | if (!cmpSecondPosition || !cmpSecondPosition->IsInWorld()) | ||||
continue; | continue; | ||||
Show All 21 Lines | void PerformQuery(const Query& q, std::vector<entity_id_t>& r, CFixedVector2D pos) | ||||
else | else | ||||
{ | { | ||||
// Get a quick list of entities that are potentially in range | // Get a quick list of entities that are potentially in range | ||||
m_SubdivisionResults.clear(); | m_SubdivisionResults.clear(); | ||||
m_Subdivision.GetNear(m_SubdivisionResults, pos, q.maxRange); | m_Subdivision.GetNear(m_SubdivisionResults, pos, q.maxRange); | ||||
for (size_t i = 0; i < m_SubdivisionResults.size(); ++i) | for (size_t i = 0; i < m_SubdivisionResults.size(); ++i) | ||||
{ | { | ||||
EntityMap<EntityData>::const_iterator it = m_EntityData.find(m_SubdivisionResults[i]); | EntityMap::const_iterator it = m_EntityData.find(m_SubdivisionResults[i]); | ||||
ENSURE(it != m_EntityData.end()); | ENSURE(it != m_EntityData.end()); | ||||
if (!TestEntityQuery(q, it->first, it->second)) | if (!TestEntityQuery(q, it->first, it->second)) | ||||
continue; | continue; | ||||
// Restrict based on precise distance | // Restrict based on precise distance | ||||
int distVsMax = (CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(q.maxRange); | int distVsMax = (CFixedVector2D(it->second.x, it->second.z) - pos).CompareLength(q.maxRange); | ||||
if (distVsMax > 0) | if (distVsMax > 0) | ||||
▲ Show 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | if (identifier == "injured") | ||||
return FlagMasks::Injured; | return FlagMasks::Injured; | ||||
LOGWARNING("CCmpRangeManager: Invalid flag identifier %s", identifier.c_str()); | LOGWARNING("CCmpRangeManager: Invalid flag identifier %s", identifier.c_str()); | ||||
return FlagMasks::None; | return FlagMasks::None; | ||||
} | } | ||||
virtual void SetEntityFlag(entity_id_t ent, const std::string& identifier, bool value) | virtual void SetEntityFlag(entity_id_t ent, const std::string& identifier, bool value) | ||||
{ | { | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
// We don't have this entity | // We don't have this entity | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
return; | return; | ||||
u8 flag = GetEntityFlagMask(identifier); | u8 flag = GetEntityFlagMask(identifier); | ||||
if (flag == FlagMasks::None) | if (flag == FlagMasks::None) | ||||
Show All 11 Lines | virtual CLosQuerier GetLosQuerier(player_id_t player) const | ||||
if (GetLosRevealAll(player)) | if (GetLosRevealAll(player)) | ||||
return CLosQuerier(0xFFFFFFFFu, m_LosStateRevealed, m_TerrainVerticesPerSide); | return CLosQuerier(0xFFFFFFFFu, m_LosStateRevealed, m_TerrainVerticesPerSide); | ||||
else | else | ||||
return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); | return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); | ||||
} | } | ||||
virtual void ActivateScriptedVisibility(entity_id_t ent, bool status) | virtual void ActivateScriptedVisibility(entity_id_t ent, bool status) | ||||
{ | { | ||||
EntityMap<EntityData>::iterator it = m_EntityData.find(ent); | EntityMap::iterator it = m_EntityData.find(ent); | ||||
if (it != m_EntityData.end()) | if (it != m_EntityData.end()) | ||||
it->second.SetFlag<FlagMasks::ScriptedVisibility>(status); | it->second.SetFlag<FlagMasks::ScriptedVisibility>(status); | ||||
} | } | ||||
ELosVisibility ComputeLosVisibility(CEntityHandle ent, player_id_t player) const | ELosVisibility ComputeLosVisibility(CEntityHandle ent, player_id_t player) const | ||||
{ | { | ||||
// Entities not with positions in the world are never visible | // Entities not with positions in the world are never visible | ||||
if (ent.GetId() == INVALID_ENTITY) | if (ent.GetId() == INVALID_ENTITY) | ||||
Show All 21 Lines | ELosVisibility ComputeLosVisibility(CEntityHandle ent, player_id_t player) const | ||||
} | } | ||||
// Get visible regions | // Get visible regions | ||||
CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); | CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); | ||||
CmpPtr<ICmpVisibility> cmpVisibility(ent); | CmpPtr<ICmpVisibility> cmpVisibility(ent); | ||||
// Possibly ask the scripted Visibility component | // Possibly ask the scripted Visibility component | ||||
EntityMap<EntityData>::const_iterator it = m_EntityData.find(ent.GetId()); | EntityMap::const_iterator it = m_EntityData.find(ent.GetId()); | ||||
if (it != m_EntityData.end()) | if (it != m_EntityData.end()) | ||||
{ | { | ||||
if (it->second.HasFlag<FlagMasks::ScriptedVisibility>() && cmpVisibility) | if (it->second.HasFlag<FlagMasks::ScriptedVisibility>() && cmpVisibility) | ||||
return cmpVisibility->GetVisibility(player, los.IsVisible(i, j), los.IsExplored(i, j)); | return cmpVisibility->GetVisibility(player, los.IsVisible(i, j), los.IsExplored(i, j)); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (cmpVisibility && cmpVisibility->IsActivated()) | if (cmpVisibility && cmpVisibility->IsActivated()) | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player) const | ||||
i32 n = PosToLosTilesHelper(pos.X, pos.Y); | i32 n = PosToLosTilesHelper(pos.X, pos.Y); | ||||
if (IsVisibilityDirty(m_DirtyVisibility[n], player)) | if (IsVisibilityDirty(m_DirtyVisibility[n], player)) | ||||
return ComputeLosVisibility(ent, player); | return ComputeLosVisibility(ent, player); | ||||
if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), entId) != m_ModifiedEntities.end()) | if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), entId) != m_ModifiedEntities.end()) | ||||
return ComputeLosVisibility(ent, player); | return ComputeLosVisibility(ent, player); | ||||
EntityMap<EntityData>::const_iterator it = m_EntityData.find(entId); | EntityMap::const_iterator it = m_EntityData.find(entId); | ||||
if (it == m_EntityData.end()) | if (it == m_EntityData.end()) | ||||
return ComputeLosVisibility(ent, player); | return ComputeLosVisibility(ent, player); | ||||
return static_cast<ELosVisibility>(GetPlayerVisibility(it->second.visibilities, player)); | return static_cast<ELosVisibility>(GetPlayerVisibility(it->second.visibilities, player)); | ||||
} | } | ||||
virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player) const | virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player) const | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
virtual void RequestVisibilityUpdate(entity_id_t ent) | virtual void RequestVisibilityUpdate(entity_id_t ent) | ||||
{ | { | ||||
if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), ent) == m_ModifiedEntities.end()) | if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), ent) == m_ModifiedEntities.end()) | ||||
m_ModifiedEntities.push_back(ent); | m_ModifiedEntities.push_back(ent); | ||||
} | } | ||||
void UpdateVisibility(entity_id_t ent, player_id_t player) | void UpdateVisibility(entity_id_t ent, player_id_t player) | ||||
{ | { | ||||
EntityMap<EntityData>::iterator itEnts = m_EntityData.find(ent); | EntityMap::iterator itEnts = m_EntityData.find(ent); | ||||
if (itEnts == m_EntityData.end()) | if (itEnts == m_EntityData.end()) | ||||
return; | return; | ||||
u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player); | u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player); | ||||
u8 newVis = ComputeLosVisibility(itEnts->first, player); | u8 newVis = ComputeLosVisibility(itEnts->first, player); | ||||
if (oldVis == newVis) | if (oldVis == newVis) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
// Warning: Code related to fogging (like ForceMiraging) shouldn't be | // Warning: Code related to fogging (like ForceMiraging) shouldn't be | ||||
// invoked while iterating through m_EntityData. | // invoked while iterating through m_EntityData. | ||||
// Otherwise, by deleting mirage entities and so on, that code will | // Otherwise, by deleting mirage entities and so on, that code will | ||||
// change the indexes in the map, leading to segfaults. | // change the indexes in the map, leading to segfaults. | ||||
// So we just remember what entities to mirage and do that later. | // So we just remember what entities to mirage and do that later. | ||||
std::vector<entity_id_t> miragableEntities; | std::vector<entity_id_t> miragableEntities; | ||||
for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) | for (const EntityIdDataPair& data : m_EntityData) | ||||
{ | { | ||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), it->first); | CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), data.first); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
continue; | continue; | ||||
CFixedVector2D pos = cmpPosition->GetPosition2D(); | CFixedVector2D pos = cmpPosition->GetPosition2D(); | ||||
int i = (pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest(); | int i = (pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest(); | ||||
int j = (pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest(); | int j = (pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNearest(); | ||||
CLosQuerier los(GetSharedLosMask(p), m_LosState, m_TerrainVerticesPerSide); | CLosQuerier los(GetSharedLosMask(p), m_LosState, m_TerrainVerticesPerSide); | ||||
if (!los.IsExplored(i,j) || los.IsVisible(i,j)) | if (!los.IsExplored(i,j) || los.IsVisible(i,j)) | ||||
continue; | continue; | ||||
CmpPtr<ICmpFogging> cmpFogging(GetSimContext(), it->first); | CmpPtr<ICmpFogging> cmpFogging(GetSimContext(), data.first); | ||||
if (cmpFogging) | if (cmpFogging) | ||||
miragableEntities.push_back(it->first); | miragableEntities.push_back(data.first); | ||||
} | } | ||||
for (std::vector<entity_id_t>::iterator it = miragableEntities.begin(); it != miragableEntities.end(); ++it) | for (std::vector<entity_id_t>::iterator it = miragableEntities.begin(); it != miragableEntities.end(); ++it) | ||||
{ | { | ||||
CmpPtr<ICmpFogging> cmpFogging(GetSimContext(), *it); | CmpPtr<ICmpFogging> cmpFogging(GetSimContext(), *it); | ||||
ENSURE(cmpFogging && "Impossible to retrieve Fogging component, previously achieved"); | ENSURE(cmpFogging && "Impossible to retrieve Fogging component, previously achieved"); | ||||
cmpFogging->ForceMiraging(p); | cmpFogging->ForceMiraging(p); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 459 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator