mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Treasure piles can now cover several tiles.
This commit is contained in:
parent
c470b9606b
commit
e54c816c92
@ -377,7 +377,7 @@ int3 whereToExplore(HeroPtr h)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeDuplicates (nearbyVisitableObjs); //one object may occupy multiple tiles
|
vstd::removeDuplicates (nearbyVisitableObjs); //one object may occupy multiple tiles
|
||||||
boost::sort(nearbyVisitableObjs, isCloser);
|
boost::sort(nearbyVisitableObjs, isCloser);
|
||||||
if(nearbyVisitableObjs.size())
|
if(nearbyVisitableObjs.size())
|
||||||
return nearbyVisitableObjs.back()->visitablePos();
|
return nearbyVisitableObjs.back()->visitablePos();
|
||||||
|
@ -135,44 +135,6 @@ bool objWithID(const CGObjectInstance *obj)
|
|||||||
return obj->ID == id;
|
return obj->ID == id;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container, typename Item>
|
|
||||||
bool erase_if_present(Container &c, const Item &item)
|
|
||||||
{
|
|
||||||
auto i = std::find(c.begin(), c.end(), item);
|
|
||||||
if (i != c.end())
|
|
||||||
{
|
|
||||||
c.erase(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename V, typename Item, typename Item2>
|
|
||||||
bool erase_if_present(std::map<Item,V> & c, const Item2 &item)
|
|
||||||
{
|
|
||||||
auto i = c.find(item);
|
|
||||||
if (i != c.end())
|
|
||||||
{
|
|
||||||
c.erase(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container, typename Pred>
|
|
||||||
void erase(Container &c, Pred pred)
|
|
||||||
{
|
|
||||||
c.erase(boost::remove_if(c, pred), c.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void removeDuplicates(std::vector<T> &vec)
|
|
||||||
{
|
|
||||||
boost::sort(vec);
|
|
||||||
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string strFromInt3(int3 pos);
|
std::string strFromInt3(int3 pos);
|
||||||
void foreach_tile_pos(std::function<void(const int3& pos)> foo);
|
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_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3& pos)> foo); // avoid costly retrieval of thread-specific pointer
|
||||||
|
38
Global.h
38
Global.h
@ -608,6 +608,44 @@ namespace vstd
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename Item>
|
||||||
|
bool erase_if_present(Container &c, const Item &item)
|
||||||
|
{
|
||||||
|
auto i = std::find(c.begin(), c.end(), item);
|
||||||
|
if (i != c.end())
|
||||||
|
{
|
||||||
|
c.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename V, typename Item, typename Item2>
|
||||||
|
bool erase_if_present(std::map<Item,V> & c, const Item2 &item)
|
||||||
|
{
|
||||||
|
auto i = c.find(item);
|
||||||
|
if (i != c.end())
|
||||||
|
{
|
||||||
|
c.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Container, typename Pred>
|
||||||
|
void erase(Container &c, Pred pred)
|
||||||
|
{
|
||||||
|
c.erase(boost::remove_if(c, pred), c.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void removeDuplicates(std::vector<T> &vec)
|
||||||
|
{
|
||||||
|
boost::sort(vec);
|
||||||
|
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
|
||||||
|
}
|
||||||
|
|
||||||
using boost::math::round;
|
using boost::math::round;
|
||||||
}
|
}
|
||||||
using vstd::operator-=;
|
using vstd::operator-=;
|
||||||
|
@ -124,6 +124,8 @@ DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
|
|||||||
CGHeroInstance *h = gs->getHero(hid);
|
CGHeroInstance *h = gs->getHero(hid);
|
||||||
CGTownInstance *t = gs->getTown(tid);
|
CGTownInstance *t = gs->getTown(tid);
|
||||||
|
|
||||||
|
assert(h);
|
||||||
|
assert(t);
|
||||||
if(start())
|
if(start())
|
||||||
t->setVisitingHero(h);
|
t->setVisitingHero(h);
|
||||||
else
|
else
|
||||||
|
@ -460,7 +460,11 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
|
|||||||
|
|
||||||
bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||||
{
|
{
|
||||||
//TODO: read treasure values from template
|
|
||||||
|
std::map<int3, CGObjectInstance *> treasures;
|
||||||
|
std::set<int3> boundary;
|
||||||
|
int3 guardPos;
|
||||||
|
int3 nextTreasurePos = pos;
|
||||||
|
|
||||||
//default values
|
//default values
|
||||||
int maxValue = 5000;
|
int maxValue = 5000;
|
||||||
@ -477,6 +481,28 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
|||||||
CGObjectInstance * object = nullptr;
|
CGObjectInstance * object = nullptr;
|
||||||
while (currentValue < minValue)
|
while (currentValue < minValue)
|
||||||
{
|
{
|
||||||
|
//TODO: this works only for 1-tile objects
|
||||||
|
//make sure our shape is consistent
|
||||||
|
treasures[nextTreasurePos] = nullptr;
|
||||||
|
for (auto treasurePos : treasures)
|
||||||
|
{
|
||||||
|
gen->foreach_neighbour (treasurePos.first, [gen, &boundary](int3 pos)
|
||||||
|
{
|
||||||
|
boundary.insert(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (auto treasurePos : treasures)
|
||||||
|
{
|
||||||
|
//leaving only boundary around objects
|
||||||
|
vstd::erase_if_present (boundary, treasurePos.first);
|
||||||
|
}
|
||||||
|
for (auto tile : boundary)
|
||||||
|
{
|
||||||
|
//we can't extend boundary anymore
|
||||||
|
if (!(gen->isBlocked(tile) || gen->isPossible(tile)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int remaining = maxValue - currentValue;
|
int remaining = maxValue - currentValue;
|
||||||
|
|
||||||
auto oi = getRandomObject(gen, remaining);
|
auto oi = getRandomObject(gen, remaining);
|
||||||
@ -484,13 +510,47 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
|||||||
if (!object)
|
if (!object)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//TODO: generate actual zone and not just all objects on a pile
|
|
||||||
currentValue += oi.value;
|
currentValue += oi.value;
|
||||||
placeObject(gen, object, pos);
|
|
||||||
}
|
treasures[nextTreasurePos] = object;
|
||||||
if (object)
|
|
||||||
|
//now find place for next object
|
||||||
|
int3 placeFound(-1,-1,-1);
|
||||||
|
for (auto tile : boundary)
|
||||||
{
|
{
|
||||||
guardObject (gen, object, currentValue);
|
if (gen->isPossible(tile)) //we can place new treasure only on possible tile
|
||||||
|
{
|
||||||
|
bool here = true;
|
||||||
|
gen->foreach_neighbour (tile, [gen, &here](int3 pos)
|
||||||
|
{
|
||||||
|
if (!(gen->isBlocked(pos) || gen->isPossible(pos)))
|
||||||
|
here = false;
|
||||||
|
});
|
||||||
|
if (here)
|
||||||
|
{
|
||||||
|
placeFound = tile;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (placeFound.valid())
|
||||||
|
nextTreasurePos = placeFound;
|
||||||
|
}
|
||||||
|
if (treasures.size())
|
||||||
|
{
|
||||||
|
for (auto treasure : treasures)
|
||||||
|
{
|
||||||
|
placeObject(gen, treasure.second, treasure.first);
|
||||||
|
}
|
||||||
|
guardPos = *RandomGeneratorUtil::nextItem(boundary, gen->rand);
|
||||||
|
if (addMonster(gen, guardPos, currentValue))
|
||||||
|
{//block only if object is guarded
|
||||||
|
for (auto tile : boundary)
|
||||||
|
{
|
||||||
|
if (gen->isPossible(tile))
|
||||||
|
gen->setOccupied (tile, ETileType::BLOCKED);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else //we did not place eveyrthing successfully
|
else //we did not place eveyrthing successfully
|
||||||
@ -680,13 +740,12 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
|||||||
town->builtBuildings.insert(BuildingID::DEFAULT);
|
town->builtBuildings.insert(BuildingID::DEFAULT);
|
||||||
|
|
||||||
placeObject(gen, town, getPos() + town->getVisitableOffset()); //towns are big objects and should be centered around visitable position
|
placeObject(gen, town, getPos() + town->getVisitableOffset()); //towns are big objects and should be centered around visitable position
|
||||||
logGlobal->traceStream() << "Placed object";
|
|
||||||
|
|
||||||
logGlobal->traceStream() << "Fill player info " << player_id;
|
logGlobal->traceStream() << "Fill player info " << player_id;
|
||||||
auto & playerInfo = gen->map->players[player_id];
|
|
||||||
// Update player info
|
// Update player info
|
||||||
playerInfo.allowedFactions.clear();
|
playerInfo.allowedFactions.clear();
|
||||||
playerInfo.allowedFactions.insert(town->subID);
|
playerInfo.allowedFactions.insert(townId);
|
||||||
playerInfo.hasMainTown = true;
|
playerInfo.hasMainTown = true;
|
||||||
playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
|
playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
|
||||||
playerInfo.generateHeroAtMainTown = true;
|
playerInfo.generateHeroAtMainTown = true;
|
||||||
@ -913,7 +972,7 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
|
|||||||
}
|
}
|
||||||
auto guard_tile = *RandomGeneratorUtil::nextItem(tiles, gen->rand);
|
auto guard_tile = *RandomGeneratorUtil::nextItem(tiles, gen->rand);
|
||||||
|
|
||||||
if (addMonster (gen, guard_tile, str)) //do not lace obstacles aroudn unguarded object
|
if (addMonster (gen, guard_tile, str)) //do not place obstacles around unguarded object
|
||||||
{
|
{
|
||||||
for (auto pos : tiles)
|
for (auto pos : tiles)
|
||||||
gen->setOccupied(pos, ETileType::BLOCKED);
|
gen->setOccupied(pos, ETileType::BLOCKED);
|
||||||
|
Loading…
Reference in New Issue
Block a user