mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-13 01:20:34 +02:00
[0002285] Implement feature with extra resources near mines (#742)
* RMG: clear start position * [0002285] some heaps of resources are placed nearby mines * Fix leak in case of inability to place resource * Fix indentation according to vcmi style * Add constant for random amount of resources * Code review fixes
This commit is contained in:
@ -838,14 +838,14 @@ std::string CGResource::getHoverText(PlayerColor player) const
|
|||||||
|
|
||||||
CGResource::CGResource()
|
CGResource::CGResource()
|
||||||
{
|
{
|
||||||
amount = 0;
|
amount = CGResource::RANDOM_AMOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGResource::initObj(CRandomGenerator & rand)
|
void CGResource::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
|
|
||||||
if(!amount)
|
if(amount == CGResource::RANDOM_AMOUNT)
|
||||||
{
|
{
|
||||||
switch(subID)
|
switch(subID)
|
||||||
{
|
{
|
||||||
|
@ -215,7 +215,9 @@ protected:
|
|||||||
class DLL_LINKAGE CGResource : public CArmedInstance
|
class DLL_LINKAGE CGResource : public CArmedInstance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const ui32 RANDOM_AMOUNT = 0;
|
||||||
ui32 amount; //0 if random
|
ui32 amount; //0 if random
|
||||||
|
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
CGResource();
|
CGResource();
|
||||||
|
@ -790,6 +790,10 @@ void CRmgTemplateZone::addCloseObject(CGObjectInstance * obj, si32 strength)
|
|||||||
{
|
{
|
||||||
closeObjects.push_back(std::make_pair(obj, strength));
|
closeObjects.push_back(std::make_pair(obj, strength));
|
||||||
}
|
}
|
||||||
|
void CRmgTemplateZone::addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget)
|
||||||
|
{
|
||||||
|
nearbyObjects.push_back(std::make_pair(obj, nearbyTarget));
|
||||||
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::addToConnectLater(const int3& src)
|
void CRmgTemplateZone::addToConnectLater(const int3& src)
|
||||||
{
|
{
|
||||||
@ -1106,14 +1110,17 @@ void CRmgTemplateZone::initTownType ()
|
|||||||
//cut a ring around town to ensure crunchPath always hits it.
|
//cut a ring around town to ensure crunchPath always hits it.
|
||||||
auto cutPathAroundTown = [this](const CGTownInstance * town)
|
auto cutPathAroundTown = [this](const CGTownInstance * town)
|
||||||
{
|
{
|
||||||
|
auto clearPos = [this](const int3 & pos)
|
||||||
|
{
|
||||||
|
if (gen->isPossible(pos))
|
||||||
|
gen->setOccupied(pos, ETileType::FREE);
|
||||||
|
};
|
||||||
for (auto blockedTile : town->getBlockedPos())
|
for (auto blockedTile : town->getBlockedPos())
|
||||||
{
|
{
|
||||||
gen->foreach_neighbour(blockedTile, [this](const int3 & pos)
|
gen->foreach_neighbour(blockedTile, clearPos);
|
||||||
{
|
|
||||||
if (gen->isPossible(pos))
|
|
||||||
gen->setOccupied(pos, ETileType::FREE);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
//clear town entry
|
||||||
|
gen->foreach_neighbour(town->visitablePos()+int3{0,1,0}, clearPos);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto addNewTowns = [&totalTowns, this, &cutPathAroundTown](int count, bool hasFort, PlayerColor player)
|
auto addNewTowns = [&totalTowns, this, &cutPathAroundTown](int count, bool hasFort, PlayerColor player)
|
||||||
@ -1294,53 +1301,39 @@ void CRmgTemplateZone::paintZoneTerrain (ETerrainType terrainType)
|
|||||||
|
|
||||||
bool CRmgTemplateZone::placeMines ()
|
bool CRmgTemplateZone::placeMines ()
|
||||||
{
|
{
|
||||||
static const Res::ERes woodOre[] = {Res::ERes::WOOD, Res::ERes::ORE};
|
using namespace Res;
|
||||||
static const Res::ERes preciousResources[] = {Res::ERes::GEMS, Res::ERes::CRYSTAL, Res::ERes::MERCURY, Res::ERes::SULFUR};
|
static const std::map<ERes, int> mineValue{{ERes::WOOD, 1500}, {ERes::ORE, 1500}, {ERes::GEMS, 3500}, {ERes::CRYSTAL, 3500}, {ERes::MERCURY, 3500}, {ERes::SULFUR, 3500}, {ERes::GOLD, 7000}};
|
||||||
|
|
||||||
std::array<TObjectTypeHandler, 7> factory =
|
std::vector<CGMine*> createdMines;
|
||||||
|
|
||||||
|
for(const auto & mineInfo : mines)
|
||||||
{
|
{
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 0),
|
ERes res = (ERes)mineInfo.first;
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 1),
|
for(int i = 0; i < mineInfo.second; ++i)
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 2),
|
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 3),
|
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 4),
|
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 5),
|
|
||||||
VLC->objtypeh->getHandlerFor(Obj::MINE, 6)
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto & res : woodOre)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < mines[res]; i++)
|
|
||||||
{
|
{
|
||||||
auto mine = (CGMine *) factory.at(static_cast<si32>(res))->create(ObjectTemplate());
|
auto mine = (CGMine*) VLC->objtypeh->getHandlerFor(Obj::MINE, res)->create(ObjectTemplate());
|
||||||
mine->producedResource = res;
|
mine->producedResource = res;
|
||||||
mine->tempOwner = PlayerColor::NEUTRAL;
|
mine->tempOwner = PlayerColor::NEUTRAL;
|
||||||
mine->producedQuantity = mine->defaultResProduction();
|
mine->producedQuantity = mine->defaultResProduction();
|
||||||
if (!i)
|
createdMines.push_back(mine);
|
||||||
addCloseObject(mine, 1500); //only firts one is close
|
|
||||||
|
if(!i && (res == ERes::WOOD || res == ERes::ORE))
|
||||||
|
addCloseObject(mine, mineValue.at(res)); //only first woor&ore mines are close
|
||||||
else
|
else
|
||||||
addRequiredObject(mine, 1500);
|
addRequiredObject(mine, mineValue.at(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto & res : preciousResources)
|
|
||||||
|
//create extra resources
|
||||||
|
for(auto * mine : createdMines)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mines[res]; i++)
|
for(int rc = gen->rand.nextInt(1, 3); rc > 0; --rc)
|
||||||
{
|
{
|
||||||
auto mine = (CGMine *) factory.at(static_cast<si32>(res))->create(ObjectTemplate());
|
auto resourse = (CGResource*) VLC->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create(ObjectTemplate());
|
||||||
mine->producedResource = res;
|
resourse->amount = CGResource::RANDOM_AMOUNT;
|
||||||
mine->tempOwner = PlayerColor::NEUTRAL;
|
addNearbyObject(resourse, mine);
|
||||||
mine->producedQuantity = mine->defaultResProduction();
|
|
||||||
addRequiredObject(mine, 3500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < mines[Res::GOLD]; i++)
|
|
||||||
{
|
|
||||||
auto mine = (CGMine *) factory.at(Res::GOLD)->create(ObjectTemplate());
|
|
||||||
mine->producedResource = Res::GOLD;
|
|
||||||
mine->tempOwner = PlayerColor::NEUTRAL;
|
|
||||||
mine->producedQuantity = mine->defaultResProduction();
|
|
||||||
addRequiredObject(mine, 7000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1463,6 +1456,38 @@ bool CRmgTemplateZone::createRequiredObjects()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//create nearby objects (e.g. extra resources close to mines)
|
||||||
|
for(const auto & object : nearbyObjects)
|
||||||
|
{
|
||||||
|
auto obj = object.first;
|
||||||
|
std::set<int3> possiblePositions;
|
||||||
|
for (auto blockedTile : object.second->getBlockedPos())
|
||||||
|
{
|
||||||
|
gen->foreachDirectNeighbour(blockedTile, [this, &possiblePositions](int3 pos)
|
||||||
|
{
|
||||||
|
if (!gen->isBlocked(pos))
|
||||||
|
{
|
||||||
|
//some resources still could be unaccessible, at least one free cell shall be
|
||||||
|
gen->foreach_neighbour(pos, [this, &possiblePositions, &pos](int3 p)
|
||||||
|
{
|
||||||
|
if(gen->isFree(p))
|
||||||
|
possiblePositions.insert(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(possiblePositions.empty())
|
||||||
|
{
|
||||||
|
delete obj; //is it correct way to prevent leak?
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto pos = *RandomGeneratorUtil::nextItem(possiblePositions, gen->rand);
|
||||||
|
placeObject(obj, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ public:
|
|||||||
|
|
||||||
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
||||||
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
|
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
|
||||||
|
void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget);
|
||||||
void addToConnectLater(const int3& src);
|
void addToConnectLater(const int3& src);
|
||||||
bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
|
bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
|
||||||
bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
|
bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
|
||||||
@ -173,6 +174,7 @@ private:
|
|||||||
//content info
|
//content info
|
||||||
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
|
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
|
||||||
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
|
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
|
||||||
|
std::vector<std::pair<CGObjectInstance*, CGObjectInstance*>> nearbyObjects;
|
||||||
std::vector<CGObjectInstance*> objects;
|
std::vector<CGObjectInstance*> objects;
|
||||||
|
|
||||||
//placement info
|
//placement info
|
||||||
|
Reference in New Issue
Block a user