1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +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:
Nordsoft91 2022-05-23 13:08:36 +03:00 committed by GitHub
parent c293b655f5
commit a8265c7052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 42 deletions

View File

@ -838,14 +838,14 @@ std::string CGResource::getHoverText(PlayerColor player) const
CGResource::CGResource()
{
amount = 0;
amount = CGResource::RANDOM_AMOUNT;
}
void CGResource::initObj(CRandomGenerator & rand)
{
blockVisit = true;
if(!amount)
if(amount == CGResource::RANDOM_AMOUNT)
{
switch(subID)
{

View File

@ -215,7 +215,9 @@ protected:
class DLL_LINKAGE CGResource : public CArmedInstance
{
public:
static const ui32 RANDOM_AMOUNT = 0;
ui32 amount; //0 if random
std::string message;
CGResource();

View File

@ -790,6 +790,10 @@ void CRmgTemplateZone::addCloseObject(CGObjectInstance * obj, si32 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)
{
@ -1106,14 +1110,17 @@ void CRmgTemplateZone::initTownType ()
//cut a ring around town to ensure crunchPath always hits it.
auto cutPathAroundTown = [this](const CGTownInstance * town)
{
for (auto blockedTile : town->getBlockedPos())
{
gen->foreach_neighbour(blockedTile, [this](const int3 & pos)
auto clearPos = [this](const int3 & pos)
{
if (gen->isPossible(pos))
gen->setOccupied(pos, ETileType::FREE);
});
};
for (auto blockedTile : town->getBlockedPos())
{
gen->foreach_neighbour(blockedTile, clearPos);
}
//clear town entry
gen->foreach_neighbour(town->visitablePos()+int3{0,1,0}, clearPos);
};
auto addNewTowns = [&totalTowns, this, &cutPathAroundTown](int count, bool hasFort, PlayerColor player)
@ -1294,53 +1301,39 @@ void CRmgTemplateZone::paintZoneTerrain (ETerrainType terrainType)
bool CRmgTemplateZone::placeMines ()
{
static const Res::ERes woodOre[] = {Res::ERes::WOOD, Res::ERes::ORE};
static const Res::ERes preciousResources[] = {Res::ERes::GEMS, Res::ERes::CRYSTAL, Res::ERes::MERCURY, Res::ERes::SULFUR};
using namespace Res;
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 =
{
VLC->objtypeh->getHandlerFor(Obj::MINE, 0),
VLC->objtypeh->getHandlerFor(Obj::MINE, 1),
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)
};
std::vector<CGMine*> createdMines;
for (const auto & res : woodOre)
for(const auto & mineInfo : mines)
{
for (int i = 0; i < mines[res]; i++)
ERes res = (ERes)mineInfo.first;
for(int i = 0; i < mineInfo.second; ++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->tempOwner = PlayerColor::NEUTRAL;
mine->producedQuantity = mine->defaultResProduction();
if (!i)
addCloseObject(mine, 1500); //only firts one is close
createdMines.push_back(mine);
if(!i && (res == ERes::WOOD || res == ERes::ORE))
addCloseObject(mine, mineValue.at(res)); //only first woor&ore mines are close
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());
mine->producedResource = res;
mine->tempOwner = PlayerColor::NEUTRAL;
mine->producedQuantity = mine->defaultResProduction();
addRequiredObject(mine, 3500);
auto resourse = (CGResource*) VLC->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create(ObjectTemplate());
resourse->amount = CGResource::RANDOM_AMOUNT;
addNearbyObject(resourse, mine);
}
}
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;
}
@ -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;
}

View File

@ -111,6 +111,7 @@ public:
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget);
void addToConnectLater(const int3& src);
bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
@ -173,6 +174,7 @@ private:
//content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
std::vector<std::pair<CGObjectInstance*, CGObjectInstance*>> nearbyObjects;
std::vector<CGObjectInstance*> objects;
//placement info