mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +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);
|
||||
if(nearbyVisitableObjs.size())
|
||||
return nearbyVisitableObjs.back()->visitablePos();
|
||||
|
@ -135,44 +135,6 @@ bool objWithID(const CGObjectInstance *obj)
|
||||
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);
|
||||
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
|
||||
|
38
Global.h
38
Global.h
@ -608,6 +608,44 @@ namespace vstd
|
||||
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 vstd::operator-=;
|
||||
|
@ -124,6 +124,8 @@ DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
|
||||
CGHeroInstance *h = gs->getHero(hid);
|
||||
CGTownInstance *t = gs->getTown(tid);
|
||||
|
||||
assert(h);
|
||||
assert(t);
|
||||
if(start())
|
||||
t->setVisitingHero(h);
|
||||
else
|
||||
|
@ -460,7 +460,11 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
|
||||
|
||||
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
|
||||
int maxValue = 5000;
|
||||
@ -477,6 +481,28 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
CGObjectInstance * object = nullptr;
|
||||
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;
|
||||
|
||||
auto oi = getRandomObject(gen, remaining);
|
||||
@ -484,13 +510,47 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
if (!object)
|
||||
break;
|
||||
|
||||
//TODO: generate actual zone and not just all objects on a pile
|
||||
currentValue += oi.value;
|
||||
placeObject(gen, object, pos);
|
||||
}
|
||||
if (object)
|
||||
|
||||
treasures[nextTreasurePos] = 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;
|
||||
}
|
||||
else //we did not place eveyrthing successfully
|
||||
@ -680,13 +740,12 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
||||
town->builtBuildings.insert(BuildingID::DEFAULT);
|
||||
|
||||
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;
|
||||
auto & playerInfo = gen->map->players[player_id];
|
||||
|
||||
// Update player info
|
||||
playerInfo.allowedFactions.clear();
|
||||
playerInfo.allowedFactions.insert(town->subID);
|
||||
playerInfo.allowedFactions.insert(townId);
|
||||
playerInfo.hasMainTown = true;
|
||||
playerInfo.posOfMainTown = town->pos - int3(2, 0, 0);
|
||||
playerInfo.generateHeroAtMainTown = true;
|
||||
@ -913,7 +972,7 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
|
||||
}
|
||||
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)
|
||||
gen->setOccupied(pos, ETileType::BLOCKED);
|
||||
|
Loading…
Reference in New Issue
Block a user