mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-15 13:33:36 +02:00
Merge branch 'develop' into FFMpeg
This commit is contained in:
commit
ca05087c3b
@ -58,6 +58,7 @@
|
||||
"object" : {
|
||||
"index" : 0,
|
||||
"rmg" : {
|
||||
"zoneLimit" : 1,
|
||||
"value" : 100,
|
||||
"rarity" : 100
|
||||
}
|
||||
@ -106,11 +107,16 @@
|
||||
},
|
||||
|
||||
"redwoodObservatory" : {
|
||||
"index" :58,
|
||||
"index" :58,
|
||||
"handler" : "observatory",
|
||||
"types" : {
|
||||
"object" : {
|
||||
"index" : 0,
|
||||
"templates" :
|
||||
{
|
||||
"base" : { "animation" : "avxredw.def", "visitableFrom" : [ "---", "+++", "+++" ], "mask" : [ "VV", "VV", "VA"], "allowedTerrains":["grass", "swamp", "dirt", "sand", "lava", "rough"] },
|
||||
"snow" : { "animation" : "avxreds0.def", "visitableFrom" : [ "---", "+++", "+++" ], "mask" : [ "VV", "VV", "VA"], "allowedTerrains":["snow"] }
|
||||
},
|
||||
"rmg" : {
|
||||
"zoneLimit" : 1,
|
||||
"value" : 750,
|
||||
@ -629,6 +635,7 @@
|
||||
"object" : {
|
||||
"index" : 0,
|
||||
"rmg" : {
|
||||
"zoneLimit" : 1,
|
||||
"value" : 100,
|
||||
"rarity" : 20
|
||||
}
|
||||
|
@ -408,12 +408,12 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
||||
return t->hasBuilt(id);
|
||||
};
|
||||
|
||||
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
||||
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||
|
||||
if (!building->requirements.test(buildTest))
|
||||
return EBuildingState::PREREQUIRES;
|
||||
|
||||
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
||||
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||
|
||||
if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
|
||||
return EBuildingState::MISSING_BASE;
|
||||
|
||||
|
@ -815,8 +815,8 @@ void CGameState::initNewGame()
|
||||
CStopWatch sw;
|
||||
|
||||
// Gen map
|
||||
CMapGenerator mapGenerator(scenarioOps->mapGenOptions, scenarioOps->seedToBeUsed);
|
||||
map = mapGenerator.generate().release();
|
||||
CMapGenerator mapGenerator;
|
||||
map = mapGenerator.generate(scenarioOps->mapGenOptions.get(), scenarioOps->seedToBeUsed).release();
|
||||
|
||||
// Update starting options
|
||||
for(int i = 0; i < map->players.size(); ++i)
|
||||
@ -1849,7 +1849,10 @@ void CGameState::initMapObjects()
|
||||
for(CGObjectInstance *obj : map->objects)
|
||||
{
|
||||
if(obj)
|
||||
{
|
||||
logGlobal->traceStream() << boost::format ("Calling Init for object %d, %d") % obj->ID % obj->subID;
|
||||
obj->initObj();
|
||||
}
|
||||
}
|
||||
for(CGObjectInstance *obj : map->objects)
|
||||
{
|
||||
@ -3518,5 +3521,6 @@ CPathfinder::CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance
|
||||
|
||||
CRandomGenerator & CGameState::getRandomGenerator()
|
||||
{
|
||||
logGlobal->traceStream() << "Fetching CGameState::rand with seed " << rand.nextInt();
|
||||
return rand;
|
||||
}
|
||||
|
@ -853,14 +853,14 @@ void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
|
||||
{
|
||||
assert(!vstd::contains(children, child));
|
||||
children.push_back(child);
|
||||
BONUS_LOG_LINE(child->nodeName() << " #attached to# " << nodeName());
|
||||
//BONUS_LOG_LINE(child->nodeName() << " #attached to# " << nodeName());
|
||||
}
|
||||
|
||||
void CBonusSystemNode::childDetached(CBonusSystemNode *child)
|
||||
{
|
||||
assert(vstd::contains(children, child));
|
||||
children -= child;
|
||||
BONUS_LOG_LINE(child->nodeName() << " #detached from# " << nodeName());
|
||||
//BONUS_LOG_LINE(child->nodeName() << " #detached from# " << nodeName());
|
||||
}
|
||||
|
||||
void CBonusSystemNode::detachFromAll()
|
||||
|
@ -222,7 +222,7 @@ public:
|
||||
h & exp & level & name & biography & portrait & mana & secSkills & movement
|
||||
& sex & inTownGarrison & spells & patrol & moveDir & skillsInfo;
|
||||
h & visitedTown & boat;
|
||||
h & type & specialty & commander;
|
||||
h & type & specialty & commander & visitedObjects;
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
//visitied town pointer will be restored by map serialization method
|
||||
}
|
||||
|
@ -271,6 +271,8 @@ BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRan
|
||||
|
||||
void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
||||
{
|
||||
//logGlobal->debugStream() << "Seed used to configure bank is " << rng.nextInt();
|
||||
|
||||
auto bank = dynamic_cast<CBank*>(object);
|
||||
|
||||
bank->resetDuration = bankResetDuration;
|
||||
@ -282,6 +284,7 @@ void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRando
|
||||
assert(totalChance != 0);
|
||||
|
||||
si32 selectedChance = rng.nextInt(totalChance - 1);
|
||||
//logGlobal->debugStream() << "Selected chance for bank config is " << selectedChance;
|
||||
|
||||
for (auto & node : levels)
|
||||
{
|
||||
|
@ -632,6 +632,11 @@ std::string CGResource::getHoverText(PlayerColor player) const
|
||||
return VLC->generaltexth->restypes[subID];
|
||||
}
|
||||
|
||||
CGResource::CGResource()
|
||||
{
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
void CGResource::initObj()
|
||||
{
|
||||
blockVisit = true;
|
||||
|
@ -182,6 +182,7 @@ public:
|
||||
ui32 amount; //0 if random
|
||||
std::string message;
|
||||
|
||||
CGResource();
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
|
@ -65,7 +65,7 @@ si8 CMapGenOptions::getPlayerCount() const
|
||||
|
||||
void CMapGenOptions::setPlayerCount(si8 value)
|
||||
{
|
||||
assert((value >= 2 && value <= PlayerColor::PLAYER_LIMIT_I) || value == RANDOM_SIZE);
|
||||
assert((value >= 1 && value <= PlayerColor::PLAYER_LIMIT_I) || value == RANDOM_SIZE);
|
||||
playerCount = value;
|
||||
resetPlayersMap();
|
||||
}
|
||||
|
@ -24,10 +24,9 @@ void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3&
|
||||
}
|
||||
|
||||
|
||||
CMapGenerator::CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed /*= std::time(nullptr)*/) :
|
||||
mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0), zonesTotal(0)
|
||||
CMapGenerator::CMapGenerator() :
|
||||
monolithIndex(0), zonesTotal(0)
|
||||
{
|
||||
rand.setSeed(randomSeed);
|
||||
}
|
||||
|
||||
void CMapGenerator::initTiles()
|
||||
@ -78,8 +77,11 @@ void CMapGenerator::initPrisonsRemaining()
|
||||
prisonsRemaining = std::max<int> (0, prisonsRemaining - 16 * map->players.size()); //so at least 16 heroes will be available for every player
|
||||
}
|
||||
|
||||
std::unique_ptr<CMap> CMapGenerator::generate()
|
||||
std::unique_ptr<CMap> CMapGenerator::generate(CMapGenOptions * mapGenOptions, int randomSeed /*= std::time(nullptr)*/)
|
||||
{
|
||||
this->mapGenOptions = mapGenOptions;
|
||||
this->randomSeed = randomSeed;
|
||||
rand.setSeed(this->randomSeed);
|
||||
mapGenOptions->finalize(rand);
|
||||
|
||||
map = make_unique<CMap>();
|
||||
@ -95,7 +97,7 @@ std::unique_ptr<CMap> CMapGenerator::generate()
|
||||
genZones();
|
||||
map->calculateGuardingGreaturePositions(); //clear map so that all tiles are unguarded
|
||||
fillZones();
|
||||
//updated fuarded tiles will be calculated in CGameState::initMapObjects()
|
||||
//updated guarded tiles will be calculated in CGameState::initMapObjects()
|
||||
}
|
||||
catch (rmgException &e)
|
||||
{
|
||||
|
@ -51,12 +51,12 @@ public:
|
||||
class DLL_LINKAGE CMapGenerator
|
||||
{
|
||||
public:
|
||||
explicit CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed = std::time(nullptr));
|
||||
explicit CMapGenerator();
|
||||
~CMapGenerator(); // required due to unique_ptr
|
||||
|
||||
std::unique_ptr<CMap> generate();
|
||||
std::unique_ptr<CMap> generate(CMapGenOptions * mapGenOptions, int RandomSeed = std::time(nullptr));
|
||||
|
||||
shared_ptr<CMapGenOptions> mapGenOptions;
|
||||
CMapGenOptions * mapGenOptions;
|
||||
std::unique_ptr<CMap> map;
|
||||
CRandomGenerator rand;
|
||||
int randomSeed;
|
||||
|
@ -620,6 +620,7 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength,
|
||||
auto guard = new CGCreature();
|
||||
guard->ID = Obj::MONSTER;
|
||||
guard->subID = creId;
|
||||
guard->character = 1; //MUST be initialized or switch will diverge
|
||||
auto hlp = new CStackInstance(creId, amount);
|
||||
//will be set during initialization
|
||||
guard->putStack(SlotID(0), hlp);
|
||||
@ -670,10 +671,11 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
ui32 desiredValue = gen->rand.nextInt(minValue, maxValue);
|
||||
|
||||
int currentValue = 0;
|
||||
CGObjectInstance * object = nullptr;
|
||||
while (currentValue < minValue)
|
||||
while (currentValue < desiredValue)
|
||||
{
|
||||
treasures[info.nextTreasurePos] = nullptr;
|
||||
|
||||
@ -697,21 +699,22 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
break;
|
||||
}
|
||||
|
||||
int remaining = maxValue - currentValue;
|
||||
|
||||
ObjectInfo oi = getRandomObject(gen, info, remaining);
|
||||
object = oi.generateObject();
|
||||
if (!object)
|
||||
ObjectInfo oi = getRandomObject(gen, info, desiredValue - currentValue);
|
||||
if (!oi.value) //0 value indicates no object
|
||||
{
|
||||
vstd::erase_if_present(treasures, info.nextTreasurePos);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = oi.generateObject();
|
||||
|
||||
//remove from possible objects
|
||||
auto oiptr = std::find(possibleObjects.begin(), possibleObjects.end(), oi);
|
||||
assert (oiptr != possibleObjects.end());
|
||||
oiptr->maxPerZone--;
|
||||
if (!oiptr->maxPerZone)
|
||||
possibleObjects.erase(oiptr);
|
||||
//TODO
|
||||
|
||||
//update treasure pile area
|
||||
@ -730,34 +733,38 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
info.blockedPositions.insert(blockPos);
|
||||
}
|
||||
info.occupiedPositions.insert(visitablePos);
|
||||
}
|
||||
|
||||
currentValue += oi.value;
|
||||
currentValue += oi.value;
|
||||
|
||||
treasures[info.nextTreasurePos] = object;
|
||||
treasures[info.nextTreasurePos] = object;
|
||||
|
||||
//now find place for next object
|
||||
int3 placeFound(-1,-1,-1);
|
||||
//now find place for next object
|
||||
int3 placeFound(-1,-1,-1);
|
||||
|
||||
for (auto tile : boundary)
|
||||
{
|
||||
if (gen->isPossible(tile)) //we can place new treasure only on possible tile
|
||||
//randomize next position from among possible ones
|
||||
std::vector<int3> boundaryCopy (boundary.begin(), boundary.end());
|
||||
RandomGeneratorUtil::randomShuffle(boundaryCopy, gen->rand);
|
||||
|
||||
for (auto tile : boundaryCopy)
|
||||
{
|
||||
bool here = true;
|
||||
gen->foreach_neighbour (tile, [gen, &here](int3 pos)
|
||||
if (gen->isPossible(tile)) //we can place new treasure only on possible tile
|
||||
{
|
||||
if (!(gen->isBlocked(pos) || gen->isPossible(pos)))
|
||||
here = false;
|
||||
});
|
||||
if (here)
|
||||
{
|
||||
placeFound = tile;
|
||||
break;
|
||||
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())
|
||||
info.nextTreasurePos = placeFound;
|
||||
if (placeFound.valid())
|
||||
info.nextTreasurePos = placeFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (treasures.size())
|
||||
@ -865,6 +872,8 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||
{
|
||||
if (gen->isPossible(treasure.first))
|
||||
gen->setOccupied (treasure.first, ETileType::BLOCKED);
|
||||
|
||||
delete treasure.second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1077,7 +1086,8 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
|
||||
|
||||
void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
|
||||
{
|
||||
const double minDistance = std::max<float>(15.0f / sqrt(totalDensity), 2);
|
||||
//this is squared distance for optimization purposes
|
||||
const double minDistance = std::max<float>(200.f / totalDensity, 4);
|
||||
//distance lower than 2 causes objects to overlap and crash
|
||||
|
||||
do {
|
||||
@ -1230,7 +1240,7 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, float min_di
|
||||
bool allTilesAvailable = true;
|
||||
gen->foreach_neighbour (tile, [&gen, &allTilesAvailable](int3 neighbour)
|
||||
{
|
||||
if (!(gen->isPossible(neighbour) || gen->isBlocked(neighbour)))
|
||||
if (!(gen->isPossible(neighbour) || gen->shouldBeBlocked(neighbour)))
|
||||
{
|
||||
allTilesAvailable = false; //all present tiles must be already blocked or ready for new objects
|
||||
}
|
||||
@ -1488,19 +1498,20 @@ bool CRmgTemplateZone::guardObject(CMapGenerator* gen, CGObjectInstance* object,
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 value)
|
||||
ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 remaining)
|
||||
{
|
||||
//int objectsVisitableFromBottom = 0; //for debug
|
||||
|
||||
std::vector<std::pair<ui32, ObjectInfo>> tresholds;
|
||||
ui32 total = 0;
|
||||
|
||||
ui32 minValue = 0.25f * value;
|
||||
//calculate actual treasure value range based on remaining value
|
||||
ui32 minValue = 0.25f * remaining;
|
||||
|
||||
//roulette wheel
|
||||
for (ObjectInfo &oi : possibleObjects) //copy constructor turned out to be costly
|
||||
{
|
||||
if (oi.value >= minValue && oi.value <= value && oi.maxPerZone > 0)
|
||||
if (oi.value >= minValue && oi.value <= remaining && oi.maxPerZone > 0)
|
||||
{
|
||||
int3 newVisitableOffset = oi.templ.getVisitableOffset(); //visitablePos assumes object will be shifter by visitableOffset
|
||||
int3 newVisitablePos = info.nextTreasurePos;
|
||||
@ -1590,16 +1601,17 @@ ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileI
|
||||
continue;
|
||||
|
||||
total += oi.probability;
|
||||
//assert (oi.value > 0);
|
||||
tresholds.push_back (std::make_pair (total, oi));
|
||||
}
|
||||
}
|
||||
|
||||
//logGlobal->infoStream() << boost::format ("Number of objects visitable from bottom: %d") % objectsVisitableFromBottom;
|
||||
|
||||
//Generate pandora Box with gold if the value is extremely high
|
||||
ObjectInfo oi;
|
||||
if (tresholds.empty())
|
||||
{
|
||||
ObjectInfo oi;
|
||||
//Generate pandora Box with gold if the value is extremely high
|
||||
if (minValue > 20000) //we don't have object valuable enough
|
||||
{
|
||||
oi.generateObject = [minValue]() -> CGObjectInstance *
|
||||
@ -1614,25 +1626,28 @@ ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileI
|
||||
oi.value = minValue;
|
||||
oi.probability = 0;
|
||||
}
|
||||
else
|
||||
else //generate empty object with 0 value if the value if we can't spawn anything
|
||||
{
|
||||
oi.generateObject = [gen]() -> CGObjectInstance *
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
oi.setTemplate(Obj::PANDORAS_BOX, 0, terrainType); //TODO: null template or something? should be never used, but hell knows
|
||||
oi.value = 0;
|
||||
oi.value = 0; // this field is checked to determine no object
|
||||
oi.probability = 0;
|
||||
}
|
||||
return oi;
|
||||
}
|
||||
|
||||
int r = gen->rand.nextInt (1, total);
|
||||
|
||||
for (auto t : tresholds)
|
||||
else
|
||||
{
|
||||
if (r <= t.first)
|
||||
return t.second;
|
||||
int r = gen->rand.nextInt (1, total);
|
||||
|
||||
for (auto t : tresholds)
|
||||
{
|
||||
if (r <= t.first)
|
||||
return t.second;
|
||||
}
|
||||
assert (0); //we should never be here
|
||||
}
|
||||
//FIXME: control reaches end of non-void function. Missing return?
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ public:
|
||||
std::vector<CTreasureInfo> getTreasureInfo();
|
||||
std::set<int3>* getFreePaths();
|
||||
|
||||
ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 value);
|
||||
ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 remaining);
|
||||
|
||||
void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false);
|
||||
|
||||
|
@ -38,7 +38,7 @@ int3 CZonePlacer::cords (const float3 f) const
|
||||
return int3(std::max(0.f, (f.x * gen->map->width)-1), std::max(0.f, (f.y * gen->map->height-1)), f.z);
|
||||
}
|
||||
|
||||
void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGenerator * rand)
|
||||
void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenerator * rand)
|
||||
{
|
||||
//gravity-based algorithm
|
||||
|
||||
@ -207,7 +207,7 @@ d = 0.01 * dx^3 - 0.1618 * dx^2 + 1 * dx + ...
|
||||
return dx * (1 + dx * (0.1 + dx * 0.01)) + dy * (1.618 + dy * (-0.1618 + dy * 0.01618));
|
||||
}
|
||||
|
||||
void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
|
||||
void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
||||
{
|
||||
logGlobal->infoStream() << "Starting zone colouring";
|
||||
|
||||
|
@ -43,8 +43,8 @@ public:
|
||||
float metric (const int3 &a, const int3 &b) const;
|
||||
~CZonePlacer();
|
||||
|
||||
void placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGenerator * rand);
|
||||
void assignZones(shared_ptr<CMapGenOptions> mapGenOptions);
|
||||
void placeZones(const CMapGenOptions * mapGenOptions, CRandomGenerator * rand);
|
||||
void assignZones(const CMapGenOptions * mapGenOptions);
|
||||
|
||||
private:
|
||||
//metric coefiicients
|
||||
|
Loading…
x
Reference in New Issue
Block a user