mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-14 02:33:51 +02:00
Moved object type randomization to object class
This commit is contained in:
parent
03e1169781
commit
dcb8f4fc7b
@ -567,7 +567,7 @@ public:
|
|||||||
constexpr MapObjectSubID(const IdentifierBase & value):
|
constexpr MapObjectSubID(const IdentifierBase & value):
|
||||||
Identifier<MapObjectSubID>(value.getNum())
|
Identifier<MapObjectSubID>(value.getNum())
|
||||||
{}
|
{}
|
||||||
constexpr MapObjectSubID(int32_t value):
|
constexpr MapObjectSubID(int32_t value = -1):
|
||||||
Identifier<MapObjectSubID>(value)
|
Identifier<MapObjectSubID>(value)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -153,223 +153,6 @@ HeroTypeID CGameState::pickUnusedHeroTypeRandomly(const PlayerColor & owner)
|
|||||||
return HeroTypeID::NONE; // no available heroes at all
|
return HeroTypeID::NONE; // no available heroes at all
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
|
||||||
{
|
|
||||||
switch(obj->ID)
|
|
||||||
{
|
|
||||||
case Obj::RANDOM_ART:
|
|
||||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
|
|
||||||
case Obj::RANDOM_TREASURE_ART:
|
|
||||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE));
|
|
||||||
case Obj::RANDOM_MINOR_ART:
|
|
||||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_MINOR));
|
|
||||||
case Obj::RANDOM_MAJOR_ART:
|
|
||||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_MAJOR));
|
|
||||||
case Obj::RANDOM_RELIC_ART:
|
|
||||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_RELIC));
|
|
||||||
case Obj::RANDOM_HERO:
|
|
||||||
return std::make_pair(Obj::HERO, pickNextHeroType(obj->tempOwner));
|
|
||||||
case Obj::RANDOM_MONSTER:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator()));
|
|
||||||
case Obj::RANDOM_MONSTER_L1:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 1));
|
|
||||||
case Obj::RANDOM_MONSTER_L2:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 2));
|
|
||||||
case Obj::RANDOM_MONSTER_L3:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 3));
|
|
||||||
case Obj::RANDOM_MONSTER_L4:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 4));
|
|
||||||
case Obj::RANDOM_RESOURCE:
|
|
||||||
return std::make_pair(Obj::RESOURCE,getRandomGenerator().nextInt(6)); //now it's OH3 style, use %8 for mithril
|
|
||||||
case Obj::RANDOM_TOWN:
|
|
||||||
{
|
|
||||||
PlayerColor align = (dynamic_cast<CGTownInstance *>(obj))->alignmentToPlayer;
|
|
||||||
si32 f; // can be negative (for random)
|
|
||||||
if(!align.isValidPlayer()) //same as owner / random
|
|
||||||
{
|
|
||||||
if(!obj->tempOwner.isValidPlayer())
|
|
||||||
f = -1; //random
|
|
||||||
else
|
|
||||||
f = scenarioOps->getIthPlayersSettings(obj->tempOwner).castle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f = scenarioOps->getIthPlayersSettings(align).castle;
|
|
||||||
}
|
|
||||||
if(f<0)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
f = getRandomGenerator().nextInt((int)VLC->townh->size() - 1);
|
|
||||||
}
|
|
||||||
while ((*VLC->townh)[f]->town == nullptr); // find playable faction
|
|
||||||
}
|
|
||||||
return std::make_pair(Obj::TOWN,f);
|
|
||||||
}
|
|
||||||
case Obj::RANDOM_MONSTER_L5:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 5));
|
|
||||||
case Obj::RANDOM_MONSTER_L6:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 6));
|
|
||||||
case Obj::RANDOM_MONSTER_L7:
|
|
||||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 7));
|
|
||||||
case Obj::RANDOM_DWELLING:
|
|
||||||
case Obj::RANDOM_DWELLING_LVL:
|
|
||||||
case Obj::RANDOM_DWELLING_FACTION:
|
|
||||||
{
|
|
||||||
auto * dwl = dynamic_cast<CGDwelling *>(obj);
|
|
||||||
int faction;
|
|
||||||
|
|
||||||
//if castle alignment available
|
|
||||||
if(auto * info = dynamic_cast<CCreGenAsCastleInfo *>(dwl->info))
|
|
||||||
{
|
|
||||||
faction = getRandomGenerator().nextInt((int)VLC->townh->size() - 1);
|
|
||||||
if(info->asCastle && !info->instanceId.empty())
|
|
||||||
{
|
|
||||||
auto iter = map->instanceNames.find(info->instanceId);
|
|
||||||
|
|
||||||
if(iter == map->instanceNames.end())
|
|
||||||
logGlobal->error("Map object not found: %s", info->instanceId);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto elem = iter->second;
|
|
||||||
if(elem->ID==Obj::RANDOM_TOWN)
|
|
||||||
{
|
|
||||||
randomizeObject(elem.get()); //we have to randomize the castle first
|
|
||||||
faction = elem->subID;
|
|
||||||
}
|
|
||||||
else if(elem->ID==Obj::TOWN)
|
|
||||||
faction = elem->subID;
|
|
||||||
else
|
|
||||||
logGlobal->error("Map object must be town: %s", info->instanceId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(info->asCastle)
|
|
||||||
{
|
|
||||||
|
|
||||||
for(auto & elem : map->objects)
|
|
||||||
{
|
|
||||||
if(!elem)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(elem->ID==Obj::RANDOM_TOWN
|
|
||||||
&& dynamic_cast<CGTownInstance*>(elem.get())->identifier == info->identifier)
|
|
||||||
{
|
|
||||||
randomizeObject(elem); //we have to randomize the castle first
|
|
||||||
faction = elem->subID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if(elem->ID==Obj::TOWN
|
|
||||||
&& dynamic_cast<CGTownInstance*>(elem.get())->identifier == info->identifier)
|
|
||||||
{
|
|
||||||
faction = elem->subID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::set<int> temp;
|
|
||||||
|
|
||||||
for(int i = 0; i < info->allowedFactions.size(); i++)
|
|
||||||
if(info->allowedFactions[i])
|
|
||||||
temp.insert(i);
|
|
||||||
|
|
||||||
if(temp.empty())
|
|
||||||
logGlobal->error("Random faction selection failed. Nothing is allowed. Fall back to random.");
|
|
||||||
else
|
|
||||||
faction = *RandomGeneratorUtil::nextItem(temp, getRandomGenerator());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // castle alignment fixed
|
|
||||||
faction = obj->subID;
|
|
||||||
|
|
||||||
int level;
|
|
||||||
|
|
||||||
//if level set to range
|
|
||||||
if(auto * info = dynamic_cast<CCreGenLeveledInfo *>(dwl->info))
|
|
||||||
{
|
|
||||||
level = getRandomGenerator().nextInt(info->minLevel, info->maxLevel) - 1;
|
|
||||||
}
|
|
||||||
else // fixed level
|
|
||||||
{
|
|
||||||
level = obj->subID;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete dwl->info;
|
|
||||||
dwl->info = nullptr;
|
|
||||||
|
|
||||||
std::pair<Obj, int> result(Obj::NO_OBJ, -1);
|
|
||||||
CreatureID cid;
|
|
||||||
if((*VLC->townh)[faction]->town)
|
|
||||||
cid = (*VLC->townh)[faction]->town->creatures[level][0];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//neutral faction
|
|
||||||
std::vector<CCreature*> possibleCreatures;
|
|
||||||
std::copy_if(VLC->creh->objects.begin(), VLC->creh->objects.end(), std::back_inserter(possibleCreatures), [faction](const CCreature * c)
|
|
||||||
{
|
|
||||||
return c->getFaction().getNum() == faction;
|
|
||||||
});
|
|
||||||
assert(!possibleCreatures.empty());
|
|
||||||
cid = (*RandomGeneratorUtil::nextItem(possibleCreatures, getRandomGenerator()))->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: this will pick last dwelling with this creature (Mantis #900)
|
|
||||||
//check for block map equality is better but more complex solution
|
|
||||||
auto testID = [&](const Obj & primaryID) -> void
|
|
||||||
{
|
|
||||||
auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID);
|
|
||||||
for (si32 entry : dwellingIDs)
|
|
||||||
{
|
|
||||||
const auto * handler = dynamic_cast<const DwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(primaryID, entry).get());
|
|
||||||
|
|
||||||
if (handler->producesCreature(VLC->creh->objects[cid]))
|
|
||||||
result = std::make_pair(primaryID, entry);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
testID(Obj::CREATURE_GENERATOR1);
|
|
||||||
if (result.first == Obj::NO_OBJ)
|
|
||||||
testID(Obj::CREATURE_GENERATOR4);
|
|
||||||
|
|
||||||
if (result.first == Obj::NO_OBJ)
|
|
||||||
{
|
|
||||||
logGlobal->error("Error: failed to find dwelling for %s of level %d", (*VLC->townh)[faction]->getNameTranslated(), int(level));
|
|
||||||
result = std::make_pair(Obj::CREATURE_GENERATOR1, *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), getRandomGenerator()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(Obj::NO_OBJ,-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGameState::randomizeObject(CGObjectInstance *cur)
|
|
||||||
{
|
|
||||||
std::pair<Obj,int> ran = pickObject(cur);
|
|
||||||
if(ran.first == Obj::NO_OBJ || ran.second<0) //this is not a random object, or we couldn't find anything
|
|
||||||
{
|
|
||||||
if(cur->ID==Obj::TOWN || cur->ID==Obj::MONSTER)
|
|
||||||
cur->setType(cur->ID, cur->subID); // update def, if necessary
|
|
||||||
}
|
|
||||||
else if(ran.first==Obj::HERO)//special code for hero
|
|
||||||
{
|
|
||||||
auto * h = dynamic_cast<CGHeroInstance *>(cur);
|
|
||||||
cur->setType(ran.first, ran.second);
|
|
||||||
map->heroesOnMap.emplace_back(h);
|
|
||||||
}
|
|
||||||
else if(ran.first==Obj::TOWN)//special code for town
|
|
||||||
{
|
|
||||||
auto * t = dynamic_cast<CGTownInstance *>(cur);
|
|
||||||
cur->setType(ran.first, ran.second);
|
|
||||||
map->towns.emplace_back(t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cur->setType(ran.first, ran.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int CGameState::getDate(Date mode) const
|
int CGameState::getDate(Date mode) const
|
||||||
{
|
{
|
||||||
int temp;
|
int temp;
|
||||||
@ -766,9 +549,33 @@ void CGameState::randomizeMapObjects()
|
|||||||
logGlobal->debug("\tRandomizing objects");
|
logGlobal->debug("\tRandomizing objects");
|
||||||
for(CGObjectInstance *obj : map->objects)
|
for(CGObjectInstance *obj : map->objects)
|
||||||
{
|
{
|
||||||
if(!obj) continue;
|
if(!obj)
|
||||||
|
continue;
|
||||||
|
|
||||||
randomizeObject(obj);
|
{
|
||||||
|
std::pair<Obj,int> ran = pickObject(obj);
|
||||||
|
if(ran.first == Obj::NO_OBJ || ran.second<0) //this is not a random object, or we couldn't find anything
|
||||||
|
{
|
||||||
|
if(obj->ID==Obj::TOWN || obj->ID==Obj::MONSTER)
|
||||||
|
obj->setType(obj->ID, obj->subID); // update def, if necessary
|
||||||
|
}
|
||||||
|
else if(ran.first==Obj::HERO)//special code for hero
|
||||||
|
{
|
||||||
|
auto * h = dynamic_cast<CGHeroInstance *>(obj);
|
||||||
|
obj->setType(ran.first, ran.second);
|
||||||
|
map->heroesOnMap.emplace_back(h);
|
||||||
|
}
|
||||||
|
else if(ran.first==Obj::TOWN)//special code for town
|
||||||
|
{
|
||||||
|
auto * t = dynamic_cast<CGTownInstance *>(obj);
|
||||||
|
obj->setType(ran.first, ran.second);
|
||||||
|
map->towns.emplace_back(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj->setType(ran.first, ran.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//handle Favouring Winds - mark tiles under it
|
//handle Favouring Winds - mark tiles under it
|
||||||
if(obj->ID == Obj::FAVORABLE_WINDS)
|
if(obj->ID == Obj::FAVORABLE_WINDS)
|
||||||
|
@ -187,7 +187,6 @@ private:
|
|||||||
void initGrailPosition();
|
void initGrailPosition();
|
||||||
void initRandomFactionsForPlayers();
|
void initRandomFactionsForPlayers();
|
||||||
void randomizeMapObjects();
|
void randomizeMapObjects();
|
||||||
void randomizeObject(CGObjectInstance *cur);
|
|
||||||
void initPlayerStates();
|
void initPlayerStates();
|
||||||
void placeStartingHeroes();
|
void placeStartingHeroes();
|
||||||
void placeStartingHero(const PlayerColor & playerColor, const HeroTypeID & heroTypeId, int3 townPos);
|
void placeStartingHero(const PlayerColor & playerColor, const HeroTypeID & heroTypeId, int3 townPos);
|
||||||
@ -214,7 +213,6 @@ private:
|
|||||||
CGHeroInstance * getUsedHero(const HeroTypeID & hid) const;
|
CGHeroInstance * getUsedHero(const HeroTypeID & hid) const;
|
||||||
bool isUsedHero(const HeroTypeID & hid) const; //looks in heroes and prisons
|
bool isUsedHero(const HeroTypeID & hid) const; //looks in heroes and prisons
|
||||||
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
|
std::set<HeroTypeID> getUnusedAllowedHeroes(bool alsoIncludeNotAllowed = false) const;
|
||||||
std::pair<Obj,int> pickObject(CGObjectInstance *obj); //chooses type of object to be randomized, returns <type, subtype>
|
|
||||||
HeroTypeID pickUnusedHeroTypeRandomly(const PlayerColor & owner); // picks a unused hero type randomly
|
HeroTypeID pickUnusedHeroTypeRandomly(const PlayerColor & owner); // picks a unused hero type randomly
|
||||||
HeroTypeID pickNextHeroType(const PlayerColor & owner); // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
|
HeroTypeID pickNextHeroType(const PlayerColor & owner); // picks next free hero type of the H3 hero init sequence -> chosen starting hero, then unused hero type randomly
|
||||||
UpgradeInfo fillUpgradeInfo(const CStackInstance &stack) const;
|
UpgradeInfo fillUpgradeInfo(const CStackInstance &stack) const;
|
||||||
|
@ -160,6 +160,38 @@ CreatureID CGCreature::getCreature() const
|
|||||||
return CreatureID(getObjTypeIndex().getNum());
|
return CreatureID(getObjTypeIndex().getNum());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGCreature::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
switch(ID)
|
||||||
|
{
|
||||||
|
case MapObjectID::RANDOM_MONSTER:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L1:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 1);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L2:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 2);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L3:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 3);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L4:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 4);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L5:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 5);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L6:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 6);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MONSTER_L7:
|
||||||
|
subID = VLC->creh->pickRandomMonster(rand, 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ID = MapObjectID::MONSTER;
|
||||||
|
}
|
||||||
|
|
||||||
void CGCreature::initObj(CRandomGenerator & rand)
|
void CGCreature::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
std::string getHoverText(PlayerColor player) const override;
|
std::string getHoverText(PlayerColor player) const override;
|
||||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void newTurn(CRandomGenerator & rand) const override;
|
void newTurn(CRandomGenerator & rand) const override;
|
||||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CGDwelling.h"
|
#include "CGDwelling.h"
|
||||||
#include "../serializer/JsonSerializeFormat.h"
|
#include "../serializer/JsonSerializeFormat.h"
|
||||||
|
#include "../mapping/CMap.h"
|
||||||
#include "../mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
|
#include "../mapObjectConstructors/DwellingInstanceConstructor.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../networkPacks/StackLocation.h"
|
#include "../networkPacks/StackLocation.h"
|
||||||
#include "../networkPacks/PacksForClient.h"
|
#include "../networkPacks/PacksForClient.h"
|
||||||
@ -26,41 +28,10 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
CSpecObjInfo::CSpecObjInfo():
|
void CGDwellingRandomizationInfo::serializeJson(JsonSerializeFormat & handler)
|
||||||
owner(nullptr)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreGenAsCastleInfo::serializeJson(JsonSerializeFormat & handler)
|
|
||||||
{
|
{
|
||||||
handler.serializeString("sameAsTown", instanceId);
|
handler.serializeString("sameAsTown", instanceId);
|
||||||
|
handler.serializeIdArray("allowedFactions", allowedFactions);
|
||||||
if(!handler.saving)
|
|
||||||
{
|
|
||||||
asCastle = !instanceId.empty();
|
|
||||||
allowedFactions.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!asCastle)
|
|
||||||
{
|
|
||||||
std::vector<bool> standard;
|
|
||||||
standard.resize(VLC->townh->size(), true);
|
|
||||||
|
|
||||||
JsonSerializeFormat::LIC allowedLIC(standard, &FactionID::decode, &FactionID::encode);
|
|
||||||
allowedLIC.any = allowedFactions;
|
|
||||||
|
|
||||||
handler.serializeLIC("allowedFactions", allowedLIC);
|
|
||||||
|
|
||||||
if(!handler.saving)
|
|
||||||
{
|
|
||||||
allowedFactions = allowedLIC.any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreGenLeveledInfo::serializeJson(JsonSerializeFormat & handler)
|
|
||||||
{
|
|
||||||
handler.serializeInt("minLevel", minLevel, static_cast<uint8_t>(1));
|
handler.serializeInt("minLevel", minLevel, static_cast<uint8_t>(1));
|
||||||
handler.serializeInt("maxLevel", maxLevel, static_cast<uint8_t>(7));
|
handler.serializeInt("maxLevel", maxLevel, static_cast<uint8_t>(7));
|
||||||
|
|
||||||
@ -72,20 +43,119 @@ void CCreGenLeveledInfo::serializeJson(JsonSerializeFormat & handler)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreGenLeveledCastleInfo::serializeJson(JsonSerializeFormat & handler)
|
CGDwelling::CGDwelling() = default;
|
||||||
|
CGDwelling::~CGDwelling() = default;
|
||||||
|
|
||||||
|
FactionID CGDwelling::randomizeFaction(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
CCreGenAsCastleInfo::serializeJson(handler);
|
assert(randomizationInfo.has_value());
|
||||||
CCreGenLeveledInfo::serializeJson(handler);
|
if (!randomizationInfo)
|
||||||
|
return FactionID::CASTLE;
|
||||||
|
|
||||||
|
CGTownInstance * linkedTown = nullptr;
|
||||||
|
|
||||||
|
if (!randomizationInfo->instanceId.empty())
|
||||||
|
{
|
||||||
|
auto iter = cb->gameState()->map->instanceNames.find(randomizationInfo->instanceId);
|
||||||
|
|
||||||
|
if(iter == cb->gameState()->map->instanceNames.end())
|
||||||
|
logGlobal->error("Map object not found: %s", randomizationInfo->instanceId);
|
||||||
|
linkedTown = dynamic_cast<CGTownInstance *>(iter->second.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (randomizationInfo->identifier != 0)
|
||||||
|
{
|
||||||
|
for(auto & elem : cb->gameState()->map->objects)
|
||||||
|
{
|
||||||
|
auto town = dynamic_cast<CGTownInstance*>(elem.get());
|
||||||
|
if(town && town->identifier == randomizationInfo->identifier)
|
||||||
|
{
|
||||||
|
linkedTown = town;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkedTown)
|
||||||
|
{
|
||||||
|
if(linkedTown->ID==Obj::RANDOM_TOWN)
|
||||||
|
linkedTown->pickRandomObject(rand); //we have to randomize the castle first
|
||||||
|
|
||||||
|
assert(linkedTown->ID == Obj::TOWN);
|
||||||
|
if(linkedTown->ID==Obj::TOWN)
|
||||||
|
return linkedTown->getFaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!randomizationInfo->allowedFactions.empty())
|
||||||
|
return *RandomGeneratorUtil::nextItem(randomizationInfo->allowedFactions, rand);
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<FactionID> potentialPicks;
|
||||||
|
|
||||||
|
for (FactionID faction(0); faction < VLC->townh->size(); ++faction)
|
||||||
|
if (VLC->factions()->getById(faction)->hasTown())
|
||||||
|
potentialPicks.push_back(faction);
|
||||||
|
|
||||||
|
assert(!potentialPicks.empty());
|
||||||
|
return *RandomGeneratorUtil::nextItem(potentialPicks, rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGDwelling::CGDwelling()
|
int CGDwelling::randomizeLevel(CRandomGenerator & rand)
|
||||||
: info(nullptr)
|
|
||||||
{
|
{
|
||||||
|
assert(randomizationInfo.has_value());
|
||||||
|
|
||||||
|
if (!randomizationInfo)
|
||||||
|
return rand.nextInt(1, 7) - 1;
|
||||||
|
|
||||||
|
if(randomizationInfo->minLevel == randomizationInfo->maxLevel)
|
||||||
|
return randomizationInfo->minLevel - 1;
|
||||||
|
|
||||||
|
return rand.nextInt(randomizationInfo->minLevel, randomizationInfo->maxLevel) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGDwelling::~CGDwelling()
|
void CGDwelling::pickRandomObject(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
vstd::clear_pointer(info);
|
if (ID == Obj::RANDOM_DWELLING || ID == Obj::RANDOM_DWELLING_LVL || ID == Obj::RANDOM_DWELLING_FACTION)
|
||||||
|
{
|
||||||
|
FactionID faction = randomizeFaction(rand);
|
||||||
|
int level = randomizeLevel(rand);
|
||||||
|
assert(faction != FactionID::NONE && faction != FactionID::NEUTRAL);
|
||||||
|
assert(level >= 1 && level <= 7);
|
||||||
|
randomizationInfo.reset();
|
||||||
|
|
||||||
|
CreatureID cid = (*VLC->townh)[faction]->town->creatures[level][0];
|
||||||
|
|
||||||
|
//NOTE: this will pick last dwelling with this creature (Mantis #900)
|
||||||
|
//check for block map equality is better but more complex solution
|
||||||
|
auto testID = [&](const Obj & primaryID) -> MapObjectSubID
|
||||||
|
{
|
||||||
|
auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID);
|
||||||
|
for (si32 entry : dwellingIDs)
|
||||||
|
{
|
||||||
|
const auto * handler = dynamic_cast<const DwellingInstanceConstructor *>(VLC->objtypeh->getHandlerFor(primaryID, entry).get());
|
||||||
|
|
||||||
|
if (handler->producesCreature(VLC->creh->objects[cid]))
|
||||||
|
return MapObjectSubID(entry);
|
||||||
|
}
|
||||||
|
return MapObjectSubID();
|
||||||
|
};
|
||||||
|
|
||||||
|
ID = Obj::CREATURE_GENERATOR1;
|
||||||
|
subID = testID(Obj::CREATURE_GENERATOR1);
|
||||||
|
|
||||||
|
if (subID == MapObjectSubID())
|
||||||
|
{
|
||||||
|
ID = Obj::CREATURE_GENERATOR4;
|
||||||
|
subID = testID(Obj::CREATURE_GENERATOR4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subID == MapObjectSubID())
|
||||||
|
{
|
||||||
|
logGlobal->error("Error: failed to find dwelling for %s of level %d", (*VLC->townh)[faction]->getNameTranslated(), int(level));
|
||||||
|
ID = Obj::CREATURE_GENERATOR4;
|
||||||
|
subID = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGDwelling::initObj(CRandomGenerator & rand)
|
void CGDwelling::initObj(CRandomGenerator & rand)
|
||||||
@ -121,23 +191,6 @@ void CGDwelling::initObj(CRandomGenerator & rand)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGDwelling::initRandomObjectInfo()
|
|
||||||
{
|
|
||||||
vstd::clear_pointer(info);
|
|
||||||
switch(ID)
|
|
||||||
{
|
|
||||||
case Obj::RANDOM_DWELLING: info = new CCreGenLeveledCastleInfo();
|
|
||||||
break;
|
|
||||||
case Obj::RANDOM_DWELLING_LVL: info = new CCreGenAsCastleInfo();
|
|
||||||
break;
|
|
||||||
case Obj::RANDOM_DWELLING_FACTION: info = new CCreGenLeveledInfo();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(info)
|
|
||||||
info->owner = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CGDwelling::setPropertyDer(ui8 what, ui32 val)
|
void CGDwelling::setPropertyDer(ui8 what, ui32 val)
|
||||||
{
|
{
|
||||||
switch (what)
|
switch (what)
|
||||||
@ -425,9 +478,6 @@ void CGDwelling::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
|
|||||||
|
|
||||||
void CGDwelling::serializeJsonOptions(JsonSerializeFormat & handler)
|
void CGDwelling::serializeJsonOptions(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
if(!handler.saving)
|
|
||||||
initRandomObjectInfo();
|
|
||||||
|
|
||||||
switch (ID)
|
switch (ID)
|
||||||
{
|
{
|
||||||
case Obj::WAR_MACHINE_FACTORY:
|
case Obj::WAR_MACHINE_FACTORY:
|
||||||
@ -437,8 +487,10 @@ void CGDwelling::serializeJsonOptions(JsonSerializeFormat & handler)
|
|||||||
case Obj::RANDOM_DWELLING:
|
case Obj::RANDOM_DWELLING:
|
||||||
case Obj::RANDOM_DWELLING_LVL:
|
case Obj::RANDOM_DWELLING_LVL:
|
||||||
case Obj::RANDOM_DWELLING_FACTION:
|
case Obj::RANDOM_DWELLING_FACTION:
|
||||||
info->serializeJson(handler);
|
if (!handler.saving)
|
||||||
//fall through
|
randomizationInfo = CGDwellingRandomizationInfo();
|
||||||
|
randomizationInfo->serializeJson(handler);
|
||||||
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
serializeJsonOwner(handler);
|
serializeJsonOwner(handler);
|
||||||
break;
|
break;
|
||||||
|
@ -16,62 +16,39 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
class CGDwelling;
|
class CGDwelling;
|
||||||
|
|
||||||
class DLL_LINKAGE CSpecObjInfo
|
class DLL_LINKAGE CGDwellingRandomizationInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSpecObjInfo();
|
std::set<FactionID> allowedFactions;
|
||||||
virtual ~CSpecObjInfo() = default;
|
|
||||||
|
|
||||||
virtual void serializeJson(JsonSerializeFormat & handler) = 0;
|
|
||||||
|
|
||||||
const CGDwelling * owner;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CCreGenAsCastleInfo : public virtual CSpecObjInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool asCastle = false;
|
|
||||||
ui32 identifier = 0;//h3m internal identifier
|
|
||||||
|
|
||||||
std::vector<bool> allowedFactions;
|
|
||||||
|
|
||||||
std::string instanceId;//vcmi map instance identifier
|
std::string instanceId;//vcmi map instance identifier
|
||||||
void serializeJson(JsonSerializeFormat & handler) override;
|
int32_t identifier = 0;//h3m internal identifier
|
||||||
|
|
||||||
|
uint8_t minLevel = 1;
|
||||||
|
uint8_t maxLevel = 7; //minimal and maximal level of creature in dwelling: <1, 7>
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CCreGenLeveledInfo : public virtual CSpecObjInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ui8 minLevel = 1;
|
|
||||||
ui8 maxLevel = 7; //minimal and maximal level of creature in dwelling: <1, 7>
|
|
||||||
|
|
||||||
void serializeJson(JsonSerializeFormat & handler) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DLL_LINKAGE CCreGenLeveledCastleInfo : public CCreGenAsCastleInfo, public CCreGenLeveledInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCreGenLeveledCastleInfo() = default;
|
|
||||||
void serializeJson(JsonSerializeFormat & handler) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class DLL_LINKAGE CGDwelling : public CArmedInstance
|
class DLL_LINKAGE CGDwelling : public CArmedInstance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::vector<std::pair<ui32, std::vector<CreatureID> > > TCreaturesSet;
|
typedef std::vector<std::pair<ui32, std::vector<CreatureID> > > TCreaturesSet;
|
||||||
|
|
||||||
CSpecObjInfo * info; //random dwelling options; not serialized
|
std::optional<CGDwellingRandomizationInfo> randomizationInfo; //random dwelling options; not serialized
|
||||||
TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
|
TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
|
||||||
|
|
||||||
CGDwelling();
|
CGDwelling();
|
||||||
~CGDwelling() override;
|
~CGDwelling() override;
|
||||||
|
|
||||||
void initRandomObjectInfo();
|
|
||||||
protected:
|
protected:
|
||||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FactionID randomizeFaction(CRandomGenerator & rand);
|
||||||
|
int randomizeLevel(CRandomGenerator & rand);
|
||||||
|
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void newTurn(CRandomGenerator & rand) const override;
|
void newTurn(CRandomGenerator & rand) const override;
|
||||||
|
@ -571,6 +571,17 @@ void CGHeroInstance::SecondarySkillsInfo::resetWisdomCounter()
|
|||||||
wisdomCounter = 1;
|
wisdomCounter = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGHeroInstance::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
assert(ID == Obj::HERO || ID == Obj::PRISON || ID == Obj::RANDOM_HERO);
|
||||||
|
|
||||||
|
if (ID == Obj::RANDOM_HERO)
|
||||||
|
{
|
||||||
|
ID = Obj::HERO;
|
||||||
|
subID = cb->gameState()->pickNextHeroType(getOwner());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGHeroInstance::initObj(CRandomGenerator & rand)
|
void CGHeroInstance::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
if(!type)
|
if(!type)
|
||||||
|
@ -295,6 +295,7 @@ public:
|
|||||||
void deserializationFix();
|
void deserializationFix();
|
||||||
|
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
std::string getObjectName() const override;
|
std::string getObjectName() const override;
|
||||||
|
|
||||||
|
@ -166,6 +166,11 @@ void CGObjectInstance::setType(si32 newID, si32 newSubID)
|
|||||||
cb->gameState()->map->addBlockVisTiles(this);
|
cb->gameState()->map->addBlockVisTiles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGObjectInstance::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
void CGObjectInstance::initObj(CRandomGenerator & rand)
|
void CGObjectInstance::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
switch(ID)
|
switch(ID)
|
||||||
|
@ -128,6 +128,7 @@ public:
|
|||||||
/** OVERRIDES OF IObjectInterface **/
|
/** OVERRIDES OF IObjectInterface **/
|
||||||
|
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
|
/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
|
||||||
void setProperty(ui8 what, ui32 val) final;
|
void setProperty(ui8 what, ui32 val) final;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "../gameState/CGameState.h"
|
#include "../gameState/CGameState.h"
|
||||||
#include "../mapping/CMap.h"
|
#include "../mapping/CMap.h"
|
||||||
#include "../CPlayerState.h"
|
#include "../CPlayerState.h"
|
||||||
|
#include "../StartInfo.h"
|
||||||
#include "../TerrainHandler.h"
|
#include "../TerrainHandler.h"
|
||||||
#include "../mapObjectConstructors/AObjectTypeHandler.h"
|
#include "../mapObjectConstructors/AObjectTypeHandler.h"
|
||||||
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
@ -459,6 +460,34 @@ void CGTownInstance::deleteTownBonus(BuildingID bid)
|
|||||||
delete freeIt;
|
delete freeIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FactionID CGTownInstance::randomizeFaction(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
if(getOwner().isValidPlayer())
|
||||||
|
return cb->gameState()->scenarioOps->getIthPlayersSettings(getOwner()).castle;
|
||||||
|
|
||||||
|
if(alignmentToPlayer.isValidPlayer())
|
||||||
|
return cb->gameState()->scenarioOps->getIthPlayersSettings(alignmentToPlayer).castle;
|
||||||
|
|
||||||
|
std::vector<FactionID> potentialPicks;
|
||||||
|
|
||||||
|
for (FactionID faction(0); faction < VLC->townh->size(); ++faction)
|
||||||
|
if (VLC->factions()->getById(faction)->hasTown())
|
||||||
|
potentialPicks.push_back(faction);
|
||||||
|
|
||||||
|
assert(!potentialPicks.empty());
|
||||||
|
return *RandomGeneratorUtil::nextItem(potentialPicks, rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGTownInstance::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
assert(ID == MapObjectID::TOWN || ID == MapObjectID::RANDOM_TOWN);
|
||||||
|
if (ID == MapObjectID::RANDOM_TOWN)
|
||||||
|
{
|
||||||
|
ID = MapObjectID::TOWN;
|
||||||
|
subID = randomizeFaction(rand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGTownInstance::initObj(CRandomGenerator & rand) ///initialize town structures
|
void CGTownInstance::initObj(CRandomGenerator & rand) ///initialize town structures
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
|
@ -197,6 +197,7 @@ public:
|
|||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void onHeroLeave(const CGHeroInstance * h) const override;
|
void onHeroLeave(const CGHeroInstance * h) const override;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
|
void battleFinished(const CGHeroInstance * hero, const BattleResult & result) const override;
|
||||||
std::string getObjectName() const override;
|
std::string getObjectName() const override;
|
||||||
|
|
||||||
@ -216,6 +217,7 @@ protected:
|
|||||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FactionID randomizeFaction(CRandomGenerator & rand);
|
||||||
void setOwner(const PlayerColor & owner) const;
|
void setOwner(const PlayerColor & owner) const;
|
||||||
void onTownCaptured(const PlayerColor & winner) const;
|
void onTownCaptured(const PlayerColor & winner) const;
|
||||||
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
|
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
virtual void onHeroLeave(const CGHeroInstance * h) const;
|
virtual void onHeroLeave(const CGHeroInstance * h) const;
|
||||||
virtual void newTurn(CRandomGenerator & rand) const;
|
virtual void newTurn(CRandomGenerator & rand) const;
|
||||||
virtual void initObj(CRandomGenerator & rand); //synchr
|
virtual void initObj(CRandomGenerator & rand); //synchr
|
||||||
|
virtual void pickRandomObject(CRandomGenerator & rand);
|
||||||
virtual void setProperty(ui8 what, ui32 val);//synchr
|
virtual void setProperty(ui8 what, ui32 val);//synchr
|
||||||
|
|
||||||
//Called when queries created DURING HERO VISIT are resolved
|
//Called when queries created DURING HERO VISIT are resolved
|
||||||
|
@ -247,6 +247,17 @@ std::string CGResource::getHoverText(PlayerColor player) const
|
|||||||
return VLC->generaltexth->restypes[resourceID()];
|
return VLC->generaltexth->restypes[resourceID()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGResource::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
assert(ID == Obj::RESOURCE || ID == Obj::RANDOM_RESOURCE);
|
||||||
|
|
||||||
|
if (ID == Obj::RANDOM_RESOURCE)
|
||||||
|
{
|
||||||
|
ID = Obj::RESOURCE;
|
||||||
|
subID = rand.nextInt(EGameResID::WOOD, EGameResID::GOLD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CGResource::initObj(CRandomGenerator & rand)
|
void CGResource::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
@ -701,6 +712,31 @@ ArtifactID CGArtifact::getArtifact() const
|
|||||||
return getObjTypeIndex().getNum();
|
return getObjTypeIndex().getNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGArtifact::pickRandomObject(CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
switch(ID)
|
||||||
|
{
|
||||||
|
case MapObjectID::RANDOM_ART:
|
||||||
|
subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_TREASURE_ART:
|
||||||
|
subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MINOR_ART:
|
||||||
|
subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_MAJOR_ART:
|
||||||
|
subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR);
|
||||||
|
break;
|
||||||
|
case MapObjectID::RANDOM_RELIC_ART:
|
||||||
|
subID = VLC->arth->pickRandomArtifact(rand, CArtifact::ART_RELIC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ID != Obj::SPELL_SCROLL)
|
||||||
|
ID = MapObjectID::ARTIFACT;
|
||||||
|
}
|
||||||
|
|
||||||
void CGArtifact::initObj(CRandomGenerator & rand)
|
void CGArtifact::initObj(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
blockVisit = true;
|
blockVisit = true;
|
||||||
|
@ -89,6 +89,7 @@ public:
|
|||||||
|
|
||||||
void pick( const CGHeroInstance * h ) const;
|
void pick( const CGHeroInstance * h ) const;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
|
|
||||||
void afterAddToMap(CMap * map) override;
|
void afterAddToMap(CMap * map) override;
|
||||||
BattleField getBattlefield() const override;
|
BattleField getBattlefield() const override;
|
||||||
@ -115,6 +116,7 @@ public:
|
|||||||
|
|
||||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||||
void initObj(CRandomGenerator & rand) override;
|
void initObj(CRandomGenerator & rand) override;
|
||||||
|
void pickRandomObject(CRandomGenerator & rand) override;
|
||||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||||
std::string getHoverText(PlayerColor player) const override;
|
std::string getHoverText(PlayerColor player) const override;
|
||||||
|
@ -1322,60 +1322,27 @@ CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, s
|
|||||||
{
|
{
|
||||||
auto * object = new CGDwelling();
|
auto * object = new CGDwelling();
|
||||||
|
|
||||||
CSpecObjInfo * spec = nullptr;
|
|
||||||
switch(objectTemplate->id)
|
|
||||||
{
|
|
||||||
case Obj::RANDOM_DWELLING:
|
|
||||||
spec = new CCreGenLeveledCastleInfo();
|
|
||||||
break;
|
|
||||||
case Obj::RANDOM_DWELLING_LVL:
|
|
||||||
spec = new CCreGenAsCastleInfo();
|
|
||||||
break;
|
|
||||||
case Obj::RANDOM_DWELLING_FACTION:
|
|
||||||
spec = new CCreGenLeveledInfo();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Invalid random dwelling format");
|
|
||||||
}
|
|
||||||
spec->owner = object;
|
|
||||||
|
|
||||||
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
|
||||||
|
|
||||||
//216 and 217
|
object->randomizationInfo = CGDwellingRandomizationInfo();
|
||||||
if(auto * castleSpec = dynamic_cast<CCreGenAsCastleInfo *>(spec))
|
|
||||||
|
bool hasFactionInfo = objectTemplate->id == Obj::RANDOM_DWELLING || objectTemplate->id == Obj::RANDOM_DWELLING_FACTION;
|
||||||
|
bool hasLevelInfo = objectTemplate->id == Obj::RANDOM_DWELLING || objectTemplate->id == Obj::RANDOM_DWELLING_LVL;
|
||||||
|
|
||||||
|
if (hasFactionInfo)
|
||||||
{
|
{
|
||||||
castleSpec->instanceId = "";
|
object->randomizationInfo->identifier = reader->readUInt32();
|
||||||
castleSpec->identifier = reader->readUInt32();
|
|
||||||
if(!castleSpec->identifier)
|
|
||||||
{
|
|
||||||
castleSpec->asCastle = false;
|
|
||||||
const int MASK_SIZE = 8;
|
|
||||||
ui8 mask[2];
|
|
||||||
mask[0] = reader->readUInt8();
|
|
||||||
mask[1] = reader->readUInt8();
|
|
||||||
|
|
||||||
castleSpec->allowedFactions.clear();
|
if(object->randomizationInfo->identifier != 0)
|
||||||
castleSpec->allowedFactions.resize(VLC->townh->size(), false);
|
reader->readBitmaskFactions(object->randomizationInfo->allowedFactions, false);
|
||||||
|
|
||||||
for(int i = 0; i < MASK_SIZE; i++)
|
|
||||||
castleSpec->allowedFactions[i] = ((mask[0] & (1 << i)) > 0);
|
|
||||||
|
|
||||||
for(int i = 0; i < (GameConstants::F_NUMBER - MASK_SIZE); i++)
|
|
||||||
castleSpec->allowedFactions[i + MASK_SIZE] = ((mask[1] & (1 << i)) > 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
castleSpec->asCastle = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//216 and 218
|
if(hasLevelInfo)
|
||||||
if(auto * lvlSpec = dynamic_cast<CCreGenLeveledInfo *>(spec))
|
|
||||||
{
|
{
|
||||||
lvlSpec->minLevel = std::max(reader->readUInt8(), static_cast<ui8>(0)) + 1;
|
object->randomizationInfo->minLevel = std::max(reader->readUInt8(), static_cast<ui8>(0)) + 1;
|
||||||
lvlSpec->maxLevel = std::min(reader->readUInt8(), static_cast<ui8>(6)) + 1;
|
object->randomizationInfo->maxLevel = std::min(reader->readUInt8(), static_cast<ui8>(6)) + 1;
|
||||||
}
|
}
|
||||||
object->info = spec;
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user