forked from 0ad/0ad
Matei
0ed2815c8b
LOS issues still outstanding: - LOS looks ugly because of quad tesselation into 2 triangles - Quad tesselation is unspecified by OpenGL (in fact using GL_QUADS on LOS quads seemed to give different tesselations than it did for the underlying terrain quads, but terrain rendering also used GL_QUADS). This should be fixed once we decide on the quad tesselation issue. - Units with traits.vision.permanent set are visible through FOW even if you havent seen them before; this should only be true when you have seen them before. But it gets even more complicated - if a permanent unit seen through FOW dies or gets upgraded or something, perhaps you should remember the old version. I'm not completely sure how to do this (probably involves cloning its actor somehow). This was SVN commit r2876.
170 lines
3.5 KiB
C++
170 lines
3.5 KiB
C++
#include "precompiled.h"
|
|
|
|
#include "LOSManager.h"
|
|
|
|
#include "Game.h"
|
|
#include "Player.h"
|
|
#include "Terrain.h"
|
|
#include "Entity.h"
|
|
#include "EntityManager.h"
|
|
#include "Unit.h"
|
|
#include "Bound.h"
|
|
#include "Model.h"
|
|
|
|
using namespace std;
|
|
|
|
CLOSManager::CLOSManager()
|
|
{
|
|
m_MapRevealed = false;
|
|
}
|
|
|
|
CLOSManager::~CLOSManager()
|
|
{
|
|
}
|
|
|
|
void CLOSManager::Initialize()
|
|
{
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
int tilesPerSide = terrain->GetVerticesPerSide() - 1;
|
|
|
|
// Create the LOS data arrays
|
|
|
|
m_Explored = new int*[tilesPerSide];
|
|
for(int i=0; i<tilesPerSide; i++)
|
|
{
|
|
m_Explored[i] = new int[tilesPerSide];
|
|
}
|
|
|
|
m_Visible = new int*[tilesPerSide];
|
|
for(int i=0; i<tilesPerSide; i++)
|
|
{
|
|
m_Visible[i] = new int[tilesPerSide];
|
|
}
|
|
|
|
// TODO: This memory should be freed somewhere when the engine supports
|
|
// multiple sessions without restarting the program.
|
|
|
|
// Clear everything to unexplored
|
|
for(int x=0; x<tilesPerSide; x++)
|
|
{
|
|
memset(m_Explored[x], 0, tilesPerSide*sizeof(int));
|
|
}
|
|
|
|
// Just Update() to set the visible array and also mark currently visible tiles as explored.
|
|
// NOTE: this will have to be changed if we decide to use incremental LOS
|
|
|
|
Update();
|
|
}
|
|
|
|
// NOTE: this will have to be changed if we decide to use incremental LOS
|
|
void CLOSManager::Update()
|
|
{
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
int tilesPerSide = terrain->GetVerticesPerSide() - 1;
|
|
|
|
// Clear the visible array
|
|
for(int x=0; x<tilesPerSide; x++)
|
|
{
|
|
memset(m_Visible[x], 0, tilesPerSide*sizeof(int));
|
|
}
|
|
|
|
// Set visibility for each entity
|
|
vector<CEntity*> extant;
|
|
g_Game->GetWorld()->GetEntityManager()->GetExtant(extant);
|
|
for(size_t i=0; i<extant.size(); i++)
|
|
{
|
|
CEntity* e = extant[i];
|
|
|
|
int los = e->m_los;
|
|
if(los == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int mask = (1 << e->GetPlayer()->GetPlayerID());
|
|
|
|
int cx = min(int(e->m_position.X/CELL_SIZE), tilesPerSide-1);
|
|
int cz = min(int(e->m_position.Z/CELL_SIZE), tilesPerSide-1);
|
|
|
|
int minX = max(cx-los, 0);
|
|
int minZ = max(cz-los, 0);
|
|
int maxX = min(cx+los, tilesPerSide-1);
|
|
int maxZ = min(cz+los, tilesPerSide-1);
|
|
|
|
for(int x=minX; x<=maxX; x++)
|
|
{
|
|
for(int z=minZ; z<=maxZ; z++)
|
|
{
|
|
if((x-cx)*(x-cx) + (z-cz)*(z-cz) <= los*los)
|
|
{
|
|
m_Visible[x][z] |= mask;
|
|
m_Explored[x][z] |= mask;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ELOSStatus CLOSManager::GetStatus(int tx, int tz, CPlayer* player)
|
|
{
|
|
int mask = (1 << player->GetPlayerID());
|
|
|
|
if(m_MapRevealed)
|
|
{
|
|
return LOS_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
if(m_Visible[tx][tz] & mask)
|
|
{
|
|
return LOS_VISIBLE;
|
|
}
|
|
else if(m_Explored[tx][tz] & mask)
|
|
{
|
|
return LOS_EXPLORED;
|
|
}
|
|
else
|
|
{
|
|
return LOS_UNEXPLORED;
|
|
}
|
|
}
|
|
}
|
|
|
|
ELOSStatus CLOSManager::GetStatus(float fx, float fz, CPlayer* player)
|
|
{
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
int tilesPerSide = terrain->GetVerticesPerSide() - 1;
|
|
|
|
int ix = min(int(fx/CELL_SIZE), tilesPerSide-1);
|
|
int iz = min(int(fz/CELL_SIZE), tilesPerSide-1);
|
|
return GetStatus(ix, iz, player);
|
|
}
|
|
|
|
EUnitLOSStatus CLOSManager::GetUnitStatus(CUnit* unit, CPlayer* player)
|
|
{
|
|
CVector3D centre;
|
|
unit->GetModel()->GetBounds().GetCentre(centre);
|
|
ELOSStatus status = GetStatus(centre.X, centre.Z, player);
|
|
if(status == LOS_VISIBLE)
|
|
{
|
|
return UNIT_VISIBLE;
|
|
}
|
|
else if(status == LOS_EXPLORED)
|
|
{
|
|
if(unit->GetEntity() != 0 && unit->GetEntity()->m_permanent)
|
|
{
|
|
return UNIT_REMEMBERED;
|
|
}
|
|
else
|
|
{
|
|
return UNIT_HIDDEN;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return UNIT_HIDDEN;
|
|
}
|
|
}
|
|
|
|
|