1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Merge pull request #3473 from IvanSavenko/const_lib

[1.5] Remove non-const global variables from library
This commit is contained in:
Ivan Savenko 2024-01-20 19:22:46 +02:00 committed by GitHub
commit 6b760089a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
190 changed files with 1111 additions and 1099 deletions

View File

@ -350,10 +350,11 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack)
LOGL("Casting spells sounds like fun. Let's see..."); LOGL("Casting spells sounds like fun. Let's see...");
//Get all spells we can cast //Get all spells we can cast
std::vector<const CSpell*> possibleSpells; std::vector<const CSpell*> possibleSpells;
vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero, this](const CSpell *s) -> bool
{ for (auto const & s : VLC->spellh->objects)
return s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero); if (s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero))
}); possibleSpells.push_back(s.get());
LOGFL("I can cast %d spells.", possibleSpells.size()); LOGFL("I can cast %d spells.", possibleSpells.size());
vstd::erase_if(possibleSpells, [](const CSpell *s) vstd::erase_if(possibleSpells, [](const CSpell *s)

View File

@ -276,12 +276,10 @@ creInfo infoFromDC(const dwellingContent & dc)
ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed
if (ci.creID != CreatureID::NONE) if (ci.creID != CreatureID::NONE)
{ {
ci.cre = VLC->creatures()->getById(ci.creID); ci.level = ci.creID.toCreature()->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore.
} }
else else
{ {
ci.cre = nullptr;
ci.level = 0; ci.level = 0;
} }
return ci; return ci;

View File

@ -163,7 +163,6 @@ struct creInfo
{ {
int count; int count;
CreatureID creID; CreatureID creID;
const Creature * cre;
int level; int level;
}; };
creInfo infoFromDC(const dwellingContent & dc); creInfo infoFromDC(const dwellingContent & dc);

View File

@ -63,9 +63,9 @@ std::vector<SlotInfo> ArmyManager::toSlotInfo(std::vector<creInfo> army) const
{ {
SlotInfo slot; SlotInfo slot;
slot.creature = VLC->creh->objects[i.cre->getId()]; slot.creature = i.creID.toCreature();
slot.count = i.count; slot.count = i.count;
slot.power = evaluateStackPower(i.cre, i.count); slot.power = evaluateStackPower(i.creID.toCreature(), i.count);
result.push_back(slot); result.push_back(slot);
} }
@ -128,7 +128,7 @@ class TemporaryArmy : public CArmedInstance
public: public:
void armyChanged() override {} void armyChanged() override {}
TemporaryArmy() TemporaryArmy()
:CArmedInstance(true) :CArmedInstance(nullptr, true)
{ {
} }
}; };
@ -259,7 +259,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
if(!ci.count || ci.creID == CreatureID::NONE) if(!ci.count || ci.creID == CreatureID::NONE)
continue; continue;
vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford
if(!ci.count) if(!ci.count)
continue; continue;
@ -270,7 +270,7 @@ std::shared_ptr<CCreatureSet> ArmyManager::getArmyAvailableToBuyAsCCreatureSet(
break; break;
army->setCreature(dst, ci.creID, ci.count); army->setCreature(dst, ci.creID, ci.count);
availableRes -= ci.cre->getFullRecruitCost() * ci.count; availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count;
} }
return army; return army;
@ -287,7 +287,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(
for(const creInfo & ci : army) for(const creInfo & ci : army)
{ {
aivalue += ci.count * ci.cre->getAIValue(); aivalue += ci.count * ci.creID.toCreature()->getAIValue();
} }
return aivalue; return aivalue;
@ -320,7 +320,7 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
if(i < GameConstants::CREATURES_PER_TOWN && countGrowth) if(i < GameConstants::CREATURES_PER_TOWN && countGrowth)
{ {
ci.count += town ? town->creatureGrowth(i) : ci.cre->getGrowth(); ci.count += town ? town->creatureGrowth(i) : ci.creID.toCreature()->getGrowth();
} }
if(!ci.count) continue; if(!ci.count) continue;
@ -334,13 +334,13 @@ std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(
freeHeroSlots--; //new slot will be occupied freeHeroSlots--; //new slot will be occupied
} }
vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford
if(!ci.count) continue; if(!ci.count) continue;
ci.level = i; //this is important for Dungeon Summoning Portal ci.level = i; //this is important for Dungeon Summoning Portal
creaturesInDwellings.push_back(ci); creaturesInDwellings.push_back(ci);
availableRes -= ci.cre->getFullRecruitCost() * ci.count; availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count;
} }
return creaturesInDwellings; return creaturesInDwellings;

View File

@ -165,7 +165,7 @@ void DangerHitMapAnalyzer::calculateTileOwners()
auto addTownHero = [&](const CGTownInstance * town) auto addTownHero = [&](const CGTownInstance * town)
{ {
auto townHero = new CGHeroInstance(); auto townHero = new CGHeroInstance(town->cb);
CRandomGenerator rng; CRandomGenerator rng;
auto visitablePos = town->visitablePos(); auto visitablePos = town->visitablePos();

View File

@ -30,7 +30,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
ui64 totalStrength = 0; ui64 totalStrength = 0;
ui8 totalChance = 0; ui8 totalChance = 0;
for(auto config : bankInfo->getPossibleGuards()) for(auto config : bankInfo->getPossibleGuards(bank->cb))
{ {
totalStrength += config.second.totalStrength * config.first; totalStrength += config.second.totalStrength * config.first;
totalChance += config.first; totalChance += config.first;

View File

@ -141,7 +141,7 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero
{ {
auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance); auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance);
CBankInfo * bankInfo = dynamic_cast<CBankInfo *>(objectInfo.get()); CBankInfo * bankInfo = dynamic_cast<CBankInfo *>(objectInfo.get());
auto creatures = bankInfo->getPossibleCreaturesReward(); auto creatures = bankInfo->getPossibleCreaturesReward(target->cb);
uint64_t result = 0; uint64_t result = 0;
const auto& slots = hero->Slots(); const auto& slots = hero->Slots();
@ -236,7 +236,7 @@ int getDwellingArmyCost(const CGObjectInstance * target)
return cost; return cost;
} }
uint64_t evaluateArtifactArmyValue(CArtifactInstance * art) static uint64_t evaluateArtifactArmyValue(const CArtifactInstance * art)
{ {
if(art->artType->getId() == ArtifactID::SPELL_SCROLL) if(art->artType->getId() == ArtifactID::SPELL_SCROLL)
return 1500; return 1500;

View File

@ -54,12 +54,12 @@ void BuyArmy::accept(AIGateway * ai)
if(objid != CreatureID::NONE && ci.creID.getNum() != objid) if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
continue; continue;
vstd::amin(ci.count, res / ci.cre->getFullRecruitCost()); vstd::amin(ci.count, res / ci.creID.toCreature()->getFullRecruitCost());
if(ci.count) if(ci.count)
{ {
cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level); cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
valueBought += ci.count * ci.cre->getAIValue(); valueBought += ci.count * ci.creID.toCreature()->getAIValue();
} }
} }

View File

@ -98,7 +98,7 @@ std::string CompleteQuest::questToString() const
return "inactive quest"; return "inactive quest";
MetaString ms; MetaString ms;
q.quest->getRolloverText(ms, false); q.quest->getRolloverText(q.obj->cb, ms, false);
return ms.toString(); return ms.toString();
} }

View File

@ -373,10 +373,10 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
for(auto & creatureToBuy : buyArmy) for(auto & creatureToBuy : buyArmy)
{ {
auto targetSlot = target->getSlotFor(dynamic_cast<const CCreature*>(creatureToBuy.cre)); auto targetSlot = target->getSlotFor(creatureToBuy.creID.toCreature());
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count); target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
target->armyCost += creatureToBuy.cre->getFullRecruitCost() * creatureToBuy.count; target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count;
target->requireBuyArmy = true; target->requireBuyArmy = true;
} }
} }

View File

@ -31,7 +31,7 @@ public:
virtual bool needsLastStack() const override; virtual bool needsLastStack() const override;
std::shared_ptr<SpecialAction> getActorAction() const; std::shared_ptr<SpecialAction> getActorAction() const;
HeroExchangeArmy(): CArmedInstance(true), requireBuyArmy(false) {} HeroExchangeArmy(): CArmedInstance(nullptr, true), requireBuyArmy(false) {}
}; };
struct ExchangeResult struct ExchangeResult

View File

@ -72,7 +72,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
ui64 totalStrength = 0; ui64 totalStrength = 0;
ui8 totalChance = 0; ui8 totalChance = 0;
for(auto config : bankInfo->getPossibleGuards()) for(auto config : bankInfo->getPossibleGuards(bank->cb))
{ {
totalStrength += config.second.totalStrength * config.first; totalStrength += config.second.totalStrength * config.first;
totalChance += config.first; totalChance += config.first;

View File

@ -103,7 +103,7 @@ std::string CompleteQuest::questToString() const
return "inactive quest"; return "inactive quest";
MetaString ms; MetaString ms;
q.quest->getRolloverText(ms, false); q.quest->getRolloverText(q.obj->cb, ms, false);
return ms.toString(); return ms.toString();
} }

View File

@ -22,7 +22,6 @@
#include "../../lib/CHeroHandler.h" #include "../../lib/CHeroHandler.h"
#include "../../lib/GameSettings.h" #include "../../lib/GameSettings.h"
#include "../../lib/gameState/CGameState.h" #include "../../lib/gameState/CGameState.h"
#include "../../lib/bonuses/CBonusSystemNode.h"
#include "../../lib/bonuses/Limiters.h" #include "../../lib/bonuses/Limiters.h"
#include "../../lib/bonuses/Updaters.h" #include "../../lib/bonuses/Updaters.h"
#include "../../lib/bonuses/Propagators.h" #include "../../lib/bonuses/Propagators.h"

View File

@ -16,6 +16,7 @@
#include "client/Client.h" #include "client/Client.h"
#include "lib/mapping/CMap.h" #include "lib/mapping/CMap.h"
#include "lib/mapObjects/CGHeroInstance.h" #include "lib/mapObjects/CGHeroInstance.h"
#include "lib/mapObjects/CGTownInstance.h"
#include "lib/CBuildingHandler.h" #include "lib/CBuildingHandler.h"
#include "lib/CGeneralTextHandler.h" #include "lib/CGeneralTextHandler.h"
#include "lib/CHeroHandler.h" #include "lib/CHeroHandler.h"

View File

@ -12,16 +12,13 @@
#include "../lib/VCMI_Lib.h" #include "../lib/VCMI_Lib.h"
const CGameInfo * CGI; CGameInfo * CGI;
CClientState * CCS = nullptr; CClientState * CCS = nullptr;
CServerHandler * CSH; CServerHandler * CSH;
CGameInfo::CGameInfo() CGameInfo::CGameInfo()
{ {
generaltexth = nullptr;
mh = nullptr;
townh = nullptr;
globalServices = nullptr; globalServices = nullptr;
} }

View File

@ -56,7 +56,7 @@ extern CClientState * CCS;
/// CGameInfo class /// CGameInfo class
/// for allowing different functions for accessing game informations /// for allowing different functions for accessing game informations
class CGameInfo : public Services class CGameInfo final : public Services
{ {
public: public:
const ArtifactService * artifacts() const override; const ArtifactService * artifacts() const override;
@ -78,19 +78,20 @@ public:
const spells::effects::Registry * spellEffects() const override; const spells::effects::Registry * spellEffects() const override;
spells::effects::Registry * spellEffects() override; spells::effects::Registry * spellEffects() override;
ConstTransitivePtr<CModHandler> modh; //public? std::shared_ptr<const CModHandler> modh;
ConstTransitivePtr<BattleFieldHandler> battleFieldHandler; std::shared_ptr<const BattleFieldHandler> battleFieldHandler;
ConstTransitivePtr<CHeroHandler> heroh; std::shared_ptr<const CHeroHandler> heroh;
ConstTransitivePtr<CCreatureHandler> creh; std::shared_ptr<const CCreatureHandler> creh;
ConstTransitivePtr<CSpellHandler> spellh; std::shared_ptr<const CSpellHandler> spellh;
ConstTransitivePtr<CSkillHandler> skillh; std::shared_ptr<const CSkillHandler> skillh;
ConstTransitivePtr<CObjectHandler> objh; std::shared_ptr<const CObjectHandler> objh;
ConstTransitivePtr<TerrainTypeHandler> terrainTypeHandler; std::shared_ptr<const TerrainTypeHandler> terrainTypeHandler;
ConstTransitivePtr<CObjectClassesHandler> objtypeh; std::shared_ptr<const CObjectClassesHandler> objtypeh;
ConstTransitivePtr<ObstacleHandler> obstacleHandler; std::shared_ptr<const ObstacleHandler> obstacleHandler;
CGeneralTextHandler * generaltexth; std::shared_ptr<const CGeneralTextHandler> generaltexth;
CMapHandler * mh; std::shared_ptr<const CTownHandler> townh;
CTownHandler * townh;
std::shared_ptr<CMapHandler> mh;
void setFromLib(); void setFromLib();
@ -98,4 +99,4 @@ public:
private: private:
const Services * globalServices; const Services * globalServices;
}; };
extern const CGameInfo* CGI; extern CGameInfo* CGI;

View File

@ -72,7 +72,7 @@ void init()
CStopWatch tmh; CStopWatch tmh;
loadDLLClasses(); loadDLLClasses();
const_cast<CGameInfo*>(CGI)->setFromLib(); CGI->setFromLib();
logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff()); logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff());

View File

@ -82,7 +82,6 @@
#include "../lib/UnlockGuard.h" #include "../lib/UnlockGuard.h"
#include "../lib/VCMIDirs.h" #include "../lib/VCMIDirs.h"
#include "../lib/bonuses/CBonusSystemNode.h"
#include "../lib/bonuses/Limiters.h" #include "../lib/bonuses/Limiters.h"
#include "../lib/bonuses/Propagators.h" #include "../lib/bonuses/Propagators.h"
#include "../lib/bonuses/Updaters.h" #include "../lib/bonuses/Updaters.h"

View File

@ -142,6 +142,8 @@ CServerHandler::CServerHandler()
registerTypesLobbyPacks(*applier); registerTypesLobbyPacks(*applier);
} }
CServerHandler::~CServerHandler() = default;
void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names) void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names)
{ {
hostClientId = -1; hostClientId = -1;
@ -260,6 +262,9 @@ void CServerHandler::justConnectToServer(const std::string & addr, const ui16 po
addr.size() ? addr : getHostAddress(), addr.size() ? addr : getHostAddress(),
port ? port : getHostPort(), port ? port : getHostPort(),
NAME, uuid); NAME, uuid);
nextClient = std::make_unique<CClient>();
c->iser.cb = nextClient.get();
} }
catch(std::runtime_error & error) catch(std::runtime_error & error)
{ {
@ -636,7 +641,8 @@ void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameSta
{ {
if(CMM) if(CMM)
CMM->disable(); CMM->disable();
client = new CClient();
std::swap(client, nextClient);
highScoreCalc = nullptr; highScoreCalc = nullptr;
@ -687,7 +693,7 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
} }
client->endGame(); client->endGame();
vstd::clear_pointer(client); client.reset();
if(!restart) if(!restart)
{ {
@ -704,6 +710,8 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
if(c) if(c)
{ {
nextClient = std::make_unique<CClient>();
c->iser.cb = nextClient.get();
c->enterLobbyConnectionMode(); c->enterLobbyConnectionMode();
c->disableStackSendingByID(); c->disableStackSendingByID();
} }

View File

@ -95,6 +95,10 @@ class CServerHandler : public IServerAPI, public LobbyInfo
std::shared_ptr<HighScoreCalculation> highScoreCalc; std::shared_ptr<HighScoreCalculation> highScoreCalc;
/// temporary helper member that exists while game in lobby mode
/// required to correctly deserialize gamestate using client-side game callback
std::unique_ptr<CClient> nextClient;
void threadHandleConnection(); void threadHandleConnection();
void threadRunServer(); void threadRunServer();
void onServerFinished(); void onServerFinished();
@ -116,13 +120,14 @@ public:
std::shared_ptr<boost::thread> threadRunLocalServer; std::shared_ptr<boost::thread> threadRunLocalServer;
std::shared_ptr<CConnection> c; std::shared_ptr<CConnection> c;
CClient * client; std::unique_ptr<CClient> client;
CondSh<bool> campaignServerRestartLock; CondSh<bool> campaignServerRestartLock;
static const std::string localhostAddress; static const std::string localhostAddress;
CServerHandler(); CServerHandler();
~CServerHandler();
std::string getHostAddress() const; std::string getHostAddress() const;
ui16 getHostPort() const; ui16 getHostPort() const;

View File

@ -139,14 +139,10 @@ CClient::CClient()
waitingRequest.clear(); waitingRequest.clear();
applier = std::make_shared<CApplier<CBaseForCLApply>>(); applier = std::make_shared<CApplier<CBaseForCLApply>>();
registerTypesClientPacks(*applier); registerTypesClientPacks(*applier);
IObjectInterface::cb = this;
gs = nullptr; gs = nullptr;
} }
CClient::~CClient() CClient::~CClient() = default;
{
IObjectInterface::cb = nullptr;
}
const Services * CClient::services() const const Services * CClient::services() const
{ {
@ -177,8 +173,9 @@ void CClient::newGame(CGameState * initializedGameState)
{ {
CSH->th->update(); CSH->th->update();
CMapService mapService; CMapService mapService;
gs = initializedGameState ? initializedGameState : new CGameState(); assert(initializedGameState);
gs->preInit(VLC); gs = initializedGameState;
gs->preInit(VLC, this);
logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff());
if(!initializedGameState) if(!initializedGameState)
{ {
@ -200,7 +197,7 @@ void CClient::loadGame(CGameState * initializedGameState)
logNetwork->info("Game state was transferred over network, loading."); logNetwork->info("Game state was transferred over network, loading.");
gs = initializedGameState; gs = initializedGameState;
gs->preInit(VLC); gs->preInit(VLC, this);
gs->updateOnLoad(CSH->si.get()); gs->updateOnLoad(CSH->si.get());
logNetwork->info("Game loaded, initialize interfaces."); logNetwork->info("Game loaded, initialize interfaces.");
@ -370,7 +367,7 @@ void CClient::endGame()
logNetwork->info("Ending current game!"); logNetwork->info("Ending current game!");
removeGUI(); removeGUI();
vstd::clear_pointer(const_cast<CGameInfo *>(CGI)->mh); CGI->mh.reset();
vstd::clear_pointer(gs); vstd::clear_pointer(gs);
logNetwork->info("Deleted mapHandler and gameState."); logNetwork->info("Deleted mapHandler and gameState.");
@ -392,7 +389,7 @@ void CClient::initMapHandler()
// During loading CPlayerInterface from serialized state it's depend on MH // During loading CPlayerInterface from serialized state it's depend on MH
if(!settings["session"]["headless"].Bool()) if(!settings["session"]["headless"].Bool())
{ {
const_cast<CGameInfo *>(CGI)->mh = new CMapHandler(gs->map); CGI->mh = std::make_shared<CMapHandler>(gs->map);
logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff()); logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff());
} }

View File

@ -203,7 +203,7 @@ void ClientCommandManager::handleConvertTextCommand()
try try
{ {
// load and drop loaded map - we only need loader to run over all maps // load and drop loaded map - we only need loader to run over all maps
mapService.loadMap(mapName); mapService.loadMap(mapName, nullptr);
} }
catch(std::exception & e) catch(std::exception & e)
{ {
@ -216,7 +216,7 @@ void ClientCommandManager::handleConvertTextCommand()
{ {
auto state = CampaignHandler::getCampaign(campaignName.getName()); auto state = CampaignHandler::getCampaign(campaignName.getName());
for (auto const & part : state->allScenarios()) for (auto const & part : state->allScenarios())
state->getMap(part); state->getMap(part, nullptr);
} }
VLC->generaltexth->dumpAllTexts(); VLC->generaltexth->dumpAllTexts();

View File

@ -39,6 +39,7 @@
#include "../lib/StartInfo.h" #include "../lib/StartInfo.h"
#include "../lib/CConfigHandler.h" #include "../lib/CConfigHandler.h"
#include "../lib/mapObjects/CGMarket.h" #include "../lib/mapObjects/CGMarket.h"
#include "../lib/mapObjects/CGTownInstance.h"
#include "../lib/gameState/CGameState.h" #include "../lib/gameState/CGameState.h"
#include "../lib/CStack.h" #include "../lib/CStack.h"
#include "../lib/battle/BattleInfo.h" #include "../lib/battle/BattleInfo.h"

View File

@ -530,7 +530,7 @@ void StackInfoBasicPanel::initializeData(const CStack * stack)
if (hasGraphics) if (hasGraphics)
{ {
//FIXME: support permanent duration //FIXME: support permanent duration
int duration = stack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; int duration = stack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain;
icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); icons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));
if(settings["general"]["enableUiEnhancements"].Bool()) if(settings["general"]["enableUiEnhancements"].Bool())

View File

@ -601,7 +601,7 @@ void BattleWindow::bSpellf()
{ {
//TODO: move to spell mechanics, add more information to spell cast problem //TODO: move to spell mechanics, add more information to spell cast problem
//Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible //Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible
auto blockingBonus = owner.currentHero()->getBonusLocalFirst(Selector::type()(BonusType::BLOCK_ALL_MAGIC)); auto blockingBonus = owner.currentHero()->getFirstBonus(Selector::type()(BonusType::BLOCK_ALL_MAGIC));
if (!blockingBonus) if (!blockingBonus)
return; return;

View File

@ -21,6 +21,7 @@
#include "../../lib/Point.h" #include "../../lib/Point.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/MiscObjects.h"
#include "../../lib/spells/CSpellHandler.h" #include "../../lib/spells/CSpellHandler.h"
#include "../../lib/mapping/CMap.h" #include "../../lib/mapping/CMap.h"
#include "../../lib/pathfinder/CGPathNode.h" #include "../../lib/pathfinder/CGPathNode.h"

View File

@ -225,7 +225,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int
spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds."
boost::replace_first(spellText, "%s", spell->getNameTranslated()); boost::replace_first(spellText, "%s", spell->getNameTranslated());
//FIXME: support permanent duration //FIXME: support permanent duration
int duration = battleStack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; int duration = battleStack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain;
boost::replace_first(spellText, "%d", std::to_string(duration)); boost::replace_first(spellText, "%d", std::to_string(duration));
spellIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); spellIcons.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed));

View File

@ -104,7 +104,7 @@ std::vector<Canvas> CMapOverviewWidget::createMinimaps(ResourcePath resource) co
std::unique_ptr<CMap> map; std::unique_ptr<CMap> map;
try try
{ {
map = mapService.loadMap(resource); map = mapService.loadMap(resource, nullptr);
} }
catch (const std::exception & e) catch (const std::exception & e)
{ {
@ -169,7 +169,7 @@ CMapOverviewWidget::CMapOverviewWidget(CMapOverview& parent):
lf >> *(mapHeader) >> startInfo; lf >> *(mapHeader) >> startInfo;
if(startInfo->campState) if(startInfo->campState)
campaignMap = startInfo->campState->getMap(*startInfo->campState->currentScenario()); campaignMap = startInfo->campState->getMap(*startInfo->campState->currentScenario(), nullptr);
res = ResourcePath(startInfo->fileURI, EResType::MAP); res = ResourcePath(startInfo->fileURI, EResType::MAP);
} }
if(!campaignMap) if(!campaignMap)

View File

@ -160,7 +160,7 @@ void CQuestLog::recreateLabelList()
} }
MetaString text; MetaString text;
quests[i].quest->getRolloverText (text, false); quests[i].quest->getRolloverText (quests[i].obj->cb, text, false);
if (quests[i].obj) if (quests[i].obj)
{ {
if (auto seersHut = dynamic_cast<const CGSeerHut *>(quests[i].obj)) if (auto seersHut = dynamic_cast<const CGSeerHut *>(quests[i].obj))
@ -236,7 +236,7 @@ void CQuestLog::selectQuest(int which, int labelId)
MetaString text; MetaString text;
std::vector<Component> components; std::vector<Component> components;
currentQuest->quest->getVisitText(text, components, true); currentQuest->quest->getVisitText(currentQuest->obj->cb, text, components, true);
if(description->slider) if(description->slider)
description->slider->scrollToMin(); // scroll text to start position description->slider->scrollToMin(); // scroll text to start position
description->setText(text.toString()); //TODO: use special log entry text description->setText(text.toString()); //TODO: use special log entry text

View File

@ -619,6 +619,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/CThreadHelper.h ${MAIN_LIB_DIR}/CThreadHelper.h
${MAIN_LIB_DIR}/CTownHandler.h ${MAIN_LIB_DIR}/CTownHandler.h
${MAIN_LIB_DIR}/FunctionList.h ${MAIN_LIB_DIR}/FunctionList.h
${MAIN_LIB_DIR}/GameCallbackHolder.h
${MAIN_LIB_DIR}/GameConstants.h ${MAIN_LIB_DIR}/GameConstants.h
${MAIN_LIB_DIR}/GameSettings.h ${MAIN_LIB_DIR}/GameSettings.h
${MAIN_LIB_DIR}/IBonusTypeHandler.h ${MAIN_LIB_DIR}/IBonusTypeHandler.h

View File

@ -187,14 +187,14 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid) DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid)
{ {
auto ret = new CArtifactInstance(VLC->arth->objects[ArtifactID::SPELL_SCROLL]); auto ret = new CArtifactInstance(ArtifactID(ArtifactID::SPELL_SCROLL).toArtifact());
auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELL, auto bonus = std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SPELL,
BonusSource::ARTIFACT_INSTANCE, -1, BonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), BonusSubtypeID(sid)); BonusSource::ARTIFACT_INSTANCE, -1, BonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), BonusSubtypeID(sid));
ret->addNewBonus(bonus); ret->addNewBonus(bonus);
return ret; return ret;
} }
DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifact * art) DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const CArtifact * art)
{ {
assert(art); assert(art);
@ -216,7 +216,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa
DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const ArtifactID & aid) DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const ArtifactID & aid)
{ {
return ArtifactUtils::createNewArtifactInstance((*VLC->arth)[aid]); return ArtifactUtils::createNewArtifactInstance(aid.toArtifact());
} }
DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID) DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID)

View File

@ -40,7 +40,7 @@ namespace ArtifactUtils
DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1); DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid); DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid);
DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid); DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid);
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art);
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid);
DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID = SpellID::NONE); DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID = SpellID::NONE);
DLL_LINKAGE void insertScrrollSpellName(std::string & description, const SpellID & sid); DLL_LINKAGE void insertScrrollSpellName(std::string & description, const SpellID & sid);

View File

@ -49,12 +49,12 @@ bool CCombinedArtifact::isCombined() const
return !(constituents.empty()); return !(constituents.empty());
} }
const std::vector<CArtifact*> & CCombinedArtifact::getConstituents() const const std::vector<const CArtifact*> & CCombinedArtifact::getConstituents() const
{ {
return constituents; return constituents;
} }
const std::vector<CArtifact*> & CCombinedArtifact::getPartOf() const const std::vector<const CArtifact*> & CCombinedArtifact::getPartOf() const
{ {
return partOf; return partOf;
} }
@ -328,7 +328,7 @@ std::vector<JsonNode> CArtHandler::loadLegacyData()
const std::vector<std::string> artSlots = { ART_POS_LIST }; const std::vector<std::string> artSlots = { ART_POS_LIST };
#undef ART_POS #undef ART_POS
static std::map<char, std::string> classes = static const std::map<char, std::string> classes =
{{'S',"SPECIAL"}, {'T',"TREASURE"},{'N',"MINOR"},{'J',"MAJOR"},{'R',"RELIC"},}; {{'S',"SPECIAL"}, {'T',"TREASURE"},{'N',"MINOR"},{'J',"MAJOR"},{'R',"RELIC"},};
CLegacyConfigParser parser(TextPath::builtin("DATA/ARTRAITS.TXT")); CLegacyConfigParser parser(TextPath::builtin("DATA/ARTRAITS.TXT"));
@ -353,7 +353,7 @@ std::vector<JsonNode> CArtHandler::loadLegacyData()
artData["slot"].Vector().back().String() = artSlot; artData["slot"].Vector().back().String() = artSlot;
} }
} }
artData["class"].String() = classes[parser.readString()[0]]; artData["class"].String() = classes.at(parser.readString()[0]);
artData["text"]["description"].String() = parser.readString(); artData["text"]["description"].String() = parser.readString();
parser.endLine(); parser.endLine();
@ -597,7 +597,7 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
{ {
// when this code is called both combinational art as well as component are loaded // when this code is called both combinational art as well as component are loaded
// so it is safe to access any of them // so it is safe to access any of them
art->constituents.push_back(objects[id]); art->constituents.push_back(ArtifactID(id).toArtifact());
objects[id]->partOf.push_back(art); objects[id]->partOf.push_back(art);
}); });
} }

View File

@ -47,12 +47,12 @@ class DLL_LINKAGE CCombinedArtifact
protected: protected:
CCombinedArtifact() = default; CCombinedArtifact() = default;
std::vector<CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr. std::vector<const CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
std::vector<CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art std::vector<const CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
public: public:
bool isCombined() const; bool isCombined() const;
const std::vector<CArtifact*> & getConstituents() const; const std::vector<const CArtifact*> & getConstituents() const;
const std::vector<CArtifact*> & getPartOf() const; const std::vector<const CArtifact*> & getPartOf() const;
}; };
class DLL_LINKAGE CScrollArtifact class DLL_LINKAGE CScrollArtifact

View File

@ -62,7 +62,7 @@ void CCombinedArtifactInstance::addPlacementMap(CArtifactSet::ArtPlacementMap &
SpellID CScrollArtifactInstance::getScrollSpellID() const SpellID CScrollArtifactInstance::getScrollSpellID() const
{ {
auto artInst = static_cast<const CArtifactInstance*>(this); auto artInst = static_cast<const CArtifactInstance*>(this);
const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); const auto bonus = artInst->getFirstBonus(Selector::type()(BonusType::SPELL));
if(!bonus) if(!bonus)
return SpellID::NONE; return SpellID::NONE;
return bonus->subtype.as<SpellID>(); return bonus->subtype.as<SpellID>();
@ -107,7 +107,7 @@ void CArtifactInstance::init()
setNodeType(ARTIFACT_INSTANCE); setNodeType(ARTIFACT_INSTANCE);
} }
CArtifactInstance::CArtifactInstance(CArtifact * art) CArtifactInstance::CArtifactInstance(const CArtifact * art)
{ {
init(); init();
setType(art); setType(art);
@ -118,10 +118,10 @@ CArtifactInstance::CArtifactInstance()
init(); init();
} }
void CArtifactInstance::setType(CArtifact * art) void CArtifactInstance::setType(const CArtifact * art)
{ {
artType = art; artType = art;
attachTo(*art); attachToSource(*art);
} }
std::string CArtifactInstance::nodeName() const std::string CArtifactInstance::nodeName() const

View File

@ -73,11 +73,11 @@ protected:
ArtifactInstanceID id; ArtifactInstanceID id;
public: public:
ConstTransitivePtr<CArtifact> artType; const CArtifact * artType = nullptr;
CArtifactInstance(CArtifact * art); CArtifactInstance(const CArtifact * art);
CArtifactInstance(); CArtifactInstance();
void setType(CArtifact * art); void setType(const CArtifact * art);
std::string nodeName() const override; std::string nodeName() const override;
std::string getDescription() const; std::string getDescription() const;
ArtifactID getTypeId() const; ArtifactID getTypeId() const;

View File

@ -407,20 +407,9 @@ void CCreature::serializeJson(JsonSerializeFormat & handler)
CCreatureHandler::CCreatureHandler() CCreatureHandler::CCreatureHandler()
: expAfterUpgrade(0) : expAfterUpgrade(0)
{ {
VLC->creh = this;
loadCommanders(); loadCommanders();
} }
const CCreature * CCreatureHandler::getCreature(const std::string & scope, const std::string & identifier) const
{
std::optional<si32> index = VLC->identifiers()->getIdentifier(scope, "creature", identifier);
if(!index)
throw std::runtime_error("Creature not found "+identifier);
return objects[*index];
}
void CCreatureHandler::loadCommanders() void CCreatureHandler::loadCommanders()
{ {
auto configResource = JsonPath::builtin("config/commanders.json"); auto configResource = JsonPath::builtin("config/commanders.json");
@ -797,7 +786,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
bl.clear(); bl.clear();
loadStackExp(b, bl, parser); loadStackExp(b, bl, parser);
for(const auto & b : bl) for(const auto & b : bl)
(*this)[sid]->addNewBonus(b); //add directly to CCreature Node objects[sid.getNum()]->addNewBonus(b); //add directly to CCreature Node
} }
while (parser.endLine()); while (parser.endLine());

View File

@ -222,8 +222,6 @@ public:
std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE std::vector< std::vector <ui8> > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE
std::vector <std::pair <std::shared_ptr<Bonus>, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it std::vector <std::pair <std::shared_ptr<Bonus>, std::pair <ui8, ui8> > > skillRequirements; // first - Bonus, second - which two skills are needed to use it
const CCreature * getCreature(const std::string & scope, const std::string & identifier) const;
CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any
CCreatureHandler(); CCreatureHandler();

View File

@ -739,11 +739,10 @@ void CStackInstance::giveStackExp(TExpType exp)
if (!vstd::iswithin(level, 1, 7)) if (!vstd::iswithin(level, 1, 7))
level = 0; level = 0;
CCreatureHandler * creh = VLC->creh; ui32 maxExp = VLC->creh->expRanks[level].back();
ui32 maxExp = creh->expRanks[level].back();
vstd::amin(exp, static_cast<TExpType>(maxExp)); //prevent exp overflow due to different types vstd::amin(exp, static_cast<TExpType>(maxExp)); //prevent exp overflow due to different types
vstd::amin(exp, (maxExp * creh->maxExpPerBattle[level])/100); vstd::amin(exp, (maxExp * VLC->creh->maxExpPerBattle[level])/100);
vstd::amin(experience += exp, maxExp); //can't get more exp than this limit vstd::amin(experience += exp, maxExp); //can't get more exp than this limit
} }
@ -759,7 +758,7 @@ void CStackInstance::setType(const CCreature *c)
{ {
if(type) if(type)
{ {
detachFrom(const_cast<CCreature&>(*type)); detachFromSource(*type);
if (type->isMyUpgrade(c) && VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) if (type->isMyUpgrade(c) && VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE))
experience = static_cast<TExpType>(experience * VLC->creh->expAfterUpgrade / 100.0); experience = static_cast<TExpType>(experience * VLC->creh->expAfterUpgrade / 100.0);
} }
@ -767,7 +766,7 @@ void CStackInstance::setType(const CCreature *c)
CStackBasicDescriptor::setType(c); CStackBasicDescriptor::setType(c);
if(type) if(type)
attachTo(const_cast<CCreature&>(*type)); attachToSource(*type);
} }
std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const std::string CStackInstance::bonusToString(const std::shared_ptr<Bonus>& bonus, bool description) const
{ {
@ -1055,7 +1054,7 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler)
std::string typeName; std::string typeName;
handler.serializeString("type", typeName); handler.serializeString("type", typeName);
if(!typeName.empty()) if(!typeName.empty())
setType(VLC->creh->getCreature(ModScope::scopeMap(), typeName)); setType(CreatureID(CreatureID::decode(typeName)).toCreature());
} }
} }

View File

@ -16,6 +16,8 @@
#include "gameState/TavernHeroesPool.h" #include "gameState/TavernHeroesPool.h"
#include "gameState/QuestInfo.h" #include "gameState/QuestInfo.h"
#include "mapObjects/CGHeroInstance.h" #include "mapObjects/CGHeroInstance.h"
#include "mapObjects/CGTownInstance.h"
#include "mapObjects/MiscObjects.h"
#include "networkPacks/ArtifactLocation.h" #include "networkPacks/ArtifactLocation.h"
#include "CGeneralTextHandler.h" #include "CGeneralTextHandler.h"
#include "StartInfo.h" // for StartInfo #include "StartInfo.h" // for StartInfo
@ -382,7 +384,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
if(creature->getFaction() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue) if(creature->getFaction() == factionIndex && static_cast<int>(creature->getAIValue()) > maxAIValue)
{ {
maxAIValue = creature->getAIValue(); maxAIValue = creature->getAIValue();
mostStrong = creature; mostStrong = creature.get();
} }
} }
@ -791,7 +793,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio ) int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio )
{ {
if (!getPlayerID() || CGObelisk::obeliskCount == 0) if (!getPlayerID() || gs->map->obeliskCount == 0)
{ {
*outKnownRatio = 0.0; *outKnownRatio = 0.0;
} }
@ -799,10 +801,10 @@ int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio )
{ {
TeamID t = gs->getPlayerTeam(*getPlayerID())->id; TeamID t = gs->getPlayerTeam(*getPlayerID())->id;
double visited = 0.0; double visited = 0.0;
if(CGObelisk::visited.count(t)) if(gs->map->obelisksVisited.count(t))
visited = static_cast<double>(CGObelisk::visited[t]); visited = static_cast<double>(gs->map->obelisksVisited[t]);
*outKnownRatio = visited / CGObelisk::obeliskCount; *outKnownRatio = visited / gs->map->obeliskCount;
} }
return gs->map->grailPos; return gs->map->grailPos;
} }

View File

@ -155,6 +155,14 @@ bool CHeroClass::isMagicHero() const
return affinity == MAGIC; return affinity == MAGIC;
} }
int CHeroClass::tavernProbability(FactionID targetFaction) const
{
auto it = selectionProbability.find(targetFaction);
if (it != selectionProbability.end())
return it->second;
return 0;
}
EAlignment CHeroClass::getAlignment() const EAlignment CHeroClass::getAlignment() const
{ {
return VLC->factions()->getById(faction)->getAlignment(); return VLC->factions()->getById(faction)->getAlignment();
@ -292,7 +300,7 @@ CHeroClass * CHeroClassHandler::loadFromJson(const std::string & scope, const Js
VLC->identifiers()->requestIdentifier ("creature", node["commander"], VLC->identifiers()->requestIdentifier ("creature", node["commander"],
[=](si32 commanderID) [=](si32 commanderID)
{ {
heroClass->commander = VLC->creh->objects[commanderID]; heroClass->commander = CreatureID(commanderID).toCreature();
}); });
heroClass->defaultTavernChance = static_cast<ui32>(node["defaultTavern"].Float()); heroClass->defaultTavernChance = static_cast<ui32>(node["defaultTavern"].Float());
@ -369,9 +377,9 @@ std::vector<JsonNode> CHeroClassHandler::loadLegacyData()
void CHeroClassHandler::afterLoadFinalization() void CHeroClassHandler::afterLoadFinalization()
{ {
// for each pair <class, town> set selection probability if it was not set before in tavern entries // for each pair <class, town> set selection probability if it was not set before in tavern entries
for(CHeroClass * heroClass : objects) for(auto & heroClass : objects)
{ {
for(CFaction * faction : VLC->townh->objects) for(auto & faction : VLC->townh->objects)
{ {
if (!faction->town) if (!faction->town)
continue; continue;
@ -394,9 +402,9 @@ void CHeroClassHandler::afterLoadFinalization()
} }
} }
for(CHeroClass * hc : objects) for(const auto & hc : objects)
{ {
if (!hc->imageMapMale.empty()) if(!hc->imageMapMale.empty())
{ {
JsonNode templ; JsonNode templ;
templ["animation"].String() = hc->imageMapMale; templ["animation"].String() = hc->imageMapMale;
@ -454,7 +462,7 @@ CHero * CHeroHandler::loadFromJson(const std::string & scope, const JsonNode & n
VLC->identifiers()->requestIdentifier("heroClass", node["class"], VLC->identifiers()->requestIdentifier("heroClass", node["class"],
[=](si32 classID) [=](si32 classID)
{ {
hero->heroClass = classes[HeroClassID(classID)]; hero->heroClass = HeroClassID(classID).toHeroClass();
}); });
return hero; return hero;
@ -532,7 +540,7 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ba
{ {
std::set<CreatureID> oldTargets = targets; std::set<CreatureID> oldTargets = targets;
for (auto const & upgradeSourceID : oldTargets) for(const auto & upgradeSourceID : oldTargets)
{ {
const CCreature * upgradeSource = upgradeSourceID.toCreature(); const CCreature * upgradeSource = upgradeSourceID.toCreature();
targets.insert(upgradeSource->upgrades.begin(), upgradeSource->upgrades.end()); targets.insert(upgradeSource->upgrades.begin(), upgradeSource->upgrades.end());
@ -544,7 +552,7 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ba
for(CreatureID cid : targets) for(CreatureID cid : targets)
{ {
auto const & specCreature = *cid.toCreature(); const auto & specCreature = *cid.toCreature();
int stepSize = specCreature.getLevel() ? specCreature.getLevel() : 5; int stepSize = specCreature.getLevel() ? specCreature.getLevel() : 5;
{ {
@ -604,7 +612,7 @@ void CHeroHandler::beforeValidate(JsonNode & object)
void CHeroHandler::afterLoadFinalization() void CHeroHandler::afterLoadFinalization()
{ {
for (auto const & functor : callAfterLoadFinalization) for(const auto & functor : callAfterLoadFinalization)
functor(); functor();
callAfterLoadFinalization.clear(); callAfterLoadFinalization.clear();
@ -790,7 +798,7 @@ std::set<HeroTypeID> CHeroHandler::getDefaultAllowed() const
{ {
std::set<HeroTypeID> result; std::set<HeroTypeID> result;
for(const CHero * hero : objects) for(auto & hero : objects)
if (hero && !hero->special) if (hero && !hero->special)
result.insert(hero->getId()); result.insert(hero->getId());

View File

@ -57,7 +57,7 @@ public:
std::vector<InitialArmyStack> initialArmy; std::vector<InitialArmyStack> initialArmy;
CHeroClass * heroClass{}; const CHeroClass * heroClass = nullptr;
std::vector<std::pair<SecondarySkill, ui8> > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert) std::vector<std::pair<SecondarySkill, ui8> > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert)
BonusList specialty; BonusList specialty;
std::set<SpellID> spells; std::set<SpellID> spells;
@ -121,7 +121,7 @@ public:
// resulting chance = sqrt(town.chance * heroClass.chance) // resulting chance = sqrt(town.chance * heroClass.chance)
ui32 defaultTavernChance; ui32 defaultTavernChance;
CCreature * commander; const CCreature * commander;
std::vector<int> primarySkillInitial; // initial primary skills std::vector<int> primarySkillInitial; // initial primary skills
std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level
@ -154,6 +154,8 @@ public:
void serializeJson(JsonSerializeFormat & handler); void serializeJson(JsonSerializeFormat & handler);
EAlignment getAlignment() const; EAlignment getAlignment() const;
int tavernProbability(FactionID faction) const;
}; };
class DLL_LINKAGE CHeroClassHandler : public CHandlerBase<HeroClassID, HeroClass, CHeroClass, HeroClassService> class DLL_LINKAGE CHeroClassHandler : public CHandlerBase<HeroClassID, HeroClass, CHeroClass, HeroClassService>
@ -189,8 +191,6 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase<HeroTypeID, HeroType, CHero
std::vector<std::function<void()>> callAfterLoadFinalization; std::vector<std::function<void()>> callAfterLoadFinalization;
public: public:
CHeroClassHandler classes;
ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount
TExpType reqExp(ui32 level) const; //calculates experience required for given level TExpType reqExp(ui32 level) const; //calculates experience required for given level
ui32 maxSupportedLevel() const; ui32 maxSupportedLevel() const;

View File

@ -23,8 +23,6 @@ PlayerState::PlayerState()
setNodeType(PLAYER); setNodeType(PLAYER);
} }
PlayerState::PlayerState(PlayerState && other) noexcept = default;
PlayerState::~PlayerState() = default; PlayerState::~PlayerState() = default;
std::string PlayerState::nodeName() const std::string PlayerState::nodeName() const

View File

@ -67,7 +67,6 @@ public:
TurnTimerInfo turnTimer; TurnTimerInfo turnTimer;
PlayerState(); PlayerState();
PlayerState(PlayerState && other) noexcept;
~PlayerState(); ~PlayerState();
std::string nodeName() const override; std::string nodeName() const override;
@ -123,7 +122,6 @@ public:
std::unique_ptr<boost::multi_array<ui8, 3>> fogOfWarMap; //[z][x][y] true - visible, false - hidden std::unique_ptr<boost::multi_array<ui8, 3>> fogOfWarMap; //[z][x][y] true - visible, false - hidden
TeamState(); TeamState();
TeamState(TeamState && other) noexcept;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@ -72,7 +72,7 @@ void CStack::localInit(BattleInfo * battleInfo)
CArmedInstance * army = battle->battleGetArmyObject(side); CArmedInstance * army = battle->battleGetArmyObject(side);
assert(army); assert(army);
attachTo(*army); attachTo(*army);
attachTo(const_cast<CCreature&>(*type)); attachToSource(*type);
} }
nativeTerrain = getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock nativeTerrain = getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock
CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered

View File

@ -336,9 +336,9 @@ JsonNode readBuilding(CLegacyConfigParser & parser)
return ret; return ret;
} }
TPropagatorPtr & CTownHandler::emptyPropagator() const TPropagatorPtr & CTownHandler::emptyPropagator()
{ {
static TPropagatorPtr emptyProp(nullptr); static const TPropagatorPtr emptyProp(nullptr);
return emptyProp; return emptyProp;
} }
@ -534,7 +534,7 @@ R CTownHandler::getMappedValue(const JsonNode & node, const R defval, const std:
void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const
{ {
std::shared_ptr<Bonus> b; std::shared_ptr<Bonus> b;
static TPropagatorPtr playerPropagator = std::make_shared<CPropagatorNodeType>(CBonusSystemNode::ENodeTypes::PLAYER); static const TPropagatorPtr playerPropagator = std::make_shared<CPropagatorNodeType>(CBonusSystemNode::ENodeTypes::PLAYER);
if(building->bid == BuildingID::TAVERN) if(building->bid == BuildingID::TAVERN)
{ {
@ -578,7 +578,7 @@ std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType ty
return createBonus(build, type, val, subtype, emptyPropagator()); return createBonus(build, type, val, subtype, emptyPropagator());
} }
std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, TPropagatorPtr & prop) const std::shared_ptr<Bonus> CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const
{ {
std::ostringstream descr; std::ostringstream descr;
descr << build->getNameTranslated(); descr << build->getNameTranslated();
@ -589,7 +589,7 @@ std::shared_ptr<Bonus> CTownHandler::createBonusImpl(const BuildingID & building
const FactionID & faction, const FactionID & faction,
BonusType type, BonusType type,
int val, int val,
TPropagatorPtr & prop, const TPropagatorPtr & prop,
const std::string & description, const std::string & description,
BonusSubtypeID subtype) const BonusSubtypeID subtype) const
{ {
@ -991,7 +991,7 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
VLC->identifiers()->requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID) VLC->identifiers()->requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID)
{ {
VLC->heroh->classes[HeroClassID(classID)]->selectionProbability[town->faction->getId()] = chance; VLC->heroclassesh->objects[classID]->selectionProbability[town->faction->getId()] = chance;
}); });
} }

View File

@ -290,7 +290,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
std::vector<BuildingRequirementsHelper> requirementsToLoad; std::vector<BuildingRequirementsHelper> requirementsToLoad;
std::vector<BuildingRequirementsHelper> overriddenBidsToLoad; //list of buildings, which bonuses should be overridden. std::vector<BuildingRequirementsHelper> overriddenBidsToLoad; //list of buildings, which bonuses should be overridden.
static TPropagatorPtr & emptyPropagator(); static const TPropagatorPtr & emptyPropagator();
void initializeRequirements(); void initializeRequirements();
void initializeOverridden(); void initializeOverridden();
@ -303,12 +303,12 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val) const;
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype) const;
std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, TPropagatorPtr & prop) const; std::shared_ptr<Bonus> createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const;
std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building, std::shared_ptr<Bonus> createBonusImpl(const BuildingID & building,
const FactionID & faction, const FactionID & faction,
BonusType type, BonusType type,
int val, int val,
TPropagatorPtr & prop, const TPropagatorPtr & prop,
const std::string & description, const std::string & description,
BonusSubtypeID subtype) const; BonusSubtypeID subtype) const;

26
lib/GameCallbackHolder.h Normal file
View File

@ -0,0 +1,26 @@
/*
* GameCallbackHolder.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class IGameCallback;
class DLL_LINKAGE GameCallbackHolder
{
public:
IGameCallback * const cb;
explicit GameCallbackHolder(IGameCallback *cb):
cb(cb)
{}
};
VCMI_LIB_NAMESPACE_END

View File

@ -16,7 +16,6 @@
#include "CBonusTypeHandler.h" #include "CBonusTypeHandler.h"
#include "BattleFieldHandler.h" #include "BattleFieldHandler.h"
#include "ObstacleHandler.h" #include "ObstacleHandler.h"
#include "bonuses/CBonusSystemNode.h"
#include "bonuses/Limiters.h" #include "bonuses/Limiters.h"
#include "bonuses/Propagators.h" #include "bonuses/Propagators.h"
#include "bonuses/Updaters.h" #include "bonuses/Updaters.h"
@ -26,7 +25,10 @@
#include "rmg/CMapGenOptions.h" #include "rmg/CMapGenOptions.h"
#include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/AObjectTypeHandler.h"
#include "mapObjectConstructors/CObjectClassesHandler.h" #include "mapObjectConstructors/CObjectClassesHandler.h"
#include "mapObjects/CGTownInstance.h"
#include "mapObjects/CObjectHandler.h" #include "mapObjects/CObjectHandler.h"
#include "mapObjects/CQuest.h"
#include "mapObjects/MiscObjects.h"
#include "mapObjects/ObjectTemplate.h" #include "mapObjects/ObjectTemplate.h"
#include "campaign/CampaignState.h" #include "campaign/CampaignState.h"
#include "StartInfo.h" #include "StartInfo.h"

View File

@ -44,11 +44,21 @@ public:
/// allows handler to do post-loading step for validation or integration of loaded data /// allows handler to do post-loading step for validation or integration of loaded data
virtual void afterLoadFinalization(){}; virtual void afterLoadFinalization(){};
virtual ~IHandlerBase(){} virtual ~IHandlerBase() = default;
}; };
template <class _ObjectID, class _ObjectBase, class _Object, class _ServiceBase> class CHandlerBase : public _ServiceBase, public IHandlerBase template <class _ObjectID, class _ObjectBase, class _Object, class _ServiceBase> class CHandlerBase : public _ServiceBase, public IHandlerBase
{ {
const _Object * getObjectImpl(const int32_t index) const
{
if(index < 0 || index >= objects.size())
{
logMod->error("%s id %d is invalid", getTypeNames()[0], index);
throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front());
}
return objects[index].get();
}
public: public:
virtual ~CHandlerBase() virtual ~CHandlerBase()
{ {
@ -56,22 +66,21 @@ public:
{ {
o.dellNull(); o.dellNull();
} }
} }
const Entity * getBaseByIndex(const int32_t index) const override const Entity * getBaseByIndex(const int32_t index) const override
{ {
return getByIndex(index); return getObjectImpl(index);
} }
const _ObjectBase * getById(const _ObjectID & id) const override const _ObjectBase * getById(const _ObjectID & id) const override
{ {
return (*this)[id].get(); return getObjectImpl(id.getNum());
} }
const _ObjectBase * getByIndex(const int32_t index) const override const _ObjectBase * getByIndex(const int32_t index) const override
{ {
return (*this)[_ObjectID(index)].get(); return getObjectImpl(index);
} }
void forEachBase(const std::function<void(const Entity * entity, bool & stop)> & cb) const override void forEachBase(const std::function<void(const Entity * entity, bool & stop)> & cb) const override
@ -105,21 +114,14 @@ public:
registerObject(scope, type_name, name, object->getIndex()); registerObject(scope, type_name, name, object->getIndex());
} }
ConstTransitivePtr<_Object> operator[] (const _ObjectID id) const const _Object * operator[] (const _ObjectID id) const
{ {
const int32_t raw_id = id.getNum(); return getObjectImpl(id.getNum());
return operator[](raw_id);
} }
ConstTransitivePtr<_Object> operator[] (int32_t index) const const _Object * operator[] (int32_t index) const
{ {
if(index < 0 || index >= objects.size()) return getObjectImpl(index);
{
logMod->error("%s id %d is invalid", getTypeNames()[0], index);
throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front());
}
return objects[index];
} }
void updateEntity(int32_t index, const JsonNode & data) void updateEntity(int32_t index, const JsonNode & data)

View File

@ -690,7 +690,6 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
template <typename T> template <typename T>
const T parseByMap(const std::map<std::string, T> & map, const JsonNode * val, const std::string & err) const T parseByMap(const std::map<std::string, T> & map, const JsonNode * val, const std::string & err)
{ {
static T defaultValue = T();
if (!val->isNull()) if (!val->isNull())
{ {
const std::string & type = val->String(); const std::string & type = val->String();
@ -698,7 +697,7 @@ const T parseByMap(const std::map<std::string, T> & map, const JsonNode * val, c
if (it == map.end()) if (it == map.end())
{ {
logMod->error("Error: invalid %s%s.", err, type); logMod->error("Error: invalid %s%s.", err, type);
return defaultValue; return {};
} }
else else
{ {
@ -706,7 +705,7 @@ const T parseByMap(const std::map<std::string, T> & map, const JsonNode * val, c
} }
} }
else else
return defaultValue; return {};
} }
template <typename T> template <typename T>

View File

@ -31,9 +31,7 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
namespace JsonRandom si32 JsonRandom::loadVariable(const std::string & variableGroup, const std::string & value, const Variables & variables, si32 defaultValue)
{
si32 loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue)
{ {
if (value.empty() || value[0] != '@') if (value.empty() || value[0] != '@')
{ {
@ -51,12 +49,12 @@ namespace JsonRandom
return variables.at(variableID); return variables.at(variableID);
} }
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue) si32 JsonRandom::loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue)
{ {
if(value.isNull()) if(value.isNull())
return defaultValue; return defaultValue;
if(value.isNumber()) if(value.isNumber())
return static_cast<si32>(value.Float()); return value.Integer();
if (value.isString()) if (value.isString())
return loadVariable("number", value.String(), variables, defaultValue); return loadVariable("number", value.String(), variables, defaultValue);
@ -70,16 +68,16 @@ namespace JsonRandom
if(value.isStruct()) if(value.isStruct())
{ {
if (!value["amount"].isNull()) if (!value["amount"].isNull())
return static_cast<si32>(loadValue(value["amount"], rng, variables, defaultValue)); return loadValue(value["amount"], rng, variables, defaultValue);
si32 min = static_cast<si32>(loadValue(value["min"], rng, variables, 0)); si32 min = loadValue(value["min"], rng, variables, 0);
si32 max = static_cast<si32>(loadValue(value["max"], rng, variables, 0)); si32 max = loadValue(value["max"], rng, variables, 0);
return rng.getIntRange(min, max)(); return rng.getIntRange(min, max)();
} }
return defaultValue; return defaultValue;
} }
template<typename IdentifierType> template<typename IdentifierType>
IdentifierType decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) IdentifierType JsonRandom::decodeKey(const std::string & modScope, const std::string & value, const Variables & variables)
{ {
if (value.empty() || value[0] != '@') if (value.empty() || value[0] != '@')
return IdentifierType(*VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value)); return IdentifierType(*VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value));
@ -88,7 +86,7 @@ namespace JsonRandom
} }
template<typename IdentifierType> template<typename IdentifierType>
IdentifierType decodeKey(const JsonNode & value, const Variables & variables) IdentifierType JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
{ {
if (value.String().empty() || value.String()[0] != '@') if (value.String().empty() || value.String()[0] != '@')
return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value)); return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value));
@ -97,19 +95,19 @@ namespace JsonRandom
} }
template<> template<>
PlayerColor decodeKey(const JsonNode & value, const Variables & variables) PlayerColor JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
{ {
return PlayerColor(*VLC->identifiers()->getIdentifier("playerColor", value)); return PlayerColor(*VLC->identifiers()->getIdentifier("playerColor", value));
} }
template<> template<>
PrimarySkill decodeKey(const JsonNode & value, const Variables & variables) PrimarySkill JsonRandom::decodeKey(const JsonNode & value, const Variables & variables)
{ {
return PrimarySkill(*VLC->identifiers()->getIdentifier("primarySkill", value)); return PrimarySkill(*VLC->identifiers()->getIdentifier("primarySkill", value));
} }
template<> template<>
PrimarySkill decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) PrimarySkill JsonRandom::decodeKey(const std::string & modScope, const std::string & value, const Variables & variables)
{ {
if (value.empty() || value[0] != '@') if (value.empty() || value[0] != '@')
return PrimarySkill(*VLC->identifiers()->getIdentifier(modScope, "primarySkill", value)); return PrimarySkill(*VLC->identifiers()->getIdentifier(modScope, "primarySkill", value));
@ -120,13 +118,13 @@ namespace JsonRandom
/// Method that allows type-specific object filtering /// Method that allows type-specific object filtering
/// Default implementation is to accept all input objects /// Default implementation is to accept all input objects
template<typename IdentifierType> template<typename IdentifierType>
std::set<IdentifierType> filterKeysTyped(const JsonNode & value, const std::set<IdentifierType> & valuesSet) std::set<IdentifierType> JsonRandom::filterKeysTyped(const JsonNode & value, const std::set<IdentifierType> & valuesSet)
{ {
return valuesSet; return valuesSet;
} }
template<> template<>
std::set<ArtifactID> filterKeysTyped(const JsonNode & value, const std::set<ArtifactID> & valuesSet) std::set<ArtifactID> JsonRandom::filterKeysTyped(const JsonNode & value, const std::set<ArtifactID> & valuesSet)
{ {
assert(value.isStruct()); assert(value.isStruct());
@ -164,7 +162,7 @@ namespace JsonRandom
if(!allowedClasses.empty() && !allowedClasses.count(art->aClass)) if(!allowedClasses.empty() && !allowedClasses.count(art->aClass))
continue; continue;
if(!IObjectInterface::cb->isAllowed(art->getId())) if(!cb->isAllowed(art->getId()))
continue; continue;
if(!allowedPositions.empty()) if(!allowedPositions.empty())
@ -186,7 +184,7 @@ namespace JsonRandom
} }
template<> template<>
std::set<SpellID> filterKeysTyped(const JsonNode & value, const std::set<SpellID> & valuesSet) std::set<SpellID> JsonRandom::filterKeysTyped(const JsonNode & value, const std::set<SpellID> & valuesSet)
{ {
std::set<SpellID> result = valuesSet; std::set<SpellID> result = valuesSet;
@ -213,7 +211,7 @@ namespace JsonRandom
} }
template<typename IdentifierType> template<typename IdentifierType>
std::set<IdentifierType> filterKeys(const JsonNode & value, const std::set<IdentifierType> & valuesSet, const Variables & variables) std::set<IdentifierType> JsonRandom::filterKeys(const JsonNode & value, const std::set<IdentifierType> & valuesSet, const Variables & variables)
{ {
if(value.isString()) if(value.isString())
return { decodeKey<IdentifierType>(value, variables) }; return { decodeKey<IdentifierType>(value, variables) };
@ -257,7 +255,7 @@ namespace JsonRandom
return valuesSet; return valuesSet;
} }
TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) TResources JsonRandom::loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
TResources ret; TResources ret;
@ -275,7 +273,7 @@ namespace JsonRandom
return ret; return ret;
} }
TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) TResources JsonRandom::loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::set<GameResID> defaultResources{ std::set<GameResID> defaultResources{
GameResID::WOOD, GameResID::WOOD,
@ -296,7 +294,7 @@ namespace JsonRandom
return ret; return ret;
} }
PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) PrimarySkill JsonRandom::loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::set<PrimarySkill> defaultSkills{ std::set<PrimarySkill> defaultSkills{
PrimarySkill::ATTACK, PrimarySkill::ATTACK,
@ -308,7 +306,7 @@ namespace JsonRandom
return *RandomGeneratorUtil::nextItem(potentialPicks, rng); return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
} }
std::vector<si32> loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::vector<si32> JsonRandom::loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::vector<si32> ret(GameConstants::PRIMARY_SKILLS, 0); std::vector<si32> ret(GameConstants::PRIMARY_SKILLS, 0);
std::set<PrimarySkill> defaultSkills{ std::set<PrimarySkill> defaultSkills{
@ -340,18 +338,18 @@ namespace JsonRandom
return ret; return ret;
} }
SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) SecondarySkill JsonRandom::loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::set<SecondarySkill> defaultSkills; std::set<SecondarySkill> defaultSkills;
for(const auto & skill : VLC->skillh->objects) for(const auto & skill : VLC->skillh->objects)
if (IObjectInterface::cb->isAllowed(skill->getId())) if (cb->isAllowed(skill->getId()))
defaultSkills.insert(skill->getId()); defaultSkills.insert(skill->getId());
std::set<SecondarySkill> potentialPicks = filterKeys(value, defaultSkills, variables); std::set<SecondarySkill> potentialPicks = filterKeys(value, defaultSkills, variables);
return *RandomGeneratorUtil::nextItem(potentialPicks, rng); return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
} }
std::map<SecondarySkill, si32> loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::map<SecondarySkill, si32> JsonRandom::loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::map<SecondarySkill, si32> ret; std::map<SecondarySkill, si32> ret;
if(value.isStruct()) if(value.isStruct())
@ -366,7 +364,7 @@ namespace JsonRandom
{ {
std::set<SecondarySkill> defaultSkills; std::set<SecondarySkill> defaultSkills;
for(const auto & skill : VLC->skillh->objects) for(const auto & skill : VLC->skillh->objects)
if (IObjectInterface::cb->isAllowed(skill->getId())) if (cb->isAllowed(skill->getId()))
defaultSkills.insert(skill->getId()); defaultSkills.insert(skill->getId());
for(const auto & element : value.Vector()) for(const auto & element : value.Vector())
@ -381,19 +379,19 @@ namespace JsonRandom
return ret; return ret;
} }
ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) ArtifactID JsonRandom::loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::set<ArtifactID> allowedArts; std::set<ArtifactID> allowedArts;
for(const auto & artifact : VLC->arth->objects) for(const auto & artifact : VLC->arth->objects)
if (IObjectInterface::cb->isAllowed(artifact->getId()) && VLC->arth->legalArtifact(artifact->getId())) if (cb->isAllowed(artifact->getId()) && VLC->arth->legalArtifact(artifact->getId()))
allowedArts.insert(artifact->getId()); allowedArts.insert(artifact->getId());
std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts, variables); std::set<ArtifactID> potentialPicks = filterKeys(value, allowedArts, variables);
return IObjectInterface::cb->gameState()->pickRandomArtifact(rng, potentialPicks); return cb->gameState()->pickRandomArtifact(rng, potentialPicks);
} }
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::vector<ArtifactID> JsonRandom::loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::vector<ArtifactID> ret; std::vector<ArtifactID> ret;
for (const JsonNode & entry : value.Vector()) for (const JsonNode & entry : value.Vector())
@ -403,11 +401,11 @@ namespace JsonRandom
return ret; return ret;
} }
SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) SpellID JsonRandom::loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::set<SpellID> defaultSpells; std::set<SpellID> defaultSpells;
for(const auto & spell : VLC->spellh->objects) for(const auto & spell : VLC->spellh->objects)
if (IObjectInterface::cb->isAllowed(spell->getId()) && !spell->isSpecial()) if (cb->isAllowed(spell->getId()) && !spell->isSpecial())
defaultSpells.insert(spell->getId()); defaultSpells.insert(spell->getId());
std::set<SpellID> potentialPicks = filterKeys(value, defaultSpells, variables); std::set<SpellID> potentialPicks = filterKeys(value, defaultSpells, variables);
@ -420,7 +418,7 @@ namespace JsonRandom
return *RandomGeneratorUtil::nextItem(potentialPicks, rng); return *RandomGeneratorUtil::nextItem(potentialPicks, rng);
} }
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::vector<SpellID> JsonRandom::loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::vector<SpellID> ret; std::vector<SpellID> ret;
for (const JsonNode & entry : value.Vector()) for (const JsonNode & entry : value.Vector())
@ -430,7 +428,7 @@ namespace JsonRandom
return ret; return ret;
} }
std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::vector<PlayerColor> JsonRandom::loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::vector<PlayerColor> ret; std::vector<PlayerColor> ret;
std::set<PlayerColor> defaultPlayers; std::set<PlayerColor> defaultPlayers;
@ -446,7 +444,7 @@ namespace JsonRandom
return ret; return ret;
} }
std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng) std::vector<HeroTypeID> JsonRandom::loadHeroes(const JsonNode & value, CRandomGenerator & rng)
{ {
std::vector<HeroTypeID> ret; std::vector<HeroTypeID> ret;
for(auto & entry : value.Vector()) for(auto & entry : value.Vector())
@ -456,7 +454,7 @@ namespace JsonRandom
return ret; return ret;
} }
std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng) std::vector<HeroClassID> JsonRandom::loadHeroClasses(const JsonNode & value, CRandomGenerator & rng)
{ {
std::vector<HeroClassID> ret; std::vector<HeroClassID> ret;
for(auto & entry : value.Vector()) for(auto & entry : value.Vector())
@ -466,7 +464,7 @@ namespace JsonRandom
return ret; return ret;
} }
CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) CStackBasicDescriptor JsonRandom::loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
CStackBasicDescriptor stack; CStackBasicDescriptor stack;
@ -495,7 +493,7 @@ namespace JsonRandom
return stack; return stack;
} }
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) std::vector<CStackBasicDescriptor> JsonRandom::loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables)
{ {
std::vector<CStackBasicDescriptor> ret; std::vector<CStackBasicDescriptor> ret;
for (const JsonNode & node : value.Vector()) for (const JsonNode & node : value.Vector())
@ -505,7 +503,7 @@ namespace JsonRandom
return ret; return ret;
} }
std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value, const Variables & variables) std::vector<JsonRandom::RandomStackInfo> JsonRandom::evaluateCreatures(const JsonNode & value, const Variables & variables)
{ {
std::vector<RandomStackInfo> ret; std::vector<RandomStackInfo> ret;
for (const JsonNode & node : value.Vector()) for (const JsonNode & node : value.Vector())
@ -519,7 +517,8 @@ namespace JsonRandom
info.minAmount = static_cast<si32>(node["min"].Float()); info.minAmount = static_cast<si32>(node["min"].Float());
info.maxAmount = static_cast<si32>(node["max"].Float()); info.maxAmount = static_cast<si32>(node["max"].Float());
} }
const CCreature * crea = VLC->creh->objects[VLC->identifiers()->getIdentifier("creature", node["type"]).value()]; CreatureID creatureID(VLC->identifiers()->getIdentifier("creature", node["type"]).value());
const CCreature * crea = creatureID.toCreature();
info.allowedCreatures.push_back(crea); info.allowedCreatures.push_back(crea);
if (node["upgradeChance"].Float() > 0) if (node["upgradeChance"].Float() > 0)
{ {
@ -531,7 +530,7 @@ namespace JsonRandom
return ret; return ret;
} }
std::vector<Bonus> DLL_LINKAGE loadBonuses(const JsonNode & value) std::vector<Bonus> JsonRandom::loadBonuses(const JsonNode & value)
{ {
std::vector<Bonus> ret; std::vector<Bonus> ret;
for (const JsonNode & entry : value.Vector()) for (const JsonNode & entry : value.Vector())
@ -542,6 +541,4 @@ namespace JsonRandom
return ret; return ret;
} }
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -11,6 +11,7 @@
#include "GameConstants.h" #include "GameConstants.h"
#include "ResourceSet.h" #include "ResourceSet.h"
#include "GameCallbackHolder.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -22,10 +23,29 @@ struct Bonus;
struct Component; struct Component;
class CStackBasicDescriptor; class CStackBasicDescriptor;
namespace JsonRandom class DLL_LINKAGE JsonRandom : public GameCallbackHolder
{ {
public:
using Variables = std::map<std::string, int>; using Variables = std::map<std::string, int>;
private:
template<typename IdentifierType>
std::set<IdentifierType> filterKeys(const JsonNode & value, const std::set<IdentifierType> & valuesSet, const Variables & variables);
template<typename IdentifierType>
std::set<IdentifierType> filterKeysTyped(const JsonNode & value, const std::set<IdentifierType> & valuesSet);
template<typename IdentifierType>
IdentifierType decodeKey(const std::string & modScope, const std::string & value, const Variables & variables);
template<typename IdentifierType>
IdentifierType decodeKey(const JsonNode & value, const Variables & variables);
si32 loadVariable(const std::string & variableGroup, const std::string & value, const Variables & variables, si32 defaultValue);
public:
using GameCallbackHolder::GameCallbackHolder;
struct DLL_LINKAGE RandomStackInfo struct DLL_LINKAGE RandomStackInfo
{ {
std::vector<const CCreature *> allowedCreatures; std::vector<const CCreature *> allowedCreatures;
@ -33,30 +53,30 @@ namespace JsonRandom
si32 maxAmount; si32 maxAmount;
}; };
DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue = 0); si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue = 0);
DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<si32> loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::vector<si32> loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::map<SecondarySkill, si32> loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::map<SecondarySkill, si32> loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value, const Variables & variables); std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value, const Variables & variables);
DLL_LINKAGE std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); std::vector<PlayerColor> loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables);
DLL_LINKAGE std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng); std::vector<HeroTypeID> loadHeroes(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng); std::vector<HeroClassID> loadHeroClasses(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE std::vector<Bonus> loadBonuses(const JsonNode & value); static std::vector<Bonus> loadBonuses(const JsonNode & value);
} };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
RiverTypeHandler::RiverTypeHandler() RiverTypeHandler::RiverTypeHandler()
{ {
objects.push_back(new RiverType); objects.push_back(new RiverType());
VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), ""); VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), "");
} }

View File

@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN
RoadTypeHandler::RoadTypeHandler() RoadTypeHandler::RoadTypeHandler()
{ {
objects.push_back(new RoadType); objects.push_back(new RoadType());
VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), ""); VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), "");
} }

View File

@ -32,7 +32,7 @@ FactionID PlayerSettings::getCastleValidated() const
{ {
if (!castle.isValid()) if (!castle.isValid())
return FactionID(0); return FactionID(0);
if (castle.getNum() < VLC->townh->size() && VLC->townh->objects[castle.getNum()]->town != nullptr) if (castle.getNum() < VLC->townh->size() && castle.toEntity(VLC)->hasTown())
return castle; return castle;
return FactionID(0); return FactionID(0);

View File

@ -65,54 +65,54 @@ DLL_LINKAGE void loadDLLClasses(bool onlyEssential)
const ArtifactService * LibClasses::artifacts() const const ArtifactService * LibClasses::artifacts() const
{ {
return arth; return arth.get();
} }
const CreatureService * LibClasses::creatures() const const CreatureService * LibClasses::creatures() const
{ {
return creh; return creh.get();
} }
const FactionService * LibClasses::factions() const const FactionService * LibClasses::factions() const
{ {
return townh; return townh.get();
} }
const HeroClassService * LibClasses::heroClasses() const const HeroClassService * LibClasses::heroClasses() const
{ {
return &heroh->classes; return heroclassesh.get();
} }
const HeroTypeService * LibClasses::heroTypes() const const HeroTypeService * LibClasses::heroTypes() const
{ {
return heroh; return heroh.get();
} }
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
const scripting::Service * LibClasses::scripts() const const scripting::Service * LibClasses::scripts() const
{ {
return scriptHandler; return scriptHandler.get();
} }
#endif #endif
const spells::Service * LibClasses::spells() const const spells::Service * LibClasses::spells() const
{ {
return spellh; return spellh.get();
} }
const SkillService * LibClasses::skills() const const SkillService * LibClasses::skills() const
{ {
return skillh; return skillh.get();
} }
const IBonusTypeHandler * LibClasses::getBth() const const IBonusTypeHandler * LibClasses::getBth() const
{ {
return bth; return bth.get();
} }
const CIdentifierStorage * LibClasses::identifiers() const const CIdentifierStorage * LibClasses::identifiers() const
{ {
return identifiersHandler; return identifiersHandler.get();
} }
const spells::effects::Registry * LibClasses::spellEffects() const const spells::effects::Registry * LibClasses::spellEffects() const
@ -127,17 +127,17 @@ spells::effects::Registry * LibClasses::spellEffects()
const BattleFieldService * LibClasses::battlefields() const const BattleFieldService * LibClasses::battlefields() const
{ {
return battlefieldsHandler; return battlefieldsHandler.get();
} }
const ObstacleService * LibClasses::obstacles() const const ObstacleService * LibClasses::obstacles() const
{ {
return obstacleHandler; return obstacleHandler.get();
} }
const IGameSettings * LibClasses::settings() const const IGameSettings * LibClasses::settings() const
{ {
return settingsHandler; return settingsHandler.get();
} }
void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & data) void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & data)
@ -154,7 +154,7 @@ void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode &
townh->updateEntity(index, data); townh->updateEntity(index, data);
break; break;
case Metatype::HERO_CLASS: case Metatype::HERO_CLASS:
heroh->classes.updateEntity(index, data); heroclassesh->updateEntity(index, data);
break; break;
case Metatype::HERO_TYPE: case Metatype::HERO_TYPE:
heroh->updateEntity(index, data); heroh->updateEntity(index, data);
@ -185,8 +185,8 @@ void LibClasses::loadFilesystem(bool extractArchives)
void LibClasses::loadModFilesystem() void LibClasses::loadModFilesystem()
{ {
CStopWatch loadTime; CStopWatch loadTime;
modh = new CModHandler(); modh = std::make_unique<CModHandler>();
identifiersHandler = new CIdentifierStorage(); identifiersHandler = std::make_unique<CIdentifierStorage>();
modh->loadMods(); modh->loadMods();
logGlobal->info("\tMod handler: %d ms", loadTime.getDiff()); logGlobal->info("\tMod handler: %d ms", loadTime.getDiff());
@ -199,9 +199,9 @@ static void logHandlerLoaded(const std::string & name, CStopWatch & timer)
logGlobal->info("\t\t %s handler: %d ms", name, timer.getDiff()); logGlobal->info("\t\t %s handler: %d ms", name, timer.getDiff());
} }
template <class Handler> void createHandler(Handler *&handler, const std::string &name, CStopWatch &timer) template <class Handler> void createHandler(std::shared_ptr<Handler> & handler, const std::string &name, CStopWatch &timer)
{ {
handler = new Handler(); handler = std::make_shared<Handler>();
logHandlerLoaded(name, timer); logHandlerLoaded(name, timer);
} }
@ -219,6 +219,7 @@ void LibClasses::init(bool onlyEssential)
createHandler(riverTypeHandler, "River", pomtime); createHandler(riverTypeHandler, "River", pomtime);
createHandler(terrainTypeHandler, "Terrain", pomtime); createHandler(terrainTypeHandler, "Terrain", pomtime);
createHandler(heroh, "Hero", pomtime); createHandler(heroh, "Hero", pomtime);
createHandler(heroclassesh, "Hero classes", pomtime);
createHandler(arth, "Artifact", pomtime); createHandler(arth, "Artifact", pomtime);
createHandler(creh, "Creature", pomtime); createHandler(creh, "Creature", pomtime);
createHandler(townh, "Town", pomtime); createHandler(townh, "Town", pomtime);
@ -239,77 +240,6 @@ void LibClasses::init(bool onlyEssential)
modh->afterLoad(onlyEssential); modh->afterLoad(onlyEssential);
} }
void LibClasses::clear()
{
delete heroh;
delete arth;
delete creh;
delete townh;
delete objh;
delete objtypeh;
delete spellh;
delete skillh;
delete modh;
delete bth;
delete tplh;
delete terviewh;
#if SCRIPTING_ENABLED
delete scriptHandler;
#endif
delete battlefieldsHandler;
delete generaltexth;
delete identifiersHandler;
delete obstacleHandler;
delete terrainTypeHandler;
delete riverTypeHandler;
delete roadTypeHandler;
delete settingsHandler;
makeNull();
}
void LibClasses::makeNull()
{
generaltexth = nullptr;
heroh = nullptr;
arth = nullptr;
creh = nullptr;
townh = nullptr;
objh = nullptr;
objtypeh = nullptr;
spellh = nullptr;
skillh = nullptr;
modh = nullptr;
bth = nullptr;
tplh = nullptr;
terviewh = nullptr;
#if SCRIPTING_ENABLED
scriptHandler = nullptr;
#endif
battlefieldsHandler = nullptr;
identifiersHandler = nullptr;
obstacleHandler = nullptr;
terrainTypeHandler = nullptr;
riverTypeHandler = nullptr;
roadTypeHandler = nullptr;
settingsHandler = nullptr;
}
LibClasses::LibClasses()
{
//init pointers to handlers
makeNull();
}
void LibClasses::callWhenDeserializing()
{
//FIXME: check if any of these are needed
//generaltexth = new CGeneralTextHandler();
//generaltexth->load();
//arth->load(true);
//modh->recreateHandlers();
//modh->loadConfigFromFile ("defaultMods"); //TODO: remember last saved config
}
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
void LibClasses::scriptsLoaded() void LibClasses::scriptsLoaded()
{ {
@ -317,10 +247,8 @@ void LibClasses::scriptsLoaded()
} }
#endif #endif
LibClasses::~LibClasses() LibClasses::LibClasses() = default;
{ LibClasses::~LibClasses() = default;
clear();
}
std::shared_ptr<CContentHandler> LibClasses::getContent() const std::shared_ptr<CContentHandler> LibClasses::getContent() const
{ {

View File

@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class CConsoleHandler; class CConsoleHandler;
class CArtHandler; class CArtHandler;
class CHeroHandler; class CHeroHandler;
class CHeroClassHandler;
class CCreatureHandler; class CCreatureHandler;
class CSpellHandler; class CSpellHandler;
class CSkillHandler; class CSkillHandler;
@ -47,20 +48,15 @@ namespace scripting
} }
#endif #endif
/// Loads and constructs several handlers /// Loads and constructs several handlers
class DLL_LINKAGE LibClasses : public Services class DLL_LINKAGE LibClasses final : public Services
{ {
CBonusTypeHandler * bth; std::shared_ptr<CBonusTypeHandler> bth;
void callWhenDeserializing(); //should be called only by serialize !!!
void makeNull(); //sets all handler pointers to null
std::shared_ptr<CContentHandler> getContent() const; std::shared_ptr<CContentHandler> getContent() const;
void setContent(std::shared_ptr<CContentHandler> content); void setContent(std::shared_ptr<CContentHandler> content);
public: public:
bool IS_AI_ENABLED = false; //unused?
const ArtifactService * artifacts() const override; const ArtifactService * artifacts() const override;
const CreatureService * creatures() const override; const CreatureService * creatures() const override;
const FactionService * factions() const override; const FactionService * factions() const override;
@ -83,35 +79,34 @@ public:
const IBonusTypeHandler * getBth() const; //deprecated const IBonusTypeHandler * getBth() const; //deprecated
const CIdentifierStorage * identifiers() const; const CIdentifierStorage * identifiers() const;
CArtHandler * arth; std::shared_ptr<CArtHandler> arth;
CHeroHandler * heroh; std::shared_ptr<CHeroHandler> heroh;
CCreatureHandler * creh; std::shared_ptr<CHeroClassHandler> heroclassesh;
CSpellHandler * spellh; std::shared_ptr<CCreatureHandler> creh;
CSkillHandler * skillh; std::shared_ptr<CSpellHandler> spellh;
CObjectHandler * objh; std::shared_ptr<CSkillHandler> skillh;
CObjectClassesHandler * objtypeh; std::shared_ptr<CObjectHandler> objh;
CTownHandler * townh; std::shared_ptr<CObjectClassesHandler> objtypeh;
CGeneralTextHandler * generaltexth; std::shared_ptr<CTownHandler> townh;
CModHandler * modh; std::shared_ptr<CGeneralTextHandler> generaltexth;
std::shared_ptr<CModHandler> modh;
std::shared_ptr<TerrainTypeHandler> terrainTypeHandler;
std::shared_ptr<RoadTypeHandler> roadTypeHandler;
std::shared_ptr<RiverTypeHandler> riverTypeHandler;
std::shared_ptr<CIdentifierStorage> identifiersHandler;
std::shared_ptr<CTerrainViewPatternConfig> terviewh;
std::shared_ptr<CRmgTemplateStorage> tplh;
std::shared_ptr<BattleFieldHandler> battlefieldsHandler;
std::shared_ptr<ObstacleHandler> obstacleHandler;
std::shared_ptr<GameSettings> settingsHandler;
TerrainTypeHandler * terrainTypeHandler;
RoadTypeHandler * roadTypeHandler;
RiverTypeHandler * riverTypeHandler;
CIdentifierStorage * identifiersHandler;
CTerrainViewPatternConfig * terviewh;
CRmgTemplateStorage * tplh;
BattleFieldHandler * battlefieldsHandler;
ObstacleHandler * obstacleHandler;
GameSettings * settingsHandler;
#if SCRIPTING_ENABLED #if SCRIPTING_ENABLED
scripting::ScriptHandler * scriptHandler; std::shared_ptr<scripting::ScriptHandler> scriptHandler;
#endif #endif
LibClasses(); //c-tor, loads .lods and NULLs handlers LibClasses(); //c-tor, loads .lods and NULLs handlers
~LibClasses(); ~LibClasses();
void init(bool onlyEssential); //uses standard config file void init(bool onlyEssential); //uses standard config file
void clear(); //deletes all handlers and its data
// basic initialization. should be called before init(). Can also extract original H3 archives // basic initialization. should be called before init(). Can also extract original H3 archives
void loadFilesystem(bool extractArchives); void loadFilesystem(bool extractArchives);

View File

@ -240,7 +240,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
{ {
try try
{ {
RangeGenerator obidgen(0, VLC->obstacleHandler->objects.size() - 1, ourRand); RangeGenerator obidgen(0, VLC->obstacleHandler->size() - 1, ourRand);
auto obstPtr = std::make_shared<CObstacleInstance>(); auto obstPtr = std::make_shared<CObstacleInstance>();
obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE; obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle); obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
@ -262,7 +262,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
{ {
while(tilesToBlock > 0) while(tilesToBlock > 0)
{ {
RangeGenerator obidgen(0, VLC->obstacleHandler->objects.size() - 1, ourRand); RangeGenerator obidgen(0, VLC->obstacleHandler->size() - 1, ourRand);
auto tileAccessibility = curB->getAccesibility(); auto tileAccessibility = curB->getAccesibility();
const int obid = obidgen.getSuchNumber(appropriateUsualObstacle); const int obid = obidgen.getSuchNumber(appropriateUsualObstacle);
const ObstacleInfo &obi = *Obstacle(obid).getInfo(); const ObstacleInfo &obi = *Obstacle(obid).getInfo();
@ -1009,7 +1009,7 @@ scripting::Pool * BattleInfo::getContextPool() const
{ {
//this is real battle, use global scripting context pool //this is real battle, use global scripting context pool
//TODO: make this line not ugly //TODO: make this line not ugly
return IObjectInterface::cb->getGlobalContextPool(); return battleGetFightingHero(0)->cb->getGlobalContextPool();
} }
#endif #endif

View File

@ -401,10 +401,9 @@ PlayerColor CBattleInfoEssentials::battleGetOwner(const battle::Unit * unit) con
PlayerColor initialOwner = getBattle()->getSidePlayer(unit->unitSide()); PlayerColor initialOwner = getBattle()->getSidePlayer(unit->unitSide());
static CSelector selector = Selector::type()(BonusType::HYPNOTIZED); static const CSelector selector = Selector::type()(BonusType::HYPNOTIZED);
static std::string cachingString = "type_103s-1";
if(unit->hasBonus(selector, cachingString)) if(unit->hasBonus(selector))
return otherPlayer(initialOwner); return otherPlayer(initialOwner);
else else
return initialOwner; return initialOwner;

View File

@ -10,7 +10,6 @@
#include "StdInc.h" #include "StdInc.h"
#include "Bonus.h" #include "Bonus.h"
#include "CBonusSystemNode.h"
#include "Limiters.h" #include "Limiters.h"
#include "Updaters.h" #include "Updaters.h"
#include "Propagators.h" #include "Propagators.h"

View File

@ -15,39 +15,39 @@ VCMI_LIB_NAMESPACE_BEGIN
namespace Selector namespace Selector
{ {
DLL_LINKAGE CSelectFieldEqual<BonusType> & type() DLL_LINKAGE const CSelectFieldEqual<BonusType> & type()
{ {
static CSelectFieldEqual<BonusType> stype(&Bonus::type); static const CSelectFieldEqual<BonusType> stype(&Bonus::type);
return stype; return stype;
} }
DLL_LINKAGE CSelectFieldEqual<BonusSubtypeID> & subtype() DLL_LINKAGE const CSelectFieldEqual<BonusSubtypeID> & subtype()
{ {
static CSelectFieldEqual<BonusSubtypeID> ssubtype(&Bonus::subtype); static const CSelectFieldEqual<BonusSubtypeID> ssubtype(&Bonus::subtype);
return ssubtype; return ssubtype;
} }
DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info() DLL_LINKAGE const CSelectFieldEqual<CAddInfo> & info()
{ {
static CSelectFieldEqual<CAddInfo> sinfo(&Bonus::additionalInfo); static const CSelectFieldEqual<CAddInfo> sinfo(&Bonus::additionalInfo);
return sinfo; return sinfo;
} }
DLL_LINKAGE CSelectFieldEqual<BonusSource> & sourceType() DLL_LINKAGE const CSelectFieldEqual<BonusSource> & sourceType()
{ {
static CSelectFieldEqual<BonusSource> ssourceType(&Bonus::source); static const CSelectFieldEqual<BonusSource> ssourceType(&Bonus::source);
return ssourceType; return ssourceType;
} }
DLL_LINKAGE CSelectFieldEqual<BonusSource> & targetSourceType() DLL_LINKAGE const CSelectFieldEqual<BonusSource> & targetSourceType()
{ {
static CSelectFieldEqual<BonusSource> ssourceType(&Bonus::targetSourceType); static const CSelectFieldEqual<BonusSource> ssourceType(&Bonus::targetSourceType);
return ssourceType; return ssourceType;
} }
DLL_LINKAGE CSelectFieldEqual<BonusLimitEffect> & effectRange() DLL_LINKAGE const CSelectFieldEqual<BonusLimitEffect> & effectRange()
{ {
static CSelectFieldEqual<BonusLimitEffect> seffectRange(&Bonus::effectRange); static const CSelectFieldEqual<BonusLimitEffect> seffectRange(&Bonus::effectRange);
return seffectRange; return seffectRange;
} }

View File

@ -125,12 +125,12 @@ public:
namespace Selector namespace Selector
{ {
extern DLL_LINKAGE CSelectFieldEqual<BonusType> & type(); extern DLL_LINKAGE const CSelectFieldEqual<BonusType> & type();
extern DLL_LINKAGE CSelectFieldEqual<BonusSubtypeID> & subtype(); extern DLL_LINKAGE const CSelectFieldEqual<BonusSubtypeID> & subtype();
extern DLL_LINKAGE CSelectFieldEqual<CAddInfo> & info(); extern DLL_LINKAGE const CSelectFieldEqual<CAddInfo> & info();
extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & sourceType(); extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & sourceType();
extern DLL_LINKAGE CSelectFieldEqual<BonusSource> & targetSourceType(); extern DLL_LINKAGE const CSelectFieldEqual<BonusSource> & targetSourceType();
extern DLL_LINKAGE CSelectFieldEqual<BonusLimitEffect> & effectRange(); extern DLL_LINKAGE const CSelectFieldEqual<BonusLimitEffect> & effectRange();
extern DLL_LINKAGE CWillLastTurns turns; extern DLL_LINKAGE CWillLastTurns turns;
extern DLL_LINKAGE CWillLastDays days; extern DLL_LINKAGE CWillLastDays days;

View File

@ -20,18 +20,25 @@ VCMI_LIB_NAMESPACE_BEGIN
std::atomic<int64_t> CBonusSystemNode::treeChanged(1); std::atomic<int64_t> CBonusSystemNode::treeChanged(1);
constexpr bool CBonusSystemNode::cachingEnabled = true; constexpr bool CBonusSystemNode::cachingEnabled = true;
#define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); for(CBonusSystemNode *pname : lparents) std::shared_ptr<Bonus> CBonusSystemNode::getLocalBonus(const CSelector & selector)
#define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); for(CBonusSystemNode *pname : lchildren) {
auto ret = bonuses.getFirst(selector);
if(ret)
return ret;
return nullptr;
}
std::shared_ptr<Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) std::shared_ptr<const Bonus> CBonusSystemNode::getFirstBonus(const CSelector & selector) const
{ {
auto ret = bonuses.getFirst(selector); auto ret = bonuses.getFirst(selector);
if(ret) if(ret)
return ret; return ret;
FOREACH_PARENT(pname) TCNodes lparents;
getParents(lparents);
for(const CBonusSystemNode *pname : lparents)
{ {
ret = pname->getBonusLocalFirst(selector); ret = pname->getFirstBonus(selector);
if (ret) if (ret)
return ret; return ret;
} }
@ -39,28 +46,15 @@ std::shared_ptr<Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector & se
return nullptr; return nullptr;
} }
std::shared_ptr<const Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) const
{
return (const_cast<CBonusSystemNode*>(this))->getBonusLocalFirst(selector);
}
void CBonusSystemNode::getParents(TCNodes & out) const /*retrieves list of parent nodes (nodes to inherit bonuses from) */ void CBonusSystemNode::getParents(TCNodes & out) const /*retrieves list of parent nodes (nodes to inherit bonuses from) */
{ {
for(const auto * elem : parents) for(const auto * elem : parentsToInherit)
out.insert(elem); out.insert(elem);
} }
void CBonusSystemNode::getParents(TNodes &out)
{
for (auto * elem : parents)
{
out.insert(elem);
}
}
void CBonusSystemNode::getAllParents(TCNodes & out) const //retrieves list of parent nodes (nodes to inherit bonuses from) void CBonusSystemNode::getAllParents(TCNodes & out) const //retrieves list of parent nodes (nodes to inherit bonuses from)
{ {
for(auto * parent : parents) for(auto * parent : parentsToInherit)
{ {
out.insert(parent); out.insert(parent);
parent->getAllParents(out); parent->getAllParents(out);
@ -227,39 +221,6 @@ CBonusSystemNode::CBonusSystemNode(ENodeTypes NodeType):
{ {
} }
CBonusSystemNode::CBonusSystemNode(CBonusSystemNode && other) noexcept:
bonuses(std::move(other.bonuses)),
exportedBonuses(std::move(other.exportedBonuses)),
nodeType(other.nodeType),
cachedLast(0),
isHypotheticNode(other.isHypotheticNode)
{
std::swap(parents, other.parents);
std::swap(children, other.children);
//fixing bonus tree without recalculation
if(!isHypothetic())
{
for(CBonusSystemNode * n : parents)
{
n->children -= &other;
n->children.push_back(this);
}
}
for(CBonusSystemNode * n : children)
{
n->parents -= &other;
n->parents.push_back(this);
}
//cache ignored
//cachedBonuses
//cachedRequests
}
CBonusSystemNode::~CBonusSystemNode() CBonusSystemNode::~CBonusSystemNode()
{ {
detachFromAll(); detachFromAll();
@ -273,14 +234,14 @@ CBonusSystemNode::~CBonusSystemNode()
void CBonusSystemNode::attachTo(CBonusSystemNode & parent) void CBonusSystemNode::attachTo(CBonusSystemNode & parent)
{ {
assert(!vstd::contains(parents, &parent)); assert(!vstd::contains(parentsToPropagate, &parent));
parents.push_back(&parent); parentsToPropagate.push_back(&parent);
attachToSource(parent);
if(!isHypothetic()) if(!isHypothetic())
{ {
if(parent.actsAsBonusSourceOnly()) if(!parent.actsAsBonusSourceOnly())
parent.newRedDescendant(*this);
else
newRedDescendant(parent); newRedDescendant(parent);
parent.newChildAttached(*this); parent.newChildAttached(*this);
@ -289,21 +250,35 @@ void CBonusSystemNode::attachTo(CBonusSystemNode & parent)
CBonusSystemNode::treeHasChanged(); CBonusSystemNode::treeHasChanged();
} }
void CBonusSystemNode::detachFrom(CBonusSystemNode & parent) void CBonusSystemNode::attachToSource(const CBonusSystemNode & parent)
{ {
assert(vstd::contains(parents, &parent)); assert(!vstd::contains(parentsToInherit, &parent));
parentsToInherit.push_back(&parent);
if(!isHypothetic()) if(!isHypothetic())
{ {
if(parent.actsAsBonusSourceOnly()) if(parent.actsAsBonusSourceOnly())
parent.removedRedDescendant(*this); parent.newRedDescendant(*this);
else }
CBonusSystemNode::treeHasChanged();
}
void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
{
assert(vstd::contains(parentsToPropagate, &parent));
if(!isHypothetic())
{
if(!parent.actsAsBonusSourceOnly())
removedRedDescendant(parent); removedRedDescendant(parent);
} }
if (vstd::contains(parents, &parent)) detachFromSource(parent);
if (vstd::contains(parentsToPropagate, &parent))
{ {
parents -= &parent; parentsToPropagate -= &parent;
} }
else else
{ {
@ -318,6 +293,30 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode & parent)
CBonusSystemNode::treeHasChanged(); CBonusSystemNode::treeHasChanged();
} }
void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent)
{
assert(vstd::contains(parentsToInherit, &parent));
if(!isHypothetic())
{
if(parent.actsAsBonusSourceOnly())
parent.removedRedDescendant(*this);
}
if (vstd::contains(parentsToInherit, &parent))
{
parentsToInherit -= &parent;
}
else
{
logBonus->error("Error on Detach. Node %s (nodeType=%d) has not parent %s (nodeType=%d)"
, nodeShortInfo(), nodeType, parent.nodeShortInfo(), parent.nodeType);
}
CBonusSystemNode::treeHasChanged();
}
void CBonusSystemNode::removeBonusesRecursive(const CSelector & s) void CBonusSystemNode::removeBonusesRecursive(const CSelector & s)
{ {
removeBonuses(s); removeBonuses(s);
@ -405,8 +404,10 @@ void CBonusSystemNode::propagateBonus(const std::shared_ptr<Bonus> & b, const CB
logBonus->trace("#$# %s #propagated to# %s", propagated->Description(), nodeName()); logBonus->trace("#$# %s #propagated to# %s", propagated->Description(), nodeName());
} }
FOREACH_RED_CHILD(child) TNodes lchildren;
child->propagateBonus(b, source); getRedChildren(lchildren);
for(CBonusSystemNode *pname : lchildren)
pname->propagateBonus(b, source);
} }
void CBonusSystemNode::unpropagateBonus(const std::shared_ptr<Bonus> & b) void CBonusSystemNode::unpropagateBonus(const std::shared_ptr<Bonus> & b)
@ -417,8 +418,10 @@ void CBonusSystemNode::unpropagateBonus(const std::shared_ptr<Bonus> & b)
logBonus->trace("#$# %s #is no longer propagated to# %s", b->Description(), nodeName()); logBonus->trace("#$# %s #is no longer propagated to# %s", b->Description(), nodeName());
} }
FOREACH_RED_CHILD(child) TNodes lchildren;
child->unpropagateBonus(b); getRedChildren(lchildren);
for(CBonusSystemNode *pname : lchildren)
pname->unpropagateBonus(b);
} }
void CBonusSystemNode::newChildAttached(CBonusSystemNode & child) void CBonusSystemNode::newChildAttached(CBonusSystemNode & child)
@ -440,13 +443,16 @@ void CBonusSystemNode::childDetached(CBonusSystemNode & child)
void CBonusSystemNode::detachFromAll() void CBonusSystemNode::detachFromAll()
{ {
while(!parents.empty()) while(!parentsToPropagate.empty())
detachFrom(*parents.front()); detachFrom(*parentsToPropagate.front());
while(!parentsToInherit.empty())
detachFromSource(*parentsToInherit.front());
} }
bool CBonusSystemNode::isIndependentNode() const bool CBonusSystemNode::isIndependentNode() const
{ {
return parents.empty() && children.empty(); return parentsToInherit.empty() && parentsToPropagate.empty() && children.empty();
} }
std::string CBonusSystemNode::nodeName() const std::string CBonusSystemNode::nodeName() const
@ -464,12 +470,13 @@ std::string CBonusSystemNode::nodeShortInfo() const
void CBonusSystemNode::deserializationFix() void CBonusSystemNode::deserializationFix()
{ {
exportBonuses(); exportBonuses();
} }
void CBonusSystemNode::getRedParents(TNodes & out) void CBonusSystemNode::getRedParents(TCNodes & out) const
{ {
FOREACH_PARENT(pname) TCNodes lparents;
getParents(lparents);
for(const CBonusSystemNode *pname : lparents)
{ {
if(pname->actsAsBonusSourceOnly()) if(pname->actsAsBonusSourceOnly())
{ {
@ -479,7 +486,7 @@ void CBonusSystemNode::getRedParents(TNodes & out)
if(!actsAsBonusSourceOnly()) if(!actsAsBonusSourceOnly())
{ {
for(CBonusSystemNode *child : children) for(const CBonusSystemNode *child : children)
{ {
out.insert(child); out.insert(child);
} }
@ -488,7 +495,7 @@ void CBonusSystemNode::getRedParents(TNodes & out)
void CBonusSystemNode::getRedChildren(TNodes &out) void CBonusSystemNode::getRedChildren(TNodes &out)
{ {
FOREACH_PARENT(pname) for(CBonusSystemNode *pname : parentsToPropagate)
{ {
if(!pname->actsAsBonusSourceOnly()) if(!pname->actsAsBonusSourceOnly())
{ {
@ -505,17 +512,17 @@ void CBonusSystemNode::getRedChildren(TNodes &out)
} }
} }
void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) const
{ {
for(const auto & b : exportedBonuses) for(const auto & b : exportedBonuses)
{ {
if(b->propagator) if(b->propagator)
descendant.propagateBonus(b, *this); descendant.propagateBonus(b, *this);
} }
TNodes redParents; TCNodes redParents;
getRedAncestors(redParents); //get all red parents recursively getRedAncestors(redParents); //get all red parents recursively
for(auto * parent : redParents) for(const auto * parent : redParents)
{ {
for(const auto & b : parent->exportedBonuses) for(const auto & b : parent->exportedBonuses)
{ {
@ -525,13 +532,13 @@ void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant)
} }
} }
void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) const
{ {
for(const auto & b : exportedBonuses) for(const auto & b : exportedBonuses)
if(b->propagator) if(b->propagator)
descendant.unpropagateBonus(b); descendant.unpropagateBonus(b);
TNodes redParents; TCNodes redParents;
getRedAncestors(redParents); //get all red parents recursively getRedAncestors(redParents); //get all red parents recursively
for(auto * parent : redParents) for(auto * parent : redParents)
@ -542,14 +549,14 @@ void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant)
} }
} }
void CBonusSystemNode::getRedAncestors(TNodes &out) void CBonusSystemNode::getRedAncestors(TCNodes &out) const
{ {
getRedParents(out); getRedParents(out);
TNodes redParents; TCNodes redParents;
getRedParents(redParents); getRedParents(redParents);
for(CBonusSystemNode * parent : redParents) for(const CBonusSystemNode * parent : redParents)
parent->getRedAncestors(out); parent->getRedAncestors(out);
} }
@ -574,9 +581,9 @@ CBonusSystemNode::ENodeTypes CBonusSystemNode::getNodeType() const
return nodeType; return nodeType;
} }
const TNodesVector& CBonusSystemNode::getParentNodes() const const TCNodesVector& CBonusSystemNode::getParentNodes() const
{ {
return parents; return parentsToInherit;
} }
void CBonusSystemNode::setNodeType(CBonusSystemNode::ENodeTypes type) void CBonusSystemNode::setNodeType(CBonusSystemNode::ENodeTypes type)
@ -646,4 +653,4 @@ int64_t CBonusSystemNode::getTreeVersion() const
return treeChanged; return treeChanged;
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -19,6 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN
using TNodes = std::set<CBonusSystemNode *>; using TNodes = std::set<CBonusSystemNode *>;
using TCNodes = std::set<const CBonusSystemNode *>; using TCNodes = std::set<const CBonusSystemNode *>;
using TNodesVector = std::vector<CBonusSystemNode *>; using TNodesVector = std::vector<CBonusSystemNode *>;
using TCNodesVector = std::vector<const CBonusSystemNode *>;
class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public boost::noncopyable class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public boost::noncopyable
{ {
@ -33,7 +34,8 @@ private:
BonusList bonuses; //wielded bonuses (local or up-propagated here) BonusList bonuses; //wielded bonuses (local or up-propagated here)
BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away) BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away)
TNodesVector parents; //parents -> we inherit bonuses from them, we may attach our bonuses to them TCNodesVector parentsToInherit; // we inherit bonuses from them
TNodesVector parentsToPropagate; // we may attach our bonuses to them
TNodesVector children; TNodesVector children;
ENodeTypes nodeType; ENodeTypes nodeType;
@ -54,8 +56,8 @@ private:
TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const; TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const;
std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const; std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const;
void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from) void getRedParents(TCNodes &out) const; //retrieves list of red parent nodes (nodes bonuses propagate from)
void getRedAncestors(TNodes &out); void getRedAncestors(TCNodes &out) const;
void getRedChildren(TNodes &out); void getRedChildren(TNodes &out);
void getAllParents(TCNodes & out) const; void getAllParents(TCNodes & out) const;
@ -66,8 +68,8 @@ private:
void unpropagateBonus(const std::shared_ptr<Bonus> & b); void unpropagateBonus(const std::shared_ptr<Bonus> & b);
bool actsAsBonusSourceOnly() const; bool actsAsBonusSourceOnly() const;
void newRedDescendant(CBonusSystemNode & descendant); //propagation needed void newRedDescendant(CBonusSystemNode & descendant) const; //propagation needed
void removedRedDescendant(CBonusSystemNode & descendant); //de-propagation needed void removedRedDescendant(CBonusSystemNode & descendant) const; //de-propagation needed
std::string nodeShortInfo() const; std::string nodeShortInfo() const;
@ -80,21 +82,23 @@ protected:
public: public:
explicit CBonusSystemNode(bool isHypotetic = false); explicit CBonusSystemNode(bool isHypotetic = false);
explicit CBonusSystemNode(ENodeTypes NodeType); explicit CBonusSystemNode(ENodeTypes NodeType);
CBonusSystemNode(CBonusSystemNode && other) noexcept;
virtual ~CBonusSystemNode(); virtual ~CBonusSystemNode();
void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here
TBonusListPtr limitBonuses(const BonusList &allBonuses) const; //same as above, returns out by val for convienence TBonusListPtr limitBonuses(const BonusList &allBonuses) const; //same as above, returns out by val for convienence
TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override; TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override;
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from), void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
std::shared_ptr<const Bonus> getBonusLocalFirst(const CSelector & selector) const;
//non-const interface /// Returns first bonus matching selector
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from) std::shared_ptr<const Bonus> getFirstBonus(const CSelector & selector) const;
std::shared_ptr<Bonus> getBonusLocalFirst(const CSelector & selector);
/// Provides write access to first bonus from this node that matches selector
std::shared_ptr<Bonus> getLocalBonus(const CSelector & selector);
void attachTo(CBonusSystemNode & parent); void attachTo(CBonusSystemNode & parent);
void attachToSource(const CBonusSystemNode & parent);
void detachFrom(CBonusSystemNode & parent); void detachFrom(CBonusSystemNode & parent);
void detachFromSource(const CBonusSystemNode & parent);
void detachFromAll(); void detachFromAll();
virtual void addNewBonus(const std::shared_ptr<Bonus>& b); virtual void addNewBonus(const std::shared_ptr<Bonus>& b);
void accumulateBonus(const std::shared_ptr<Bonus>& b); //add value of bonus with same type/subtype or create new void accumulateBonus(const std::shared_ptr<Bonus>& b); //add value of bonus with same type/subtype or create new
@ -115,7 +119,7 @@ public:
const BonusList & getExportedBonusList() const; const BonusList & getExportedBonusList() const;
CBonusSystemNode::ENodeTypes getNodeType() const; CBonusSystemNode::ENodeTypes getNodeType() const;
void setNodeType(CBonusSystemNode::ENodeTypes type); void setNodeType(CBonusSystemNode::ENodeTypes type);
const TNodesVector & getParentNodes() const; const TCNodesVector & getParentNodes() const;
static void treeHasChanged(); static void treeHasChanged();
@ -128,14 +132,12 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
// h & bonuses;
h & nodeType; h & nodeType;
h & exportedBonuses; h & exportedBonuses;
BONUS_TREE_DESERIALIZATION_FIX BONUS_TREE_DESERIALIZATION_FIX
//h & parents & children;
} }
friend class CBonusProxy; friend class CBonusProxy;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -10,7 +10,7 @@
#include "StdInc.h" #include "StdInc.h"
#include "CBonusSystemNode.h" #include "IBonusBearer.h"
#include "BonusList.h" #include "BonusList.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -11,6 +11,7 @@
#include "CampaignState.h" #include "CampaignState.h"
#include "../JsonNode.h" #include "../JsonNode.h"
#include "../Point.h"
#include "../filesystem/ResourcePath.h" #include "../filesystem/ResourcePath.h"
#include "../VCMI_Lib.h" #include "../VCMI_Lib.h"
#include "../CGeneralTextHandler.h" #include "../CGeneralTextHandler.h"
@ -224,7 +225,7 @@ std::set<HeroTypeID> CampaignState::getReservedHeroes() const
const CGHeroInstance * CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const const CGHeroInstance * CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const
{ {
std::function<bool(const JsonNode & node)> isOwned = [owner](const JsonNode & node) std::function<bool(const JsonNode & node)> isOwned = [&](const JsonNode & node)
{ {
auto * h = CampaignState::crossoverDeserialize(node, nullptr); auto * h = CampaignState::crossoverDeserialize(node, nullptr);
bool result = h->tempOwner == owner; bool result = h->tempOwner == owner;
@ -316,7 +317,7 @@ std::optional<ui8> CampaignState::getBonusID(CampaignScenarioID which) const
return chosenCampaignBonuses.at(which); return chosenCampaignBonuses.at(which);
} }
std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId) const std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId, IGameCallback * cb) const
{ {
// FIXME: there is certainly better way to handle maps inside campaigns // FIXME: there is certainly better way to handle maps inside campaigns
if(scenarioId == CampaignScenarioID::NONE) if(scenarioId == CampaignScenarioID::NONE)
@ -327,7 +328,7 @@ std::unique_ptr<CMap> CampaignState::getMap(CampaignScenarioID scenarioId) const
boost::to_lower(scenarioName); boost::to_lower(scenarioName);
scenarioName += ':' + std::to_string(scenarioId.getNum()); scenarioName += ':' + std::to_string(scenarioId.getNum());
const auto & mapContent = mapPieces.find(scenarioId)->second; const auto & mapContent = mapPieces.find(scenarioId)->second;
return mapService.loadMap(mapContent.data(), mapContent.size(), scenarioName, getModName(), getEncoding()); return mapService.loadMap(mapContent.data(), mapContent.size(), scenarioName, getModName(), getEncoding(), cb);
} }
std::unique_ptr<CMapHeader> CampaignState::getMapHeader(CampaignScenarioID scenarioId) const std::unique_ptr<CMapHeader> CampaignState::getMapHeader(CampaignScenarioID scenarioId) const
@ -355,7 +356,7 @@ std::shared_ptr<CMapInfo> CampaignState::getMapInfo(CampaignScenarioID scenarioI
return mapInfo; return mapInfo;
} }
JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) const
{ {
JsonNode node; JsonNode node;
JsonSerializer handler(nullptr, node); JsonSerializer handler(nullptr, node);
@ -363,10 +364,10 @@ JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero)
return node; return node;
} }
CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) const
{ {
JsonDeserializer handler(nullptr, const_cast<JsonNode&>(node)); JsonDeserializer handler(nullptr, const_cast<JsonNode&>(node));
auto * hero = new CGHeroInstance(); auto * hero = new CGHeroInstance(map->cb);
hero->ID = Obj::HERO; hero->ID = Obj::HERO;
hero->serializeJsonOptions(handler); hero->serializeJsonOptions(handler);
if (map) if (map)

View File

@ -27,6 +27,7 @@ class CMapHeader;
class CMapInfo; class CMapInfo;
class JsonNode; class JsonNode;
class Point; class Point;
class IGameCallback;
class DLL_LINKAGE CampaignRegions class DLL_LINKAGE CampaignRegions
{ {
@ -277,7 +278,7 @@ public:
/// Returns true if all available scenarios have been completed and campaign is finished /// Returns true if all available scenarios have been completed and campaign is finished
bool isCampaignFinished() const; bool isCampaignFinished() const;
std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId) const; std::unique_ptr<CMap> getMap(CampaignScenarioID scenarioId, IGameCallback * cb) const;
std::unique_ptr<CMapHeader> getMapHeader(CampaignScenarioID scenarioId) const; std::unique_ptr<CMapHeader> getMapHeader(CampaignScenarioID scenarioId) const;
std::shared_ptr<CMapInfo> getMapInfo(CampaignScenarioID scenarioId) const; std::shared_ptr<CMapInfo> getMapInfo(CampaignScenarioID scenarioId) const;
@ -298,8 +299,8 @@ public:
/// May return empty JsonNode if such hero was not found /// May return empty JsonNode if such hero was not found
const JsonNode & getHeroByType(HeroTypeID heroID) const; const JsonNode & getHeroByType(HeroTypeID heroID) const;
static JsonNode crossoverSerialize(CGHeroInstance * hero); JsonNode crossoverSerialize(CGHeroInstance * hero) const;
static CGHeroInstance * crossoverDeserialize(const JsonNode & node, CMap * map); CGHeroInstance * crossoverDeserialize(const JsonNode & node, CMap * map) const;
std::string campaignSet; std::string campaignSet;

View File

@ -151,6 +151,16 @@ std::string HeroClassID::entityType()
return "heroClass"; return "heroClass";
} }
const CHeroClass * HeroClassID::toHeroClass() const
{
return dynamic_cast<const CHeroClass*>(toEntity(VLC));
}
const HeroClass * HeroClassID::toEntity(const Services * services) const
{
return services->heroClasses()->getByIndex(num);
}
si32 ObjectInstanceID::decode(const std::string & identifier) si32 ObjectInstanceID::decode(const std::string & identifier)
{ {
return std::stoi(identifier); return std::stoi(identifier);

View File

@ -21,6 +21,8 @@ class Creature;
class CreatureService; class CreatureService;
class HeroType; class HeroType;
class CHero; class CHero;
class CHeroClass;
class HeroClass;
class HeroTypeService; class HeroTypeService;
class Faction; class Faction;
class Skill; class Skill;
@ -81,6 +83,9 @@ public:
DLL_LINKAGE static si32 decode(const std::string & identifier); DLL_LINKAGE static si32 decode(const std::string & identifier);
DLL_LINKAGE static std::string encode(const si32 index); DLL_LINKAGE static std::string encode(const si32 index);
static std::string entityType(); static std::string entityType();
const CHeroClass * toHeroClass() const;
const HeroClass * toEntity(const Services * services) const;
}; };
class DLL_LINKAGE HeroTypeID : public EntityIdentifier<HeroTypeID> class DLL_LINKAGE HeroTypeID : public EntityIdentifier<HeroTypeID>

View File

@ -36,6 +36,8 @@
#include "../mapObjectConstructors/DwellingInstanceConstructor.h" #include "../mapObjectConstructors/DwellingInstanceConstructor.h"
#include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h" #include "../mapObjects/CGTownInstance.h"
#include "../mapObjects/CQuest.h"
#include "../mapObjects/MiscObjects.h"
#include "../mapping/CMap.h" #include "../mapping/CMap.h"
#include "../mapping/CMapEditManager.h" #include "../mapping/CMapEditManager.h"
#include "../mapping/CMapService.h" #include "../mapping/CMapService.h"
@ -97,7 +99,7 @@ HeroTypeID CGameState::pickUnusedHeroTypeRandomly(const PlayerColor & owner)
const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner); const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner);
for(const HeroTypeID & hid : getUnusedAllowedHeroes()) for(const HeroTypeID & hid : getUnusedAllowedHeroes())
{ {
if(VLC->heroh->objects[hid.getNum()]->heroClass->faction == ps.castle) if(hid.toHeroType()->heroClass->faction == ps.castle)
factionHeroes.push_back(hid); factionHeroes.push_back(hid);
else else
otherHeroes.push_back(hid); otherHeroes.push_back(hid);
@ -169,14 +171,16 @@ CGameState::~CGameState()
initialOpts.dellNull(); initialOpts.dellNull();
} }
void CGameState::preInit(Services * services) void CGameState::preInit(Services * newServices, IGameCallback * newCallback)
{ {
this->services = services; services = newServices;
callback = newCallback;
} }
void CGameState::init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap) void CGameState::init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap)
{ {
preInitAuto(); assert(services);
assert(callback);
logGlobal->info("\tUsing random seed: %d", si->seedToBeUsed); logGlobal->info("\tUsing random seed: %d", si->seedToBeUsed);
getRandomGenerator().setSeed(si->seedToBeUsed); getRandomGenerator().setSeed(si->seedToBeUsed);
scenarioOps = CMemorySerializer::deepCopy(*si).release(); scenarioOps = CMemorySerializer::deepCopy(*si).release();
@ -224,7 +228,7 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog
for(auto & elem : teams) for(auto & elem : teams)
{ {
CGObelisk::visited[elem.first] = 0; map->obelisksVisited[elem.first] = 0;
} }
logGlobal->debug("\tChecking objectives"); logGlobal->debug("\tChecking objectives");
@ -284,21 +288,13 @@ void CGameState::updateEntity(Metatype metatype, int32_t index, const JsonNode &
void CGameState::updateOnLoad(StartInfo * si) void CGameState::updateOnLoad(StartInfo * si)
{ {
preInitAuto(); assert(services);
assert(callback);
scenarioOps->playerInfos = si->playerInfos; scenarioOps->playerInfos = si->playerInfos;
for(auto & i : si->playerInfos) for(auto & i : si->playerInfos)
gs->players[i.first].human = i.second.isControlledByHuman(); gs->players[i.first].human = i.second.isControlledByHuman();
} }
void CGameState::preInitAuto()
{
if(services == nullptr)
{
logGlobal->error("Game state preinit missing");
preInit(VLC);
}
}
void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking) void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking)
{ {
if(scenarioOps->createRandomMap()) if(scenarioOps->createRandomMap())
@ -307,7 +303,7 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan
CStopWatch sw; CStopWatch sw;
// Gen map // Gen map
CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, scenarioOps->seedToBeUsed); CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, callback, scenarioOps->seedToBeUsed);
progressTracking.include(mapGenerator); progressTracking.include(mapGenerator);
std::unique_ptr<CMap> randomMap = mapGenerator.generate(); std::unique_ptr<CMap> randomMap = mapGenerator.generate();
@ -370,7 +366,7 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan
{ {
logGlobal->info("Open map file: %s", scenarioOps->mapname); logGlobal->info("Open map file: %s", scenarioOps->mapname);
const ResourcePath mapURI(scenarioOps->mapname, EResType::MAP); const ResourcePath mapURI(scenarioOps->mapname, EResType::MAP);
map = mapService->loadMap(mapURI).release(); map = mapService->loadMap(mapURI, callback).release();
} }
} }
@ -561,7 +557,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
} }
auto handler = VLC->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex()); auto handler = VLC->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex());
CGObjectInstance * obj = handler->create(handler->getTemplates().front()); CGObjectInstance * obj = handler->create(callback, handler->getTemplates().front());
CGHeroInstance * hero = dynamic_cast<CGHeroInstance *>(obj); CGHeroInstance * hero = dynamic_cast<CGHeroInstance *>(obj);
hero->ID = Obj::HERO; hero->ID = Obj::HERO;
@ -635,7 +631,7 @@ void CGameState::initHeroes()
if (tile.terType->isWater()) if (tile.terType->isWater())
{ {
auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum()); auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum());
CGBoat * boat = dynamic_cast<CGBoat*>(handler->create()); auto boat = dynamic_cast<CGBoat*>(handler->create(callback, nullptr));
handler->configureObject(boat, gs->getRandomGenerator()); handler->configureObject(boat, gs->getRandomGenerator());
boat->pos = hero->pos; boat->pos = hero->pos;
@ -673,7 +669,7 @@ void CGameState::initHeroes()
for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool
{ {
auto * vhi = new CGHeroInstance(); auto * vhi = new CGHeroInstance(callback);
vhi->initHero(getRandomGenerator(), htype); vhi->initHero(getRandomGenerator(), htype);
int typeID = htype.getNum(); int typeID = htype.getNum();
@ -772,11 +768,11 @@ void CGameState::initTowns()
if (campaign) if (campaign)
campaign->initTowns(); campaign->initTowns();
CGTownInstance::universitySkills.clear(); map->townUniversitySkills.clear();
CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC)); map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC));
CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC)); map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC));
CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC)); map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC));
CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC)); map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC));
for (auto & elem : map->towns) for (auto & elem : map->towns)
{ {
@ -936,7 +932,7 @@ void CGameState::initMapObjects()
} }
} }
} }
CGSubterraneanGate::postInit(); //pairing subterranean gates CGSubterraneanGate::postInit(callback); //pairing subterranean gates
map->calculateGuardingGreaturePositions(); //calculate once again when all the guards are placed and initialized map->calculateGuardingGreaturePositions(); //calculate once again when all the guards are placed and initialized
} }
@ -1208,7 +1204,7 @@ int3 CGameState::guardingCreaturePosition (int3 pos) const
void CGameState::updateRumor() void CGameState::updateRumor()
{ {
static std::vector<RumorState::ERumorType> rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND}; static const std::vector<RumorState::ERumorType> rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND};
std::vector<RumorState::ERumorTypeSpecial> sRumorTypes = { std::vector<RumorState::ERumorTypeSpecial> sRumorTypes = {
RumorState::RUMOR_OBELISKS, RumorState::RUMOR_ARTIFACTS, RumorState::RUMOR_ARMY, RumorState::RUMOR_INCOME}; RumorState::RUMOR_OBELISKS, RumorState::RUMOR_ARTIFACTS, RumorState::RUMOR_ARMY, RumorState::RUMOR_INCOME};
if(map->grailPos.valid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce if(map->grailPos.valid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce
@ -1722,10 +1718,10 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
} }
if(level >= 3) //obelisks found if(level >= 3) //obelisks found
{ {
auto getObeliskVisited = [](const TeamID & t) auto getObeliskVisited = [&](const TeamID & t)
{ {
if(CGObelisk::visited.count(t)) if(map->obelisksVisited.count(t))
return CGObelisk::visited[t]; return map->obelisksVisited[t];
else else
return ui8(0); return ui8(0);
}; };
@ -1928,14 +1924,6 @@ TeamState::TeamState()
fogOfWarMap = std::make_unique<boost::multi_array<ui8, 3>>(); fogOfWarMap = std::make_unique<boost::multi_array<ui8, 3>>();
} }
TeamState::TeamState(TeamState && other) noexcept:
CBonusSystemNode(std::move(other)),
id(other.id)
{
std::swap(players, other.players);
std::swap(fogOfWarMap, other.fogOfWarMap);
}
CRandomGenerator & CGameState::getRandomGenerator() CRandomGenerator & CGameState::getRandomGenerator()
{ {
return rand; return rand;

View File

@ -97,10 +97,12 @@ public:
/// list of players currently making turn. Usually - just one, except for simturns /// list of players currently making turn. Usually - just one, except for simturns
std::set<PlayerColor> actingPlayers; std::set<PlayerColor> actingPlayers;
IGameCallback * callback;
CGameState(); CGameState();
virtual ~CGameState(); virtual ~CGameState();
void preInit(Services * services); void preInit(Services * services, IGameCallback * callback);
void init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator &, bool allowSavingRandomMap = true); void init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator &, bool allowSavingRandomMap = true);
void updateOnLoad(StartInfo * si); void updateOnLoad(StartInfo * si);
@ -193,7 +195,6 @@ public:
private: private:
// ----- initialization ----- // ----- initialization -----
void preInitAuto();
void initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking); void initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking);
void checkMapChecksum(); void checkMapChecksum();
void initGlobalBonuses(); void initGlobalBonuses();

View File

@ -16,6 +16,7 @@
#include "../campaign/CampaignState.h" #include "../campaign/CampaignState.h"
#include "../mapping/CMapEditManager.h" #include "../mapping/CMapEditManager.h"
#include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h"
#include "../networkPacks/ArtifactLocation.h" #include "../networkPacks/ArtifactLocation.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
@ -90,7 +91,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(std::vector<CampaignHeroR
.And(Selector::subtype()(BonusSubtypeID(g))) .And(Selector::subtype()(BonusSubtypeID(g)))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)); .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL));
cgh->getBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g.getNum()]; cgh->getLocalBonus(sel)->val = cgh->type->heroClass->primarySkillInitial[g.getNum()];
} }
} }
} }
@ -347,7 +348,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vector<CampaignHer
if(heroPlaceholder->tempOwner.isValidPlayer()) if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->tempOwner = heroPlaceholder->tempOwner;
heroToPlace->pos = heroPlaceholder->pos; heroToPlace->pos = heroPlaceholder->pos;
heroToPlace->type = VLC->heroh->objects[heroToPlace->getHeroType().getNum()]; heroToPlace->type = heroToPlace->getHeroType().toHeroType();
heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front();
gameState->map->removeBlockVisTiles(heroPlaceholder, true); gameState->map->removeBlockVisTiles(heroPlaceholder, true);
@ -402,7 +403,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
continue; continue;
} }
CGHeroInstance * hero = CampaignState::crossoverDeserialize(node, gameState->map); CGHeroInstance * hero = campaignState->crossoverDeserialize(node, gameState->map);
logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated()); logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated());
@ -427,7 +428,7 @@ std::vector<CampaignHeroReplacement> CGameStateCampaign::generateCampaignHeroesT
if (nodeListIter == nodeList.end()) if (nodeListIter == nodeList.end())
break; break;
CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map); CGHeroInstance * hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map);
nodeListIter++; nodeListIter++;
logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated()); logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated());
@ -599,7 +600,7 @@ bool CGameStateCampaign::playerHasStartingHero(PlayerColor playerColor) const
std::unique_ptr<CMap> CGameStateCampaign::getCurrentMap() const std::unique_ptr<CMap> CGameStateCampaign::getCurrentMap() const
{ {
return gameState->scenarioOps->campState->getMap(CampaignScenarioID::NONE); return gameState->scenarioOps->campState->getMap(CampaignScenarioID::NONE, gameState->callback);
} }
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -19,6 +19,7 @@ class ObjectTemplate;
class CGObjectInstance; class CGObjectInstance;
class CRandomGenerator; class CRandomGenerator;
class IObjectInfo; class IObjectInfo;
class IGameCallback;
/// Class responsible for creation of objects of specific type & subtype /// Class responsible for creation of objects of specific type & subtype
class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable
@ -109,7 +110,7 @@ public:
/// Creates object and set up core properties (like ID/subID). Object is NOT initialized /// Creates object and set up core properties (like ID/subID). Object is NOT initialized
/// to allow creating objects before game start (e.g. map loading) /// to allow creating objects before game start (e.g. map loading)
virtual CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const = 0; virtual CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily /// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
/// This should set remaining properties, including randomized or depending on map /// This should set remaining properties, including randomized or depending on map

View File

@ -34,18 +34,19 @@ void CBankInstanceConstructor::initTypeData(const JsonNode & input)
coastVisitable = input["coastVisitable"].Bool(); coastVisitable = input["coastVisitable"].Bool();
} }
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const BankConfig CBankInstanceConstructor::generateConfig(IGameCallback * cb, const JsonNode & level, CRandomGenerator & rng) const
{ {
BankConfig bc; BankConfig bc;
JsonRandom randomizer(cb);
JsonRandom::Variables emptyVariables; JsonRandom::Variables emptyVariables;
bc.chance = static_cast<ui32>(level["chance"].Float()); bc.chance = static_cast<ui32>(level["chance"].Float());
bc.guards = JsonRandom::loadCreatures(level["guards"], rng, emptyVariables); bc.guards = randomizer.loadCreatures(level["guards"], rng, emptyVariables);
bc.resources = ResourceSet(level["reward"]["resources"]); bc.resources = ResourceSet(level["reward"]["resources"]);
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng, emptyVariables); bc.creatures = randomizer.loadCreatures(level["reward"]["creatures"], rng, emptyVariables);
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng, emptyVariables); bc.artifacts = randomizer.loadArtifacts(level["reward"]["artifacts"], rng, emptyVariables);
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, emptyVariables); bc.spells = randomizer.loadSpells(level["reward"]["spells"], rng, emptyVariables);
return bc; return bc;
} }
@ -70,7 +71,7 @@ void CBankInstanceConstructor::randomizeObject(CBank * bank, CRandomGenerator &
cumulativeChance += static_cast<int>(node["chance"].Float()); cumulativeChance += static_cast<int>(node["chance"].Float());
if(selectedChance < cumulativeChance) if(selectedChance < cumulativeChance)
{ {
bank->setConfig(generateConfig(node, rng)); bank->setConfig(generateConfig(bank->cb, node, rng));
break; break;
} }
} }
@ -82,80 +83,16 @@ CBankInfo::CBankInfo(const JsonVector & Config) :
assert(!Config.empty()); assert(!Config.empty());
} }
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount) TPossibleGuards CBankInfo::getPossibleGuards(IGameCallback * cb) const
{
army.totalStrength += crea->getFightValue() * amount;
bool walker = true;
if(crea->hasBonusOfType(BonusType::SHOOTER))
{
army.shootersStrength += crea->getFightValue() * amount;
walker = false;
}
if(crea->hasBonusOfType(BonusType::FLYING))
{
army.flyersStrength += crea->getFightValue() * amount;
walker = false;
}
if(walker)
army.walkersStrength += crea->getFightValue() * amount;
}
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
{
JsonRandom::Variables emptyVariables;
std::vector<IObjectInfo::CArmyStructure> armies;
for(auto configEntry : config)
{
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables);
IObjectInfo::CArmyStructure army;
for(auto & stack : stacks)
{
assert(!stack.allowedCreatures.empty());
auto weakest = boost::range::min_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
{
return a->getFightValue() < b->getFightValue();
});
addStackToArmy(army, *weakest, stack.minAmount);
}
armies.push_back(army);
}
return *boost::range::min_element(armies);
}
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
{
JsonRandom::Variables emptyVariables;
std::vector<IObjectInfo::CArmyStructure> armies;
for(auto configEntry : config)
{
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables);
IObjectInfo::CArmyStructure army;
for(auto & stack : stacks)
{
assert(!stack.allowedCreatures.empty());
auto strongest = boost::range::max_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
{
return a->getFightValue() < b->getFightValue();
});
addStackToArmy(army, *strongest, stack.maxAmount);
}
armies.push_back(army);
}
return *boost::range::max_element(armies);
}
TPossibleGuards CBankInfo::getPossibleGuards() const
{ {
JsonRandom::Variables emptyVariables; JsonRandom::Variables emptyVariables;
JsonRandom randomizer(cb);
TPossibleGuards out; TPossibleGuards out;
for(const JsonNode & configEntry : config) for(const JsonNode & configEntry : config)
{ {
const JsonNode & guardsInfo = configEntry["guards"]; const JsonNode & guardsInfo = configEntry["guards"];
auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables); auto stacks = randomizer.evaluateCreatures(guardsInfo, emptyVariables);
IObjectInfo::CArmyStructure army; IObjectInfo::CArmyStructure army;
@ -188,15 +125,16 @@ std::vector<PossibleReward<TResources>> CBankInfo::getPossibleResourcesReward()
return result; return result;
} }
std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward() const std::vector<PossibleReward<CStackBasicDescriptor>> CBankInfo::getPossibleCreaturesReward(IGameCallback * cb) const
{ {
JsonRandom::Variables emptyVariables; JsonRandom::Variables emptyVariables;
JsonRandom randomizer(cb);
std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward; std::vector<PossibleReward<CStackBasicDescriptor>> aproximateReward;
for(const JsonNode & configEntry : config) for(const JsonNode & configEntry : config)
{ {
const JsonNode & guardsInfo = configEntry["reward"]["creatures"]; const JsonNode & guardsInfo = configEntry["reward"]["creatures"];
auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables); auto stacks = randomizer.evaluateCreatures(guardsInfo, emptyVariables);
for(auto stack : stacks) for(auto stack : stacks)
{ {

View File

@ -55,13 +55,9 @@ class DLL_LINKAGE CBankInfo : public IObjectInfo
public: public:
CBankInfo(const JsonVector & Config); CBankInfo(const JsonVector & Config);
TPossibleGuards getPossibleGuards() const; TPossibleGuards getPossibleGuards(IGameCallback * cb) const;
std::vector<PossibleReward<TResources>> getPossibleResourcesReward() const; std::vector<PossibleReward<TResources>> getPossibleResourcesReward() const;
std::vector<PossibleReward<CStackBasicDescriptor>> getPossibleCreaturesReward() const; std::vector<PossibleReward<CStackBasicDescriptor>> getPossibleCreaturesReward(IGameCallback * cb) const;
// These functions should try to evaluate minimal possible/max possible guards to give provide information on possible thread to AI
CArmyStructure minGuards() const override;
CArmyStructure maxGuards() const override;
bool givesResources() const override; bool givesResources() const override;
bool givesArtifacts() const override; bool givesArtifacts() const override;
@ -71,7 +67,7 @@ public:
class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank> class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
{ {
BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const; BankConfig generateConfig(IGameCallback * cb, const JsonNode & conf, CRandomGenerator & rng) const;
JsonVector levels; JsonVector levels;

View File

@ -27,9 +27,9 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
randomizeObject(castedObject, rng); randomizeObject(castedObject, rng);
} }
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const final CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
{ {
ObjectType * result = createObject(); ObjectType * result = createObject(cb);
preInitObject(result); preInitObject(result);
@ -44,9 +44,9 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
protected: protected:
virtual void initializeObject(ObjectType * object) const {} virtual void initializeObject(ObjectType * object) const {}
virtual void randomizeObject(ObjectType * object, CRandomGenerator & rng) const {} virtual void randomizeObject(ObjectType * object, CRandomGenerator & rng) const {}
virtual ObjectType * createObject() const virtual ObjectType * createObject(IGameCallback * cb) const
{ {
return new ObjectType(); return new ObjectType(cb);
} }
}; };

View File

@ -31,9 +31,9 @@ bool CRewardableConstructor::hasNameTextID() const
return !objectInfo.getParameters()["name"].isNull(); return !objectInfo.getParameters()["name"].isNull();
} }
CGObjectInstance * CRewardableConstructor::create(std::shared_ptr<const ObjectTemplate> tmpl) const CGObjectInstance * CRewardableConstructor::create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const
{ {
auto * ret = new CRewardableObject(); auto * ret = new CRewardableObject(cb);
preInitObject(ret); preInitObject(ret);
ret->appearance = tmpl; ret->appearance = tmpl;
ret->blockVisit = blockVisit; ret->blockVisit = blockVisit;
@ -44,7 +44,7 @@ void CRewardableConstructor::configureObject(CGObjectInstance * object, CRandomG
{ {
if(auto * rewardableObject = dynamic_cast<CRewardableObject*>(object)) if(auto * rewardableObject = dynamic_cast<CRewardableObject*>(object))
{ {
objectInfo.configureObject(rewardableObject->configuration, rng); objectInfo.configureObject(rewardableObject->configuration, rng, object->cb);
for(auto & rewardInfo : rewardableObject->configuration.info) for(auto & rewardInfo : rewardableObject->configuration.info)
{ {
for (auto & bonus : rewardInfo.reward.bonuses) for (auto & bonus : rewardInfo.reward.bonuses)

View File

@ -25,7 +25,7 @@ class DLL_LINKAGE CRewardableConstructor : public AObjectTypeHandler
public: public:
bool hasNameTextID() const override; bool hasNameTextID() const override;
CGObjectInstance * create(std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override; CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override; void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;

View File

@ -102,7 +102,7 @@ void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const
void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, CRandomGenerator & rng) const void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, CRandomGenerator & rng) const
{ {
auto templ = getOverride(CGObjectInstance::cb->getTile(object->pos)->terType->getId(), object); auto templ = getOverride(object->cb->getTile(object->pos)->terType->getId(), object);
if(templ) if(templ)
object->appearance = templ; object->appearance = templ;
} }
@ -122,7 +122,7 @@ void CHeroInstanceConstructor::initTypeData(const JsonNode & input)
VLC->identifiers()->requestIdentifier( VLC->identifiers()->requestIdentifier(
"heroClass", "heroClass",
input["heroClass"], input["heroClass"],
[&](si32 index) { heroClass = VLC->heroh->classes[index]; }); [&](si32 index) { heroClass = HeroClassID(index).toHeroClass(); });
filtersJson = input["filters"]; filtersJson = input["filters"];
} }
@ -224,7 +224,7 @@ void MarketInstanceConstructor::initTypeData(const JsonNode & input)
speech = input["speech"].String(); speech = input["speech"].String();
} }
CGMarket * MarketInstanceConstructor::createObject() const CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
{ {
if(marketModes.size() == 1) if(marketModes.size() == 1)
{ {
@ -232,13 +232,13 @@ CGMarket * MarketInstanceConstructor::createObject() const
{ {
case EMarketMode::ARTIFACT_RESOURCE: case EMarketMode::ARTIFACT_RESOURCE:
case EMarketMode::RESOURCE_ARTIFACT: case EMarketMode::RESOURCE_ARTIFACT:
return new CGBlackMarket; return new CGBlackMarket(cb);
case EMarketMode::RESOURCE_SKILL: case EMarketMode::RESOURCE_SKILL:
return new CGUniversity; return new CGUniversity(cb);
} }
} }
return new CGMarket; return new CGMarket(cb);
} }
void MarketInstanceConstructor::initializeObject(CGMarket * market) const void MarketInstanceConstructor::initializeObject(CGMarket * market) const
@ -256,11 +256,12 @@ void MarketInstanceConstructor::initializeObject(CGMarket * market) const
void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const
{ {
JsonRandom randomizer(object->cb);
JsonRandom::Variables emptyVariables; JsonRandom::Variables emptyVariables;
if(auto * university = dynamic_cast<CGUniversity *>(object)) if(auto * university = dynamic_cast<CGUniversity *>(object))
{ {
for(auto skill : JsonRandom::loadSecondaries(predefinedOffer, rng, emptyVariables)) for(auto skill : randomizer.loadSecondaries(predefinedOffer, rng, emptyVariables))
university->skills.push_back(skill.first); university->skills.push_back(skill.first);
} }
} }

View File

@ -57,7 +57,7 @@ protected:
void initTypeData(const JsonNode & input) override; void initTypeData(const JsonNode & input) override;
public: public:
CFaction * faction = nullptr; const CFaction * faction = nullptr;
std::map<std::string, LogicalExpression<BuildingID>> filters; std::map<std::string, LogicalExpression<BuildingID>> filters;
void initializeObject(CGTownInstance * object) const override; void initializeObject(CGTownInstance * object) const override;
@ -76,7 +76,7 @@ protected:
void initTypeData(const JsonNode & input) override; void initTypeData(const JsonNode & input) override;
public: public:
CHeroClass * heroClass = nullptr; const CHeroClass * heroClass = nullptr;
std::map<std::string, LogicalExpression<HeroTypeID>> filters; std::map<std::string, LogicalExpression<HeroTypeID>> filters;
void initializeObject(CGHeroInstance * object) const override; void initializeObject(CGHeroInstance * object) const override;
@ -121,7 +121,7 @@ protected:
std::string speech; std::string speech;
public: public:
CGMarket * createObject() const override; CGMarket * createObject(IGameCallback * cb) const override;
void initializeObject(CGMarket * object) const override; void initializeObject(CGMarket * object) const override;
void randomizeObject(CGMarket * object, CRandomGenerator & rng) const override; void randomizeObject(CGMarket * object, CRandomGenerator & rng) const override;

View File

@ -45,7 +45,7 @@ void DwellingInstanceConstructor::initTypeData(const JsonNode & input)
{ {
VLC->identifiers()->requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index) VLC->identifiers()->requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index)
{ {
availableCreatures[currentLevel][currentCreature] = VLC->creh->objects[index]; availableCreatures[currentLevel][currentCreature] = CreatureID(index).toCreature();
}); });
} }
assert(!availableCreatures[currentLevel].empty()); assert(!availableCreatures[currentLevel].empty());
@ -68,9 +68,9 @@ void DwellingInstanceConstructor::initializeObject(CGDwelling * obj) const
} }
} }
void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGenerator &rng) const void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, CRandomGenerator &rng) const
{ {
auto * dwelling = dynamic_cast<CGDwelling *>(object); JsonRandom randomizer(dwelling->cb);
dwelling->creatures.clear(); dwelling->creatures.clear();
dwelling->creatures.reserve(availableCreatures.size()); dwelling->creatures.reserve(availableCreatures.size());
@ -94,7 +94,7 @@ void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGe
else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux) else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux)
{ {
JsonRandom::Variables emptyVariables; JsonRandom::Variables emptyVariables;
for(auto & stack : JsonRandom::loadCreatures(guards, rng, emptyVariables)) for(auto & stack : randomizer.loadCreatures(guards, rng, emptyVariables))
{ {
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count)); dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count));
} }

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include "CDefaultObjectTypeHandler.h" #include "CDefaultObjectTypeHandler.h"
#include "../mapObjects/CGDwelling.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include "CDefaultObjectTypeHandler.h" #include "CDefaultObjectTypeHandler.h"
#include "../mapObjects/MiscObjects.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -34,11 +34,6 @@ public:
} }
}; };
/// Returns possible composition of guards. Actual guards would be
/// somewhere between these two values
virtual CArmyStructure minGuards() const { return CArmyStructure(); }
virtual CArmyStructure maxGuards() const { return CArmyStructure(); }
virtual bool givesResources() const { return false; } virtual bool givesResources() const { return false; }
virtual bool givesExperience() const { return false; } virtual bool givesExperience() const { return false; }

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include "CDefaultObjectTypeHandler.h" #include "CDefaultObjectTypeHandler.h"
#include "../mapObjects/MiscObjects.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN

View File

@ -40,12 +40,13 @@ void CArmedInstance::randomizeArmy(FactionID type)
// Take Angelic Alliance troop-mixing freedom of non-evil units into account. // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX); CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX);
CArmedInstance::CArmedInstance() CArmedInstance::CArmedInstance(IGameCallback *cb)
:CArmedInstance(false) :CArmedInstance(cb, false)
{ {
} }
CArmedInstance::CArmedInstance(bool isHypothetic): CArmedInstance::CArmedInstance(IGameCallback *cb, bool isHypothetic):
CGObjectInstance(cb),
CBonusSystemNode(isHypothetic), CBonusSystemNode(isHypothetic),
nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector), nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector),
battle(nullptr) battle(nullptr)

View File

@ -42,8 +42,8 @@ public:
virtual CBonusSystemNode & whatShouldBeAttached(); virtual CBonusSystemNode & whatShouldBeAttached();
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
CArmedInstance(); CArmedInstance(IGameCallback *cb);
CArmedInstance(bool isHypothetic); CArmedInstance(IGameCallback *cb, bool isHypothetic);
PlayerColor getOwner() const override PlayerColor getOwner() const override
{ {

View File

@ -37,8 +37,10 @@ static std::string visitedTxt(const bool visited)
return VLC->generaltexth->allTexts[id]; return VLC->generaltexth->allTexts[id];
} }
//must be instantiated in .cpp file for access to complete types of all member fields CBank::CBank(IGameCallback *cb)
CBank::CBank() = default; : CArmedInstance(cb)
{}
//must be instantiated in .cpp file for access to complete types of all member fields //must be instantiated in .cpp file for access to complete types of all member fields
CBank::~CBank() = default; CBank::~CBank() = default;

View File

@ -27,7 +27,7 @@ class DLL_LINKAGE CBank : public CArmedInstance
void doVisit(const CGHeroInstance * hero) const; void doVisit(const CGHeroInstance * hero) const;
public: public:
CBank(); CBank(IGameCallback *cb);
~CBank() override; ~CBank() override;
void setConfig(const BankConfig & bc); void setConfig(const BankConfig & bc);

View File

@ -313,11 +313,11 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
powerFactor = -3; powerFactor = -3;
std::set<CreatureID> myKindCres; //what creatures are the same kind as we std::set<CreatureID> myKindCres; //what creatures are the same kind as we
const CCreature * myCreature = VLC->creh->objects[getCreature().getNum()]; const CCreature * myCreature = getCreature().toCreature();
myKindCres.insert(myCreature->getId()); //we myKindCres.insert(myCreature->getId()); //we
myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades
for(ConstTransitivePtr<CCreature> &crea : VLC->creh->objects) for(auto const & crea : VLC->creh->objects)
{ {
if(vstd::contains(crea->upgrades, myCreature->getId())) //it's our base creatures if(vstd::contains(crea->upgrades, myCreature->getId())) //it's our base creatures
myKindCres.insert(crea->getId()); myKindCres.insert(crea->getId());

View File

@ -18,6 +18,8 @@ VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map
{ {
public: public:
using CArmedInstance::CArmedInstance;
enum Action { enum Action {
FIGHT = -2, FLEE = -1, JOIN_FOR_FREE = 0 //values > 0 mean gold price FIGHT = -2, FLEE = -1, JOIN_FOR_FREE = 0 //values > 0 mean gold price
}; };

View File

@ -16,6 +16,7 @@
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjectConstructors/DwellingInstanceConstructor.h" #include "../mapObjectConstructors/DwellingInstanceConstructor.h"
#include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h"
#include "../networkPacks/StackLocation.h" #include "../networkPacks/StackLocation.h"
#include "../networkPacks/PacksForClient.h" #include "../networkPacks/PacksForClient.h"
#include "../networkPacks/PacksForClientBattle.h" #include "../networkPacks/PacksForClientBattle.h"
@ -43,7 +44,10 @@ void CGDwellingRandomizationInfo::serializeJson(JsonSerializeFormat & handler)
} }
} }
CGDwelling::CGDwelling() = default; CGDwelling::CGDwelling(IGameCallback *cb):
CArmedInstance(cb)
{}
CGDwelling::~CGDwelling() = default; CGDwelling::~CGDwelling() = default;
FactionID CGDwelling::randomizeFaction(CRandomGenerator & rand) FactionID CGDwelling::randomizeFaction(CRandomGenerator & rand)

View File

@ -38,7 +38,7 @@ public:
std::optional<CGDwellingRandomizationInfo> randomizationInfo; //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(IGameCallback *cb);
~CGDwelling() override; ~CGDwelling() override;
protected: protected:

View File

@ -33,6 +33,7 @@
#include "../serializer/JsonSerializeFormat.h" #include "../serializer/JsonSerializeFormat.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjects/MiscObjects.h"
#include "../modding/ModScope.h" #include "../modding/ModScope.h"
#include "../networkPacks/PacksForClient.h" #include "../networkPacks/PacksForClient.h"
#include "../networkPacks/PacksForClientBattle.h" #include "../networkPacks/PacksForClientBattle.h"
@ -274,7 +275,9 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti)
return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusCustomSubtype::heroMovementLand : BonusCustomSubtype::heroMovementSea); return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusCustomSubtype::heroMovementLand : BonusCustomSubtype::heroMovementSea);
} }
CGHeroInstance::CGHeroInstance(): CGHeroInstance::CGHeroInstance(IGameCallback * cb)
: CArmedInstance(cb),
type(nullptr),
tacticFormationEnabled(false), tacticFormationEnabled(false),
inTownGarrison(false), inTownGarrison(false),
moveDir(4), moveDir(4),
@ -316,7 +319,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand)
{ {
assert(validTypes(true)); assert(validTypes(true));
if(!type) if(!type)
type = VLC->heroh->objects[getHeroType().getNum()]; type = getHeroType().toHeroType();
if (ID == Obj::HERO) if (ID == Obj::HERO)
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
@ -590,11 +593,11 @@ void CGHeroInstance::pickRandomObject(CRandomGenerator & rand)
{ {
ID = Obj::HERO; ID = Obj::HERO;
subID = cb->gameState()->pickNextHeroType(getOwner()); subID = cb->gameState()->pickNextHeroType(getOwner());
type = VLC->heroh->objects[getHeroType().getNum()]; type = getHeroType().toHeroType();
randomizeArmy(type->heroClass->faction); randomizeArmy(type->heroClass->faction);
} }
else else
type = VLC->heroh->objects[getHeroType().getNum()]; type = getHeroType().toHeroType();
auto oldSubID = subID; auto oldSubID = subID;
@ -789,7 +792,7 @@ void CGHeroInstance::spendMana(ServerCallback * server, const int spellCost) con
bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const
{ {
const bool isAllowed = IObjectInterface::cb->isAllowed(spell->getId()); const bool isAllowed = cb->isAllowed(spell->getId());
const bool inSpellBook = vstd::contains(spells, spell->getId()) && hasSpellbook(); const bool inSpellBook = vstd::contains(spells, spell->getId()) && hasSpellbook();
const bool specificBonus = hasBonusOfType(BonusType::SPELL, BonusSubtypeID(spell->getId())); const bool specificBonus = hasBonusOfType(BonusType::SPELL, BonusSubtypeID(spell->getId()));
@ -853,7 +856,7 @@ bool CGHeroInstance::canLearnSpell(const spells::Spell * spell, bool allowBanned
return false;//creature abilities can not be learned return false;//creature abilities can not be learned
} }
if(!allowBanned && !IObjectInterface::cb->isAllowed(spell->getId())) if(!allowBanned && !cb->isAllowed(spell->getId()))
{ {
logGlobal->warn("Hero %s try to learn banned spell %s", nodeName(), spell->getNameTranslated()); logGlobal->warn("Hero %s try to learn banned spell %s", nodeName(), spell->getNameTranslated());
return false;//banned spells should not be learned return false;//banned spells should not be learned
@ -879,7 +882,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
double necromancySkill = valOfBonuses(BonusType::UNDEAD_RAISE_PERCENTAGE) / 100.0; double necromancySkill = valOfBonuses(BonusType::UNDEAD_RAISE_PERCENTAGE) / 100.0;
const ui8 necromancyLevel = valOfBonuses(BonusType::IMPROVED_NECROMANCY); const ui8 necromancyLevel = valOfBonuses(BonusType::IMPROVED_NECROMANCY);
vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all... vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all...
const std::map<ui32,si32> &casualties = battleResult.casualties[!battleResult.winner]; const std::map<CreatureID,si32> &casualties = battleResult.casualties[!battleResult.winner];
// figure out what to raise - pick strongest creature meeting requirements // figure out what to raise - pick strongest creature meeting requirements
CreatureID creatureTypeRaised = CreatureID::NONE; //now we always have IMPROVED_NECROMANCY, no need for hardcode CreatureID creatureTypeRaised = CreatureID::NONE; //now we always have IMPROVED_NECROMANCY, no need for hardcode
int requiredCasualtyLevel = 1; int requiredCasualtyLevel = 1;
@ -888,7 +891,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
{ {
int maxCasualtyLevel = 1; int maxCasualtyLevel = 1;
for(const auto & casualty : casualties) for(const auto & casualty : casualties)
vstd::amax(maxCasualtyLevel, VLC->creatures()->getByIndex(casualty.first)->getLevel()); vstd::amax(maxCasualtyLevel, VLC->creatures()->getById(casualty.first)->getLevel());
// pick best bonus available // pick best bonus available
std::shared_ptr<Bonus> topPick; std::shared_ptr<Bonus> topPick;
for(const std::shared_ptr<Bonus> & newPick : *improvedNecromancy) for(const std::shared_ptr<Bonus> & newPick : *improvedNecromancy)
@ -936,7 +939,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
double raisedUnits = 0; double raisedUnits = 0;
for(const auto & casualty : casualties) for(const auto & casualty : casualties)
{ {
const CCreature * c = VLC->creh->objects[casualty.first]; const CCreature * c = casualty.first.toCreature();
double raisedFromCasualty = std::min(c->getMaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill; double raisedFromCasualty = std::min(c->getMaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill;
if(c->getLevel() < requiredCasualtyLevel) if(c->getLevel() < requiredCasualtyLevel)
raisedFromCasualty *= 0.5; raisedFromCasualty *= 0.5;
@ -1258,7 +1261,7 @@ EDiggingStatus CGHeroInstance::diggingStatus() const
{ {
if(static_cast<int>(movement) < movementPointsLimit(true)) if(static_cast<int>(movement) < movementPointsLimit(true))
return EDiggingStatus::LACK_OF_MOVEMENT; return EDiggingStatus::LACK_OF_MOVEMENT;
if(!VLC->arth->objects[ArtifactID::GRAIL]->canBePutAt(this)) if(ArtifactID(ArtifactID::GRAIL).toArtifact()->canBePutAt(this))
return EDiggingStatus::BACKPACK_IS_FULL; return EDiggingStatus::BACKPACK_IS_FULL;
return cb->getTileDigStatus(visitablePos()); return cb->getTileDigStatus(visitablePos());
} }
@ -1409,7 +1412,7 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill primarySkill, si64 value, ui8
{ {
if(primarySkill < PrimarySkill::EXPERIENCE) if(primarySkill < PrimarySkill::EXPERIENCE)
{ {
auto skill = getBonusLocalFirst(Selector::type()(BonusType::PRIMARY_SKILL) auto skill = getLocalBonus(Selector::type()(BonusType::PRIMARY_SKILL)
.And(Selector::subtype()(BonusSubtypeID(primarySkill))) .And(Selector::subtype()(BonusSubtypeID(primarySkill)))
.And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL))); .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)));
assert(skill); assert(skill);
@ -1742,7 +1745,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler)
if(!appearance) if(!appearance)
{ {
// crossoverDeserialize // crossoverDeserialize
type = VLC->heroh->objects[getHeroType().getNum()]; type = getHeroType().toHeroType();
appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front();
} }
@ -1760,7 +1763,7 @@ void CGHeroInstance::serializeJsonDefinition(JsonSerializeFormat & handler)
bool CGHeroInstance::isMissionCritical() const bool CGHeroInstance::isMissionCritical() const
{ {
for(const TriggeredEvent & event : IObjectInterface::cb->getMapHeader()->triggeredEvents) for(const TriggeredEvent & event : cb->getMapHeader()->triggeredEvents)
{ {
if (event.effect.type != EventEffect::DEFEAT) if (event.effect.type != EventEffect::DEFEAT)
continue; continue;

View File

@ -28,6 +28,8 @@ enum class EHeroGender : uint8_t;
class DLL_LINKAGE CGHeroPlaceholder : public CGObjectInstance class DLL_LINKAGE CGHeroPlaceholder : public CGObjectInstance
{ {
public: public:
using CGObjectInstance::CGObjectInstance;
/// if this is placeholder by power, then power rank of desired hero /// if this is placeholder by power, then power rank of desired hero
std::optional<ui8> powerRank; std::optional<ui8> powerRank;
@ -69,7 +71,7 @@ public:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
ConstTransitivePtr<CHero> type; const CHero * type;
TExpType exp; //experience points TExpType exp; //experience points
ui32 level; //current level of hero ui32 level; //current level of hero
@ -249,7 +251,7 @@ public:
/// If this hero perishes, the scenario is failed /// If this hero perishes, the scenario is failed
bool isMissionCritical() const; bool isMissionCritical() const;
CGHeroInstance(); CGHeroInstance(IGameCallback *cb);
virtual ~CGHeroInstance(); virtual ~CGHeroInstance();
PlayerColor getOwner() const override; PlayerColor getOwner() const override;

View File

@ -55,9 +55,9 @@ std::vector<TradeItemBuy> CGMarket::availableItemsIds(EMarketMode mode) const
return std::vector<TradeItemBuy>(); return std::vector<TradeItemBuy>();
} }
CGMarket::CGMarket() CGMarket::CGMarket(IGameCallback *cb):
{ CGObjectInstance(cb)
} {}
std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) const std::vector<TradeItemBuy> CGBlackMarket::availableItemsIds(EMarketMode mode) const
{ {

View File

@ -25,7 +25,7 @@ public:
std::string title; std::string title;
std::string speech; //currently shown only in university std::string speech; //currently shown only in university
CGMarket(); CGMarket(IGameCallback *cb);
///IObjectInterface ///IObjectInterface
void onHeroVisit(const CGHeroInstance * h) const override; //open trading window void onHeroVisit(const CGHeroInstance * h) const override; //open trading window
void initObj(CRandomGenerator & rand) override;//set skills for trade void initObj(CRandomGenerator & rand) override;//set skills for trade
@ -49,6 +49,8 @@ public:
class DLL_LINKAGE CGBlackMarket : public CGMarket class DLL_LINKAGE CGBlackMarket : public CGMarket
{ {
public: public:
using CGMarket::CGMarket;
std::vector<const CArtifact *> artifacts; //available artifacts std::vector<const CArtifact *> artifacts; //available artifacts
void newTurn(CRandomGenerator & rand) const override; //reset artifacts for black market every month void newTurn(CRandomGenerator & rand) const override; //reset artifacts for black market every month
@ -64,6 +66,8 @@ public:
class DLL_LINKAGE CGUniversity : public CGMarket class DLL_LINKAGE CGUniversity : public CGMarket
{ {
public: public:
using CGMarket::CGMarket;
std::vector<TradeItemBuy> skills; //available skills std::vector<TradeItemBuy> skills; //available skills
std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override; std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;

View File

@ -28,7 +28,8 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
//TODO: remove constructor //TODO: remove constructor
CGObjectInstance::CGObjectInstance(): CGObjectInstance::CGObjectInstance(IGameCallback *cb):
IObjectInterface(cb),
pos(-1,-1,-1), pos(-1,-1,-1),
ID(Obj::NO_OBJ), ID(Obj::NO_OBJ),
subID(-1), subID(-1),

Some files were not shown because too many files have changed in this diff Show More