mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Rotation rebase2 (#912)
* Instead of [x][y][z] coordinates, map will be stored as [z][x][y]. * Nullkiller AI can get it too. * Use boost::multi_array instead of nested vectors * In MapHandler too * Rotate foreach algorithms, too * VCAI gets rotated, too
This commit is contained in:
parent
e85f8a56bb
commit
7ba271edf1
@ -205,12 +205,14 @@ void foreach_tile_pos(const Func & foo)
|
||||
// some micro-optimizations since this function gets called a LOT
|
||||
// callback pointer is thread-specific and slow to retrieve -> read map size only once
|
||||
int3 mapSize = cb->getMapSize();
|
||||
for(int i = 0; i < mapSize.x; i++)
|
||||
for(int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
for(int j = 0; j < mapSize.y; j++)
|
||||
for(int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for(int k = 0; k < mapSize.z; k++)
|
||||
foo(int3(i, j, k));
|
||||
for(int y = 0; y < mapSize.y; y++)
|
||||
{
|
||||
foo(int3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -219,12 +221,14 @@ template<class Func>
|
||||
void foreach_tile_pos(CCallback * cbp, const Func & foo) // avoid costly retrieval of thread-specific pointer
|
||||
{
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
for(int i = 0; i < mapSize.x; i++)
|
||||
for(int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
for(int j = 0; j < mapSize.y; j++)
|
||||
for(int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for(int k = 0; k < mapSize.z; k++)
|
||||
foo(cbp, int3(i, j, k));
|
||||
for(int y = 0; y < mapSize.y; y++)
|
||||
{
|
||||
foo(cbp, int3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,21 +280,21 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
|
||||
template<typename TFunc>
|
||||
void pforeachTilePos(crint3 mapSize, TFunc fn)
|
||||
{
|
||||
parallel_for(blocked_range<size_t>(0, mapSize.x), [&](const blocked_range<size_t>& r)
|
||||
for(int z = 0; z < mapSize.z; ++z)
|
||||
{
|
||||
int3 pos;
|
||||
|
||||
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
|
||||
parallel_for(blocked_range<size_t>(0, mapSize.x), [&](const blocked_range<size_t>& r)
|
||||
{
|
||||
for(pos.y = 0; pos.y < mapSize.y; ++pos.y)
|
||||
int3 pos(0, 0, z);
|
||||
|
||||
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
|
||||
{
|
||||
for(pos.z = 0; pos.z < mapSize.z; ++pos.z)
|
||||
for(pos.y = 0; pos.y < mapSize.y; ++pos.y)
|
||||
{
|
||||
fn(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class CDistanceSorter
|
||||
|
@ -39,7 +39,7 @@ AISharedStorage::AISharedStorage(int3 sizes)
|
||||
{
|
||||
if(!shared){
|
||||
shared.reset(new boost::multi_array<AIPathNode, 5>(
|
||||
boost::extents[sizes.x][sizes.y][sizes.z][EPathfindingLayer::NUM_LAYERS][NUM_CHAINS]));
|
||||
boost::extents[EPathfindingLayer::NUM_LAYERS][sizes.z][sizes.x][sizes.y][NUM_CHAINS]));
|
||||
}
|
||||
|
||||
nodes = shared;
|
||||
@ -69,40 +69,41 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
||||
|
||||
//TODO: fix this code duplication with NodeStorage::initialize, problem is to keep `resetTile` inline
|
||||
const PlayerColor fowPlayer = ai->playerID;
|
||||
const auto & fow = static_cast<const CGameInfoCallback *>(gs)->getPlayerTeam(fowPlayer)->fogOfWarMap;
|
||||
const auto fow = static_cast<const CGameInfoCallback *>(gs)->getPlayerTeam(fowPlayer)->fogOfWarMap;
|
||||
const int3 sizes = gs->getMapSize();
|
||||
|
||||
//Each thread gets different x, but an array of y located next to each other in memory
|
||||
|
||||
parallel_for(blocked_range<size_t>(0, sizes.x), [&](const blocked_range<size_t>& r)
|
||||
{
|
||||
//make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching)
|
||||
const bool useFlying = options.useFlying;
|
||||
const bool useWaterWalking = options.useWaterWalking;
|
||||
const PlayerColor player = playerID;
|
||||
|
||||
int3 pos;
|
||||
|
||||
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
|
||||
for(pos.z = 0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
for(pos.y = 0; pos.y < sizes.y; ++pos.y)
|
||||
const bool useFlying = options.useFlying;
|
||||
const bool useWaterWalking = options.useWaterWalking;
|
||||
const PlayerColor player = playerID;
|
||||
|
||||
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
|
||||
{
|
||||
for(pos.z = 0; pos.z < sizes.z; ++pos.z)
|
||||
for(pos.y = 0; pos.y < sizes.y; ++pos.y)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
if(!tile->terType.isPassable())
|
||||
const TerrainTile* tile = &gs->map->getTile(pos);
|
||||
if (!tile->terType.isPassable())
|
||||
continue;
|
||||
|
||||
if(tile->terType.isWater())
|
||||
|
||||
if (tile->terType.isWater())
|
||||
{
|
||||
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
if (useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
if(useWaterWalking)
|
||||
if (useWaterWalking)
|
||||
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs));
|
||||
}
|
||||
else
|
||||
{
|
||||
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
if (useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
}
|
||||
}
|
||||
@ -140,7 +141,7 @@ boost::optional<AIPathNode *> AINodeStorage::getOrCreateNode(
|
||||
{
|
||||
int bucketIndex = ((uintptr_t)actor) % BUCKET_COUNT;
|
||||
int bucketOffset = bucketIndex * BUCKET_SIZE;
|
||||
auto chains = nodes.get(pos, layer);
|
||||
auto chains = nodes.get(pos, layer); //FIXME: chain was the innermost layer
|
||||
|
||||
if(chains[0].blocked())
|
||||
{
|
||||
|
@ -120,23 +120,19 @@ enum EHeroChainPass
|
||||
|
||||
class AISharedStorage
|
||||
{
|
||||
/// 1-3 - position on map, 4 - layer (air, water, land), 5 - chain (normal, battle, spellcast and combinations)
|
||||
// 1 - layer (air, water, land)
|
||||
// 2-4 - position on map[z][x][y]
|
||||
// 5 - chain (normal, battle, spellcast and combinations)
|
||||
static std::shared_ptr<boost::multi_array<AIPathNode, 5>> shared;
|
||||
std::shared_ptr<boost::multi_array<AIPathNode, 5>> nodes;
|
||||
public:
|
||||
AISharedStorage(int3 mapSize);
|
||||
~AISharedStorage();
|
||||
|
||||
/*STRONG_INLINE
|
||||
boost::detail::multi_array::sub_array<AIPathNode, 1> get(int3 tile, EPathfindingLayer layer)
|
||||
{
|
||||
return (*nodes)[tile.x][tile.y][tile.z][layer];
|
||||
}*/
|
||||
|
||||
STRONG_INLINE
|
||||
boost::detail::multi_array::sub_array<AIPathNode, 1> get(int3 tile, EPathfindingLayer layer) const
|
||||
{
|
||||
return (*nodes)[tile.x][tile.y][tile.z][layer];
|
||||
return (*nodes)[layer][tile.z][tile.x][tile.y];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,55 +137,6 @@ bool HeroPtr::operator==(const HeroPtr & rhs) const
|
||||
return h == rhs.get(true);
|
||||
}
|
||||
|
||||
void foreach_tile_pos(std::function<void(const int3 & pos)> foo)
|
||||
{
|
||||
// some micro-optimizations since this function gets called a LOT
|
||||
// callback pointer is thread-specific and slow to retrieve -> read map size only once
|
||||
int3 mapSize = cb->getMapSize();
|
||||
for(int i = 0; i < mapSize.x; i++)
|
||||
{
|
||||
for(int j = 0; j < mapSize.y; j++)
|
||||
{
|
||||
for(int k = 0; k < mapSize.z; k++)
|
||||
foo(int3(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3 & pos)> foo)
|
||||
{
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
for(int i = 0; i < mapSize.x; i++)
|
||||
{
|
||||
for(int j = 0; j < mapSize.y; j++)
|
||||
{
|
||||
for(int k = 0; k < mapSize.z; k++)
|
||||
foo(cbp, int3(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo)
|
||||
{
|
||||
CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer
|
||||
for(const int3 & dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
foo(pos + dir);
|
||||
}
|
||||
}
|
||||
|
||||
void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo)
|
||||
{
|
||||
for(const int3 & dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
foo(cbp, pos + dir);
|
||||
}
|
||||
}
|
||||
|
||||
bool CDistanceSorter::operator()(const CGObjectInstance * lhs, const CGObjectInstance * rhs) const
|
||||
{
|
||||
const CGPathNode * ln = ai->myCb->getPathsInfo(hero)->getPathInfo(lhs->visitablePos());
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "../../lib/mapObjects/CObjectHandler.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../CCallback.h"
|
||||
|
||||
class CCallback;
|
||||
struct creInfo;
|
||||
@ -34,6 +35,8 @@ const int ALLOWED_ROAMING_HEROES = 8;
|
||||
extern const double SAFE_ATTACK_CONSTANT;
|
||||
extern const int GOLD_RESERVE;
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
|
||||
//provisional class for AI to store a reference to an owned hero object
|
||||
//checks if it's valid on access, should be used in place of const CGHeroInstance*
|
||||
|
||||
@ -154,10 +157,62 @@ struct creInfo
|
||||
};
|
||||
creInfo infoFromDC(const dwellingContent & dc);
|
||||
|
||||
void foreach_tile_pos(std::function<void(const int3 & pos)> foo);
|
||||
void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
|
||||
void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo);
|
||||
void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
|
||||
template<class Func>
|
||||
void foreach_tile_pos(const Func & foo)
|
||||
{
|
||||
// some micro-optimizations since this function gets called a LOT
|
||||
// callback pointer is thread-specific and slow to retrieve -> read map size only once
|
||||
int3 mapSize = cb->getMapSize();
|
||||
for(int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
for(int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for(int y = 0; y < mapSize.y; y++)
|
||||
{
|
||||
foo(int3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Func>
|
||||
void foreach_tile_pos(CCallback * cbp, const Func & foo) // avoid costly retrieval of thread-specific pointer
|
||||
{
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
for(int z = 0; z < mapSize.z; z++)
|
||||
{
|
||||
for(int x = 0; x < mapSize.x; x++)
|
||||
{
|
||||
for(int y = 0; y < mapSize.y; y++)
|
||||
{
|
||||
foo(cbp, int3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Func>
|
||||
void foreach_neighbour(const int3 & pos, const Func & foo)
|
||||
{
|
||||
CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer
|
||||
for(const int3 & dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
foo(pos + dir);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Func>
|
||||
void foreach_neighbour(CCallback * cbp, const int3 & pos, const Func & foo) // avoid costly retrieval of thread-specific pointer
|
||||
{
|
||||
for(const int3 & dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
foo(cbp, pos + dir);
|
||||
}
|
||||
}
|
||||
|
||||
bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
|
||||
bool isBlockedBorderGate(int3 tileToHit);
|
||||
|
@ -17,8 +17,6 @@ set(VCAI_SRCS
|
||||
ArmyManager.cpp
|
||||
ResourceManager.cpp
|
||||
BuildingManager.cpp
|
||||
SectorMap.cpp
|
||||
BuildingManager.cpp
|
||||
MapObjectsEvaluator.cpp
|
||||
FuzzyEngines.cpp
|
||||
FuzzyHelper.cpp
|
||||
@ -68,8 +66,6 @@ set(VCAI_HEADERS
|
||||
ArmyManager.h
|
||||
ResourceManager.h
|
||||
BuildingManager.h
|
||||
SectorMap.h
|
||||
BuildingManager.h
|
||||
MapObjectsEvaluator.h
|
||||
FuzzyEngines.h
|
||||
FuzzyHelper.h
|
||||
|
@ -18,6 +18,7 @@
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
class CCallback;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
|
@ -57,13 +57,16 @@ namespace Goals
|
||||
|
||||
void scanSector(int scanRadius)
|
||||
{
|
||||
for(int x = ourPos.x - scanRadius; x <= ourPos.x + scanRadius; x++)
|
||||
{
|
||||
for(int y = ourPos.y - scanRadius; y <= ourPos.y + scanRadius; y++)
|
||||
{
|
||||
int3 tile = int3(x, y, ourPos.z);
|
||||
int3 tile = int3(0, 0, ourPos.z);
|
||||
|
||||
if(cbp->isInTheMap(tile) && ts->fogOfWarMap[tile.x][tile.y][tile.z])
|
||||
const auto & slice = (*(ts->fogOfWarMap))[ourPos.z];
|
||||
|
||||
for(tile.x = ourPos.x - scanRadius; tile.x <= ourPos.x + scanRadius; tile.x++)
|
||||
{
|
||||
for(tile.y = ourPos.y - scanRadius; tile.y <= ourPos.y + scanRadius; tile.y++)
|
||||
{
|
||||
|
||||
if(cbp->isInTheMap(tile) && slice[tile.x][tile.y])
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
@ -84,13 +87,13 @@ namespace Goals
|
||||
|
||||
foreach_tile_pos([&](const int3 & pos)
|
||||
{
|
||||
if(ts->fogOfWarMap[pos.x][pos.y][pos.z])
|
||||
if((*(ts->fogOfWarMap))[pos.z][pos.x][pos.y])
|
||||
{
|
||||
bool hasInvisibleNeighbor = false;
|
||||
|
||||
foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(!ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
if(!(*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y])
|
||||
{
|
||||
hasInvisibleNeighbor = true;
|
||||
}
|
||||
@ -174,7 +177,7 @@ namespace Goals
|
||||
{
|
||||
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
if((*(ts->fogOfWarMap))[neighbour.z][neighbour.x][neighbour.y])
|
||||
{
|
||||
out.push_back(neighbour);
|
||||
}
|
||||
@ -182,18 +185,20 @@ namespace Goals
|
||||
}
|
||||
}
|
||||
|
||||
int howManyTilesWillBeDiscovered(
|
||||
const int3 & pos) const
|
||||
int howManyTilesWillBeDiscovered(const int3 & pos) const
|
||||
{
|
||||
int ret = 0;
|
||||
for(int x = pos.x - sightRadius; x <= pos.x + sightRadius; x++)
|
||||
int3 npos = int3(0, 0, pos.z);
|
||||
|
||||
const auto & slice = (*(ts->fogOfWarMap))[pos.z];
|
||||
|
||||
for(npos.x = pos.x - sightRadius; npos.x <= pos.x + sightRadius; npos.x++)
|
||||
{
|
||||
for(int y = pos.y - sightRadius; y <= pos.y + sightRadius; y++)
|
||||
for(npos.y = pos.y - sightRadius; npos.y <= pos.y + sightRadius; npos.y++)
|
||||
{
|
||||
int3 npos = int3(x, y, pos.z);
|
||||
if(cbp->isInTheMap(npos)
|
||||
&& pos.dist2d(npos) - 0.5 < sightRadius
|
||||
&& !ts->fogOfWarMap[npos.x][npos.y][npos.z])
|
||||
&& !slice[npos.x][npos.y])
|
||||
{
|
||||
if(allowDeadEndCancellation
|
||||
&& !hasReachableNeighbor(npos))
|
||||
|
@ -20,7 +20,7 @@
|
||||
AINodeStorage::AINodeStorage(const int3 & Sizes)
|
||||
: sizes(Sizes)
|
||||
{
|
||||
nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][EPathfindingLayer::NUM_LAYERS][NUM_CHAINS]);
|
||||
nodes.resize(boost::extents[EPathfindingLayer::NUM_LAYERS][sizes.z][sizes.x][sizes.y][NUM_CHAINS]);
|
||||
dangerEvaluator.reset(new FuzzyHelper());
|
||||
}
|
||||
|
||||
@ -28,8 +28,6 @@ AINodeStorage::~AINodeStorage() = default;
|
||||
|
||||
void AINodeStorage::initialize(const PathfinderOptions & options, const CGameState * gs)
|
||||
{
|
||||
//TODO: fix this code duplication with NodeStorage::initialize, problem is to keep `resetTile` inline
|
||||
|
||||
int3 pos;
|
||||
const int3 sizes = gs->getMapSize();
|
||||
const auto & fow = static_cast<const CGameInfoCallback *>(gs)->getPlayerTeam(hero->tempOwner)->fogOfWarMap;
|
||||
@ -39,11 +37,11 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
||||
const bool useFlying = options.useFlying;
|
||||
const bool useWaterWalking = options.useWaterWalking;
|
||||
|
||||
for(pos.x=0; pos.x < sizes.x; ++pos.x)
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
for(pos.y=0; pos.y < sizes.y; ++pos.y)
|
||||
for(pos.x=0; pos.x < sizes.x; ++pos.x)
|
||||
{
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
for(pos.y=0; pos.y < sizes.y; ++pos.y)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
if(!tile->terType.isPassable())
|
||||
@ -87,7 +85,7 @@ bool AINodeStorage::isBattleNode(const CGPathNode * node) const
|
||||
|
||||
boost::optional<AIPathNode *> AINodeStorage::getOrCreateNode(const int3 & pos, const EPathfindingLayer layer, int chainNumber)
|
||||
{
|
||||
auto chains = nodes[pos.x][pos.y][pos.z][layer];
|
||||
auto chains = nodes[layer][pos.z][pos.x][pos.y];
|
||||
|
||||
for(AIPathNode & node : chains)
|
||||
{
|
||||
@ -126,7 +124,7 @@ void AINodeStorage::resetTile(const int3 & coord, EPathfindingLayer layer, CGPat
|
||||
{
|
||||
for(int i = 0; i < NUM_CHAINS; i++)
|
||||
{
|
||||
AIPathNode & heroNode = nodes[coord.x][coord.y][coord.z][layer][i];
|
||||
AIPathNode & heroNode = nodes[layer][coord.z][coord.x][coord.y][i];
|
||||
|
||||
heroNode.chainMask = 0;
|
||||
heroNode.danger = 0;
|
||||
@ -290,7 +288,7 @@ void AINodeStorage::calculateTownPortalTeleportations(
|
||||
bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNodeInfo & destination) const
|
||||
{
|
||||
auto pos = destination.coord;
|
||||
auto chains = nodes[pos.x][pos.y][pos.z][EPathfindingLayer::LAND];
|
||||
auto chains = nodes[EPathfindingLayer::LAND][pos.z][pos.x][pos.y];
|
||||
auto destinationNode = getAINode(destination.node);
|
||||
|
||||
for(const AIPathNode & node : chains)
|
||||
@ -323,7 +321,7 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
|
||||
|
||||
bool AINodeStorage::isTileAccessible(const int3 & pos, const EPathfindingLayer layer) const
|
||||
{
|
||||
const AIPathNode & node = nodes[pos.x][pos.y][pos.z][layer][0];
|
||||
const AIPathNode & node = nodes[layer][pos.z][pos.x][pos.y][0];
|
||||
|
||||
return node.action != CGPathNode::ENodeAction::UNKNOWN;
|
||||
}
|
||||
@ -331,7 +329,7 @@ bool AINodeStorage::isTileAccessible(const int3 & pos, const EPathfindingLayer l
|
||||
std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand) const
|
||||
{
|
||||
std::vector<AIPath> paths;
|
||||
auto chains = nodes[pos.x][pos.y][pos.z][isOnLand ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL];
|
||||
auto chains = nodes[isOnLand ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL][pos.z][pos.x][pos.y];
|
||||
auto initialPos = hero->visitablePos();
|
||||
|
||||
for(const AIPathNode & node : chains)
|
||||
|
@ -17,6 +17,10 @@
|
||||
#include "../Goals/AbstractGoal.h"
|
||||
#include "Actions/ISpecialAction.h"
|
||||
|
||||
class CCallback;
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb; //for templates
|
||||
|
||||
struct AIPathNode : public CGPathNode
|
||||
{
|
||||
uint32_t chainMask;
|
||||
@ -57,7 +61,9 @@ class AINodeStorage : public INodeStorage
|
||||
private:
|
||||
int3 sizes;
|
||||
|
||||
/// 1-3 - position on map, 4 - layer (air, water, land), 5 - chain (normal, battle, spellcast and combinations)
|
||||
// 1 - layer (air, water, land)
|
||||
// 2-4 - position on map[z][x][y]
|
||||
// 5 - chain (normal, battle, spellcast and combinations)
|
||||
boost::multi_array<AIPathNode, 5> nodes;
|
||||
const CPlayerSpecificInfoCallback * cb;
|
||||
const VCAI * ai;
|
||||
|
@ -1,431 +0,0 @@
|
||||
/*
|
||||
* SectorMap.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "SectorMap.h"
|
||||
#include "VCAI.h"
|
||||
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
SectorMap::SectorMap()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
SectorMap::SectorMap(HeroPtr h)
|
||||
{
|
||||
update();
|
||||
makeParentBFS(h->visitablePos());
|
||||
}
|
||||
|
||||
bool SectorMap::markIfBlocked(TSectorID & sec, crint3 pos, const TerrainTile * t)
|
||||
{
|
||||
if (t->blocked && !t->visitable)
|
||||
{
|
||||
sec = NOT_AVAILABLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SectorMap::markIfBlocked(TSectorID & sec, crint3 pos)
|
||||
{
|
||||
return markIfBlocked(sec, pos, getTile(pos));
|
||||
}
|
||||
|
||||
void SectorMap::update()
|
||||
{
|
||||
visibleTiles = cb->getAllVisibleTiles();
|
||||
auto shape = visibleTiles->shape();
|
||||
sector.resize(boost::extents[shape[0]][shape[1]][shape[2]]);
|
||||
|
||||
clear();
|
||||
int curSector = 3; //0 is invisible, 1 is not explored
|
||||
|
||||
CCallback * cbp = cb.get(); //optimization
|
||||
foreach_tile_pos([&](crint3 pos)
|
||||
{
|
||||
if (retrieveTile(pos) == NOT_CHECKED)
|
||||
{
|
||||
if (!markIfBlocked(retrieveTile(pos), pos))
|
||||
exploreNewSector(pos, curSector++, cbp);
|
||||
}
|
||||
});
|
||||
valid = true;
|
||||
}
|
||||
|
||||
SectorMap::TSectorID & SectorMap::retrieveTileN(SectorMap::TSectorArray & a, const int3 & pos)
|
||||
{
|
||||
return a[pos.x][pos.y][pos.z];
|
||||
}
|
||||
|
||||
const SectorMap::TSectorID & SectorMap::retrieveTileN(const SectorMap::TSectorArray & a, const int3 & pos)
|
||||
{
|
||||
return a[pos.x][pos.y][pos.z];
|
||||
}
|
||||
|
||||
void SectorMap::clear()
|
||||
{
|
||||
//TODO: rotate to [z][x][y]
|
||||
auto fow = cb->getVisibilityMap();
|
||||
//TODO: any magic to automate this? will need array->array conversion
|
||||
//std::transform(fow.begin(), fow.end(), sector.begin(), [](const ui8 &f) -> unsigned short
|
||||
//{
|
||||
// return f; //type conversion
|
||||
//});
|
||||
auto width = fow.size();
|
||||
auto height = fow.front().size();
|
||||
auto depth = fow.front().front().size();
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
for (size_t z = 0; z < depth; z++)
|
||||
sector[x][y][z] = fow[x][y][z];
|
||||
}
|
||||
}
|
||||
valid = false;
|
||||
}
|
||||
|
||||
void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp)
|
||||
{
|
||||
Sector & s = infoOnSectors[num];
|
||||
s.id = num;
|
||||
s.water = getTile(pos)->isWater();
|
||||
|
||||
std::queue<int3> toVisit;
|
||||
toVisit.push(pos);
|
||||
while (!toVisit.empty())
|
||||
{
|
||||
int3 curPos = toVisit.front();
|
||||
toVisit.pop();
|
||||
TSectorID & sec = retrieveTile(curPos);
|
||||
if (sec == NOT_CHECKED)
|
||||
{
|
||||
const TerrainTile * t = getTile(curPos);
|
||||
if (!markIfBlocked(sec, curPos, t))
|
||||
{
|
||||
if (t->isWater() == s.water) //sector is only-water or only-land
|
||||
{
|
||||
sec = num;
|
||||
s.tiles.push_back(curPos);
|
||||
foreach_neighbour(cbp, curPos, [&](CCallback * cbp, crint3 neighPos)
|
||||
{
|
||||
if (retrieveTile(neighPos) == NOT_CHECKED)
|
||||
{
|
||||
toVisit.push(neighPos);
|
||||
//parent[neighPos] = curPos;
|
||||
}
|
||||
const TerrainTile * nt = getTile(neighPos);
|
||||
if (nt && nt->isWater() != s.water && canBeEmbarkmentPoint(nt, s.water))
|
||||
{
|
||||
s.embarkmentPoints.push_back(neighPos);
|
||||
}
|
||||
});
|
||||
|
||||
if (t->visitable)
|
||||
{
|
||||
auto obj = t->visitableObjects.front();
|
||||
if (cb->getObj(obj->id, false)) // FIXME: we have to filter invisible objcts like events, but probably TerrainTile shouldn't be used in SectorMap at all
|
||||
s.visitableObjs.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vstd::removeDuplicates(s.embarkmentPoints);
|
||||
}
|
||||
|
||||
void SectorMap::write(crstring fname)
|
||||
{
|
||||
std::ofstream out(fname);
|
||||
for (int k = 0; k < cb->getMapSize().z; k++)
|
||||
{
|
||||
for (int j = 0; j < cb->getMapSize().y; j++)
|
||||
{
|
||||
for (int i = 0; i < cb->getMapSize().x; i++)
|
||||
{
|
||||
out << (int)sector[i][j][k] << '\t';
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this functions returns one target tile or invalid tile. We will use it to poll possible destinations
|
||||
For ship construction etc, another function (goal?) is needed
|
||||
*/
|
||||
int3 SectorMap::firstTileToGet(HeroPtr h, crint3 dst)
|
||||
{
|
||||
int3 ret(-1, -1, -1);
|
||||
|
||||
int sourceSector = retrieveTile(h->visitablePos());
|
||||
int destinationSector = retrieveTile(dst);
|
||||
|
||||
const Sector * src = &infoOnSectors[sourceSector];
|
||||
const Sector * dest = &infoOnSectors[destinationSector];
|
||||
|
||||
if (sourceSector != destinationSector) //use ships, shipyards etc..
|
||||
{
|
||||
if (ai->isAccessibleForHero(dst, h)) //pathfinder can find a way using ships and gates if tile is not blocked by objects
|
||||
return dst;
|
||||
|
||||
std::map<const Sector *, const Sector *> preds;
|
||||
std::queue<const Sector *> sectorQueue;
|
||||
sectorQueue.push(src);
|
||||
while (!sectorQueue.empty())
|
||||
{
|
||||
const Sector * s = sectorQueue.front();
|
||||
sectorQueue.pop();
|
||||
|
||||
for (int3 ep : s->embarkmentPoints)
|
||||
{
|
||||
Sector * neigh = &infoOnSectors[retrieveTile(ep)];
|
||||
//preds[s].push_back(neigh);
|
||||
if (!preds[neigh])
|
||||
{
|
||||
preds[neigh] = s;
|
||||
sectorQueue.push(neigh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!preds[dest])
|
||||
{
|
||||
//write("test.txt");
|
||||
|
||||
return ret;
|
||||
//throw cannotFulfillGoalException(boost::str(boost::format("Cannot find connection between sectors %d and %d") % src->id % dst->id));
|
||||
}
|
||||
|
||||
std::vector<const Sector *> toTraverse;
|
||||
toTraverse.push_back(dest);
|
||||
while (toTraverse.back() != src)
|
||||
{
|
||||
toTraverse.push_back(preds[toTraverse.back()]);
|
||||
}
|
||||
|
||||
if (preds[dest])
|
||||
{
|
||||
//TODO: would be nice to find sectors in loop
|
||||
const Sector * sectorToReach = toTraverse.at(toTraverse.size() - 2);
|
||||
|
||||
if (!src->water && sectorToReach->water) //embark
|
||||
{
|
||||
//embark on ship -> look for an EP with a boat
|
||||
auto firstEP = boost::find_if(src->embarkmentPoints, [=](crint3 pos) -> bool
|
||||
{
|
||||
const TerrainTile * t = getTile(pos);
|
||||
if (t && t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT)
|
||||
{
|
||||
if (retrieveTile(pos) == sectorToReach->id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (firstEP != src->embarkmentPoints.end())
|
||||
{
|
||||
return *firstEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we need to find a shipyard with an access to the desired sector's EP
|
||||
//TODO what about Summon Boat spell?
|
||||
std::vector<const IShipyard *> shipyards;
|
||||
for (const CGTownInstance * t : cb->getTownsInfo())
|
||||
{
|
||||
if (t->hasBuilt(BuildingID::SHIPYARD))
|
||||
shipyards.push_back(t);
|
||||
}
|
||||
|
||||
for (const CGObjectInstance * obj : ai->getFlaggedObjects())
|
||||
{
|
||||
if (obj->ID != Obj::TOWN) //towns were handled in the previous loop
|
||||
{
|
||||
if (const IShipyard * shipyard = IShipyard::castFrom(obj))
|
||||
shipyards.push_back(shipyard);
|
||||
}
|
||||
}
|
||||
|
||||
shipyards.erase(boost::remove_if(shipyards, [=](const IShipyard * shipyard) -> bool
|
||||
{
|
||||
return shipyard->shipyardStatus() != 0 || retrieveTile(shipyard->bestLocation()) != sectorToReach->id;
|
||||
}), shipyards.end());
|
||||
|
||||
if (!shipyards.size())
|
||||
{
|
||||
//TODO consider possibility of building shipyard in a town
|
||||
return ret;
|
||||
|
||||
//throw cannotFulfillGoalException("There is no known shipyard!");
|
||||
}
|
||||
|
||||
//we have only shipyards that possibly can build ships onto the appropriate EP
|
||||
auto ownedGoodShipyard = boost::find_if(shipyards, [](const IShipyard * s) -> bool
|
||||
{
|
||||
return s->o->tempOwner == ai->playerID;
|
||||
});
|
||||
|
||||
if (ownedGoodShipyard != shipyards.end())
|
||||
{
|
||||
const IShipyard * s = *ownedGoodShipyard;
|
||||
TResources shipCost;
|
||||
s->getBoatCost(shipCost);
|
||||
if (cb->getResourceAmount().canAfford(shipCost))
|
||||
{
|
||||
int3 ret = s->bestLocation();
|
||||
cb->buildBoat(s); //TODO: move actions elsewhere
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO gather res
|
||||
return ret;
|
||||
|
||||
//throw cannotFulfillGoalException("Not enough resources to build a boat");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO pick best shipyard to take over
|
||||
return shipyards.front()->o->visitablePos();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (src->water && !sectorToReach->water)
|
||||
{
|
||||
//TODO
|
||||
//disembark
|
||||
return ret;
|
||||
}
|
||||
else //use subterranean gates - not needed since gates are now handled via Pathfinder
|
||||
{
|
||||
return ret;
|
||||
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
//throw cannotFulfillGoalException("Inter-sector route detection failed: not connected sectors?");
|
||||
}
|
||||
}
|
||||
else //tiles are in same sector
|
||||
{
|
||||
return findFirstVisitableTile(h, dst);
|
||||
}
|
||||
}
|
||||
|
||||
int3 SectorMap::findFirstVisitableTile(HeroPtr h, crint3 dst)
|
||||
{
|
||||
int3 ret(-1, -1, -1);
|
||||
int3 curtile = dst;
|
||||
|
||||
while (curtile != h->visitablePos())
|
||||
{
|
||||
auto topObj = cb->getTopObj(curtile);
|
||||
if (topObj && topObj->ID == Obj::HERO && topObj != h.h)
|
||||
{
|
||||
if (cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
|
||||
{
|
||||
logAi->warn("Another allied hero stands in our way");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (ai->myCb->getPathsInfo(h.get())->getPathInfo(curtile)->reachable())
|
||||
{
|
||||
return curtile;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto i = parent.find(curtile);
|
||||
if (i != parent.end())
|
||||
{
|
||||
assert(curtile != i->second);
|
||||
curtile = i->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
//throw cannotFulfillGoalException("Unreachable tile in sector? Should not happen!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SectorMap::makeParentBFS(crint3 source)
|
||||
{
|
||||
parent.clear();
|
||||
|
||||
int mySector = retrieveTile(source);
|
||||
std::queue<int3> toVisit;
|
||||
toVisit.push(source);
|
||||
while (!toVisit.empty())
|
||||
{
|
||||
int3 curPos = toVisit.front();
|
||||
toVisit.pop();
|
||||
TSectorID & sec = retrieveTile(curPos);
|
||||
assert(sec == mySector); //consider only tiles from the same sector
|
||||
UNUSED(sec);
|
||||
|
||||
foreach_neighbour(curPos, [&](crint3 neighPos)
|
||||
{
|
||||
if (retrieveTile(neighPos) == mySector && !vstd::contains(parent, neighPos))
|
||||
{
|
||||
if (cb->canMoveBetween(curPos, neighPos))
|
||||
{
|
||||
toVisit.push(neighPos);
|
||||
parent[neighPos] = curPos;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SectorMap::TSectorID & SectorMap::retrieveTile(crint3 pos)
|
||||
{
|
||||
return retrieveTileN(sector, pos);
|
||||
}
|
||||
|
||||
TerrainTile * SectorMap::getTile(crint3 pos) const
|
||||
{
|
||||
//out of bounds access should be handled by boost::multi_array
|
||||
//still we cached this array to avoid any checks
|
||||
return visibleTiles->operator[](pos.x)[pos.y][pos.z];
|
||||
}
|
||||
|
||||
std::vector<const CGObjectInstance *> SectorMap::getNearbyObjs(HeroPtr h, bool sectorsAround)
|
||||
{
|
||||
const Sector * heroSector = &infoOnSectors[retrieveTile(h->visitablePos())];
|
||||
if (sectorsAround)
|
||||
{
|
||||
std::vector<const CGObjectInstance *> ret;
|
||||
for (auto embarkPoint : heroSector->embarkmentPoints)
|
||||
{
|
||||
const Sector * embarkSector = &infoOnSectors[retrieveTile(embarkPoint)];
|
||||
range::copy(embarkSector->visitableObjs, std::back_inserter(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return heroSector->visitableObjs;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* SectorMap.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AIUtility.h"
|
||||
|
||||
enum
|
||||
{
|
||||
NOT_VISIBLE = 0,
|
||||
NOT_CHECKED = 1,
|
||||
NOT_AVAILABLE
|
||||
};
|
||||
|
||||
struct SectorMap
|
||||
{
|
||||
//a sector is set of tiles that would be mutually reachable if all visitable objs would be passable (incl monsters)
|
||||
struct Sector
|
||||
{
|
||||
int id;
|
||||
std::vector<int3> tiles;
|
||||
std::vector<int3> embarkmentPoints; //tiles of other sectors onto which we can (dis)embark
|
||||
std::vector<const CGObjectInstance *> visitableObjs;
|
||||
bool water; //all tiles of sector are land or water
|
||||
Sector()
|
||||
{
|
||||
id = -1;
|
||||
water = false;
|
||||
}
|
||||
};
|
||||
|
||||
typedef unsigned short TSectorID; //smaller than int to allow -1 value. Max number of sectors 65K should be enough for any proper map.
|
||||
typedef boost::multi_array<TSectorID, 3> TSectorArray;
|
||||
|
||||
bool valid; //some kind of lazy eval
|
||||
std::map<int3, int3> parent;
|
||||
TSectorArray sector;
|
||||
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
|
||||
|
||||
std::map<int, Sector> infoOnSectors;
|
||||
std::shared_ptr<boost::multi_array<TerrainTile *, 3>> visibleTiles;
|
||||
|
||||
SectorMap();
|
||||
SectorMap(HeroPtr h);
|
||||
void update();
|
||||
void clear();
|
||||
void exploreNewSector(crint3 pos, int num, CCallback * cbp);
|
||||
void write(crstring fname);
|
||||
|
||||
bool markIfBlocked(TSectorID & sec, crint3 pos, const TerrainTile * t);
|
||||
bool markIfBlocked(TSectorID & sec, crint3 pos);
|
||||
TSectorID & retrieveTile(crint3 pos);
|
||||
TSectorID & retrieveTileN(TSectorArray & vectors, const int3 & pos);
|
||||
const TSectorID & retrieveTileN(const TSectorArray & vectors, const int3 & pos);
|
||||
TerrainTile * getTile(crint3 pos) const;
|
||||
std::vector<const CGObjectInstance *> getNearbyObjs(HeroPtr h, bool sectorsAround);
|
||||
|
||||
void makeParentBFS(crint3 source);
|
||||
|
||||
int3 firstTileToGet(HeroPtr h, crint3 dst); //if h wants to reach tile dst, which tile he should visit to clear the way?
|
||||
int3 findFirstVisitableTile(HeroPtr h, crint3 dst);
|
||||
};
|
@ -324,7 +324,7 @@ int3 CCallback::getGuardingCreaturePosition(int3 tile)
|
||||
if (!gs->map->isInTheMap(tile))
|
||||
return int3(-1,-1,-1);
|
||||
|
||||
return gs->map->guardingCreaturePositions[tile.x][tile.y][tile.z];
|
||||
return gs->map->guardingCreaturePositions[tile.z][tile.x][tile.y];
|
||||
}
|
||||
|
||||
void CCallback::calculatePaths( const CGHeroInstance *hero, CPathsInfo &out)
|
||||
|
@ -218,7 +218,7 @@ void CPlayerInterface::yourTurn()
|
||||
|
||||
STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const ObjectInstanceID & hid)
|
||||
{
|
||||
TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
|
||||
TerrainTile2 & hlp = CGI->mh->ttiles[z][x][y];
|
||||
for (auto & elem : hlp.objects)
|
||||
if (elem.obj && elem.obj->id == hid)
|
||||
{
|
||||
@ -229,7 +229,7 @@ STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SD
|
||||
|
||||
STRONG_INLINE void delObjRect(const int & x, const int & y, const int & z, const ObjectInstanceID & hid)
|
||||
{
|
||||
TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
|
||||
TerrainTile2 & hlp = CGI->mh->ttiles[z][x][y];
|
||||
for (int h=0; h<hlp.objects.size(); ++h)
|
||||
if (hlp.objects[h].obj && hlp.objects[h].obj->id == hid)
|
||||
{
|
||||
@ -244,6 +244,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
if(LOCPLINT != this)
|
||||
return;
|
||||
|
||||
//FIXME: read once and store
|
||||
if(settings["session"]["spectate"].Bool() && settings["session"]["spectate-ignore-hero"].Bool())
|
||||
return;
|
||||
|
||||
@ -255,7 +256,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
|
||||
//AI hero left the visible area (we can't obtain info)
|
||||
//TODO very evil workaround -> retrieve pointer to hero so we could animate it
|
||||
// TODO -> we should not need full CGHeroInstance structure to display animation or it should not be handled by playerint (but by the client itself)
|
||||
const TerrainTile2 & tile = CGI->mh->ttiles[hp.x - 1][hp.y][hp.z];
|
||||
const TerrainTile2 & tile = CGI->mh->ttiles[hp.z][hp.x - 1][hp.y];
|
||||
for(auto & elem : tile.objects)
|
||||
if(elem.obj && elem.obj->id == details.id)
|
||||
hero = dynamic_cast<const CGHeroInstance *>(elem.obj);
|
||||
@ -1738,41 +1739,43 @@ int CPlayerInterface::getLastIndex( std::string namePrefix)
|
||||
|
||||
void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroInstance * ho, const int3 &hp )
|
||||
{
|
||||
auto subArr = (CGI->mh->ttiles)[hp.z];
|
||||
|
||||
if (details.end.x+1 == details.start.x && details.end.y+1 == details.start.y) //tl
|
||||
{
|
||||
//ho->moveDir = 1;
|
||||
ho->isStanding = false;
|
||||
CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -31)));
|
||||
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, -31)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, -31)));
|
||||
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, -31)));
|
||||
subArr[hp.x-3][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -31)));
|
||||
subArr[hp.x-2][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, -31)));
|
||||
subArr[hp.x-1][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, -31)));
|
||||
subArr[hp.x][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, -31)));
|
||||
|
||||
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 1)));
|
||||
subArr[hp.x-3][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 1)));
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 1), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 1), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 1), ho->id);
|
||||
|
||||
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 33)));
|
||||
subArr[hp.x-3][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 33)));
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 33), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 33), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 33), ho->id);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y-2].objects.begin(), subArr[hp.x-3][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y-2].objects.begin(), subArr[hp.x-2][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y-2].objects.begin(), subArr[hp.x-1][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y-2].objects.begin(), subArr[hp.x][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y-1].objects.begin(), subArr[hp.x-3][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y].objects.begin(), subArr[hp.x-3][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x == details.start.x && details.end.y+1 == details.start.y) //t
|
||||
{
|
||||
//ho->moveDir = 2;
|
||||
ho->isStanding = false;
|
||||
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, -31)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, -31)));
|
||||
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, -31)));
|
||||
subArr[hp.x-2][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, -31)));
|
||||
subArr[hp.x-1][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, -31)));
|
||||
subArr[hp.x][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, -31)));
|
||||
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 0, 1), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 32, 1), ho->id);
|
||||
@ -1782,37 +1785,37 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 32, 33), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 64, 33), ho->id);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y-2].objects.begin(), subArr[hp.x-2][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y-2].objects.begin(), subArr[hp.x-1][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y-2].objects.begin(), subArr[hp.x][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x-1 == details.start.x && details.end.y+1 == details.start.y) //tr
|
||||
{
|
||||
//ho->moveDir = 3;
|
||||
ho->isStanding = false;
|
||||
CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, -31)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, -31)));
|
||||
CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, -31)));
|
||||
CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -31)));
|
||||
subArr[hp.x-2][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, -31)));
|
||||
subArr[hp.x-1][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, -31)));
|
||||
subArr[hp.x][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, -31)));
|
||||
subArr[hp.x+1][hp.y-2].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -31)));
|
||||
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 1), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 1), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 1), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 1)));
|
||||
subArr[hp.x+1][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 1)));
|
||||
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 33), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 33), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 33), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 33)));
|
||||
subArr[hp.x+1][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 33)));
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-2][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y-2].objects.begin(), subArr[hp.x-2][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y-2].objects.begin(), subArr[hp.x-1][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y-2].objects.begin(), subArr[hp.x][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y-2].objects.begin(), subArr[hp.x+1][hp.y-2].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y-1].objects.begin(), subArr[hp.x+1][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y].objects.begin(), subArr[hp.x+1][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x-1 == details.start.x && details.end.y == details.start.y) //r
|
||||
{
|
||||
@ -1821,16 +1824,16 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, 0), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, 0), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, 0), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 0)));
|
||||
subArr[hp.x+1][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 0)));
|
||||
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 32), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 32), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 32), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 32)));
|
||||
subArr[hp.x+1][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 32)));
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y-1].objects.begin(), subArr[hp.x+1][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y].objects.begin(), subArr[hp.x+1][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x-1 == details.start.x && details.end.y-1 == details.start.y) //br
|
||||
{
|
||||
@ -1839,26 +1842,26 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, -1, -1), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 31, -1), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 63, -1), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -1)));
|
||||
subArr[hp.x+1][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, -1)));
|
||||
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, -1, 31), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 31, 31), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 63, 31), ho->id);
|
||||
CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 31)));
|
||||
subArr[hp.x+1][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 31)));
|
||||
|
||||
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, 63)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, 63)));
|
||||
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, 63)));
|
||||
CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 63)));
|
||||
subArr[hp.x-2][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -1, 63)));
|
||||
subArr[hp.x-1][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 31, 63)));
|
||||
subArr[hp.x][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 63, 63)));
|
||||
subArr[hp.x+1][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 95, 63)));
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y-1].objects.begin(), subArr[hp.x+1][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y].objects.begin(), subArr[hp.x+1][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x+1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y+1].objects.begin(), subArr[hp.x-2][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y+1].objects.begin(), subArr[hp.x-1][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y+1].objects.begin(), subArr[hp.x][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x+1][hp.y+1].objects.begin(), subArr[hp.x+1][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x == details.start.x && details.end.y-1 == details.start.y) //b
|
||||
{
|
||||
@ -1872,59 +1875,59 @@ void CPlayerInterface::initMovement( const TryMoveHero &details, const CGHeroIns
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 32, 31), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 64, 31), ho->id);
|
||||
|
||||
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, 63)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, 63)));
|
||||
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, 63)));
|
||||
subArr[hp.x-2][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 0, 63)));
|
||||
subArr[hp.x-1][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 32, 63)));
|
||||
subArr[hp.x][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 64, 63)));
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y+1].objects.begin(), subArr[hp.x-2][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y+1].objects.begin(), subArr[hp.x-1][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y+1].objects.begin(), subArr[hp.x][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x+1 == details.start.x && details.end.y-1 == details.start.y) //bl
|
||||
{
|
||||
//ho->moveDir = 7;
|
||||
ho->isStanding = false;
|
||||
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -1)));
|
||||
subArr[hp.x-3][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, -1)));
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, -1), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, -1), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, -1), ho->id);
|
||||
|
||||
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 31)));
|
||||
subArr[hp.x-3][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 31)));
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 31), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 31), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 31), ho->id);
|
||||
|
||||
CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 63)));
|
||||
CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, 63)));
|
||||
CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, 63)));
|
||||
CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, 63)));
|
||||
subArr[hp.x-3][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 63)));
|
||||
subArr[hp.x-2][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 1, 63)));
|
||||
subArr[hp.x-1][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 33, 63)));
|
||||
subArr[hp.x][hp.y+1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, 65, 63)));
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y-1].objects.begin(), subArr[hp.x-3][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y].objects.begin(), subArr[hp.x-3][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-2][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-1][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x][hp.y+1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y+1].objects.begin(), subArr[hp.x-3][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-2][hp.y+1].objects.begin(), subArr[hp.x-2][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-1][hp.y+1].objects.begin(), subArr[hp.x-1][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x][hp.y+1].objects.begin(), subArr[hp.x][hp.y+1].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
else if (details.end.x+1 == details.start.x && details.end.y == details.start.y) //l
|
||||
{
|
||||
//ho->moveDir = 8;
|
||||
ho->isStanding = false;
|
||||
CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 0)));
|
||||
subArr[hp.x-3][hp.y-1].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 0)));
|
||||
subRect(hp.x-2, hp.y-1, hp.z, genRect(32, 32, 1, 0), ho->id);
|
||||
subRect(hp.x-1, hp.y-1, hp.z, genRect(32, 32, 33, 0), ho->id);
|
||||
subRect(hp.x, hp.y-1, hp.z, genRect(32, 32, 65, 0), ho->id);
|
||||
|
||||
CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 32)));
|
||||
subArr[hp.x-3][hp.y].objects.push_back(TerrainTileObject(ho, genRect(32, 32, -31, 32)));
|
||||
subRect(hp.x-2, hp.y, hp.z, genRect(32, 32, 1, 32), ho->id);
|
||||
subRect(hp.x-1, hp.y, hp.z, genRect(32, 32, 33, 32), ho->id);
|
||||
subRect(hp.x, hp.y, hp.z, genRect(32, 32, 65, 32), ho->id);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y-1][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y-1].objects.begin(), subArr[hp.x-3][hp.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.begin(), CGI->mh->ttiles[hp.x-3][hp.y][hp.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[hp.x-3][hp.y].objects.begin(), subArr[hp.x-3][hp.y].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2154,13 +2157,16 @@ void CPlayerInterface::finishMovement( const TryMoveHero &details, const int3 &h
|
||||
subRect(details.end.x, details.end.y, details.end.z, genRect(32, 32, 64, 32), ho->id);
|
||||
|
||||
//restoring good order of objects
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y-1][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-2][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x-1][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.begin(), CGI->mh->ttiles[details.end.x][details.end.y][details.end.z].objects.end(), objectBlitOrderSorter);
|
||||
boost::detail::multi_array::sub_array<TerrainTile2, 2> subArr = (CGI->mh->ttiles)[details.end.z];
|
||||
|
||||
std::stable_sort(subArr[details.end.x-2][details.end.y-1].objects.begin(), subArr[details.end.x-2][details.end.y-1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[details.end.x-1][details.end.y-1].objects.begin(), subArr[details.end.x-1][details.end.y-1].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[details.end.x][details.end.y-1].objects.begin(), subArr[details.end.x][details.end.y-1].objects.end(), objectBlitOrderSorter);
|
||||
|
||||
std::stable_sort(subArr[details.end.x-2][details.end.y].objects.begin(), subArr[details.end.x-2][details.end.y].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[details.end.x-1][details.end.y].objects.begin(), subArr[details.end.x-1][details.end.y].objects.end(), objectBlitOrderSorter);
|
||||
std::stable_sort(subArr[details.end.x][details.end.y].objects.begin(), subArr[details.end.x][details.end.y].objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
|
||||
void CPlayerInterface::gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult )
|
||||
@ -2882,7 +2888,7 @@ void CPlayerInterface::updateAmbientSounds(bool resetAll)
|
||||
{
|
||||
int dist = pos.dist(tile, int3::DIST_CHEBYSHEV);
|
||||
// We want sound for every special terrain on tile and not just one on top
|
||||
for(auto & ttObj : CGI->mh->ttiles[tile.x][tile.y][tile.z].objects)
|
||||
for(auto & ttObj : CGI->mh->ttiles[tile.z][tile.x][tile.y].objects)
|
||||
{
|
||||
if(ttObj.ambientSound)
|
||||
updateSounds(ttObj.ambientSound.get(), dist);
|
||||
|
@ -52,20 +52,22 @@ struct NeighborTilesInfo
|
||||
d1,
|
||||
d2,
|
||||
d3;
|
||||
NeighborTilesInfo(const int3 & pos, const int3 & sizes, const std::vector< std::vector< std::vector<ui8> > > & visibilityMap)
|
||||
NeighborTilesInfo(const int3 & pos, const int3 & sizes, std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap)
|
||||
{
|
||||
auto getTile = [&](int dx, int dy)->bool
|
||||
{
|
||||
if ( dx + pos.x < 0 || dx + pos.x >= sizes.x
|
||||
|| dy + pos.y < 0 || dy + pos.y >= sizes.y)
|
||||
return false;
|
||||
return settings["session"]["spectate"].Bool() ? true : visibilityMap[dx+pos.x][dy+pos.y][pos.z];
|
||||
|
||||
//FIXME: please do not read settings for every tile...
|
||||
return settings["session"]["spectate"].Bool() ? true : (*visibilityMap)[pos.z][dx+pos.x][dy+pos.y];
|
||||
};
|
||||
d7 = getTile(-1, -1); //789
|
||||
d8 = getTile( 0, -1); //456
|
||||
d9 = getTile(+1, -1); //123
|
||||
d4 = getTile(-1, 0);
|
||||
d5 = visibilityMap[pos.x][pos.y][pos.z];
|
||||
d5 = (*visibilityMap)[pos.z][pos.x][pos.y];
|
||||
d6 = getTile(+1, 0);
|
||||
d1 = getTile(-1, +1);
|
||||
d2 = getTile( 0, +1);
|
||||
@ -113,22 +115,9 @@ void CMapHandler::prepareFOWDefs()
|
||||
FoWfullHide[frame] = graphics->fogOfWarFullHide->getImage(frame);
|
||||
|
||||
//initialization of type of full-hide image
|
||||
hideBitmap.resize(sizes.x);
|
||||
for (auto & elem : hideBitmap)
|
||||
{
|
||||
elem.resize(sizes.y);
|
||||
}
|
||||
for (auto & elem : hideBitmap)
|
||||
{
|
||||
for (int j = 0; j < sizes.y; ++j)
|
||||
{
|
||||
elem[j].resize(sizes.z);
|
||||
for(int k = 0; k < sizes.z; ++k)
|
||||
{
|
||||
elem[j][k] = CRandomGenerator::getDefault().nextInt((int)size - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
hideBitmap.resize(boost::extents[sizes.z][sizes.x][sizes.y]);
|
||||
for (int i = 0; i < hideBitmap.num_elements(); i++)
|
||||
hideBitmap.data()[i] = CRandomGenerator::getDefault().nextInt(size - 1);
|
||||
|
||||
size = graphics->fogOfWarPartialHide->size(0);
|
||||
FoWpartialHide.resize(size);
|
||||
@ -211,16 +200,12 @@ void CMapHandler::initTerrainGraphics()
|
||||
|
||||
// Create enough room for the whole map and its frame
|
||||
|
||||
ttiles.resize(sizes.x, frameW, frameW);
|
||||
for (int i=0-frameW;i<ttiles.size()-frameW;i++)
|
||||
{
|
||||
ttiles[i].resize(sizes.y, frameH, frameH);
|
||||
}
|
||||
for (int i=0-frameW;i<ttiles.size()-frameW;i++)
|
||||
{
|
||||
for (int j=0-frameH;j<(int)sizes.y+frameH;j++)
|
||||
ttiles[i][j].resize(sizes.z, 0, 0);
|
||||
}
|
||||
//ttiles.resize(sizes.x, frameW, frameW);
|
||||
|
||||
//FIXME: why do we even handle array with z (surface and undeground) at the same time?
|
||||
|
||||
ttiles.resize(boost::extents[sizes.z][sizes.x + 2 * frameW][sizes.y + 2 * frameH]);
|
||||
ttiles.reindex(std::list<int>{ 0, -frameW, -frameH }); //need to move starting coordinates so that used index is always positive
|
||||
}
|
||||
|
||||
void CMapHandler::initBorderGraphics()
|
||||
@ -321,19 +306,21 @@ void CMapHandler::initObjectRects()
|
||||
obj->coveringAt(currTile.x, currTile.y) // object is visible here
|
||||
)
|
||||
{
|
||||
ttiles[currTile.x][currTile.y][currTile.z].objects.push_back(toAdd);
|
||||
ttiles[currTile.z][currTile.x][currTile.y].objects.push_back(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int ix=0; ix<ttiles.size()-frameW; ++ix)
|
||||
auto shape = ttiles.shape();
|
||||
for(size_t z = 0; z < shape[0]; z++)
|
||||
{
|
||||
for(int iy=0; iy<ttiles[0].size()-frameH; ++iy)
|
||||
for(size_t x = 0; x < shape[1] - frameW; x++)
|
||||
{
|
||||
for(int iz=0; iz<ttiles[0][0].size(); ++iz)
|
||||
for(size_t y = 0; y < shape[2] - frameH; y++)
|
||||
{
|
||||
stable_sort(ttiles[ix][iy][iz].objects.begin(), ttiles[ix][iy][iz].objects.end(), objectBlitOrderSorter);
|
||||
auto & objects = ttiles[z][x][y].objects;
|
||||
stable_sort(objects.begin(), objects.end(), objectBlitOrderSorter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,7 +338,7 @@ void CMapHandler::init()
|
||||
//sizes of terrain
|
||||
sizes.x = map->width;
|
||||
sizes.y = map->height;
|
||||
sizes.z = map->twoLevel ? 2 : 1;
|
||||
sizes.z = map->levels();
|
||||
|
||||
// Total number of visible tiles. Subtract the center tile, then
|
||||
// compute the number of tiles on each side, and reassemble.
|
||||
@ -557,7 +544,9 @@ void CMapHandler::CMapWorldViewBlitter::drawTileOverlay(SDL_Surface * targetSurf
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
|
||||
const bool sameLevel = obj->pos.z == pos.z;
|
||||
const bool isVisible = settings["session"]["spectate"].Bool() ? true : (*info->visibilityMap)[pos.x][pos.y][pos.z];
|
||||
|
||||
//FIXME: Don't read options in a loop :v
|
||||
const bool isVisible = settings["session"]["spectate"].Bool() ? true : (*info->visibilityMap)[pos.z][pos.x][pos.y];
|
||||
const bool isVisitable = obj->visitableAt(pos.x, pos.y);
|
||||
|
||||
if(sameLevel && isVisible && isVisitable)
|
||||
@ -826,11 +815,11 @@ void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const Terrain
|
||||
|
||||
void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
|
||||
{
|
||||
const NeighborTilesInfo neighborInfo(pos, parent->sizes, *info->visibilityMap);
|
||||
const NeighborTilesInfo neighborInfo(pos, parent->sizes, info->visibilityMap);
|
||||
|
||||
int retBitmapID = neighborInfo.getBitmapID();// >=0 -> partial hide, <0 - full hide
|
||||
if (retBitmapID < 0)
|
||||
retBitmapID = - parent->hideBitmap[pos.x][pos.y][pos.z] - 1; //fully hidden
|
||||
retBitmapID = - parent->hideBitmap[pos.z][pos.x][pos.y] - 1; //fully hidden
|
||||
|
||||
std::shared_ptr<IImage> image;
|
||||
|
||||
@ -865,7 +854,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
realTileRect.x = realPos.x;
|
||||
realTileRect.y = realPos.y;
|
||||
|
||||
const TerrainTile2 & tile = parent->ttiles[pos.x][pos.y][pos.z];
|
||||
const TerrainTile2 & tile = parent->ttiles[pos.z][pos.x][pos.y];
|
||||
const TerrainTile & tinfo = parent->map->getTile(pos);
|
||||
const TerrainTile * tinfoUpper = pos.y > 0 ? &parent->map->getTile(int3(pos.x, pos.y - 1, pos.z)) : nullptr;
|
||||
|
||||
@ -896,9 +885,9 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
}
|
||||
else
|
||||
{
|
||||
const TerrainTile2 & tile = parent->ttiles[pos.x][pos.y][pos.z];
|
||||
const TerrainTile2 & tile = parent->ttiles[pos.z][pos.x][pos.y];
|
||||
|
||||
if(!settings["session"]["spectate"].Bool() && !(*info->visibilityMap)[pos.x][pos.y][topTile.z] && !info->showAllTerrain)
|
||||
if(!settings["session"]["spectate"].Bool() && !(*info->visibilityMap)[topTile.z][pos.x][pos.y] && !info->showAllTerrain)
|
||||
drawFow(targetSurf);
|
||||
|
||||
// overlay needs to be drawn over fow, because of artifacts-aura-like spells
|
||||
@ -1105,7 +1094,7 @@ bool CMapHandler::CMapBlitter::canDrawCurrentTile() const
|
||||
if(settings["session"]["spectate"].Bool())
|
||||
return true;
|
||||
|
||||
const NeighborTilesInfo neighbors(pos, parent->sizes, *info->visibilityMap);
|
||||
const NeighborTilesInfo neighbors(pos, parent->sizes, info->visibilityMap);
|
||||
return !neighbors.areAllHidden();
|
||||
}
|
||||
|
||||
@ -1136,7 +1125,7 @@ bool CMapHandler::updateObjectsFade()
|
||||
++iter;
|
||||
else // fade finished
|
||||
{
|
||||
auto &objs = ttiles[pos.x][pos.y][pos.z].objects;
|
||||
auto &objs = ttiles[pos.z][pos.x][pos.y].objects;
|
||||
for (auto objIter = objs.begin(); objIter != objs.end(); ++objIter)
|
||||
{
|
||||
if ((*objIter).fadeAnimKey == (*iter).first)
|
||||
@ -1210,6 +1199,9 @@ bool CMapHandler::printObject(const CGObjectInstance * obj, bool fadein)
|
||||
const int tilesW = bitmap->width()/32;
|
||||
const int tilesH = bitmap->height()/32;
|
||||
|
||||
auto ttilesWidth = ttiles.shape()[1];
|
||||
auto ttilesHeight = ttiles.shape()[2];
|
||||
|
||||
for(int fx=0; fx<tilesW; ++fx)
|
||||
{
|
||||
for(int fy=0; fy<tilesH; ++fy)
|
||||
@ -1220,10 +1212,13 @@ bool CMapHandler::printObject(const CGObjectInstance * obj, bool fadein)
|
||||
cr.x = fx*32;
|
||||
cr.y = fy*32;
|
||||
|
||||
if((obj->pos.x + fx - tilesW+1)>=0 && (obj->pos.x + fx - tilesW+1)<ttiles.size()-frameW && (obj->pos.y + fy - tilesH+1)>=0 && (obj->pos.y + fy - tilesH+1)<ttiles[0].size()-frameH)
|
||||
if((obj->pos.x + fx - tilesW + 1) >= 0 &&
|
||||
(obj->pos.x + fx - tilesW + 1) < ttilesWidth - frameW &&
|
||||
(obj->pos.y + fy - tilesH + 1) >= 0 &&
|
||||
(obj->pos.y + fy - tilesH + 1) < ttilesHeight - frameH)
|
||||
{
|
||||
int3 pos(obj->pos.x + fx - tilesW + 1, obj->pos.y + fy - tilesH + 1, obj->pos.z);
|
||||
TerrainTile2 & curt = ttiles[pos.x][pos.y][pos.z];
|
||||
TerrainTile2 & curt = ttiles[pos.z][pos.x][pos.y];
|
||||
|
||||
TerrainTileObject toAdd(obj, cr, obj->visitableAt(pos.x, pos.y));
|
||||
if (fadein && ADVOPT.objectFading)
|
||||
@ -1252,59 +1247,26 @@ bool CMapHandler::printObject(const CGObjectInstance * obj, bool fadein)
|
||||
|
||||
bool CMapHandler::hideObject(const CGObjectInstance * obj, bool fadeout)
|
||||
{
|
||||
//optimized version which reveals weird bugs with missing def name
|
||||
//auto pos = obj->pos;
|
||||
|
||||
//for (size_t i = pos.x; i > pos.x - obj->getWidth(); i--)
|
||||
//{
|
||||
// for (size_t j = pos.y; j > pos.y - obj->getHeight(); j--)
|
||||
// {
|
||||
// int3 t(i, j, pos.z);
|
||||
// if (!map->isInTheMap(t))
|
||||
// continue;
|
||||
|
||||
// auto &objs = ttiles[i][j][pos.z].objects;
|
||||
// for (size_t x = 0; x < objs.size(); x++)
|
||||
// {
|
||||
// auto ourObj = objs[x].obj;
|
||||
// if (ourObj && ourObj->id == obj->id)
|
||||
// {
|
||||
// if (fadeout && ADVOPT.objectFading) // object should be faded == erase is delayed until the end of fadeout
|
||||
// {
|
||||
// if (startObjectFade(objs[x], false, t))
|
||||
// objs[x].obj = nullptr; //set original pointer to null
|
||||
// else
|
||||
// objs.erase(objs.begin() + x);
|
||||
// }
|
||||
// else
|
||||
// objs.erase(objs.begin() + x);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
for (size_t i = 0; i<map->width; i++)
|
||||
for(size_t z = 0; z < map->levels(); z++)
|
||||
{
|
||||
for (size_t j = 0; j<map->height; j++)
|
||||
for(size_t x = 0; x < map->width; x++)
|
||||
{
|
||||
for (size_t k = 0; k<(map->twoLevel ? 2 : 1); k++)
|
||||
for(size_t y = 0; y < map->height; y++)
|
||||
{
|
||||
auto &objs = ttiles[(int)i][(int)j][(int)k].objects;
|
||||
for (size_t x = 0; x < objs.size(); x++)
|
||||
auto &objs = ttiles[(int)z][(int)x][(int)y].objects;
|
||||
for(size_t i = 0; i < objs.size(); i++)
|
||||
{
|
||||
if (objs[x].obj && objs[x].obj->id == obj->id)
|
||||
if (objs[i].obj && objs[i].obj->id == obj->id)
|
||||
{
|
||||
if (fadeout && ADVOPT.objectFading) // object should be faded == erase is delayed until the end of fadeout
|
||||
{
|
||||
if (startObjectFade(objs[x], false, int3((si32)i, (si32)j, (si32)k)))
|
||||
objs[x].obj = nullptr;
|
||||
if (startObjectFade(objs[i], false, int3((si32)x, (si32)y, (si32)z)))
|
||||
objs[i].obj = nullptr;
|
||||
else
|
||||
objs.erase(objs.begin() + x);
|
||||
objs.erase(objs.begin() + i);
|
||||
}
|
||||
else
|
||||
objs.erase(objs.begin() + x);
|
||||
objs.erase(objs.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1392,7 +1354,7 @@ CMapHandler::CMapHandler()
|
||||
|
||||
bool CMapHandler::hasObjectHole(const int3 & pos) const
|
||||
{
|
||||
const TerrainTile2 & tt = ttiles[pos.x][pos.y][pos.z];
|
||||
const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
|
||||
|
||||
for(auto & elem : tt.objects)
|
||||
{
|
||||
@ -1411,7 +1373,7 @@ void CMapHandler::getTerrainDescr(const int3 & pos, std::string & out, bool isRM
|
||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
||||
return;
|
||||
}
|
||||
const TerrainTile2 & tt = ttiles[pos.x][pos.y][pos.z];
|
||||
const TerrainTile2 & tt = ttiles[pos.z][pos.x][pos.y];
|
||||
bool isTile2Terrain = false;
|
||||
out.clear();
|
||||
|
||||
|
@ -92,7 +92,7 @@ struct MapDrawingInfo
|
||||
{
|
||||
bool scaled;
|
||||
int3 &topTile; // top-left tile in viewport [in tiles]
|
||||
const std::vector< std::vector< std::vector<ui8> > > * visibilityMap;
|
||||
std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap;
|
||||
SDL_Rect * drawBounds; // map rect drawing bounds on screen
|
||||
std::shared_ptr<CAnimation> icons; // holds overlay icons for world view mode
|
||||
float scale; // map scale for world view mode (only if scaled == true)
|
||||
@ -110,9 +110,10 @@ struct MapDrawingInfo
|
||||
|
||||
bool showAllTerrain; //for expert viewEarth
|
||||
|
||||
MapDrawingInfo(int3 &topTile_, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap_, SDL_Rect * drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
|
||||
MapDrawingInfo(int3 &topTile_, std::shared_ptr<const boost::multi_array<ui8, 3>> visibilityMap_, SDL_Rect * drawBounds_, std::shared_ptr<CAnimation> icons_ = nullptr)
|
||||
: scaled(false),
|
||||
topTile(topTile_),
|
||||
|
||||
visibilityMap(visibilityMap_),
|
||||
drawBounds(drawBounds_),
|
||||
icons(icons_),
|
||||
@ -332,7 +333,7 @@ class CMapHandler
|
||||
void initTerrainGraphics();
|
||||
void prepareFOWDefs();
|
||||
public:
|
||||
PseudoV< PseudoV< PseudoV<TerrainTile2> > > ttiles; //informations about map tiles
|
||||
boost::multi_array<TerrainTile2, 3> ttiles; //informations about map tiles [z][x][y]
|
||||
int3 sizes; //map size (x = width, y = height, z = number of levels)
|
||||
const CMap * map;
|
||||
|
||||
@ -368,7 +369,7 @@ public:
|
||||
|
||||
//Fog of War cache (not owned)
|
||||
std::vector<std::shared_ptr<IImage>> FoWfullHide;
|
||||
std::vector<std::vector<std::vector<ui8> > > hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile
|
||||
boost::multi_array<ui8, 3> hideBitmap; //frame indexes (in FoWfullHide) of graphic that should be used to fully hide a tile
|
||||
|
||||
std::vector<std::shared_ptr<IImage>> FoWpartialHide;
|
||||
|
||||
|
@ -380,7 +380,7 @@ void CTerrainRect::show(SDL_Surface * to)
|
||||
{
|
||||
if (adventureInt->mode == EAdvMapMode::NORMAL)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, &LOCPLINT->cb->getVisibilityMap(), &pos);
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), &pos);
|
||||
info.otherheroAnim = true;
|
||||
info.anim = adventureInt->anim;
|
||||
info.heroAnim = adventureInt->heroAnim;
|
||||
@ -407,7 +407,7 @@ void CTerrainRect::showAll(SDL_Surface * to)
|
||||
// world view map is static and doesn't need redraw every frame
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
{
|
||||
MapDrawingInfo info(adventureInt->position, &LOCPLINT->cb->getVisibilityMap(), &pos, adventureInt->worldViewIcons);
|
||||
MapDrawingInfo info(adventureInt->position, LOCPLINT->cb->getVisibilityMap(), &pos, adventureInt->worldViewIcons);
|
||||
info.scaled = true;
|
||||
info.scale = adventureInt->worldViewScale;
|
||||
adventureInt->worldViewOptions.adjustDrawingInfo(info);
|
||||
@ -757,7 +757,7 @@ void CAdvMapInt::fworldViewScale4x()
|
||||
void CAdvMapInt::fswitchLevel()
|
||||
{
|
||||
// with support for future multi-level maps :)
|
||||
int maxLevels = CGI->mh->map->twoLevel ? 2 : 1;
|
||||
int maxLevels = CGI->mh->map->levels();
|
||||
if (maxLevels < 2)
|
||||
return;
|
||||
|
||||
|
@ -1514,7 +1514,7 @@ void CPuzzleWindow::showAll(SDL_Surface * to)
|
||||
Rect mapRect = genRect(544, 591, pos.x + 8, pos.y + 7);
|
||||
int3 topTile = grailPos - moveInt;
|
||||
|
||||
MapDrawingInfo info(topTile, &LOCPLINT->cb->getVisibilityMap(), &mapRect);
|
||||
MapDrawingInfo info(topTile, LOCPLINT->cb->getVisibilityMap(), &mapRect);
|
||||
info.puzzleMode = true;
|
||||
info.grailPos = grailPos;
|
||||
CGI->mh->drawTerrainRectNew(to, &info);
|
||||
|
@ -502,28 +502,29 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
|
||||
}
|
||||
|
||||
//TODO: typedef?
|
||||
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
|
||||
std::shared_ptr<const boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
|
||||
{
|
||||
assert(player.is_initialized());
|
||||
auto team = getPlayerTeam(player.get());
|
||||
|
||||
size_t width = gs->map->width;
|
||||
size_t height = gs->map->height;
|
||||
size_t levels = (gs->map->twoLevel ? 2 : 1);
|
||||
size_t levels = gs->map->levels();
|
||||
|
||||
auto ptr = new boost::multi_array<TerrainTile*, 3>(boost::extents[levels][width][height]);
|
||||
|
||||
boost::multi_array<TerrainTile*, 3> tileArray(boost::extents[width][height][levels]);
|
||||
|
||||
for (size_t x = 0; x < width; x++)
|
||||
for (size_t y = 0; y < height; y++)
|
||||
for (size_t z = 0; z < levels; z++)
|
||||
int3 tile;
|
||||
for(tile.z = 0; tile.z < levels; tile.z++)
|
||||
for(tile.x = 0; tile.x < width; tile.x++)
|
||||
for(tile.y = 0; tile.y < height; tile.y++)
|
||||
{
|
||||
if (team->fogOfWarMap[x][y][z])
|
||||
tileArray[x][y][z] = &gs->map->getTile(int3((si32)x, (si32)y, (si32)z));
|
||||
if ((*team->fogOfWarMap)[tile.z][tile.x][tile.y])
|
||||
(*ptr)[tile.z][tile.x][tile.y] = &gs->map->getTile(tile);
|
||||
else
|
||||
tileArray[x][y][z] = nullptr;
|
||||
(*ptr)[tile.z][tile.x][tile.y] = nullptr;
|
||||
}
|
||||
return std::make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
|
||||
|
||||
return std::shared_ptr<const boost::multi_array<TerrainTile*, 3>>(ptr);
|
||||
}
|
||||
|
||||
EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
|
||||
@ -694,7 +695,7 @@ CGameInfoCallback::CGameInfoCallback(CGameState *GS, boost::optional<PlayerColor
|
||||
player = Player;
|
||||
}
|
||||
|
||||
const std::vector< std::vector< std::vector<ui8> > > & CPlayerSpecificInfoCallback::getVisibilityMap() const
|
||||
std::shared_ptr<const boost::multi_array<ui8, 3>> CPlayerSpecificInfoCallback::getVisibilityMap() const
|
||||
{
|
||||
//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||
return gs->getPlayerTeam(*player)->fogOfWarMap;
|
||||
|
@ -185,7 +185,7 @@ public:
|
||||
virtual const CMapHeader * getMapHeader()const;
|
||||
virtual int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
|
||||
virtual const TerrainTile * getTile(int3 tile, bool verbose = true) const;
|
||||
virtual std::shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
virtual std::shared_ptr<const boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
virtual bool isInTheMap(const int3 &pos) const;
|
||||
virtual void getVisibleTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, int3::EDistanceFormula distanceFormula = int3::DIST_2D) const;
|
||||
virtual void calculatePaths(std::shared_ptr<PathfinderConfig> config);
|
||||
@ -235,7 +235,7 @@ public:
|
||||
|
||||
virtual int getResourceAmount(Res::ERes type) const;
|
||||
virtual TResources getResourceAmount() const;
|
||||
virtual const std::vector< std::vector< std::vector<ui8> > > & getVisibilityMap()const; //returns visibility map
|
||||
virtual std::shared_ptr<const boost::multi_array<ui8, 3>> getVisibilityMap() const; //returns visibility map
|
||||
//virtual const PlayerSettings * getPlayerSettings(PlayerColor color) const;
|
||||
};
|
||||
|
||||
|
@ -954,19 +954,20 @@ void CGameState::initGrailPosition()
|
||||
static const int BORDER_WIDTH = 9; // grail must be at least 9 tiles away from border
|
||||
|
||||
// add all not blocked tiles in range
|
||||
for (int i = BORDER_WIDTH; i < map->width - BORDER_WIDTH ; i++)
|
||||
|
||||
for (int z = 0; z < map->levels(); z++)
|
||||
{
|
||||
for (int j = BORDER_WIDTH; j < map->height - BORDER_WIDTH; j++)
|
||||
for(int x = BORDER_WIDTH; x < map->width - BORDER_WIDTH ; x++)
|
||||
{
|
||||
for (int k = 0; k < (map->twoLevel ? 2 : 1); k++)
|
||||
for(int y = BORDER_WIDTH; y < map->height - BORDER_WIDTH; y++)
|
||||
{
|
||||
const TerrainTile &t = map->getTile(int3(i, j, k));
|
||||
const TerrainTile &t = map->getTile(int3(x, y, z));
|
||||
if(!t.blocked
|
||||
&& !t.visitable
|
||||
&& t.terType.isLand()
|
||||
&& t.terType.isPassable()
|
||||
&& (int)map->grailPos.dist2dSQ(int3(i, j, k)) <= (map->grailRadius * map->grailRadius))
|
||||
allowedPos.push_back(int3(i,j,k));
|
||||
&& (int)map->grailPos.dist2dSQ(int3(x, y, z)) <= (map->grailRadius * map->grailRadius))
|
||||
allowedPos.push_back(int3(x,y,z));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1593,20 +1594,13 @@ void CGameState::giveCampaignBonusToHero(CGHeroInstance * hero)
|
||||
void CGameState::initFogOfWar()
|
||||
{
|
||||
logGlobal->debug("\tFog of war"); //FIXME: should be initialized after all bonuses are set
|
||||
|
||||
int layers = map->levels();
|
||||
for(auto & elem : teams)
|
||||
{
|
||||
elem.second.fogOfWarMap.resize(map->width);
|
||||
for(int g=0; g<map->width; ++g)
|
||||
elem.second.fogOfWarMap[g].resize(map->height);
|
||||
|
||||
for(int g=-0; g<map->width; ++g)
|
||||
for(int h=0; h<map->height; ++h)
|
||||
elem.second.fogOfWarMap[g][h].resize(map->twoLevel ? 2 : 1, 0);
|
||||
|
||||
for(int g=0; g<map->width; ++g)
|
||||
for(int h=0; h<map->height; ++h)
|
||||
for(int v = 0; v < (map->twoLevel ? 2 : 1); ++v)
|
||||
elem.second.fogOfWarMap[g][h][v] = 0;
|
||||
auto fow = elem.second.fogOfWarMap;
|
||||
fow->resize(boost::extents[layers][map->width][map->height]);
|
||||
std::fill(fow->data(), fow->data() + fow->num_elements(), 0);
|
||||
|
||||
for(CGObjectInstance *obj : map->objects)
|
||||
{
|
||||
@ -1616,7 +1610,7 @@ void CGameState::initFogOfWar()
|
||||
getTilesInRange(tiles, obj->getSightCenter(), obj->getSightRadius(), obj->tempOwner, 1);
|
||||
for(int3 tile : tiles)
|
||||
{
|
||||
elem.second.fogOfWarMap[tile.x][tile.y][tile.z] = 1;
|
||||
(*elem.second.fogOfWarMap)[tile.z][tile.x][tile.y] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2019,6 +2013,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out)
|
||||
|
||||
void CGameState::calculatePaths(std::shared_ptr<PathfinderConfig> config)
|
||||
{
|
||||
//FIXME: creating pathfinder is costly, maybe reset / clear is enough?
|
||||
CPathfinder pathfinder(this, config);
|
||||
pathfinder.calculatePaths();
|
||||
}
|
||||
@ -2080,7 +2075,7 @@ std::vector<CGObjectInstance*> CGameState::guardingCreatures (int3 pos) const
|
||||
|
||||
int3 CGameState::guardingCreaturePosition (int3 pos) const
|
||||
{
|
||||
return gs->map->guardingCreaturePositions[pos.x][pos.y][pos.z];
|
||||
return gs->map->guardingCreaturePositions[pos.z][pos.x][pos.y];
|
||||
}
|
||||
|
||||
void CGameState::updateRumor()
|
||||
@ -2164,7 +2159,7 @@ bool CGameState::isVisible(int3 pos, PlayerColor player)
|
||||
if(player.isSpectator())
|
||||
return true;
|
||||
|
||||
return getPlayerTeam(player)->fogOfWarMap[pos.x][pos.y][pos.z];
|
||||
return (*getPlayerTeam(player)->fogOfWarMap)[pos.z][pos.x][pos.y];
|
||||
}
|
||||
|
||||
bool CGameState::isVisible( const CGObjectInstance *obj, boost::optional<PlayerColor> player )
|
||||
@ -3096,6 +3091,7 @@ int ArmyDescriptor::getStrength() const
|
||||
TeamState::TeamState()
|
||||
{
|
||||
setNodeType(TEAM);
|
||||
fogOfWarMap = std::make_shared<boost::multi_array<ui8, 3>>();
|
||||
}
|
||||
|
||||
TeamState::TeamState(TeamState && other):
|
||||
|
@ -33,17 +33,17 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState
|
||||
int3 pos;
|
||||
const PlayerColor player = out.hero->tempOwner;
|
||||
const int3 sizes = gs->getMapSize();
|
||||
const auto & fow = static_cast<const CGameInfoCallback *>(gs)->getPlayerTeam(player)->fogOfWarMap;
|
||||
const auto fow = static_cast<const CGameInfoCallback *>(gs)->getPlayerTeam(player)->fogOfWarMap;
|
||||
|
||||
//make 200% sure that these are loop invariants (also a bit shorter code), let compiler do the rest(loop unswitching)
|
||||
const bool useFlying = options.useFlying;
|
||||
const bool useWaterWalking = options.useWaterWalking;
|
||||
|
||||
for(pos.x=0; pos.x < sizes.x; ++pos.x)
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
for(pos.y=0; pos.y < sizes.y; ++pos.y)
|
||||
for(pos.x=0; pos.x < sizes.x; ++pos.x)
|
||||
{
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
for(pos.y=0; pos.y < sizes.y; ++pos.y)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
if(tile->terType.isWater())
|
||||
@ -1304,7 +1304,7 @@ void CGPath::convert(ui8 mode)
|
||||
CPathsInfo::CPathsInfo(const int3 & Sizes, const CGHeroInstance * hero_)
|
||||
: sizes(Sizes), hero(hero_)
|
||||
{
|
||||
nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][ELayer::NUM_LAYERS]);
|
||||
nodes.resize(boost::extents[ELayer::NUM_LAYERS][sizes.z][sizes.x][sizes.y]);
|
||||
}
|
||||
|
||||
CPathsInfo::~CPathsInfo() = default;
|
||||
@ -1336,11 +1336,11 @@ bool CPathsInfo::getPath(CGPath & out, const int3 & dst) const
|
||||
|
||||
const CGPathNode * CPathsInfo::getNode(const int3 & coord) const
|
||||
{
|
||||
auto landNode = &nodes[coord.x][coord.y][coord.z][ELayer::LAND];
|
||||
auto landNode = &nodes[ELayer::LAND][coord.z][coord.x][coord.y];
|
||||
if(landNode->reachable())
|
||||
return landNode;
|
||||
else
|
||||
return &nodes[coord.x][coord.y][coord.z][ELayer::SAIL];
|
||||
return &nodes[ELayer::SAIL][coord.z][coord.x][coord.y];
|
||||
}
|
||||
|
||||
PathNodeInfo::PathNodeInfo()
|
||||
|
@ -178,7 +178,7 @@ struct DLL_LINKAGE CPathsInfo
|
||||
const CGHeroInstance * hero;
|
||||
int3 hpos;
|
||||
int3 sizes;
|
||||
boost::multi_array<CGPathNode, 4> nodes; //[w][h][level][layer]
|
||||
boost::multi_array<CGPathNode, 4> nodes; //[layer][level][w][h]
|
||||
|
||||
CPathsInfo(const int3 & Sizes, const CGHeroInstance * hero_);
|
||||
~CPathsInfo();
|
||||
@ -189,7 +189,7 @@ struct DLL_LINKAGE CPathsInfo
|
||||
STRONG_INLINE
|
||||
CGPathNode * getNode(const int3 & coord, const ELayer layer)
|
||||
{
|
||||
return &nodes[coord.x][coord.y][coord.z][layer];
|
||||
return &nodes[layer][coord.z][coord.x][coord.y];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
TeamID id; //position in gameState::teams
|
||||
std::set<PlayerColor> players; // members of this team
|
||||
//TODO: boost::array, bool if possible
|
||||
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
|
||||
std::shared_ptr<boost::multi_array<ui8, 3>> fogOfWarMap; //[z][x][y] true - visible, false - hidden
|
||||
|
||||
TeamState();
|
||||
TeamState(TeamState && other);
|
||||
|
@ -38,14 +38,13 @@
|
||||
void CPrivilegedInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
|
||||
{
|
||||
std::vector<int> floors;
|
||||
for (int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
|
||||
for(int b = 0; b < gs->map->levels(); ++b)
|
||||
{
|
||||
floors.push_back(b);
|
||||
}
|
||||
const TerrainTile *tinfo;
|
||||
for (auto zd : floors)
|
||||
{
|
||||
|
||||
for (int xd = 0; xd < gs->map->width; xd++)
|
||||
{
|
||||
for (int yd = 0; yd < gs->map->height; yd++)
|
||||
@ -80,8 +79,8 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3, ShashInt3
|
||||
if(distance <= radious)
|
||||
{
|
||||
if(!player
|
||||
|| (mode == 1 && team->fogOfWarMap[xd][yd][pos.z]==0)
|
||||
|| (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
|
||||
|| (mode == 1 && (*team->fogOfWarMap)[pos.z][xd][yd] == 0)
|
||||
|| (mode == -1 && (*team->fogOfWarMap)[pos.z][xd][yd] == 1)
|
||||
)
|
||||
tiles.insert(int3(xd,yd,pos.z));
|
||||
}
|
||||
@ -103,7 +102,7 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> &
|
||||
std::vector<int> floors;
|
||||
if(level == -1)
|
||||
{
|
||||
for(int b = 0; b < (gs->map->twoLevel ? 2 : 1); ++b)
|
||||
for(int b = 0; b < gs->map->levels(); ++b)
|
||||
{
|
||||
floors.push_back(b);
|
||||
}
|
||||
|
@ -177,8 +177,9 @@ DLL_LINKAGE void SetMovePoints::applyGs(CGameState *gs)
|
||||
DLL_LINKAGE void FoWChange::applyGs(CGameState *gs)
|
||||
{
|
||||
TeamState * team = gs->getPlayerTeam(player);
|
||||
auto fogOfWarMap = team->fogOfWarMap;
|
||||
for(int3 t : tiles)
|
||||
team->fogOfWarMap[t.x][t.y][t.z] = mode;
|
||||
(*fogOfWarMap)[t.z][t.x][t.y] = mode;
|
||||
if (mode == 0) //do not hide too much
|
||||
{
|
||||
std::unordered_set<int3, ShashInt3> tilesRevealed;
|
||||
@ -200,7 +201,7 @@ DLL_LINKAGE void FoWChange::applyGs(CGameState *gs)
|
||||
}
|
||||
}
|
||||
for(int3 t : tilesRevealed) //probably not the most optimal solution ever
|
||||
team->fogOfWarMap[t.x][t.y][t.z] = 1;
|
||||
(*fogOfWarMap)[t.z][t.x][t.y] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,8 +562,9 @@ void TryMoveHero::applyGs(CGameState *gs)
|
||||
gs->map->addBlockVisTiles(h);
|
||||
}
|
||||
|
||||
auto fogOfWarMap = gs->getPlayerTeam(h->getOwner())->fogOfWarMap;
|
||||
for(int3 t : fowRevealed)
|
||||
gs->getPlayerTeam(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
|
||||
(*fogOfWarMap)[t.z][t.x][t.y] = 1;
|
||||
}
|
||||
|
||||
DLL_LINKAGE void NewStructures::applyGs(CGameState *gs)
|
||||
|
@ -14,13 +14,13 @@
|
||||
|
||||
namespace PathfinderUtil
|
||||
{
|
||||
using FoW = std::vector<std::vector<std::vector<ui8> > >;
|
||||
using FoW = std::shared_ptr<const boost::multi_array<ui8, 3>>;
|
||||
using ELayer = EPathfindingLayer;
|
||||
|
||||
template<EPathfindingLayer::EEPathfindingLayer layer>
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const FoW & fow, const PlayerColor player, const CGameState * gs)
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, FoW fow, const PlayerColor player, const CGameState * gs)
|
||||
{
|
||||
if(!fow[pos.x][pos.y][pos.z])
|
||||
if(!(*fow)[pos.z][pos.x][pos.y])
|
||||
return CGPathNode::BLOCKED;
|
||||
|
||||
switch(layer)
|
||||
|
@ -522,10 +522,15 @@ CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
||||
return const_cast<CStack *>(battleGetStackByID(stackID, onlyAlive));
|
||||
}
|
||||
|
||||
BattleInfo::BattleInfo()
|
||||
: round(-1), activeStack(-1), town(nullptr), tile(-1,-1,-1),
|
||||
battlefieldType(BattleField::NONE), terrainType(),
|
||||
tacticsSide(0), tacticDistance(0)
|
||||
BattleInfo::BattleInfo():
|
||||
round(-1),
|
||||
activeStack(-1),
|
||||
town(nullptr),
|
||||
tile(-1,-1,-1),
|
||||
battlefieldType(BattleField::NONE),
|
||||
terrainType(),
|
||||
tacticsSide(0),
|
||||
tacticDistance(0)
|
||||
{
|
||||
setBattle(this);
|
||||
setNodeType(BATTLE);
|
||||
|
@ -322,15 +322,15 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain)
|
||||
|
||||
size_t height = mask.size();
|
||||
size_t width = 0;
|
||||
for (auto & line : mask)
|
||||
for(auto & line : mask)
|
||||
vstd::amax(width, line.String().size());
|
||||
|
||||
setSize((ui32)width, (ui32)height);
|
||||
|
||||
for (size_t i=0; i<mask.size(); i++)
|
||||
for(size_t i = 0; i < mask.size(); i++)
|
||||
{
|
||||
const std::string & line = mask[i].String();
|
||||
for (size_t j=0; j < line.size(); j++)
|
||||
for(size_t j = 0; j < line.size(); j++)
|
||||
usedTiles[mask.size() - 1 - i][line.size() - 1 - j] = charToTile(line[j]);
|
||||
}
|
||||
|
||||
|
@ -149,19 +149,23 @@ static bool ruleIsAny(const std::string & rule)
|
||||
|
||||
///CDrawLinesOperation
|
||||
CDrawLinesOperation::CDrawLinesOperation(CMap * map, const CTerrainSelection & terrainSel, CRandomGenerator * gen):
|
||||
CMapOperation(map), terrainSel(terrainSel), gen(gen)
|
||||
CMapOperation(map),
|
||||
terrainSel(terrainSel),
|
||||
gen(gen)
|
||||
{
|
||||
}
|
||||
|
||||
///CDrawRoadsOperation
|
||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen):
|
||||
CDrawLinesOperation(map, terrainSel, gen), roadType(roadType)
|
||||
CDrawLinesOperation(map, terrainSel,gen),
|
||||
roadType(roadType)
|
||||
{
|
||||
}
|
||||
|
||||
///CDrawRiversOperation
|
||||
CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & riverType, CRandomGenerator * gen):
|
||||
CDrawLinesOperation(map, terrainSel, gen), riverType(riverType)
|
||||
CDrawLinesOperation(map, terrainSel, gen),
|
||||
riverType(riverType)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,11 @@ CMapHeader::CMapHeader() : version(EMapFormat::SOD), height(72), width(72),
|
||||
|
||||
CMapHeader::~CMapHeader()
|
||||
{
|
||||
}
|
||||
|
||||
ui8 CMapHeader::levels() const
|
||||
{
|
||||
return (twoLevel ? 2 : 1);
|
||||
}
|
||||
|
||||
CMap::CMap()
|
||||
@ -246,15 +250,15 @@ CMap::~CMap()
|
||||
{
|
||||
if(terrain)
|
||||
{
|
||||
for (int i=0; i<width; i++)
|
||||
for(int z = 0; z < levels(); z++)
|
||||
{
|
||||
for(int j=0; j<height; j++)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
delete [] terrain[i][j];
|
||||
delete [] guardingCreaturePositions[i][j];
|
||||
delete[] terrain[z][x];
|
||||
delete[] guardingCreaturePositions[z][x];
|
||||
}
|
||||
delete [] terrain[i];
|
||||
delete [] guardingCreaturePositions[i];
|
||||
delete[] terrain[z];
|
||||
delete[] guardingCreaturePositions[z];
|
||||
}
|
||||
delete [] terrain;
|
||||
delete [] guardingCreaturePositions;
|
||||
@ -271,16 +275,16 @@ CMap::~CMap()
|
||||
|
||||
void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
|
||||
{
|
||||
for(int fx=0; fx<obj->getWidth(); ++fx)
|
||||
const int zVal = obj->pos.z;
|
||||
for(int fx = 0; fx < obj->getWidth(); ++fx)
|
||||
{
|
||||
for(int fy=0; fy<obj->getHeight(); ++fy)
|
||||
int xVal = obj->pos.x - fx;
|
||||
for(int fy = 0; fy < obj->getHeight(); ++fy)
|
||||
{
|
||||
int xVal = obj->pos.x - fx;
|
||||
int yVal = obj->pos.y - fy;
|
||||
int zVal = obj->pos.z;
|
||||
if(xVal>=0 && xVal<width && yVal>=0 && yVal<height)
|
||||
if(xVal>=0 && xVal < width && yVal>=0 && yVal < height)
|
||||
{
|
||||
TerrainTile & curt = terrain[xVal][yVal][zVal];
|
||||
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
||||
if(total || obj->visitableAt(xVal, yVal))
|
||||
{
|
||||
curt.visitableObjects -= obj;
|
||||
@ -298,22 +302,22 @@ void CMap::removeBlockVisTiles(CGObjectInstance * obj, bool total)
|
||||
|
||||
void CMap::addBlockVisTiles(CGObjectInstance * obj)
|
||||
{
|
||||
for(int fx=0; fx<obj->getWidth(); ++fx)
|
||||
const int zVal = obj->pos.z;
|
||||
for(int fx = 0; fx < obj->getWidth(); ++fx)
|
||||
{
|
||||
for(int fy=0; fy<obj->getHeight(); ++fy)
|
||||
int xVal = obj->pos.x - fx;
|
||||
for(int fy = 0; fy < obj->getHeight(); ++fy)
|
||||
{
|
||||
int xVal = obj->pos.x - fx;
|
||||
int yVal = obj->pos.y - fy;
|
||||
int zVal = obj->pos.z;
|
||||
if(xVal>=0 && xVal<width && yVal>=0 && yVal<height)
|
||||
if(xVal>=0 && xVal < width && yVal >= 0 && yVal < height)
|
||||
{
|
||||
TerrainTile & curt = terrain[xVal][yVal][zVal];
|
||||
if( obj->visitableAt(xVal, yVal))
|
||||
TerrainTile & curt = terrain[zVal][xVal][yVal];
|
||||
if(obj->visitableAt(xVal, yVal))
|
||||
{
|
||||
curt.visitableObjects.push_back(obj);
|
||||
curt.visitable = true;
|
||||
}
|
||||
if( obj->blockingAt(xVal, yVal))
|
||||
if(obj->blockingAt(xVal, yVal))
|
||||
{
|
||||
curt.blockingObjects.push_back(obj);
|
||||
curt.blocked = true;
|
||||
@ -326,12 +330,14 @@ void CMap::addBlockVisTiles(CGObjectInstance * obj)
|
||||
void CMap::calculateGuardingGreaturePositions()
|
||||
{
|
||||
int levels = twoLevel ? 2 : 1;
|
||||
for (int i=0; i<width; i++)
|
||||
for(int z = 0; z < levels; z++)
|
||||
{
|
||||
for(int j=0; j<height; j++)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for (int k = 0; k < levels; k++)
|
||||
guardingCreaturePositions[i][j][k] = guardingCreaturePosition(int3(i,j,k));
|
||||
for(int y = 0; y < height; y++)
|
||||
{
|
||||
guardingCreaturePositions[z][x][y] = guardingCreaturePosition(int3(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -389,13 +395,13 @@ bool CMap::isInTheMap(const int3 & pos) const
|
||||
TerrainTile & CMap::getTile(const int3 & tile)
|
||||
{
|
||||
assert(isInTheMap(tile));
|
||||
return terrain[tile.x][tile.y][tile.z];
|
||||
return terrain[tile.z][tile.x][tile.y];
|
||||
}
|
||||
|
||||
const TerrainTile & CMap::getTile(const int3 & tile) const
|
||||
{
|
||||
assert(isInTheMap(tile));
|
||||
return terrain[tile.x][tile.y][tile.z];
|
||||
return terrain[tile.z][tile.x][tile.y];
|
||||
}
|
||||
|
||||
bool CMap::isWaterTile(const int3 &pos) const
|
||||
@ -679,17 +685,17 @@ void CMap::removeObject(CGObjectInstance * obj)
|
||||
|
||||
void CMap::initTerrain()
|
||||
{
|
||||
int level = twoLevel ? 2 : 1;
|
||||
terrain = new TerrainTile**[width];
|
||||
guardingCreaturePositions = new int3**[width];
|
||||
for (int i = 0; i < width; ++i)
|
||||
int level = levels();
|
||||
terrain = new TerrainTile**[level];
|
||||
guardingCreaturePositions = new int3**[level];
|
||||
for(int z = 0; z < level; ++z)
|
||||
{
|
||||
terrain[i] = new TerrainTile*[height];
|
||||
guardingCreaturePositions[i] = new int3*[height];
|
||||
for (int j = 0; j < height; ++j)
|
||||
terrain[z] = new TerrainTile*[width];
|
||||
guardingCreaturePositions[z] = new int3*[width];
|
||||
for(int x = 0; x < width; ++x)
|
||||
{
|
||||
terrain[i][j] = new TerrainTile[level];
|
||||
guardingCreaturePositions[i][j] = new int3[level];
|
||||
terrain[z][x] = new TerrainTile[height];
|
||||
guardingCreaturePositions[z][x] = new int3[height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +286,8 @@ public:
|
||||
CMapHeader();
|
||||
virtual ~CMapHeader();
|
||||
|
||||
ui8 levels() const;
|
||||
|
||||
EMapFormat::EMapFormat version; /// The default value is EMapFormat::SOD.
|
||||
si32 height; /// The default value is 72.
|
||||
si32 width; /// The default value is 72.
|
||||
@ -432,18 +434,18 @@ public:
|
||||
h & questIdentifierToId;
|
||||
|
||||
//TODO: viccondetails
|
||||
int level = twoLevel ? 2 : 1;
|
||||
const int level = levels();
|
||||
if(h.saving)
|
||||
{
|
||||
// Save terrain
|
||||
for(int i = 0; i < width ; ++i)
|
||||
for(int z = 0; z < level; ++z)
|
||||
{
|
||||
for(int j = 0; j < height ; ++j)
|
||||
for(int x = 0; x < width; ++x)
|
||||
{
|
||||
for(int k = 0; k < level; ++k)
|
||||
for(int y = 0; y < height; ++y)
|
||||
{
|
||||
h & terrain[i][j][k];
|
||||
h & guardingCreaturePositions[i][j][k];
|
||||
h & terrain[z][x][y];
|
||||
h & guardingCreaturePositions[z][x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -451,26 +453,27 @@ public:
|
||||
else
|
||||
{
|
||||
// Load terrain
|
||||
terrain = new TerrainTile**[width];
|
||||
guardingCreaturePositions = new int3**[width];
|
||||
for(int i = 0; i < width; ++i)
|
||||
terrain = new TerrainTile**[level];
|
||||
guardingCreaturePositions = new int3**[level];
|
||||
for(int z = 0; z < level; ++z)
|
||||
{
|
||||
terrain[i] = new TerrainTile*[height];
|
||||
guardingCreaturePositions[i] = new int3*[height];
|
||||
for(int j = 0; j < height; ++j)
|
||||
terrain[z] = new TerrainTile*[width];
|
||||
guardingCreaturePositions[z] = new int3*[width];
|
||||
for(int x = 0; x < width; ++x)
|
||||
{
|
||||
terrain[i][j] = new TerrainTile[level];
|
||||
guardingCreaturePositions[i][j] = new int3[level];
|
||||
terrain[z][x] = new TerrainTile[height];
|
||||
guardingCreaturePositions[z][x] = new int3[height];
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < width ; ++i)
|
||||
for(int z = 0; z < level; ++z)
|
||||
{
|
||||
for(int j = 0; j < height ; ++j)
|
||||
for(int x = 0; x < width; ++x)
|
||||
{
|
||||
for(int k = 0; k < level; ++k)
|
||||
for(int y = 0; y < height; ++y)
|
||||
{
|
||||
h & terrain[i][j][k];
|
||||
h & guardingCreaturePositions[i][j][k];
|
||||
|
||||
h & terrain[z][x][y];
|
||||
h & guardingCreaturePositions[z][x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ struct DLL_LINKAGE TerrainTile
|
||||
ui8 terView;
|
||||
std::string riverType;
|
||||
ui8 riverDir;
|
||||
std::string roadType;
|
||||
std::string roadType; //TODO: switch to ui8
|
||||
ui8 roadDir;
|
||||
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road);
|
||||
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
|
||||
|
@ -923,18 +923,20 @@ void CMapLoaderH3M::readTerrain()
|
||||
map->initTerrain();
|
||||
|
||||
// Read terrain
|
||||
for(int a = 0; a < 2; ++a)
|
||||
int3 pos;
|
||||
for(pos.z = 0; pos.z < 2; ++pos.z)
|
||||
{
|
||||
if(a == 1 && !map->twoLevel)
|
||||
if(pos.z == 1 && !map->twoLevel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for(int c = 0; c < map->width; c++)
|
||||
//OH3 format is [z][y][x]
|
||||
for(pos.y = 0; pos.y < map->height; pos.y++)
|
||||
{
|
||||
for(int z = 0; z < map->height; z++)
|
||||
for(pos.x = 0; pos.x < map->width; pos.x++)
|
||||
{
|
||||
auto & tile = map->getTile(int3(z, c, a));
|
||||
auto & tile = map->getTile(pos);
|
||||
tile.terType = Terrain::createTerrainTypeH3M(reader.readUInt8());
|
||||
tile.terView = reader.readUInt8();
|
||||
tile.riverType = RIVER_NAMES[reader.readUInt8()];
|
||||
|
@ -162,8 +162,8 @@ std::string CMapGenerator::getMapDescription() const
|
||||
|
||||
std::stringstream ss;
|
||||
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
|
||||
", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
|
||||
randomSeed % map->map().width % map->map().height % (map->map().twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions.getPlayerCount()) %
|
||||
", levels %d, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
|
||||
randomSeed % map->map().width % map->map().height % map->map().levels() % static_cast<int>(mapGenOptions.getPlayerCount()) %
|
||||
static_cast<int>(mapGenOptions.getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions.getWaterContent()] %
|
||||
monsterStrengthStr[monsterStrengthIndex]);
|
||||
|
||||
|
@ -498,24 +498,24 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
|
||||
zone->setPos(int3(total.x / size, total.y / size, total.z / size));
|
||||
};
|
||||
|
||||
int levels = map.map().twoLevel ? 2 : 1;
|
||||
int levels = map.map().levels();
|
||||
|
||||
/*
|
||||
1. Create Voronoi diagram
|
||||
2. find current center of mass for each zone. Move zone to that center to balance zones sizes
|
||||
*/
|
||||
|
||||
for (int i = 0; i<width; i++)
|
||||
int3 pos;
|
||||
for(pos.z = 0; pos.z < levels; pos.z++)
|
||||
{
|
||||
for (int j = 0; j<height; j++)
|
||||
for(pos.x = 0; pos.x < width; pos.x++)
|
||||
{
|
||||
for (int k = 0; k < levels; k++)
|
||||
for(pos.y = 0; pos.y < height; pos.y++)
|
||||
{
|
||||
distances.clear();
|
||||
int3 pos(i, j, k);
|
||||
for (auto zone : zones)
|
||||
for(auto zone : zones)
|
||||
{
|
||||
if (zone.second->getPos().z == k)
|
||||
if (zone.second->getPos().z == pos.z)
|
||||
distances.push_back(std::make_pair(zone.second, (float)pos.dist2dSQ(zone.second->getPos())));
|
||||
else
|
||||
distances.push_back(std::make_pair(zone.second, std::numeric_limits<float>::max()));
|
||||
@ -533,17 +533,16 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
|
||||
for (auto zone : zones)
|
||||
zone.second->clearTiles(); //now populate them again
|
||||
|
||||
for (int i=0; i<width; i++)
|
||||
for (pos.z = 0; pos.z < levels; pos.z++)
|
||||
{
|
||||
for(int j=0; j<height; j++)
|
||||
for (pos.x = 0; pos.x < width; pos.x++)
|
||||
{
|
||||
for (int k = 0; k < levels; k++)
|
||||
for (pos.y = 0; pos.y < height; pos.y++)
|
||||
{
|
||||
distances.clear();
|
||||
int3 pos(i, j, k);
|
||||
for (auto zone : zones)
|
||||
{
|
||||
if (zone.second->getPos().z == k)
|
||||
if (zone.second->getPos().z == pos.z)
|
||||
distances.push_back (std::make_pair(zone.second, metric(pos, zone.second->getPos())));
|
||||
else
|
||||
distances.push_back (std::make_pair(zone.second, std::numeric_limits<float>::max()));
|
||||
|
@ -175,46 +175,4 @@ void createObstaclesCommon2(RmgMap & map, CRandomGenerator & generator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//tighten obstacles to improve visuals
|
||||
|
||||
/*for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
int blockedTiles = 0;
|
||||
int freeTiles = 0;
|
||||
|
||||
for (int z = 0; z < (map.map().twoLevel ? 2 : 1); z++)
|
||||
{
|
||||
for (int x = 0; x < map.map().width; x++)
|
||||
{
|
||||
for (int y = 0; y < map.map().height; y++)
|
||||
{
|
||||
int3 tile(x, y, z);
|
||||
if (!map.isPossible(tile)) //only possible tiles can change
|
||||
continue;
|
||||
|
||||
int blockedNeighbours = 0;
|
||||
int freeNeighbours = 0;
|
||||
map.foreach_neighbour(tile, [&map, &blockedNeighbours, &freeNeighbours](int3 &pos)
|
||||
{
|
||||
if (map.isBlocked(pos))
|
||||
blockedNeighbours++;
|
||||
if (map.isFree(pos))
|
||||
freeNeighbours++;
|
||||
});
|
||||
if (blockedNeighbours > 4)
|
||||
{
|
||||
map.setOccupied(tile, ETileType::BLOCKED);
|
||||
blockedTiles++;
|
||||
}
|
||||
else if (freeNeighbours > 4)
|
||||
{
|
||||
map.setOccupied(tile, ETileType::FREE);
|
||||
freeTiles++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logGlobal->trace("Set %d tiles to BLOCKED and %d tiles to FREE", blockedTiles, freeTiles);
|
||||
}*/
|
||||
}
|
||||
|
@ -39,29 +39,30 @@ public:
|
||||
|
||||
public:
|
||||
MODIFICATOR(ObjectManager);
|
||||
|
||||
|
||||
|
||||
void process() override;
|
||||
void init() override;
|
||||
|
||||
|
||||
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
||||
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
|
||||
void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget);
|
||||
|
||||
|
||||
bool createRequiredObjects();
|
||||
|
||||
|
||||
int3 findPlaceForObject(const rmg::Area & searchArea, rmg::Object & obj, si32 min_dist, OptimizeType optimizer) const;
|
||||
int3 findPlaceForObject(const rmg::Area & searchArea, rmg::Object & obj, std::function<float(const int3)> weightFunction, OptimizeType optimizer) const;
|
||||
|
||||
|
||||
rmg::Path placeAndConnectObject(const rmg::Area & searchArea, rmg::Object & obj, si32 min_dist, bool isGuarded, bool onlyStraight, OptimizeType optimizer) const;
|
||||
rmg::Path placeAndConnectObject(const rmg::Area & searchArea, rmg::Object & obj, std::function<float(const int3)> weightFunction, bool isGuarded, bool onlyStraight, OptimizeType optimizer) const;
|
||||
|
||||
|
||||
CGCreature * chooseGuard(si32 strength, bool zoneGuard = false);
|
||||
bool addGuard(rmg::Object & object, si32 strength, bool zoneGuard = false);
|
||||
void placeObject(rmg::Object & object, bool guarded, bool updateDistance);
|
||||
|
||||
|
||||
void updateDistances(const rmg::Object & obj);
|
||||
void createDistancesPriorityQueue();
|
||||
|
||||
|
||||
const rmg::Area & getVisitableArea() const;
|
||||
|
||||
std::vector<CGObjectInstance*> getMines() const;
|
||||
|
@ -73,8 +73,8 @@ void RmgMap::initTiles(CMapGenerator & generator)
|
||||
{
|
||||
mapInstance->initTerrain();
|
||||
|
||||
tiles.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->twoLevel ? 2 : 1]);
|
||||
zoneColouring.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->twoLevel ? 2 : 1]);
|
||||
tiles.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->levels()]);
|
||||
zoneColouring.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->levels()]);
|
||||
|
||||
//init native town count with 0
|
||||
for (auto faction : VLC->townh->getAllowedFactions())
|
||||
@ -302,7 +302,7 @@ void RmgMap::dump(bool zoneId) const
|
||||
{
|
||||
static int id = 0;
|
||||
std::ofstream out(boost::to_string(boost::format("zone_%d.txt") % id++));
|
||||
int levels = mapInstance->twoLevel ? 2 : 1;
|
||||
int levels = mapInstance->levels();
|
||||
int width = mapInstance->width;
|
||||
int height = mapInstance->height;
|
||||
for (int k = 0; k < levels; k++)
|
||||
|
@ -369,16 +369,16 @@ void Modificator::dump()
|
||||
{
|
||||
std::ofstream out(boost::to_string(boost::format("seed_%d_modzone_%d_%s.txt") % generator.getRandomSeed() % zone.getId() % getName()));
|
||||
auto & mapInstance = map.map();
|
||||
int levels = mapInstance.twoLevel ? 2 : 1;
|
||||
int levels = mapInstance.levels();
|
||||
int width = mapInstance.width;
|
||||
int height = mapInstance.height;
|
||||
for (int k = 0; k < levels; k++)
|
||||
for(int z = 0; z < levels; z++)
|
||||
{
|
||||
for(int j=0; j<height; j++)
|
||||
{
|
||||
for (int i=0; i<width; i++)
|
||||
for(int i=0; i<width; i++)
|
||||
{
|
||||
out << dump(int3(i, j, k));
|
||||
out << dump(int3(i, j, z));
|
||||
}
|
||||
out << std::endl;
|
||||
}
|
||||
|
@ -560,6 +560,20 @@ public:
|
||||
data = boost::optional<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void load(boost::multi_array<T, 3> & data)
|
||||
{
|
||||
ui32 length = readAndCheckLength();
|
||||
ui32 x, y, z;
|
||||
load(x);
|
||||
load(y);
|
||||
load(z);
|
||||
data.resize(boost::extents[x][y][z]);
|
||||
assert(length == data.num_elements()); //x*y*z should be equal to number of elements
|
||||
for(ui32 i = 0; i < length; i++)
|
||||
load(data.data()[i]);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CLoadFile : public IBinaryReader
|
||||
|
@ -350,6 +350,18 @@ public:
|
||||
save((ui8)0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void save(const boost::multi_array<T, 3> &data)
|
||||
{
|
||||
ui32 length = data.num_elements();
|
||||
*this & length;
|
||||
auto shape = data.shape();
|
||||
ui32 x = shape[0], y = shape[1], z = shape[2];
|
||||
*this & x & y & z;
|
||||
for(ui32 i = 0; i < length; i++)
|
||||
save(data.data()[i]);
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CSaveFile : public IBinaryWriter
|
||||
|
@ -571,7 +571,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
|
||||
|
||||
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||
|
||||
const auto & fowMap = env->getCb()->getPlayerTeam(parameters.caster->getOwner())->fogOfWarMap;
|
||||
const auto fowMap = env->getCb()->getPlayerTeam(parameters.caster->getOwner())->fogOfWarMap;
|
||||
|
||||
for(const CGObjectInstance * obj : env->getMap()->objects)
|
||||
{
|
||||
@ -580,7 +580,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
|
||||
{
|
||||
ObjectPosInfo posInfo(obj);
|
||||
|
||||
if(fowMap[posInfo.pos.x][posInfo.pos.y][posInfo.pos.z] == 0)
|
||||
if((*fowMap)[posInfo.pos.x][posInfo.pos.y][posInfo.pos.z] == 0)
|
||||
pack.objectPositions.push_back(posInfo);
|
||||
}
|
||||
}
|
||||
|
@ -1993,12 +1993,14 @@ void CGameHandler::newTurn()
|
||||
fw.mode = 1;
|
||||
fw.player = player;
|
||||
// find all hidden tiles
|
||||
const auto & fow = getPlayerTeam(player)->fogOfWarMap;
|
||||
for (size_t i=0; i<fow.size(); i++)
|
||||
for (size_t j=0; j<fow.at(i).size(); j++)
|
||||
for (size_t k=0; k<fow.at(i).at(j).size(); k++)
|
||||
if (!fow.at(i).at(j).at(k))
|
||||
fw.tiles.insert(int3((si32)i,(si32)j,(si32)k));
|
||||
const auto fow = getPlayerTeam(player)->fogOfWarMap;
|
||||
|
||||
auto shape = fow->shape();
|
||||
for(size_t z = 0; z < shape[0]; z++)
|
||||
for(size_t x = 0; x < shape[1]; x++)
|
||||
for(size_t y = 0; y < shape[2]; y++)
|
||||
if (!(*fow)[z][x][y])
|
||||
fw.tiles.insert(int3(x, y, z));
|
||||
|
||||
sendAndApply (&fw);
|
||||
}
|
||||
@ -7012,13 +7014,15 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
||||
fc.mode = (cheat == "vcmieagles" ? 1 : 0);
|
||||
fc.player = player;
|
||||
const auto & fowMap = gs->getPlayerTeam(player)->fogOfWarMap;
|
||||
auto hlp_tab = new int3[gs->map->width * gs->map->height * (gs->map->twoLevel ? 2 : 1)];
|
||||
auto hlp_tab = new int3[gs->map->width * gs->map->height * (gs->map->levels())];
|
||||
int lastUnc = 0;
|
||||
for (int i = 0; i < gs->map->width; i++)
|
||||
for (int j = 0; j < gs->map->height; j++)
|
||||
for (int k = 0; k < (gs->map->twoLevel ? 2 : 1); k++)
|
||||
if (!fowMap.at(i).at(j).at(k) || !fc.mode)
|
||||
hlp_tab[lastUnc++] = int3(i, j, k);
|
||||
|
||||
for(int z = 0; z < gs->map->levels(); z++)
|
||||
for(int x = 0; x < gs->map->width; x++)
|
||||
for(int y = 0; y < gs->map->height; y++)
|
||||
if(!(*fowMap)[z][x][y] || !fc.mode)
|
||||
hlp_tab[lastUnc++] = int3(x, y, z);
|
||||
|
||||
fc.tiles.insert(hlp_tab, hlp_tab + lastUnc);
|
||||
delete [] hlp_tab;
|
||||
sendAndApply(&fc);
|
||||
|
Loading…
Reference in New Issue
Block a user