mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge branch 'develop' into feature/VCMIMapFormat1
Conflicts: lib/CArtHandler.cpp
This commit is contained in:
commit
37d0dad70a
@ -8,7 +8,7 @@
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
|
||||
using boost::optional;
|
||||
static shared_ptr<CBattleCallback> cbc;
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
#define LOGL(text) print(text)
|
||||
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl))
|
||||
@ -91,7 +91,7 @@ CBattleAI::~CBattleAI(void)
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleAI::init(shared_ptr<CBattleCallback> CB)
|
||||
void CBattleAI::init(std::shared_ptr<CBattleCallback> CB)
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
cbc = cb = CB;
|
||||
@ -610,7 +610,7 @@ ThreatMap::ThreatMap(const CStack *Endangered) : endangered(Endangered)
|
||||
|
||||
const TBonusListPtr StackWithBonuses::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= nullptr*/, const std::string &cachingStr /*= ""*/) const
|
||||
{
|
||||
TBonusListPtr ret = make_shared<BonusList>();
|
||||
TBonusListPtr ret = std::make_shared<BonusList>();
|
||||
const TBonusListPtr originalList = stack->getAllBonuses(selector, limit, root, cachingStr);
|
||||
range::copy(*originalList, std::back_inserter(*ret));
|
||||
for(auto &bonus : bonusesToAdd)
|
||||
|
@ -110,7 +110,7 @@ struct PotentialTargets
|
||||
class CBattleAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
std::shared_ptr<CBattleCallback> cb;
|
||||
|
||||
//Previous setting of cb
|
||||
bool wasWaitingForRealize, wasUnlockingGs;
|
||||
@ -120,7 +120,7 @@ public:
|
||||
CBattleAI(void);
|
||||
~CBattleAI(void);
|
||||
|
||||
void init(shared_ptr<CBattleCallback> CB) override;
|
||||
void init(std::shared_ptr<CBattleCallback> CB) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
|
@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
|
||||
{
|
||||
out = make_shared<CBattleAI>();
|
||||
out = std::make_shared<CBattleAI>();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "../../lib/CRandomGenerator.h"
|
||||
|
||||
void CEmptyAI::init(shared_ptr<CCallback> CB)
|
||||
void CEmptyAI::init(std::shared_ptr<CCallback> CB)
|
||||
{
|
||||
cb = CB;
|
||||
human=false;
|
||||
|
@ -7,10 +7,10 @@ struct HeroMoveDetails;
|
||||
|
||||
class CEmptyAI : public CGlobalAI
|
||||
{
|
||||
shared_ptr<CCallback> cb;
|
||||
std::shared_ptr<CCallback> cb;
|
||||
|
||||
public:
|
||||
void init(shared_ptr<CCallback> CB) override;
|
||||
void init(std::shared_ptr<CCallback> CB) override;
|
||||
void yourTurn() override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
|
@ -13,7 +13,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy(name,NAME);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
|
||||
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
|
||||
{
|
||||
out = make_shared<CEmptyAI>();
|
||||
out = std::make_shared<CEmptyAI>();
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
static shared_ptr<CBattleCallback> cbc;
|
||||
static std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
CStupidAI::CStupidAI(void)
|
||||
: side(-1)
|
||||
@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void)
|
||||
print("destroyed");
|
||||
}
|
||||
|
||||
void CStupidAI::init(shared_ptr<CBattleCallback> CB)
|
||||
void CStupidAI::init(std::shared_ptr<CBattleCallback> CB)
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
cbc = cb = CB;
|
||||
|
@ -5,14 +5,14 @@
|
||||
class CStupidAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
std::shared_ptr<CBattleCallback> cb;
|
||||
|
||||
void print(const std::string &text) const;
|
||||
public:
|
||||
CStupidAI(void);
|
||||
~CStupidAI(void);
|
||||
|
||||
void init(shared_ptr<CBattleCallback> CB) override;
|
||||
void init(std::shared_ptr<CBattleCallback> CB) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
|
@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
|
||||
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
|
||||
{
|
||||
out = make_shared<CStupidAI>();
|
||||
out = std::make_shared<CStupidAI>();
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ class CCallback;
|
||||
typedef const int3& crint3;
|
||||
typedef const std::string& crstring;
|
||||
|
||||
const int HERO_GOLD_COST = 2500;
|
||||
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
|
||||
const int ACTUAL_RESOURCE_COUNT = 7;
|
||||
const int ALLOWED_ROAMING_HEROES = 8;
|
||||
|
@ -31,7 +31,6 @@ class Engine;
|
||||
class InputVariable;
|
||||
class CGTownInstance;
|
||||
|
||||
using namespace vstd;
|
||||
//using namespace Goals;
|
||||
|
||||
FuzzyHelper *fh;
|
||||
@ -85,7 +84,7 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
|
||||
if (walker)
|
||||
walkersStrenght += s.second->getPower();
|
||||
|
||||
amax (maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
|
||||
vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
|
||||
}
|
||||
armyStructure as;
|
||||
as.walkers = walkersStrenght / totalStrenght;
|
||||
@ -297,7 +296,7 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
|
||||
delete threat;
|
||||
}
|
||||
|
||||
//shared_ptr<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec)
|
||||
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec)
|
||||
|
||||
Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
|
||||
{
|
||||
|
@ -83,5 +83,5 @@ public:
|
||||
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us
|
||||
|
||||
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec);
|
||||
//shared_ptr<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec);
|
||||
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec);
|
||||
};
|
||||
|
@ -19,12 +19,11 @@ extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh; //TODO: this logic should be moved inside VCAI
|
||||
|
||||
using namespace vstd;
|
||||
using namespace Goals;
|
||||
|
||||
TSubgoal Goals::sptr(const AbstractGoal & tmp)
|
||||
{
|
||||
shared_ptr<AbstractGoal> ptr;
|
||||
std::shared_ptr<AbstractGoal> ptr;
|
||||
ptr.reset(tmp.clone());
|
||||
return ptr;
|
||||
}
|
||||
@ -575,7 +574,7 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
||||
{
|
||||
//heroes = ai->getUnblockedHeroes();
|
||||
heroes = cb->getHeroesInfo();
|
||||
erase_if (heroes, [](const HeroPtr h)
|
||||
vstd::erase_if(heroes, [](const HeroPtr h)
|
||||
{
|
||||
if (ai->getGoal(h)->goalType == Goals::EXPLORE) //do not reassign hero who is already explorer
|
||||
return true;
|
||||
@ -693,8 +692,8 @@ TSubgoal RecruitHero::whatToDoToAchieve()
|
||||
if(!t)
|
||||
return sptr (Goals::BuildThis(BuildingID::TAVERN));
|
||||
|
||||
if(cb->getResourceAmount(Res::GOLD) < HERO_GOLD_COST)
|
||||
return sptr (Goals::CollectRes(Res::GOLD, HERO_GOLD_COST));
|
||||
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST)
|
||||
return sptr (Goals::CollectRes(Res::GOLD, GameConstants::HERO_GOLD_COST));
|
||||
|
||||
return iAmElementar();
|
||||
}
|
||||
@ -747,10 +746,10 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
|
||||
if (ai->canRecruitAnyHero())
|
||||
ret.push_back (sptr(Goals::RecruitHero()));
|
||||
}
|
||||
if (ret.empty())
|
||||
if(ret.empty())
|
||||
{
|
||||
auto obj = frontOrNull(cb->getVisitableObjs(tile));
|
||||
if (obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
|
||||
auto obj = vstd::frontOrNull(cb->getVisitableObjs(tile));
|
||||
if(obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
|
||||
{
|
||||
if (hero.get(true) && hero->id == obj->id) //if it's assigned hero, visit tile. If it's different hero, we can't visit tile now
|
||||
ret.push_back(sptr(Goals::VisitTile(tile).sethero(dynamic_cast<const CGHeroInstance *>(obj)).setisElementar(true)));
|
||||
@ -767,7 +766,7 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
|
||||
|
||||
TSubgoal DigAtTile::whatToDoToAchieve()
|
||||
{
|
||||
const CGObjectInstance *firstObj = frontOrNull(cb->getVisitableObjs(tile));
|
||||
const CGObjectInstance *firstObj = vstd::frontOrNull(cb->getVisitableObjs(tile));
|
||||
if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest
|
||||
{
|
||||
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj);
|
||||
@ -1057,7 +1056,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
|
||||
auto otherHeroes = cb->getHeroesInfo();
|
||||
auto heroDummy = hero;
|
||||
erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
|
||||
vstd::erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
|
||||
{
|
||||
return (h == heroDummy.h || !ai->isAccessibleForHero(heroDummy->visitablePos(), h, true)
|
||||
|| !ai->canGetArmy(heroDummy.h, h) || ai->getGoal(h)->goalType == Goals::GATHER_ARMY);
|
||||
|
@ -107,7 +107,7 @@ public:
|
||||
static TSubgoal tryRecruitHero();
|
||||
|
||||
///Visitor pattern
|
||||
//TODO: make accept work for shared_ptr... somehow
|
||||
//TODO: make accept work for std::shared_ptr... somehow
|
||||
virtual void accept (VCAI * ai); //unhandled goal will report standard error
|
||||
virtual float accept (FuzzyHelper * f);
|
||||
|
||||
@ -162,7 +162,7 @@ public:
|
||||
TSubgoal iAmElementar()
|
||||
{
|
||||
setisElementar(true);
|
||||
shared_ptr<AbstractGoal> ptr;
|
||||
std::shared_ptr<AbstractGoal> ptr;
|
||||
ptr.reset(clone());
|
||||
return ptr;
|
||||
}
|
||||
|
222
AI/VCAI/VCAI.cpp
222
AI/VCAI/VCAI.cpp
@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* CCreatureHandler.h, part of VCMI engine
|
||||
* VCAI.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
@ -29,8 +29,6 @@ class CGVisitableOPW;
|
||||
const double SAFE_ATTACK_CONSTANT = 1.5;
|
||||
const int GOLD_RESERVE = 10000; //when buying creatures we want to keep at least this much gold (10000 so at least we'll be able to reach capitol)
|
||||
|
||||
using namespace vstd;
|
||||
|
||||
//one thread may be turn of AI and another will be handling a side effect for AI2
|
||||
boost::thread_specific_ptr<CCallback> cb;
|
||||
boost::thread_specific_ptr<VCAI> ai;
|
||||
@ -124,8 +122,8 @@ void VCAI::heroMoved(const TryMoveHero & details)
|
||||
{
|
||||
const int3 from = CGHeroInstance::convertPosition(details.start, false),
|
||||
to = CGHeroInstance::convertPosition(details.end, false);
|
||||
const CGObjectInstance *o1 = frontOrNull(cb->getVisitableObjs(from)),
|
||||
*o2 = frontOrNull(cb->getVisitableObjs(to));
|
||||
const CGObjectInstance *o1 = vstd::frontOrNull(cb->getVisitableObjs(from)),
|
||||
*o2 = vstd::frontOrNull(cb->getVisitableObjs(to));
|
||||
|
||||
auto t1 = dynamic_cast<const CGTeleport *>(o1);
|
||||
auto t2 = dynamic_cast<const CGTeleport *>(o2);
|
||||
@ -394,8 +392,8 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
|
||||
LOG_TRACE(logAi);
|
||||
NET_EVENT_HANDLER;
|
||||
|
||||
erase_if_present(visitableObjs, obj);
|
||||
erase_if_present(alreadyVisited, obj);
|
||||
vstd::erase_if_present(visitableObjs, obj);
|
||||
vstd::erase_if_present(alreadyVisited, obj);
|
||||
|
||||
for (auto h : cb->getHeroesInfo())
|
||||
unreserveObject(h, obj);
|
||||
@ -518,15 +516,15 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
|
||||
{
|
||||
//we don't want to visit know object twice (do we really?)
|
||||
if(sop->val == playerID.getNum())
|
||||
erase_if_present(visitableObjs, myCb->getObj(sop->id));
|
||||
else if (myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
|
||||
vstd::erase_if_present(visitableObjs, myCb->getObj(sop->id));
|
||||
else if(myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
|
||||
{
|
||||
//we want to visit objects owned by oppponents
|
||||
auto obj = myCb->getObj(sop->id, false);
|
||||
if (obj)
|
||||
{
|
||||
addVisitableObj(obj);
|
||||
erase_if_present(alreadyVisited, obj);
|
||||
vstd::erase_if_present(alreadyVisited, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -557,7 +555,7 @@ void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions)
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void VCAI::init(shared_ptr<CCallback> CB)
|
||||
void VCAI::init(std::shared_ptr<CCallback> CB)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
myCb = CB;
|
||||
@ -738,7 +736,7 @@ void VCAI::makeTurn()
|
||||
if (isWeeklyRevisitable(obj))
|
||||
{
|
||||
addVisitableObj(obj);
|
||||
erase_if_present (alreadyVisited, obj);
|
||||
vstd::erase_if_present(alreadyVisited, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -841,7 +839,7 @@ void VCAI::makeTurnInternal()
|
||||
{
|
||||
if (h->movement)
|
||||
logAi->warnStream() << boost::format("hero %s has %d MP left") % h->name % h->movement;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(boost::thread_interrupted &e)
|
||||
{
|
||||
@ -910,7 +908,7 @@ bool VCAI::canGetArmy (const CGHeroInstance * army, const CGHeroInstance * sourc
|
||||
|
||||
|
||||
const CArmedInstance *armies[] = {army, source};
|
||||
|
||||
|
||||
//we calculate total strength for each creature type available in armies
|
||||
std::map<const CCreature*, int> creToPower;
|
||||
for(auto armyPtr : armies)
|
||||
@ -945,7 +943,7 @@ bool VCAI::canGetArmy (const CGHeroInstance * army, const CGHeroInstance * sourc
|
||||
if(armyPtr->getCreature(SlotID(j)) == bestArmy[i] && armyPtr != army) //it's a searched creature not in dst ARMY
|
||||
{
|
||||
//FIXME: line below is useless when simulating exchange between two non-singular armies
|
||||
if (!(armyPtr->needsLastStack() && armyPtr->Slots().size() == 1)) //can't take away last creature
|
||||
if(!(armyPtr->needsLastStack() && armyPtr->stacksCount() == 1)) //can't take away last creature
|
||||
return true; //at least one exchange will be performed
|
||||
else
|
||||
return false; //no further exchange possible
|
||||
@ -992,7 +990,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
|
||||
for (int j = 0; j < GameConstants::ARMY_SIZE; j++)
|
||||
{
|
||||
if(armyPtr->getCreature(SlotID(j)) == bestArmy[i] && (i != j || armyPtr != army)) //it's a searched creature not in dst SLOT
|
||||
if (!(armyPtr->needsLastStack() && armyPtr->Slots().size() == 1)) //can't take away last creature
|
||||
if(!(armyPtr->needsLastStack() && armyPtr->stacksCount() == 1)) //can't take away last creature
|
||||
cb->mergeOrSwapStacks(armyPtr, army, SlotID(j), SlotID(i));
|
||||
}
|
||||
}
|
||||
@ -1007,7 +1005,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
|
||||
}
|
||||
|
||||
void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other)
|
||||
{
|
||||
{
|
||||
auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
|
||||
{
|
||||
bool changeMade = false;
|
||||
@ -1052,6 +1050,9 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
|
||||
if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
|
||||
continue; //don't reequip artifact we already wear
|
||||
|
||||
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
|
||||
continue;
|
||||
|
||||
auto s = location.getSlot();
|
||||
if (!s || s->locked) //we can't move locks
|
||||
continue;
|
||||
@ -1118,7 +1119,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit
|
||||
// if(containsSavedRes(c->cost))
|
||||
// continue;
|
||||
|
||||
amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
|
||||
vstd::amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
|
||||
if(count > 0)
|
||||
cb->recruitCreatures(d, recruiter, creID, count, i);
|
||||
}
|
||||
@ -1445,7 +1446,7 @@ bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
|
||||
if (!t)
|
||||
t = findTownWithTavern();
|
||||
if (t)
|
||||
return cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST &&
|
||||
return cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST &&
|
||||
cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES &&
|
||||
cb->getAvailableHeroes(t).size();
|
||||
else
|
||||
@ -1481,7 +1482,7 @@ void VCAI::wander(HeroPtr h)
|
||||
}
|
||||
|
||||
range::copy(getPossibleDestinations(h), std::back_inserter(dests));
|
||||
erase_if(dests, [&](ObjectIdRef obj) -> bool
|
||||
vstd::erase_if(dests, [&](ObjectIdRef obj) -> bool
|
||||
{
|
||||
return !isSafeToVisit(h, sm->firstTileToGet(h, obj->visitablePos()));
|
||||
});
|
||||
@ -1530,10 +1531,10 @@ void VCAI::wander(HeroPtr h)
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST)
|
||||
else if(cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST)
|
||||
{
|
||||
std::vector<const CGTownInstance *> towns = cb->getTownsInfo();
|
||||
erase_if(towns, [](const CGTownInstance *t) -> bool
|
||||
vstd::erase_if(towns, [](const CGTownInstance *t) -> bool
|
||||
{
|
||||
for(const CGHeroInstance *h : cb->getHeroesInfo())
|
||||
if(!t->getArmyStrength() || howManyReinforcementsCanGet(h, t))
|
||||
@ -1584,8 +1585,8 @@ void VCAI::wander(HeroPtr h)
|
||||
|
||||
void VCAI::setGoal(HeroPtr h, Goals::TSubgoal goal)
|
||||
{ //TODO: check for presence?
|
||||
if (goal->invalid())
|
||||
erase_if_present(lockedHeroes, h);
|
||||
if(goal->invalid())
|
||||
vstd::erase_if_present(lockedHeroes, h);
|
||||
else
|
||||
{
|
||||
lockedHeroes[h] = goal;
|
||||
@ -1626,7 +1627,7 @@ void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int
|
||||
NET_EVENT_HANDLER;
|
||||
assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE);
|
||||
status.setBattle(ONGOING_BATTLE);
|
||||
const CGObjectInstance *presumedEnemy = backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
|
||||
const CGObjectInstance *presumedEnemy = vstd::backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
|
||||
battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->name : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile);
|
||||
CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side);
|
||||
}
|
||||
@ -1666,8 +1667,8 @@ void VCAI::reserveObject(HeroPtr h, const CGObjectInstance *obj)
|
||||
|
||||
void VCAI::unreserveObject(HeroPtr h, const CGObjectInstance *obj)
|
||||
{
|
||||
erase_if_present(reservedObjs, obj); //unreserve objects
|
||||
erase_if_present(reservedHeroesMap[h], obj);
|
||||
vstd::erase_if_present(reservedObjs, obj); //unreserve objects
|
||||
vstd::erase_if_present(reservedHeroesMap[h], obj);
|
||||
}
|
||||
|
||||
void VCAI::markHeroUnableToExplore (HeroPtr h)
|
||||
@ -1676,7 +1677,7 @@ void VCAI::markHeroUnableToExplore (HeroPtr h)
|
||||
}
|
||||
void VCAI::markHeroAbleToExplore (HeroPtr h)
|
||||
{
|
||||
erase_if_present(heroesUnableToExplore, h);
|
||||
vstd::erase_if_present(heroesUnableToExplore, h);
|
||||
}
|
||||
bool VCAI::isAbleToExplore (HeroPtr h)
|
||||
{
|
||||
@ -1697,7 +1698,7 @@ void VCAI::validateVisitableObjs()
|
||||
auto shouldBeErased = [&](const CGObjectInstance *obj) -> bool
|
||||
{
|
||||
if (obj)
|
||||
return !cb->getObj(obj->id);
|
||||
return !cb->getObj(obj->id, false); // no verbose output needed as we check object visibility
|
||||
else
|
||||
return true;
|
||||
|
||||
@ -1713,25 +1714,25 @@ void VCAI::validateVisitableObjs()
|
||||
|
||||
//errorMsg is captured by ref so lambda will take the new text
|
||||
errorMsg = " shouldn't be on the visitable objects list!";
|
||||
erase_if(visitableObjs, shouldBeErased);
|
||||
vstd::erase_if(visitableObjs, shouldBeErased);
|
||||
|
||||
//FIXME: how comes our own heroes become inaccessible?
|
||||
erase_if(reservedHeroesMap, [](std::pair<HeroPtr, std::set<const CGObjectInstance *>> hp) -> bool
|
||||
vstd::erase_if(reservedHeroesMap, [](std::pair<HeroPtr, std::set<const CGObjectInstance *>> hp) -> bool
|
||||
{
|
||||
return !hp.first.get(true);
|
||||
});
|
||||
for(auto &p : reservedHeroesMap)
|
||||
{
|
||||
errorMsg = " shouldn't be on list for hero " + p.first->name + "!";
|
||||
erase_if(p.second, shouldBeErased);
|
||||
vstd::erase_if(p.second, shouldBeErased);
|
||||
}
|
||||
|
||||
errorMsg = " shouldn't be on the reserved objs list!";
|
||||
erase_if(reservedObjs, shouldBeErased);
|
||||
vstd::erase_if(reservedObjs, shouldBeErased);
|
||||
|
||||
//TODO overkill, hidden object should not be removed. However, we can't know if hidden object is erased from game.
|
||||
errorMsg = " shouldn't be on the already visited objs list!";
|
||||
erase_if(alreadyVisited, shouldBeErased);
|
||||
vstd::erase_if(alreadyVisited, shouldBeErased);
|
||||
}
|
||||
|
||||
void VCAI::retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned /*= false*/) const
|
||||
@ -1762,7 +1763,7 @@ std::vector<const CGObjectInstance *> VCAI::getFlaggedObjects() const
|
||||
{
|
||||
std::vector<const CGObjectInstance *> ret;
|
||||
retreiveVisitableObjs(ret, true);
|
||||
erase_if(ret, [](const CGObjectInstance *obj)
|
||||
vstd::erase_if(ret, [](const CGObjectInstance *obj)
|
||||
{
|
||||
return obj->tempOwner != ai->playerID;
|
||||
});
|
||||
@ -1784,7 +1785,7 @@ const CGObjectInstance * VCAI::lookForArt(int aid) const
|
||||
{
|
||||
for(const CGObjectInstance *obj : ai->visitableObjs)
|
||||
{
|
||||
if(obj->ID == 5 && obj->subID == aid)
|
||||
if(obj->ID == Obj::ARTIFACT && obj->subID == aid)
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -1876,6 +1877,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst;
|
||||
throw goalFulfilledException (sptr(Goals::VisitTile(dst).sethero(h)));
|
||||
}
|
||||
int i = path.nodes.size()-1;
|
||||
|
||||
auto getObj = [&](int3 coord, bool ignoreHero)
|
||||
{
|
||||
@ -1885,6 +1887,31 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
//return cb->getTile(coord,false)->topVisitableObj(ignoreHero);
|
||||
};
|
||||
|
||||
auto isTeleportAction = [&](CGPathNode::ENodeAction action) -> bool
|
||||
{
|
||||
if(action != CGPathNode::TELEPORT_NORMAL &&
|
||||
action != CGPathNode::TELEPORT_BLOCKING_VISIT &&
|
||||
action != CGPathNode::TELEPORT_BATTLE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto getDestTeleportObj = [&](const CGObjectInstance * currentObject, const CGObjectInstance * nextObjectTop, const CGObjectInstance * nextObject) -> const CGObjectInstance *
|
||||
{
|
||||
if(CGTeleport::isConnected(currentObject, nextObjectTop))
|
||||
return nextObjectTop;
|
||||
if(nextObjectTop && nextObjectTop->ID == Obj::HERO &&
|
||||
CGTeleport::isConnected(currentObject, nextObject))
|
||||
{
|
||||
return nextObject;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
auto doMovement = [&](int3 dst, bool transit)
|
||||
{
|
||||
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
|
||||
@ -1915,17 +1942,18 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
doTeleportMovement(currentExit, currentPos);
|
||||
};
|
||||
|
||||
int i=path.nodes.size()-1;
|
||||
for(; i>0; i--)
|
||||
{
|
||||
int3 currentCoord = path.nodes[i].coord;
|
||||
int3 nextCoord = path.nodes[i-1].coord;
|
||||
|
||||
auto currentObject = getObj(currentCoord, currentCoord == CGHeroInstance::convertPosition(h->pos,false));
|
||||
auto nextObject = getObj(nextCoord, false);
|
||||
if(CGTeleport::isConnected(currentObject, nextObject))
|
||||
auto nextObjectTop = getObj(nextCoord, false);
|
||||
auto nextObject = getObj(nextCoord, true);
|
||||
auto destTeleportObj = getDestTeleportObj(currentObject, nextObjectTop, nextObject);
|
||||
if(isTeleportAction(path.nodes[i-1].action) && destTeleportObj != nullptr)
|
||||
{ //we use special login if hero standing on teleporter it's mean we need
|
||||
doTeleportMovement(nextObject->id, nextCoord);
|
||||
doTeleportMovement(destTeleportObj->id, nextCoord);
|
||||
if(teleportChannelProbingList.size())
|
||||
doChannelProbing();
|
||||
|
||||
@ -1944,8 +1972,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
continue;
|
||||
|
||||
if((i-2 >= 0) // Check there is node after next one; otherwise transit is pointless
|
||||
&& (CGTeleport::isConnected(nextObject, getObj(path.nodes[i-2].coord, false))
|
||||
|| CGTeleport::isTeleport(nextObject)))
|
||||
&& (CGTeleport::isConnected(nextObjectTop, getObj(path.nodes[i-2].coord, false))
|
||||
|| CGTeleport::isTeleport(nextObjectTop)))
|
||||
{ // Hero should be able to go through object if it's allow transit
|
||||
doMovement(endpos, true);
|
||||
}
|
||||
@ -1963,7 +1991,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
}
|
||||
if (h)
|
||||
{
|
||||
if (auto visitedObject = frontOrNull(cb->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
|
||||
if(auto visitedObject = vstd::frontOrNull(cb->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
|
||||
{
|
||||
if (visitedObject != *h)
|
||||
performObjectInteraction (visitedObject, h);
|
||||
@ -1974,16 +2002,16 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
completeGoal (sptr(Goals::VisitTile(dst).sethero(h))); //we stepped on some tile, anyway
|
||||
completeGoal (sptr(Goals::ClearWayTo(dst).sethero(h)));
|
||||
|
||||
if (!ret) //reserve object we are heading towards
|
||||
if(!ret) //reserve object we are heading towards
|
||||
{
|
||||
auto obj = frontOrNull(cb->getVisitableObjs(dst));
|
||||
if (obj && obj != *h)
|
||||
auto obj = vstd::frontOrNull(cb->getVisitableObjs(dst));
|
||||
if(obj && obj != *h)
|
||||
reserveObject(h, obj);
|
||||
}
|
||||
|
||||
if (startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target
|
||||
if(startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target
|
||||
{
|
||||
erase_if_present (lockedHeroes, h); //hero seemingly is confused
|
||||
vstd::erase_if_present(lockedHeroes, h); //hero seemingly is confused
|
||||
throw cannotFulfillGoalException("Invalid path found!"); //FIXME: should never happen
|
||||
}
|
||||
logAi->debugStream() << boost::format("Hero %s moved from %s to %s. Returning %d.") % h->name % startHpos % h->visitablePos() % ret;
|
||||
@ -2101,7 +2129,7 @@ void VCAI::tryRealize(Goals::CollectRes & g)
|
||||
cb->trade(obj, EMarketMode::RESOURCE_RESOURCE, i, g.resID, toGive);
|
||||
if(cb->getResourceAmount(static_cast<Res::ERes>(g.resID)) >= g.value)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw cannotFulfillGoalException("I cannot get needed resources by trade!");
|
||||
}
|
||||
@ -2290,7 +2318,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
|
||||
}
|
||||
else
|
||||
{
|
||||
erase_if_present (lockedHeroes, goal->hero); // we seemingly don't know what to do with hero
|
||||
vstd::erase_if_present (lockedHeroes, goal->hero); // we seemingly don't know what to do with hero
|
||||
}
|
||||
}
|
||||
|
||||
@ -2319,7 +2347,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
|
||||
completeGoal (goal);
|
||||
//completed goal was main goal //TODO: find better condition
|
||||
if (ultimateGoal->fulfillsMe(goal) || maxGoals > searchDepth2)
|
||||
return sptr(Goals::Invalid());
|
||||
return sptr(Goals::Invalid());
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
@ -2545,7 +2573,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
|
||||
for (int i = 1; i < radius; i++)
|
||||
{
|
||||
getVisibleNeighbours(tiles[i-1], tiles[i]);
|
||||
removeDuplicates(tiles[i]);
|
||||
vstd::removeDuplicates(tiles[i]);
|
||||
|
||||
for(const int3 &tile : tiles[i])
|
||||
{
|
||||
@ -2575,7 +2603,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
|
||||
{
|
||||
auto sm = getCachedSectorMap(h);
|
||||
int radius = h->getSightRadious();
|
||||
|
||||
|
||||
std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow]
|
||||
tiles.resize(radius);
|
||||
|
||||
@ -2590,10 +2618,10 @@ int3 VCAI::explorationDesperate(HeroPtr h)
|
||||
ui64 lowestDanger = -1;
|
||||
int3 bestTile(-1,-1,-1);
|
||||
|
||||
for (int i = 1; i < radius; i++)
|
||||
for(int i = 1; i < radius; i++)
|
||||
{
|
||||
getVisibleNeighbours(tiles[i-1], tiles[i]);
|
||||
removeDuplicates(tiles[i]);
|
||||
vstd::removeDuplicates(tiles[i]);
|
||||
|
||||
for(const int3 &tile : tiles[i])
|
||||
{
|
||||
@ -2705,37 +2733,26 @@ void VCAI::finish()
|
||||
|
||||
void VCAI::requestActionASAP(std::function<void()> whatToDo)
|
||||
{
|
||||
boost::mutex mutex;
|
||||
mutex.lock();
|
||||
|
||||
boost::thread newThread([&mutex,this,whatToDo]()
|
||||
boost::thread newThread([this,whatToDo]()
|
||||
{
|
||||
setThreadName("VCAI::requestActionASAP::helper");
|
||||
setThreadName("VCAI::requestActionASAP::whatToDo");
|
||||
SET_GLOBAL_STATE(this);
|
||||
boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
|
||||
// unlock mutex and allow parent function to exit
|
||||
mutex.unlock();
|
||||
whatToDo();
|
||||
});
|
||||
|
||||
// wait for mutex to unlock and for thread to initialize properly
|
||||
mutex.lock();
|
||||
|
||||
// unlock mutex - boost dislikes destruction of locked mutexes
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void VCAI::lostHero(HeroPtr h)
|
||||
{
|
||||
logAi->debugStream() << boost::format("I lost my hero %s. It's best to forget and move on.") % h.name;
|
||||
|
||||
erase_if_present(lockedHeroes, h);
|
||||
vstd::erase_if_present(lockedHeroes, h);
|
||||
for(auto obj : reservedHeroesMap[h])
|
||||
{
|
||||
erase_if_present(reservedObjs, obj); //unreserve all objects for that hero
|
||||
vstd::erase_if_present(reservedObjs, obj); //unreserve all objects for that hero
|
||||
}
|
||||
erase_if_present(reservedHeroesMap, h);
|
||||
erase_if_present(cachedSectorMaps, h);
|
||||
vstd::erase_if_present(reservedHeroesMap, h);
|
||||
vstd::erase_if_present(cachedSectorMaps, h);
|
||||
}
|
||||
|
||||
void VCAI::answerQuery(QueryID queryID, int selection)
|
||||
@ -2776,15 +2793,15 @@ void VCAI::validateObject(const CGObjectInstance *obj)
|
||||
|
||||
void VCAI::validateObject(ObjectIdRef obj)
|
||||
{
|
||||
auto matchesId = [&] (const CGObjectInstance *hlpObj) -> bool { return hlpObj->id == obj.id; };
|
||||
auto matchesId = [&](const CGObjectInstance *hlpObj) -> bool { return hlpObj->id == obj.id; };
|
||||
if(!obj)
|
||||
{
|
||||
erase_if(visitableObjs, matchesId);
|
||||
vstd::erase_if(visitableObjs, matchesId);
|
||||
|
||||
for(auto &p : reservedHeroesMap)
|
||||
erase_if(p.second, matchesId);
|
||||
vstd::erase_if(p.second, matchesId);
|
||||
|
||||
erase_if(reservedObjs, matchesId);
|
||||
vstd::erase_if(reservedObjs, matchesId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2933,8 +2950,8 @@ void AIStatus::heroVisit(const CGObjectInstance *obj, bool started)
|
||||
objectsBeingVisited.push_back(obj);
|
||||
else
|
||||
{
|
||||
// There can be more than one object visited at the time (eg. hero visits Subterranean Gate
|
||||
// causing visit to hero on the other side.
|
||||
// There can be more than one object visited at the time (eg. hero visits Subterranean Gate
|
||||
// causing visit to hero on the other side.
|
||||
// However, we are guaranteed that start/end visit notification maintain stack order.
|
||||
assert(!objectsBeingVisited.empty());
|
||||
objectsBeingVisited.pop_back();
|
||||
@ -3048,7 +3065,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp)
|
||||
s.embarkmentPoints.push_back(neighPos);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(t->visitable)
|
||||
{
|
||||
auto obj = t->visitableObjects.front();
|
||||
@ -3062,7 +3079,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp)
|
||||
}
|
||||
}
|
||||
|
||||
removeDuplicates(s.embarkmentPoints);
|
||||
vstd::removeDuplicates(s.embarkmentPoints);
|
||||
}
|
||||
|
||||
void SectorMap::write(crstring fname)
|
||||
@ -3104,7 +3121,7 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj)
|
||||
bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
{
|
||||
switch (obj->ID)
|
||||
{
|
||||
{
|
||||
case Obj::TOWN:
|
||||
case Obj::HERO: //never visit our heroes at random
|
||||
return obj->tempOwner != h->tempOwner; //do not visit our towns at random
|
||||
@ -3155,7 +3172,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
return canRecruitCreatures;
|
||||
}
|
||||
case Obj::HILL_FORT:
|
||||
{
|
||||
{
|
||||
for (auto slot : h->Slots())
|
||||
{
|
||||
if (slot.second->type->upgrades.size())
|
||||
@ -3241,21 +3258,6 @@ For ship construction etc, another function (goal?) is needed
|
||||
sectorQueue.push(neigh);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto gate : s->subterraneanGates)
|
||||
{
|
||||
auto gatePair = ai->knownSubterraneanGates.find(gate);
|
||||
if (gatePair != ai->knownSubterraneanGates.end())
|
||||
{
|
||||
//check the other side of gate
|
||||
Sector *neigh = &infoOnSectors[retreiveTile(gatePair->second->visitablePos())];
|
||||
if(!preds[neigh]) //if we didn't come into this sector yet
|
||||
{
|
||||
preds[neigh] = s; //it becomes our new target sector
|
||||
sectorQueue.push(neigh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!preds[dest])
|
||||
@ -3361,30 +3363,8 @@ For ship construction etc, another function (goal?) is needed
|
||||
//disembark
|
||||
return ret;
|
||||
}
|
||||
else //use subterranean gates
|
||||
else //use subterranean gates - not needed since gates are now handled via Pathfinder
|
||||
{
|
||||
//auto t = findFirstVisitableTile (h, dst);
|
||||
//if (t.valid())
|
||||
// return t;
|
||||
|
||||
//TODO: pop sectors linked by Subterranean Gate in loop
|
||||
|
||||
auto firstGate = boost::find_if(src->subterraneanGates, [=](const CGObjectInstance * gate) -> bool
|
||||
{
|
||||
//make sure no hero block the way
|
||||
auto pos = ai->knownSubterraneanGates[gate]->visitablePos();
|
||||
const TerrainTile *t = getTile(pos);
|
||||
return t && t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::SUBTERRANEAN_GATE
|
||||
&& retreiveTile(pos) == sectorToReach->id;
|
||||
});
|
||||
|
||||
if(firstGate != src->subterraneanGates.end())
|
||||
{
|
||||
//TODO: pahtfinder can find path through subterranean gates, but this function only reaches closest gate
|
||||
return (*firstGate)->visitablePos();
|
||||
}
|
||||
//TODO
|
||||
//Monolith? Whirlpool? ...
|
||||
return ret;
|
||||
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
|
||||
}
|
||||
@ -3455,7 +3435,7 @@ void SectorMap::makeParentBFS(crint3 source)
|
||||
ui8 &sec = retreiveTile(curPos);
|
||||
assert(sec == mySector); //consider only tiles from the same sector
|
||||
UNUSED(sec);
|
||||
|
||||
|
||||
foreach_neighbour(curPos, [&](crint3 neighPos)
|
||||
{
|
||||
if(retreiveTile(neighPos) == mySector && !vstd::contains(parent, neighPos))
|
||||
|
@ -93,7 +93,7 @@ struct SectorMap
|
||||
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
|
||||
|
||||
std::map<int, Sector> infoOnSectors;
|
||||
shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
|
||||
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
|
||||
|
||||
SectorMap();
|
||||
SectorMap(HeroPtr h);
|
||||
@ -129,7 +129,7 @@ public:
|
||||
|
||||
friend class FuzzyHelper;
|
||||
|
||||
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
|
||||
ObjectInstanceID destinationTeleport;
|
||||
int3 destinationTeleportPos;
|
||||
@ -153,9 +153,9 @@ public:
|
||||
AIStatus status;
|
||||
std::string battlename;
|
||||
|
||||
shared_ptr<CCallback> myCb;
|
||||
std::shared_ptr<CCallback> myCb;
|
||||
|
||||
unique_ptr<boost::thread> makingTurn;
|
||||
std::unique_ptr<boost::thread> makingTurn;
|
||||
|
||||
VCAI(void);
|
||||
~VCAI(void);
|
||||
@ -180,7 +180,7 @@ public:
|
||||
|
||||
virtual std::string getBattleAIName() const override;
|
||||
|
||||
virtual void init(shared_ptr<CCallback> CB) override;
|
||||
virtual void init(std::shared_ptr<CCallback> CB) override;
|
||||
virtual void yourTurn() override;
|
||||
|
||||
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||
|
@ -23,7 +23,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
|
||||
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
|
||||
}
|
||||
|
||||
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
|
||||
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
|
||||
{
|
||||
out = make_shared<VCAI>();
|
||||
out = std::make_shared<VCAI>();
|
||||
}
|
||||
|
2
AUTHORS
2
AUTHORS
@ -52,5 +52,5 @@ Alexey aka Macron1Robot, <>
|
||||
Alexander Shishkin aka alexvins,
|
||||
* MinGW platform support, modding related programming
|
||||
|
||||
Arseniy Shestakov aka SXX,
|
||||
Arseniy Shestakov aka SXX, <me@arseniyshestakov.com>
|
||||
* pathfinding improvements, programming
|
||||
|
@ -333,22 +333,22 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
|
||||
return swapCreatures(s1, s2, p1, p2);
|
||||
}
|
||||
|
||||
void CCallback::registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
void CCallback::registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
{
|
||||
cl->additionalPlayerInts[*player].push_back(gameEvents);
|
||||
}
|
||||
|
||||
void CCallback::registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
void CCallback::registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
{
|
||||
cl->additionalBattleInts[*player].push_back(battleEvents);
|
||||
}
|
||||
|
||||
void CCallback::unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
void CCallback::unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
|
||||
{
|
||||
cl->additionalPlayerInts[*player] -= gameEvents;
|
||||
}
|
||||
|
||||
void CCallback::unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
|
||||
{
|
||||
cl->additionalBattleInts[*player] -= battleEvents;
|
||||
}
|
||||
|
@ -110,10 +110,10 @@ public:
|
||||
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out);
|
||||
|
||||
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
|
||||
void registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
void unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
|
||||
void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
|
||||
|
||||
void unregisterAllInterfaces(); //stops delivering information about game events to player interfaces -> can be called ONLY after victory/loss
|
||||
|
||||
|
@ -64,7 +64,7 @@ endif()
|
||||
if (WIN32)
|
||||
add_definitions(-DBOOST_THREAD_USE_LIB)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock dbghelp)
|
||||
|
||||
#delete lib prefix for dlls (libvcmi -> vcmi)
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
|
4
Global.h
4
Global.h
@ -93,6 +93,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#ifdef VCMI_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - delete this line if something is missing.
|
||||
# define NOMINMAX // Exclude min/max macros from <Windows.h>. Use std::[min/max] from <algorithm> instead.
|
||||
# define _NO_W32_PSEUDO_MODIFIERS // Exclude more macros for compiling with MinGW on Linux.
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
@ -179,9 +180,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* Usings */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using std::make_shared;
|
||||
using namespace std::placeholders;
|
||||
namespace range = boost::range;
|
||||
|
||||
|
@ -170,9 +170,9 @@ static void prog_version(void)
|
||||
static void prog_help(const po::options_description &opts)
|
||||
{
|
||||
printf("%s - A Heroes of Might and Magic 3 clone\n", GameConstants::VCMI_VERSION.c_str());
|
||||
printf("Copyright (C) 2007-2014 VCMI dev team - see AUTHORS file\n");
|
||||
printf("This is free software; see the source for copying conditions. There is NO\n");
|
||||
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
|
||||
printf("Copyright (C) 2007-2016 VCMI dev team - see AUTHORS file\n");
|
||||
printf("This is free software; see the source for copying conditions. There is NO\n");
|
||||
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
|
||||
printf("\n");
|
||||
printf("Usage:\n");
|
||||
std::cout << opts;
|
||||
@ -244,7 +244,9 @@ int main(int argc, char** argv)
|
||||
("loadhumanplayerindices",po::value<std::vector<int>>(),"Indexes of human players (0=Red, etc.)")
|
||||
("loadplayer", po::value<int>(),"specifies which player we are in multiplayer loaded games (0=Red, etc.)")
|
||||
("loadserverip",po::value<std::string>(),"IP for loaded game server")
|
||||
("loadserverport",po::value<std::string>(),"port for loaded game server");
|
||||
("loadserverport",po::value<std::string>(),"port for loaded game server")
|
||||
("testingport",po::value<std::string>(),"port for testing, override specified in config file")
|
||||
("testingfileprefix",po::value<std::string>(),"prefix for auto save files");
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
@ -281,7 +283,7 @@ int main(int argc, char** argv)
|
||||
// it may result in very small \ very fast mouse when game in fullscreen mode
|
||||
putenv((char*)"SDL_VIDEO_X11_DGAMOUSE=0");
|
||||
|
||||
// Init old logging system and new (temporary) logging system
|
||||
// Init old logging system and new (temporary) logging system
|
||||
CStopWatch total, pomtime;
|
||||
std::cout.flags(std::ios::unitbuf);
|
||||
console = new CConsoleHandler;
|
||||
@ -291,16 +293,25 @@ int main(int argc, char** argv)
|
||||
|
||||
const bfs::path logPath = VCMIDirs::get().userCachePath() / "VCMI_Client_log.txt";
|
||||
CBasicLogConfigurator logConfig(logPath, console);
|
||||
logConfig.configureDefault();
|
||||
logConfig.configureDefault();
|
||||
logGlobal->infoStream() << "Creating console and configuring logger: " << pomtime.getDiff();
|
||||
logGlobal->infoStream() << "The log file will be saved to " << logPath;
|
||||
|
||||
// Init filesystem and settings
|
||||
// Init filesystem and settings
|
||||
preinitDLL(::console);
|
||||
settings.init();
|
||||
settings.init();
|
||||
|
||||
// Initialize logging based on settings
|
||||
logConfig.configure();
|
||||
// Init special testing settings
|
||||
Settings testingSettings = settings.write["testing"];
|
||||
if(vm.count("testingport") && vm.count("testingfileprefix"))
|
||||
{
|
||||
testingSettings["enabled"].Bool() = true;
|
||||
testingSettings["port"].String() = vm["testingport"].as<std::string>();
|
||||
testingSettings["prefix"].String() = vm["testingfileprefix"].as<std::string>();
|
||||
}
|
||||
|
||||
// Initialize logging based on settings
|
||||
logConfig.configure();
|
||||
|
||||
// Some basic data validation to produce better error messages in cases of incorrect install
|
||||
auto testFile = [](std::string filename, std::string message) -> bool
|
||||
@ -308,13 +319,15 @@ int main(int argc, char** argv)
|
||||
if (CResourceHandler::get()->existsResource(ResourceID(filename)))
|
||||
return true;
|
||||
|
||||
logGlobal->errorStream() << "Error: " << message << " was not found!";
|
||||
logGlobal->errorStream() << "Error: " << message << " was not found!";
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!testFile("DATA/HELP.TXT", "Heroes III data") ||
|
||||
!testFile("MODS/VCMI/MOD.JSON", "VCMI data"))
|
||||
!testFile("MODS/VCMI/MOD.JSON", "VCMI data"))
|
||||
{
|
||||
exit(1); // These are unrecoverable errors
|
||||
}
|
||||
|
||||
// these two are optional + some installs have them on CD and not in data directory
|
||||
testFile("VIDEO/GOOD1A.SMK", "campaign movies");
|
||||
|
@ -349,7 +349,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
|
||||
queueNext(this, "", selectedEntry->second, loop);
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(unique_ptr<MusicEntry> queued)
|
||||
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
{
|
||||
if (!initialized)
|
||||
return;
|
||||
|
@ -114,11 +114,11 @@ private:
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
|
||||
unique_ptr<MusicEntry> current;
|
||||
unique_ptr<MusicEntry> next;
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
|
||||
void queueNext(unique_ptr<MusicEntry> queued);
|
||||
void queueNext(std::unique_ptr<MusicEntry> queued);
|
||||
|
||||
std::map<std::string, std::map<int, std::string> > musicsSet;
|
||||
public:
|
||||
|
@ -133,7 +133,7 @@ CPlayerInterface::~CPlayerInterface()
|
||||
if(LOCPLINT == this)
|
||||
LOCPLINT = nullptr;
|
||||
}
|
||||
void CPlayerInterface::init(shared_ptr<CCallback> CB)
|
||||
void CPlayerInterface::init(std::shared_ptr<CCallback> CB)
|
||||
{
|
||||
cb = CB;
|
||||
if(observerInDuelMode)
|
||||
@ -157,24 +157,30 @@ void CPlayerInterface::yourTurn()
|
||||
GH.curInt = this;
|
||||
adventureInt->selection = nullptr;
|
||||
|
||||
std::string prefix = "";
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
{
|
||||
prefix = settings["testing"]["prefix"].String();
|
||||
}
|
||||
|
||||
if(firstCall)
|
||||
{
|
||||
if(howManyPeople == 1)
|
||||
adventureInt->setPlayer(playerID);
|
||||
|
||||
autosaveCount = getLastIndex("Autosave_");
|
||||
autosaveCount = getLastIndex(prefix + "Autosave_");
|
||||
|
||||
if(firstCall > 0) //new game, not loaded
|
||||
{
|
||||
int index = getLastIndex("Newgame_Autosave_");
|
||||
int index = getLastIndex(prefix + "Newgame_");
|
||||
index %= SAVES_COUNT;
|
||||
cb->save("Saves/Newgame_Autosave_" + boost::lexical_cast<std::string>(index + 1));
|
||||
cb->save("Saves/" + prefix + "Newgame_Autosave_" + boost::lexical_cast<std::string>(index + 1));
|
||||
}
|
||||
firstCall = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOCPLINT->cb->save("Saves/Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1));
|
||||
LOCPLINT->cb->save("Saves/" + prefix + "Autosave_" + boost::lexical_cast<std::string>(autosaveCount++ + 1));
|
||||
autosaveCount %= 5;
|
||||
}
|
||||
|
||||
@ -2242,8 +2248,10 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
|
||||
|
||||
void CPlayerInterface::acceptTurn()
|
||||
{
|
||||
bool centerView = true;
|
||||
if(settings["session"]["autoSkip"].Bool())
|
||||
{
|
||||
centerView = false;
|
||||
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt()))
|
||||
iw->close();
|
||||
}
|
||||
@ -2270,10 +2278,10 @@ void CPlayerInterface::acceptTurn()
|
||||
//select first hero if available.
|
||||
if(heroToSelect != nullptr)
|
||||
{
|
||||
adventureInt->select(heroToSelect);
|
||||
adventureInt->select(heroToSelect, centerView);
|
||||
}
|
||||
else
|
||||
adventureInt->select(towns.front());
|
||||
adventureInt->select(towns.front(), centerView);
|
||||
|
||||
//show new day animation and sound on infobar
|
||||
adventureInt->infoBar.showDate();
|
||||
@ -2629,6 +2637,31 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
return cb->getTile(CGHeroInstance::convertPosition(coord,false))->topVisitableObj(ignoreHero);
|
||||
};
|
||||
|
||||
auto isTeleportAction = [&](CGPathNode::ENodeAction action) -> bool
|
||||
{
|
||||
if(action != CGPathNode::TELEPORT_NORMAL &&
|
||||
action != CGPathNode::TELEPORT_BLOCKING_VISIT &&
|
||||
action != CGPathNode::TELEPORT_BATTLE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
auto getDestTeleportObj = [&](const CGObjectInstance * currentObject, const CGObjectInstance * nextObjectTop, const CGObjectInstance * nextObject) -> const CGObjectInstance *
|
||||
{
|
||||
if(CGTeleport::isConnected(currentObject, nextObjectTop))
|
||||
return nextObjectTop;
|
||||
if(nextObjectTop && nextObjectTop->ID == Obj::HERO &&
|
||||
CGTeleport::isConnected(currentObject, nextObject))
|
||||
{
|
||||
return nextObject;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
boost::unique_lock<boost::mutex> un(stillMoveHero.mx);
|
||||
stillMoveHero.data = CONTINUE_MOVE;
|
||||
auto doMovement = [&](int3 dst, bool transit)
|
||||
@ -2661,13 +2694,21 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
int3 currentCoord = path.nodes[i].coord;
|
||||
int3 nextCoord = path.nodes[i-1].coord;
|
||||
|
||||
auto nextObject = getObj(nextCoord, nextCoord == h->pos);
|
||||
if(CGTeleport::isConnected(getObj(currentCoord, currentCoord == h->pos), nextObject))
|
||||
auto currentObject = getObj(currentCoord, currentCoord == h->pos);
|
||||
auto nextObjectTop = getObj(nextCoord, false);
|
||||
auto nextObject = getObj(nextCoord, true);
|
||||
auto destTeleportObj = getDestTeleportObj(currentObject, nextObjectTop, nextObject);
|
||||
if(isTeleportAction(path.nodes[i-1].action) && destTeleportObj != nullptr)
|
||||
{
|
||||
CCS->soundh->stopSound(sh);
|
||||
destinationTeleport = nextObject->id;
|
||||
destinationTeleport = destTeleportObj->id;
|
||||
destinationTeleportPos = nextCoord;
|
||||
doMovement(h->pos, false);
|
||||
if(path.nodes[i-1].action == CGPathNode::TELEPORT_BLOCKING_VISIT)
|
||||
{
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
}
|
||||
sh = CCS->soundh->playSound(CCS->soundh->horseSounds[currentTerrain], -1);
|
||||
continue;
|
||||
}
|
||||
@ -2700,8 +2741,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
|
||||
bool useTransit = false;
|
||||
if((i-2 >= 0) // Check there is node after next one; otherwise transit is pointless
|
||||
&& (CGTeleport::isConnected(nextObject, getObj(path.nodes[i-2].coord, false))
|
||||
|| CGTeleport::isTeleport(nextObject)))
|
||||
&& (CGTeleport::isConnected(nextObjectTop, getObj(path.nodes[i-2].coord, false))
|
||||
|| CGTeleport::isTeleport(nextObjectTop)))
|
||||
{ // Hero should be able to go through object if it's allow transit
|
||||
useTransit = true;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
static CBattleInterface * battleInt; //nullptr if no battle
|
||||
CInGameConsole * cingconsole;
|
||||
|
||||
shared_ptr<CCallback> cb; //to communicate with engine
|
||||
std::shared_ptr<CCallback> cb; //to communicate with engine
|
||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
|
||||
|
||||
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||
@ -116,7 +116,7 @@ public:
|
||||
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
|
||||
|
||||
//During battle is quick combat mode is used
|
||||
shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||
std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
|
||||
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
|
||||
|
||||
const CArmedInstance * getSelection();
|
||||
@ -236,7 +236,7 @@ public:
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||
void updateInfo(const CGObjectInstance * specific);
|
||||
void init(shared_ptr<CCallback> CB) override;
|
||||
void init(std::shared_ptr<CCallback> CB) override;
|
||||
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
||||
|
||||
// show dialogs
|
||||
|
@ -1918,7 +1918,7 @@ const CMapGenOptions & CRandomMapTab::getMapGenOptions() const
|
||||
return mapGenOptions;
|
||||
}
|
||||
|
||||
void CRandomMapTab::setMapGenOptions(shared_ptr<CMapGenOptions> opts)
|
||||
void CRandomMapTab::setMapGenOptions(std::shared_ptr<CMapGenOptions> opts)
|
||||
{
|
||||
mapSizeBtnGroup->setSelected(vstd::find_pos(getPossibleMapSizes(), opts->getWidth()));
|
||||
twoLevelsBtn->setSelected(opts->getHasTwoLevels());
|
||||
@ -3291,14 +3291,14 @@ void CBonusSelection::init()
|
||||
sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
|
||||
}
|
||||
|
||||
CBonusSelection::CBonusSelection(shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
|
||||
CBonusSelection::CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
CBonusSelection::CBonusSelection(const std::string & campaignFName)
|
||||
{
|
||||
ourCampaign = make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
|
||||
ourCampaign = std::make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ public:
|
||||
CFunctionList<void (const CMapInfo *)> & getMapInfoChanged();
|
||||
const CMapInfo * getMapInfo() const;
|
||||
const CMapGenOptions & getMapGenOptions() const;
|
||||
void setMapGenOptions(shared_ptr<CMapGenOptions> opts);
|
||||
void setMapGenOptions(std::shared_ptr<CMapGenOptions> opts);
|
||||
|
||||
private:
|
||||
void addButtonsToGroup(CToggleGroup * group, const std::vector<std::string> & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const;
|
||||
@ -316,7 +316,7 @@ private:
|
||||
* compOnlyTeamsCntGroup, * waterContentGroup, * monsterStrengthGroup;
|
||||
CButton * showRandMaps;
|
||||
CMapGenOptions mapGenOptions;
|
||||
unique_ptr<CMapInfo> mapInfo;
|
||||
std::unique_ptr<CMapInfo> mapInfo;
|
||||
CFunctionList<void(const CMapInfo *)> mapInfoChanged;
|
||||
};
|
||||
|
||||
@ -463,7 +463,7 @@ class CBonusSelection : public CIntObject
|
||||
{
|
||||
public:
|
||||
CBonusSelection(const std::string & campaignFName);
|
||||
CBonusSelection(shared_ptr<CCampaignState> _ourCampaign);
|
||||
CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign);
|
||||
~CBonusSelection();
|
||||
|
||||
void showAll(SDL_Surface * to) override;
|
||||
@ -532,7 +532,7 @@ private:
|
||||
CDefHandler * sFlags;
|
||||
|
||||
// Data
|
||||
shared_ptr<CCampaignState> ourCampaign;
|
||||
std::shared_ptr<CCampaignState> ourCampaign;
|
||||
int selectedMap;
|
||||
boost::optional<int> selectedBonus;
|
||||
StartInfo startInfo;
|
||||
|
@ -246,18 +246,25 @@ void CClient::endGame( bool closeConnection /*= true*/ )
|
||||
#if 1
|
||||
void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port)
|
||||
{
|
||||
PlayerColor player(player_); //intentional shadowing
|
||||
PlayerColor player(player_); //intentional shadowing
|
||||
logNetwork->infoStream() << "Loading procedure started!";
|
||||
|
||||
logNetwork->infoStream() <<"Loading procedure started!";
|
||||
std::string realPort;
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
realPort = settings["testing"]["port"].String();
|
||||
else if(port.size())
|
||||
realPort = port;
|
||||
else
|
||||
realPort = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
|
||||
CServerHandler sh;
|
||||
if(server)
|
||||
sh.startServer();
|
||||
else
|
||||
serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
|
||||
if(server)
|
||||
sh.startServer();
|
||||
else
|
||||
serv = sh.justConnectToServer(ipaddr, realPort);
|
||||
|
||||
CStopWatch tmh;
|
||||
unique_ptr<CLoadFile> loader;
|
||||
std::unique_ptr<CLoadFile> loader;
|
||||
try
|
||||
{
|
||||
std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
|
||||
@ -454,7 +461,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
else
|
||||
{
|
||||
installNewPlayerInterface(make_shared<CPlayerInterface>(color), color);
|
||||
installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
|
||||
humanPlayers++;
|
||||
}
|
||||
}
|
||||
@ -470,7 +477,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
if(!gNoGUI)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
auto p = make_shared<CPlayerInterface>(PlayerColor::NEUTRAL);
|
||||
auto p = std::make_shared<CPlayerInterface>(PlayerColor::NEUTRAL);
|
||||
p->observerInDuelMode = true;
|
||||
installNewPlayerInterface(p, boost::none);
|
||||
GH.curInt = p.get();
|
||||
@ -535,7 +542,7 @@ void CClient::serialize(CISer & h, const int version)
|
||||
h & pid & dllname & isHuman;
|
||||
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
||||
|
||||
shared_ptr<CGameInterface> nInt;
|
||||
std::shared_ptr<CGameInterface> nInt;
|
||||
if(dllname.length())
|
||||
{
|
||||
if(pid == PlayerColor::NEUTRAL)
|
||||
@ -553,7 +560,7 @@ void CClient::serialize(CISer & h, const int version)
|
||||
else
|
||||
{
|
||||
assert(isHuman);
|
||||
nInt = make_shared<CPlayerInterface>(pid);
|
||||
nInt = std::make_shared<CPlayerInterface>(pid);
|
||||
}
|
||||
|
||||
nInt->dllName = dllname;
|
||||
@ -604,7 +611,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
|
||||
h & pid & dllname & isHuman;
|
||||
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
|
||||
|
||||
shared_ptr<CGameInterface> nInt;
|
||||
std::shared_ptr<CGameInterface> nInt;
|
||||
if(dllname.length())
|
||||
{
|
||||
if(pid == PlayerColor::NEUTRAL)
|
||||
@ -623,7 +630,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
|
||||
else
|
||||
{
|
||||
assert(isHuman);
|
||||
nInt = make_shared<CPlayerInterface>(pid);
|
||||
nInt = std::make_shared<CPlayerInterface>(pid);
|
||||
}
|
||||
|
||||
nInt->dllName = dllname;
|
||||
@ -661,11 +668,11 @@ void CClient::handlePack( CPack * pack )
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void CClient::finishCampaign( shared_ptr<CCampaignState> camp )
|
||||
void CClient::finishCampaign( std::shared_ptr<CCampaignState> camp )
|
||||
{
|
||||
}
|
||||
|
||||
void CClient::proposeNextMission(shared_ptr<CCampaignState> camp)
|
||||
void CClient::proposeNextMission(std::shared_ptr<CCampaignState> camp)
|
||||
{
|
||||
GH.pushInt(new CBonusSelection(camp));
|
||||
}
|
||||
@ -717,7 +724,7 @@ void CClient::battleStarted(const BattleInfo * info)
|
||||
// if(battleCallbacks.count(side))
|
||||
// battleCallbacks[side]->setBattle(info);
|
||||
|
||||
shared_ptr<CPlayerInterface> att, def;
|
||||
std::shared_ptr<CPlayerInterface> att, def;
|
||||
auto &leftSide = info->sides[0], &rightSide = info->sides[1];
|
||||
|
||||
|
||||
@ -783,7 +790,7 @@ PlayerColor CClient::getLocalPlayer() const
|
||||
return getCurrentPlayer();
|
||||
}
|
||||
|
||||
void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt)
|
||||
void CClient::commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> battleInt)
|
||||
{
|
||||
setThreadName("CClient::commenceTacticPhaseForInt");
|
||||
try
|
||||
@ -835,7 +842,7 @@ int CClient::sendRequest(const CPack *request, PlayerColor player)
|
||||
return requestID;
|
||||
}
|
||||
|
||||
void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
|
||||
void CClient::campaignMapFinished( std::shared_ptr<CCampaignState> camp )
|
||||
{
|
||||
endGame(false);
|
||||
|
||||
@ -858,7 +865,7 @@ void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
|
||||
}
|
||||
}
|
||||
|
||||
void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color)
|
||||
void CClient::installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||
@ -869,7 +876,7 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
|
||||
playerint[colorUsed] = gameInterface;
|
||||
|
||||
logGlobal->traceStream() << boost::format("\tInitializing the interface for player %s") % colorUsed;
|
||||
auto cb = make_shared<CCallback>(gs, color, this);
|
||||
auto cb = std::make_shared<CCallback>(gs, color, this);
|
||||
callbacks[colorUsed] = cb;
|
||||
battleCallbacks[colorUsed] = cb;
|
||||
gameInterface->init(cb);
|
||||
@ -877,7 +884,7 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
|
||||
installNewBattleInterface(gameInterface, color, false);
|
||||
}
|
||||
|
||||
void CClient::installNewBattleInterface(shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
|
||||
void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||
@ -890,7 +897,7 @@ void CClient::installNewBattleInterface(shared_ptr<CBattleGameInterface> battleI
|
||||
if(needCallback)
|
||||
{
|
||||
logGlobal->traceStream() << boost::format("\tInitializing the battle interface for player %s") % *color;
|
||||
auto cbc = make_shared<CBattleCallback>(gs, color, this);
|
||||
auto cbc = std::make_shared<CBattleCallback>(gs, color, this);
|
||||
battleCallbacks[colorUsed] = cbc;
|
||||
battleInterface->init(cbc);
|
||||
}
|
||||
@ -967,7 +974,10 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
|
||||
{
|
||||
serverThread = nullptr;
|
||||
shared = nullptr;
|
||||
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
port = settings["testing"]["port"].String();
|
||||
else
|
||||
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
verbose = true;
|
||||
|
||||
#ifndef VCMI_ANDROID
|
||||
@ -1009,6 +1019,14 @@ void CServerHandler::callServer()
|
||||
|
||||
CConnection * CServerHandler::justConnectToServer(const std::string &host, const std::string &port)
|
||||
{
|
||||
std::string realPort;
|
||||
if(settings["testing"]["enabled"].Bool())
|
||||
realPort = settings["testing"]["port"].String();
|
||||
else if(port.size())
|
||||
realPort = port;
|
||||
else
|
||||
realPort = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
|
||||
|
||||
CConnection *ret = nullptr;
|
||||
while(!ret)
|
||||
{
|
||||
@ -1016,7 +1034,7 @@ CConnection * CServerHandler::justConnectToServer(const std::string &host, const
|
||||
{
|
||||
logNetwork->infoStream() << "Establishing connection...";
|
||||
ret = new CConnection( host.size() ? host : settings["server"]["server"].String(),
|
||||
port.size() ? port : boost::lexical_cast<std::string>(settings["server"]["port"].Float()),
|
||||
realPort,
|
||||
NAME);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -115,17 +115,17 @@ public:
|
||||
/// Class which handles client - server logic
|
||||
class CClient : public IGameCallback
|
||||
{
|
||||
unique_ptr<CPathsInfo> pathInfo;
|
||||
std::unique_ptr<CPathsInfo> pathInfo;
|
||||
public:
|
||||
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||
std::vector<shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
std::vector<shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||
std::map<PlayerColor, shared_ptr<CGameInterface>> playerint;
|
||||
std::map<PlayerColor, shared_ptr<CBattleGameInterface>> battleints;
|
||||
std::map<PlayerColor,std::shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<PlayerColor,std::shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||
std::vector<std::shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
std::vector<std::shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
|
||||
std::map<PlayerColor, std::shared_ptr<CGameInterface>> playerint;
|
||||
std::map<PlayerColor, std::shared_ptr<CBattleGameInterface>> battleints;
|
||||
|
||||
std::map<PlayerColor,std::vector<shared_ptr<IGameEventsReceiver>>> additionalPlayerInts;
|
||||
std::map<PlayerColor,std::vector<shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
|
||||
std::map<PlayerColor,std::vector<std::shared_ptr<IGameEventsReceiver>>> additionalPlayerInts;
|
||||
std::map<PlayerColor,std::vector<std::shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
|
||||
|
||||
bool hotSeat;
|
||||
CConnection *serv;
|
||||
@ -146,8 +146,8 @@ public:
|
||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||
|
||||
void loadNeutralBattleAI();
|
||||
void installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
|
||||
void installNewBattleInterface(shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
||||
void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
|
||||
void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
||||
std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human
|
||||
|
||||
void endGame(bool closeConnection = true);
|
||||
@ -155,9 +155,9 @@ public:
|
||||
void save(const std::string & fname);
|
||||
void loadGame(const std::string & fname, const bool server = true, const std::vector<int>& humanplayerindices = std::vector<int>(), const int loadnumplayers = 1, int player_ = -1, const std::string & ipaddr = "", const std::string & port = "");
|
||||
void run();
|
||||
void campaignMapFinished( shared_ptr<CCampaignState> camp );
|
||||
void finishCampaign( shared_ptr<CCampaignState> camp );
|
||||
void proposeNextMission(shared_ptr<CCampaignState> camp);
|
||||
void campaignMapFinished( std::shared_ptr<CCampaignState> camp );
|
||||
void finishCampaign( std::shared_ptr<CCampaignState> camp );
|
||||
void proposeNextMission(std::shared_ptr<CCampaignState> camp);
|
||||
|
||||
void invalidatePaths();
|
||||
const CPathsInfo * getPathsInfo(const CGHeroInstance *h);
|
||||
@ -233,7 +233,7 @@ public:
|
||||
|
||||
void handlePack( CPack * pack ); //applies the given pack and deletes it
|
||||
void battleStarted(const BattleInfo * info);
|
||||
void commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt); //will be called as separate thread
|
||||
void commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> battleInt); //will be called as separate thread
|
||||
|
||||
void commitPackage(CPackForClient *pack) override;
|
||||
|
||||
|
@ -95,7 +95,7 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
|
||||
CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2,
|
||||
const CGHeroInstance *hero1, const CGHeroInstance *hero2,
|
||||
const SDL_Rect & myRect,
|
||||
shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen)
|
||||
std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen)
|
||||
: background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
|
||||
activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1),
|
||||
currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(nullptr), sp(nullptr),
|
||||
@ -3260,7 +3260,7 @@ void CBattleInterface::showStacks(SDL_Surface * to, std::vector<const CStack *>
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::showObstacles(SDL_Surface *to, std::vector<shared_ptr<const CObstacleInstance> > &obstacles)
|
||||
void CBattleInterface::showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance> > &obstacles)
|
||||
{
|
||||
for (auto & obstacle : obstacles)
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ struct BattleObjectsByHex
|
||||
typedef std::vector<int> TWallList;
|
||||
typedef std::vector<const CStack * > TStackList;
|
||||
typedef std::vector<const BattleEffect *> TEffectList;
|
||||
typedef std::vector<shared_ptr<const CObstacleInstance> > TObstacleList;
|
||||
typedef std::vector<std::shared_ptr<const CObstacleInstance> > TObstacleList;
|
||||
|
||||
struct HexData
|
||||
{
|
||||
@ -153,7 +153,7 @@ private:
|
||||
BattleHex currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
|
||||
int attackingHex; //hex from which the stack would perform attack with current cursor
|
||||
|
||||
shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
std::shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
|
||||
bool tacticsMode;
|
||||
bool stackCanCastSpell; //if true, active stack could possibly cast some target spell
|
||||
bool creatureCasting; //if true, stack currently aims to cats a spell
|
||||
@ -212,8 +212,8 @@ private:
|
||||
friend class CBattleInterface;
|
||||
} * siegeH;
|
||||
|
||||
shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
shared_ptr<CPlayerInterface> curInt; //current player interface
|
||||
std::shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
|
||||
std::shared_ptr<CPlayerInterface> curInt; //current player interface
|
||||
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
|
||||
|
||||
/** Methods for displaying battle screen */
|
||||
@ -229,7 +229,7 @@ private:
|
||||
|
||||
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
||||
void showStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
|
||||
void showObstacles(SDL_Surface *to, std::vector<shared_ptr<const CObstacleInstance> > &obstacles);
|
||||
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance> > &obstacles);
|
||||
void showPiecesOfWall(SDL_Surface * to, std::vector<int> pieces);
|
||||
|
||||
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
|
||||
@ -249,7 +249,7 @@ public:
|
||||
ui32 animIDhelper; //for giving IDs for animations
|
||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen); //c-tor
|
||||
~CBattleInterface(); //d-tor
|
||||
|
||||
//std::vector<TimeInterested*> timeinterested; //animation handling
|
||||
|
@ -66,7 +66,7 @@ private:
|
||||
|
||||
//animation raw data
|
||||
//TODO: use vector instead?
|
||||
unique_ptr<ui8[]> pixelData;
|
||||
std::unique_ptr<ui8[]> pixelData;
|
||||
size_t pixelDataSize;
|
||||
|
||||
// speed of animation, measure in frames per second
|
||||
|
@ -1576,7 +1576,7 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
|
||||
}
|
||||
}
|
||||
|
||||
if(t.hasFavourableWinds())
|
||||
if(t.hasFavorableWinds())
|
||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
||||
else if(terName)
|
||||
{
|
||||
|
@ -380,7 +380,16 @@ void MoraleLuckBox::set(const IBonusBearer *node)
|
||||
if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD)
|
||||
|| node->hasBonusOfType(Bonus::BLOCK_MORALE)
|
||||
|| node->hasBonusOfType(Bonus::NON_LIVING)))
|
||||
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
||||
{
|
||||
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
||||
bonusValue = 0;
|
||||
}
|
||||
else if(!morale && node && node->hasBonusOfType(Bonus::BLOCK_LUCK))
|
||||
{
|
||||
// TODO: there is no text like "Unaffected by luck" so probably we need own text
|
||||
text += CGI->generaltexth->arraytxt[noneTxtId];
|
||||
bonusValue = 0;
|
||||
}
|
||||
else if(modifierList->empty())
|
||||
text += CGI->generaltexth->arraytxt[noneTxtId];//no modifiers
|
||||
else
|
||||
|
@ -55,16 +55,15 @@
|
||||
*/
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
using namespace boost::logic;
|
||||
using namespace CSDL_Ext;
|
||||
|
||||
CAdvMapInt *adventureInt;
|
||||
|
||||
|
||||
CTerrainRect::CTerrainRect()
|
||||
: fadeSurface(nullptr),
|
||||
: fadeSurface(nullptr),
|
||||
fadeAnim(new CFadeAnimation()),
|
||||
curHoveredTile(-1,-1,-1),
|
||||
curHoveredTile(-1,-1,-1),
|
||||
currentPath(nullptr)
|
||||
{
|
||||
tilesw=(ADVOPT.advmapW+31)/32;
|
||||
@ -283,7 +282,7 @@ void CTerrainRect::show(SDL_Surface * to)
|
||||
info.heroAnim = adventureInt->heroAnim;
|
||||
if (ADVOPT.smoothMove)
|
||||
info.movement = int3(moveX, moveY, 0);
|
||||
|
||||
|
||||
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
|
||||
if (fadeAnim->isFading())
|
||||
{
|
||||
@ -316,7 +315,7 @@ void CTerrainRect::showAll(SDL_Surface * to)
|
||||
}
|
||||
|
||||
void CTerrainRect::showAnim(SDL_Surface * to)
|
||||
{
|
||||
{
|
||||
if (fadeAnim->isFading())
|
||||
show(to);
|
||||
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
|
||||
@ -357,7 +356,7 @@ void CTerrainRect::fadeFromCurrentView()
|
||||
return;
|
||||
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
|
||||
return;
|
||||
|
||||
|
||||
if (!fadeSurface)
|
||||
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
|
||||
SDL_BlitSurface(screen, &pos, fadeSurface, nullptr);
|
||||
@ -502,10 +501,10 @@ CAdvMapInt::CAdvMapInt():
|
||||
endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e);
|
||||
|
||||
int panelSpaceBottom = screen->h - resdatabar.pos.h - 4;
|
||||
|
||||
|
||||
panelMain = new CAdvMapPanel(nullptr, Point(0, 0));
|
||||
// TODO correct drawing position
|
||||
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
|
||||
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
|
||||
|
||||
panelMain->addChildColorableButton(kingOverview);
|
||||
panelMain->addChildColorableButton(underground);
|
||||
@ -593,7 +592,7 @@ CAdvMapInt::CAdvMapInt():
|
||||
Colors::WHITE, CGI->generaltexth->allTexts[618]));
|
||||
|
||||
activeMapPanel = panelMain;
|
||||
|
||||
|
||||
changeMode(EAdvMapMode::NORMAL);
|
||||
|
||||
underground->block(!CGI->mh->map->twoLevel);
|
||||
@ -767,6 +766,11 @@ void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
|
||||
moveHero->block(!hasPath || (h->movement == 0));
|
||||
}
|
||||
|
||||
void CAdvMapInt::updateSpellbook(const CGHeroInstance *h)
|
||||
{
|
||||
spellbook->block(!h);
|
||||
}
|
||||
|
||||
int CAdvMapInt::getNextHeroIndex(int startIndex)
|
||||
{
|
||||
if (LOCPLINT->wanderingHeroes.size() == 0)
|
||||
@ -966,7 +970,7 @@ void CAdvMapInt::show(SDL_Surface * to)
|
||||
for(int i=0;i<4;i++)
|
||||
blitAt(gems[i]->ourImages[LOCPLINT->playerID.getNum()].bitmap,ADVOPT.gemX[i],ADVOPT.gemY[i],to);
|
||||
}
|
||||
|
||||
|
||||
infoBar.show(to);
|
||||
statusbar.showAll(to);
|
||||
}
|
||||
@ -981,7 +985,7 @@ void CAdvMapInt::selectionChanged()
|
||||
void CAdvMapInt::centerOn(int3 on, bool fade /* = false */)
|
||||
{
|
||||
bool switchedLevels = on.z != position.z;
|
||||
|
||||
|
||||
if (fade)
|
||||
{
|
||||
terrain.fadeFromCurrentView();
|
||||
@ -1262,6 +1266,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
|
||||
|
||||
updateSleepWake(nullptr);
|
||||
updateMoveHero(nullptr);
|
||||
updateSpellbook(nullptr);
|
||||
}
|
||||
else //hero selected
|
||||
{
|
||||
@ -1275,6 +1280,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
|
||||
|
||||
updateSleepWake(hero);
|
||||
updateMoveHero(hero);
|
||||
updateSpellbook(hero);
|
||||
}
|
||||
townList.redraw();
|
||||
heroList.redraw();
|
||||
@ -1531,12 +1537,16 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
}
|
||||
else if(const CGHeroInstance * h = curHero())
|
||||
{
|
||||
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPos);
|
||||
int3 mapPosCopy = mapPos;
|
||||
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPosCopy);
|
||||
assert(pnode);
|
||||
|
||||
int turns = pnode->turns;
|
||||
vstd::amin(turns, 3);
|
||||
switch(pnode->action)
|
||||
{
|
||||
case CGPathNode::NORMAL:
|
||||
case CGPathNode::TELEPORT_NORMAL:
|
||||
if(pnode->layer == EPathfindingLayer::LAND)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
|
||||
else
|
||||
@ -1545,6 +1555,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
|
||||
case CGPathNode::VISIT:
|
||||
case CGPathNode::BLOCKING_VISIT:
|
||||
case CGPathNode::TELEPORT_BLOCKING_VISIT:
|
||||
if(objAtTile && objAtTile->ID == Obj::HERO)
|
||||
{
|
||||
if(selection == objAtTile)
|
||||
@ -1559,6 +1570,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
break;
|
||||
|
||||
case CGPathNode::BATTLE:
|
||||
case CGPathNode::TELEPORT_BATTLE:
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
break;
|
||||
|
||||
@ -1708,9 +1720,9 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale /* = 0.4f */)
|
||||
townList.activate();
|
||||
heroList.activate();
|
||||
infoBar.activate();
|
||||
|
||||
|
||||
worldViewOptions.clear();
|
||||
|
||||
|
||||
break;
|
||||
case EAdvMapMode::WORLD_VIEW:
|
||||
panelMain->deactivate();
|
||||
@ -1780,14 +1792,13 @@ CAdvMapInt::WorldViewOptions::WorldViewOptions()
|
||||
void CAdvMapInt::WorldViewOptions::clear()
|
||||
{
|
||||
showAllTerrain = false;
|
||||
|
||||
|
||||
iconPositions.clear();
|
||||
}
|
||||
|
||||
void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
|
||||
{
|
||||
info.showAllTerrain = showAllTerrain;
|
||||
|
||||
info.additionalIcons = &iconPositions;
|
||||
}
|
||||
|
||||
info.additionalIcons = &iconPositions;
|
||||
}
|
||||
|
@ -235,6 +235,7 @@ public:
|
||||
//button updates
|
||||
void updateSleepWake(const CGHeroInstance *h);
|
||||
void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate);
|
||||
void updateSpellbook(const CGHeroInstance *h);
|
||||
void updateNextHero(const CGHeroInstance *h);
|
||||
|
||||
/// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL
|
||||
|
@ -230,7 +230,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warnStream() << "Problem: dwelling with id " << bid << " offers no creatures!";
|
||||
logGlobal->warnStream() << "Problem: dwelling with id " << bid << " offers no creatures!";
|
||||
return "#ERROR#";
|
||||
}
|
||||
}
|
||||
@ -501,7 +501,10 @@ void CCastleBuildings::recreate()
|
||||
|
||||
if(vstd::contains(town->builtBuildings, BuildingID::SHIPYARD))
|
||||
{
|
||||
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(town->bestLocation());
|
||||
auto bayPos = town->bestLocation();
|
||||
if(!bayPos.valid())
|
||||
logGlobal->warnStream() << "Shipyard in non-coastal town!";
|
||||
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(bayPos, false);
|
||||
//there is visitable obj at shipyard output tile and it's a boat or hero (on boat)
|
||||
if(!vobjs.empty() && (vobjs.front()->ID == Obj::BOAT || vobjs.front()->ID == Obj::HERO))
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
|
||||
if (level != tile.z)
|
||||
setLevel(tile.z);
|
||||
|
||||
auto pic = make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
|
||||
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
|
||||
|
||||
pic->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
|
||||
pic->callback = std::bind (&CQuestMinimap::iconClicked, this);
|
||||
@ -179,7 +179,7 @@ void CQuestLog::recreateLabelList()
|
||||
else
|
||||
text.addReplacement(quests[i].obj->getObjectName()); //get name of the object
|
||||
}
|
||||
auto label = make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
|
||||
auto label = std::make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
|
||||
label->disable();
|
||||
|
||||
label->callback = std::bind(&CQuestLog::selectQuest, this, i, currentLabel);
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
|
||||
class CQuestMinimap : public CMinimap
|
||||
{
|
||||
std::vector <shared_ptr<CQuestIcon>> icons;
|
||||
std::vector <std::shared_ptr<CQuestIcon>> icons;
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface
|
||||
void iconClicked();
|
||||
@ -86,7 +86,7 @@ class CQuestLog : public CWindowObject
|
||||
CLabel * hideCompleteLabel;
|
||||
|
||||
const std::vector<QuestInfo> quests;
|
||||
std::vector <shared_ptr<CQuestLabel>> labels;
|
||||
std::vector <std::shared_ptr<CQuestLabel>> labels;
|
||||
CTextBox * description;
|
||||
CQuestMinimap * minimap;
|
||||
CSlider * slider; //scrolls quests
|
||||
|
@ -861,7 +861,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
||||
if(itemsType[1] == RESOURCE)
|
||||
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId));
|
||||
else if(itemsType[1] == CREATURE)
|
||||
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->Slots().size() == 1 && hero->needsLastStack());
|
||||
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack());
|
||||
else
|
||||
assert(0);
|
||||
|
||||
|
@ -704,7 +704,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
|
||||
oldSelected = -1;
|
||||
|
||||
new CLabel(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]);
|
||||
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, "2500");
|
||||
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(GameConstants::HERO_GOLD_COST));
|
||||
|
||||
auto rumorText = boost::str(boost::format(CGI->generaltexth->allTexts[216]) % LOCPLINT->cb->getTavernRumor(tavernObj));
|
||||
new CTextBox(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
|
||||
@ -714,7 +714,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
|
||||
recruit = new CButton(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN);
|
||||
thiefGuild = new CButton(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t);
|
||||
|
||||
if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < 2500) //not enough gold
|
||||
if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold
|
||||
{
|
||||
recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
|
||||
recruit->block(true);
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "BattleState.h"
|
||||
|
||||
/*
|
||||
* BattleAction.h, part of VCMI engine
|
||||
* BattleAction.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -201,9 +201,7 @@ void BattleInfo::localInitStack(CStack * s)
|
||||
|
||||
namespace CGH
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
static void readBattlePositions(const JsonNode &node, vector< vector<int> > & dest)
|
||||
static void readBattlePositions(const JsonNode &node, std::vector< std::vector<int> > & dest)
|
||||
{
|
||||
for(const JsonNode &level : node.Vector())
|
||||
{
|
||||
@ -375,7 +373,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
|
||||
try
|
||||
{
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
auto obstPtr = std::make_shared<CObstacleInstance>();
|
||||
obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
|
||||
obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
@ -424,7 +422,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
|
||||
RangeGenerator posgenerator(18, 168, ourRand);
|
||||
|
||||
auto obstPtr = make_shared<CObstacleInstance>();
|
||||
auto obstPtr = std::make_shared<CObstacleInstance>();
|
||||
obstPtr->ID = obid;
|
||||
obstPtr->pos = posgenerator.getSuchNumber(validPosition);
|
||||
obstPtr->uniqueID = curB->obstacles.size();
|
||||
@ -541,7 +539,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
}
|
||||
|
||||
//moat
|
||||
auto moat = make_shared<MoatObstacle>();
|
||||
auto moat = std::make_shared<MoatObstacle>();
|
||||
moat->ID = curB->town->subID;
|
||||
moat->obstacleType = CObstacleInstance::MOAT;
|
||||
moat->uniqueID = curB->obstacles.size();
|
||||
@ -586,19 +584,19 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
|
||||
case BFieldType::HOLY_GROUND:
|
||||
{
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(std::make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(std::make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
break;
|
||||
}
|
||||
case BFieldType::CLOVER_FIELD:
|
||||
{ //+2 luck bonus for neutral creatures
|
||||
curB->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, +2, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::NEUTRAL)));
|
||||
curB->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, +2, Bonus::TERRAIN_OVERLAY)->addLimiter(std::make_shared<CreatureAlignmentLimiter>(EAlignment::NEUTRAL)));
|
||||
break;
|
||||
}
|
||||
case BFieldType::EVIL_FOG:
|
||||
{
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)->addLimiter(std::make_shared<CreatureAlignmentLimiter>(EAlignment::GOOD)));
|
||||
curB->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, +1, Bonus::TERRAIN_OVERLAY)->addLimiter(std::make_shared<CreatureAlignmentLimiter>(EAlignment::EVIL)));
|
||||
break;
|
||||
}
|
||||
case BFieldType::CURSED_GROUND:
|
||||
@ -614,7 +612,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
|
||||
//overlay premies given
|
||||
|
||||
//native terrain bonuses
|
||||
auto nativeTerrain = make_shared<CreatureNativeTerrainLimiter>(curB->terrainType);
|
||||
auto nativeTerrain = std::make_shared<CreatureNativeTerrainLimiter>(curB->terrainType);
|
||||
curB->addNewBonus(makeFeature(Bonus::STACKS_SPEED, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::ATTACK, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
|
||||
@ -703,13 +701,13 @@ int BattleInfo::getIdForNewStack() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile) const
|
||||
std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile) const
|
||||
{
|
||||
for(auto &obs : obstacles)
|
||||
if(vstd::contains(obs->getAffectedTiles(), tile))
|
||||
return obs;
|
||||
|
||||
return shared_ptr<CObstacleInstance>();
|
||||
return std::shared_ptr<CObstacleInstance>();
|
||||
}
|
||||
|
||||
BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
|
||||
@ -719,7 +717,7 @@ BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldTy
|
||||
{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
|
||||
{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
|
||||
{BFieldType::EVIL_FOG, BattlefieldBI::EVIL_FOG},
|
||||
{BFieldType::FAVOURABLE_WINDS, BattlefieldBI::NONE},
|
||||
{BFieldType::FAVORABLE_WINDS, BattlefieldBI::NONE},
|
||||
{BFieldType::FIERY_FIELDS, BattlefieldBI::FIERY_FIELDS},
|
||||
{BFieldType::HOLY_GROUND, BattlefieldBI::HOLY_GROUND},
|
||||
{BFieldType::LUCID_POOLS, BattlefieldBI::LUCID_POOLS},
|
||||
|
@ -83,7 +83,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
||||
const CGTownInstance * town; //used during town siege, nullptr if this is not a siege (note that fortless town IS also a siege)
|
||||
int3 tile; //for background and bonuses
|
||||
std::vector<CStack*> stacks;
|
||||
std::vector<shared_ptr<CObstacleInstance> > obstacles;
|
||||
std::vector<std::shared_ptr<CObstacleInstance> > obstacles;
|
||||
SiegeInfo si;
|
||||
|
||||
BFieldType battlefieldType; //like !!BA:B
|
||||
@ -124,7 +124,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
|
||||
//std::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
|
||||
|
||||
//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
|
||||
shared_ptr<CObstacleInstance> getObstacleOnTile(BattleHex tile) const;
|
||||
std::shared_ptr<CObstacleInstance> getObstacleOnTile(BattleHex tile) const;
|
||||
std::set<BattleHex> getStoppers(bool whichSidePerspective) const;
|
||||
|
||||
ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand); //charge - number of hexes travelled before attack (for champion's jousting)
|
||||
|
@ -545,7 +545,7 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
return pickRandomArtifact(rand, flags, [](ArtifactID){ return true;});
|
||||
}
|
||||
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalInfo = 0)
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, std::shared_ptr<ILimiter> limiter = std::shared_ptr<ILimiter>(), int additionalInfo = 0)
|
||||
{
|
||||
auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
|
||||
added->additionalInfo = additionalInfo;
|
||||
@ -554,7 +554,7 @@ Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType
|
||||
return added;
|
||||
}
|
||||
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator = shared_ptr<IPropagator>(), int additionalInfo = 0)
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, std::shared_ptr<IPropagator> propagator = std::shared_ptr<IPropagator>(), int additionalInfo = 0)
|
||||
{
|
||||
auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
|
||||
added->additionalInfo = additionalInfo;
|
||||
@ -563,12 +563,12 @@ Bonus *createBonus(Bonus::BonusType type, int val, int subtype, shared_ptr<IProp
|
||||
return added;
|
||||
}
|
||||
|
||||
void CArtHandler::giveArtBonus( ArtifactID aid, Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, shared_ptr<ILimiter> limiter, int additionalInfo)
|
||||
void CArtHandler::giveArtBonus( ArtifactID aid, Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, std::shared_ptr<ILimiter> limiter, int additionalInfo)
|
||||
{
|
||||
giveArtBonus(aid, createBonus(type, val, subtype, valType, limiter, additionalInfo));
|
||||
}
|
||||
|
||||
void CArtHandler::giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator /*= nullptr*/, int additionalInfo)
|
||||
void CArtHandler::giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, std::shared_ptr<IPropagator> propagator /*= nullptr*/, int additionalInfo)
|
||||
{
|
||||
giveArtBonus(aid, createBonus(type, val, subtype, propagator, additionalInfo));
|
||||
}
|
||||
@ -737,6 +737,7 @@ void CArtHandler::afterLoadFinalization()
|
||||
bonus->sid = art->id;
|
||||
}
|
||||
}
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
CArtifactInstance::CArtifactInstance()
|
||||
|
@ -258,8 +258,8 @@ private:
|
||||
void loadComponents(CArtifact * art, const JsonNode & node);
|
||||
void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);
|
||||
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator, int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, std::shared_ptr<ILimiter> limiter = std::shared_ptr<ILimiter>(), int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, std::shared_ptr<IPropagator> propagator, int additionalinfo = 0);
|
||||
void giveArtBonus(ArtifactID aid, Bonus *bonus);
|
||||
|
||||
void erasePickedArt(ArtifactID id);
|
||||
|
@ -130,9 +130,9 @@ BFieldType CBattleInfoEssentials::battleGetBattlefieldType() const
|
||||
return getBattle()->battlefieldType;
|
||||
}
|
||||
|
||||
std::vector<shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
|
||||
std::vector<std::shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
|
||||
{
|
||||
std::vector<shared_ptr<const CObstacleInstance> > ret;
|
||||
std::vector<std::shared_ptr<const CObstacleInstance> > ret;
|
||||
RETURN_IF_NOT_BATTLE(ret);
|
||||
|
||||
if(!perspective)
|
||||
@ -1100,9 +1100,9 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
|
||||
return ret;
|
||||
}
|
||||
|
||||
shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/) const
|
||||
std::shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(shared_ptr<const CObstacleInstance>());
|
||||
RETURN_IF_NOT_BATTLE(std::shared_ptr<const CObstacleInstance>());
|
||||
|
||||
for(auto &obs : battleGetAllObstacles())
|
||||
{
|
||||
@ -1113,7 +1113,7 @@ shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(
|
||||
}
|
||||
}
|
||||
|
||||
return shared_ptr<const CObstacleInstance>();
|
||||
return std::shared_ptr<const CObstacleInstance>();
|
||||
}
|
||||
|
||||
AccessibilityInfo CBattleInfoCallback::getAccesibility() const
|
||||
|
@ -170,7 +170,7 @@ public:
|
||||
|
||||
ETerrainType battleTerrainType() const;
|
||||
BFieldType battleGetBattlefieldType() const;
|
||||
std::vector<shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
|
||||
std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
|
||||
|
||||
/** @brief Main method for getting battle stacks
|
||||
*
|
||||
@ -243,7 +243,7 @@ public:
|
||||
//battle
|
||||
boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
|
||||
|
||||
shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
||||
std::shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
|
||||
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; //returns stack info by given pos
|
||||
void battleGetStackQueue(std::vector<const CStack *> &out, const int howMany, const int turn = 0, int lastMoved = -1) const;
|
||||
void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "../lib/JsonNode.h"
|
||||
|
||||
/*
|
||||
* CConfighandler.h, part of VCMI engine
|
||||
* CConfigHandler.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -140,6 +140,7 @@ void CCreature::setId(CreatureID ID)
|
||||
if(bonus->source == Bonus::CREATURE_ABILITY)
|
||||
bonus->sid = ID;
|
||||
}
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
|
||||
static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
|
||||
@ -488,8 +489,14 @@ void CCreatureHandler::loadCrExpBon()
|
||||
}
|
||||
do //parse everything that's left
|
||||
{
|
||||
b.sid = parser.readNumber(); //id = this particular creature ID
|
||||
loadStackExp(b, creatures[b.sid]->getBonusList(), parser); //add directly to CCreature Node
|
||||
auto sid = parser.readNumber(); //id = this particular creature ID
|
||||
b.sid = sid;
|
||||
bl.clear();
|
||||
loadStackExp(b, bl, parser);
|
||||
for(Bonus * b : bl)
|
||||
{
|
||||
creatures[sid]->addNewBonus(b); //add directly to CCreature Node
|
||||
}
|
||||
}
|
||||
while (parser.endLine());
|
||||
|
||||
@ -753,7 +760,7 @@ void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode
|
||||
{
|
||||
if (val.Bool() == true)
|
||||
{
|
||||
bonus->limiter = make_shared<RankRangeLimiter>(RankRangeLimiter(lowerLimit));
|
||||
bonus->limiter = std::make_shared<RankRangeLimiter>(RankRangeLimiter(lowerLimit));
|
||||
creature->addNewBonus (new Bonus(*bonus)); //bonuses must be unique objects
|
||||
break; //TODO: allow bonuses to turn off?
|
||||
}
|
||||
|
@ -225,14 +225,39 @@ ui64 CCreatureSet::getPower (SlotID slot) const
|
||||
return getStack(slot).getPower();
|
||||
}
|
||||
|
||||
std::string CCreatureSet::getRoughAmount (SlotID slot) const
|
||||
std::string CCreatureSet::getRoughAmount(SlotID slot, int mode) const
|
||||
{
|
||||
/// Mode represent return string format
|
||||
/// "Pack" - 0, "A pack of" - 1, "a pack of" - 2
|
||||
int quantity = CCreature::getQuantityID(getStackCount(slot));
|
||||
if (quantity)
|
||||
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))];
|
||||
if(quantity)
|
||||
return VLC->generaltexth->arraytxt[(174 + mode) + 3*CCreature::getQuantityID(getStackCount(slot))];
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string CCreatureSet::getArmyDescription() const
|
||||
{
|
||||
std::string text;
|
||||
std::vector<std::string> guards;
|
||||
for(auto & elem : stacks)
|
||||
{
|
||||
auto str = boost::str(boost::format("%s %s") % getRoughAmount(elem.first, 2) % getCreature(elem.first)->namePl);
|
||||
guards.push_back(str);
|
||||
}
|
||||
if(guards.size())
|
||||
{
|
||||
for(int i = 0; i < guards.size(); i++)
|
||||
{
|
||||
text += guards[i];
|
||||
if(i + 2 < guards.size())
|
||||
text += ", ";
|
||||
else if(i + 2 == guards.size())
|
||||
text += VLC->generaltexth->allTexts[237];
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
int CCreatureSet::stacksCount() const
|
||||
{
|
||||
return stacks.size();
|
||||
|
@ -200,7 +200,8 @@ public:
|
||||
virtual bool needsLastStack() const; //true if last stack cannot be taken
|
||||
ui64 getArmyStrength() const; //sum of AI values of creatures
|
||||
ui64 getPower (SlotID slot) const; //value of specific stack
|
||||
std::string getRoughAmount (SlotID slot) const; //rough size of specific stack
|
||||
std::string getRoughAmount(SlotID slot, int mode = 0) const; //rough size of specific stack
|
||||
std::string getArmyDescription() const;
|
||||
bool hasStackAtSlot(SlotID slot) const;
|
||||
|
||||
bool contains(const CStackInstance *stack) const;
|
||||
|
@ -475,7 +475,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
|
||||
}
|
||||
|
||||
//TODO: typedef?
|
||||
shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
|
||||
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
|
||||
{
|
||||
assert(player.is_initialized());
|
||||
auto team = getPlayerTeam(player.get());
|
||||
@ -496,7 +496,7 @@ shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisible
|
||||
else
|
||||
tileArray[x][y][z] = nullptr;
|
||||
}
|
||||
return make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
|
||||
return std::make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
|
||||
}
|
||||
|
||||
EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
|
||||
@ -577,7 +577,7 @@ EPlayerStatus::EStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bo
|
||||
std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTavern) const
|
||||
{
|
||||
std::string text = "", extraText = "";
|
||||
if(gs->rumor.type == RumorState::TYPE_NONE) // (version < 755 backward compatability
|
||||
if(gs->rumor.type == RumorState::TYPE_NONE)
|
||||
return text;
|
||||
|
||||
auto rumor = gs->rumor.last[gs->rumor.type];
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
const CMapHeader * getMapHeader()const;
|
||||
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
|
||||
const TerrainTile * getTile(int3 tile, bool verbose = true) const;
|
||||
shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
|
||||
bool isInTheMap(const int3 &pos) const;
|
||||
|
||||
//town
|
||||
|
@ -24,19 +24,19 @@
|
||||
#ifdef VCMI_ANDROID
|
||||
// we can't use shared libraries on Android so here's a hack
|
||||
extern "C" DLL_EXPORT void VCAI_GetAiName(char* name);
|
||||
extern "C" DLL_EXPORT void VCAI_GetNewAI(shared_ptr<CGlobalAI> &out);
|
||||
extern "C" DLL_EXPORT void VCAI_GetNewAI(std::shared_ptr<CGlobalAI> &out);
|
||||
|
||||
extern "C" DLL_EXPORT void StupidAI_GetAiName(char* name);
|
||||
extern "C" DLL_EXPORT void StupidAI_GetNewBattleAI(shared_ptr<CGlobalAI> &out);
|
||||
extern "C" DLL_EXPORT void StupidAI_GetNewBattleAI(std::shared_ptr<CGlobalAI> &out);
|
||||
|
||||
extern "C" DLL_EXPORT void BattleAI_GetAiName(char* name);
|
||||
extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(shared_ptr<CBattleGameInterface> &out);
|
||||
extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out);
|
||||
#endif
|
||||
|
||||
template<typename rett>
|
||||
shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::string& methodName)
|
||||
std::shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::string& methodName)
|
||||
{
|
||||
typedef void(*TGetAIFun)(shared_ptr<rett>&);
|
||||
typedef void(*TGetAIFun)(std::shared_ptr<rett>&);
|
||||
typedef void(*TGetNameFun)(char*);
|
||||
|
||||
char temp[150];
|
||||
@ -102,7 +102,7 @@ shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::st
|
||||
getName(temp);
|
||||
logGlobal->infoStream() << "Loaded " << temp;
|
||||
|
||||
shared_ptr<rett> ret;
|
||||
std::shared_ptr<rett> ret;
|
||||
getAI(ret);
|
||||
if(!ret)
|
||||
logGlobal->errorStream() << "Cannot get AI!";
|
||||
@ -111,7 +111,7 @@ shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::st
|
||||
}
|
||||
|
||||
template<typename rett>
|
||||
shared_ptr<rett> createAnyAI(std::string dllname, const std::string& methodName)
|
||||
std::shared_ptr<rett> createAnyAI(std::string dllname, const std::string& methodName)
|
||||
{
|
||||
logGlobal->infoStream() << "Opening " << dllname;
|
||||
const boost::filesystem::path filePath =
|
||||
@ -121,17 +121,17 @@ shared_ptr<rett> createAnyAI(std::string dllname, const std::string& methodName)
|
||||
return ret;
|
||||
}
|
||||
|
||||
shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname)
|
||||
std::shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname)
|
||||
{
|
||||
return createAnyAI<CGlobalAI>(dllname, "GetNewAI");
|
||||
}
|
||||
|
||||
shared_ptr<CBattleGameInterface> CDynLibHandler::getNewBattleAI(std::string dllname )
|
||||
std::shared_ptr<CBattleGameInterface> CDynLibHandler::getNewBattleAI(std::string dllname )
|
||||
{
|
||||
return createAnyAI<CBattleGameInterface>(dllname, "GetNewBattleAI");
|
||||
}
|
||||
|
||||
shared_ptr<CScriptingModule> CDynLibHandler::getNewScriptingModule(std::string dllname)
|
||||
std::shared_ptr<CScriptingModule> CDynLibHandler::getNewScriptingModule(std::string dllname)
|
||||
{
|
||||
return createAny<CScriptingModule>(dllname, "GetNewModule");
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
std::string dllName;
|
||||
|
||||
virtual ~CBattleGameInterface() {};
|
||||
virtual void init(shared_ptr<CBattleCallback> CB){};
|
||||
virtual void init(std::shared_ptr<CBattleCallback> CB){};
|
||||
|
||||
//battle call-ins
|
||||
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
|
||||
@ -82,7 +82,7 @@ public:
|
||||
class DLL_LINKAGE CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
|
||||
{
|
||||
public:
|
||||
virtual void init(shared_ptr<CCallback> CB){};
|
||||
virtual void init(std::shared_ptr<CCallback> CB){};
|
||||
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
|
||||
|
||||
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||
@ -105,9 +105,9 @@ public:
|
||||
class DLL_LINKAGE CDynLibHandler
|
||||
{
|
||||
public:
|
||||
static shared_ptr<CGlobalAI> getNewAI(std::string dllname);
|
||||
static shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
|
||||
static shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
|
||||
static std::shared_ptr<CGlobalAI> getNewAI(std::string dllname);
|
||||
static std::shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
|
||||
static std::shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
|
||||
@ -123,8 +123,8 @@ class DLL_LINKAGE CAdventureAI : public CGlobalAI
|
||||
public:
|
||||
CAdventureAI() {};
|
||||
|
||||
shared_ptr<CBattleGameInterface> battleAI;
|
||||
shared_ptr<CBattleCallback> cbc;
|
||||
std::shared_ptr<CBattleGameInterface> battleAI;
|
||||
std::shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
||||
|
||||
|
@ -675,8 +675,8 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
|
||||
}
|
||||
else
|
||||
{
|
||||
cur->setType(ran.first, ran.second);
|
||||
}
|
||||
cur->setType(ran.first, ran.second);
|
||||
}
|
||||
}
|
||||
|
||||
int CGameState::getDate(Date::EDateType mode) const
|
||||
@ -1939,7 +1939,7 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile)
|
||||
case Obj::EVIL_FOG:
|
||||
return BFieldType::EVIL_FOG;
|
||||
case Obj::FAVORABLE_WINDS:
|
||||
return BFieldType::FAVOURABLE_WINDS;
|
||||
return BFieldType::FAVORABLE_WINDS;
|
||||
case Obj::FIERY_FIELDS:
|
||||
return BFieldType::FIERY_FIELDS;
|
||||
case Obj::HOLY_GROUNDS:
|
||||
@ -3177,7 +3177,7 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
|
||||
|
||||
for(const JsonNode &n : duelData["obstacles"].Vector())
|
||||
{
|
||||
auto oi = make_shared<CObstacleInstance>();
|
||||
auto oi = std::make_shared<CObstacleInstance>();
|
||||
if(n.getType() == JsonNode::DATA_VECTOR)
|
||||
{
|
||||
oi->ID = n.Vector()[0].Float();
|
||||
|
@ -100,7 +100,7 @@ struct DLL_LINKAGE RumorState
|
||||
ERumorType type;
|
||||
std::map<ERumorType, std::pair<int, int>> last;
|
||||
|
||||
RumorState(){type = TYPE_NONE; last = {};};
|
||||
RumorState(){type = TYPE_NONE;};
|
||||
bool update(int id, int extra);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -149,7 +149,7 @@ struct DLL_EXPORT DuelParameters
|
||||
}
|
||||
} sides[2];
|
||||
|
||||
std::vector<shared_ptr<CObstacleInstance> > obstacles;
|
||||
std::vector<std::shared_ptr<CObstacleInstance> > obstacles;
|
||||
|
||||
static DuelParameters fromJSON(const std::string &fname);
|
||||
|
||||
@ -249,7 +249,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects & rand;
|
||||
if(version >= 755)
|
||||
if(version >= 755) //save format backward compatibility
|
||||
{
|
||||
h & rumor;
|
||||
}
|
||||
|
@ -150,22 +150,24 @@ void CPathfinder::calculatePaths()
|
||||
continue;
|
||||
|
||||
destAction = getDestAction();
|
||||
int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, movement, hlp->getTurnInfo());
|
||||
int remains = movement - cost;
|
||||
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
|
||||
{
|
||||
remains = hero->movementPointsAfterEmbark(movement, cost, destAction - 1, hlp->getTurnInfo());
|
||||
cost = movement - remains;
|
||||
}
|
||||
int turnAtNextTile = turn;
|
||||
int turnAtNextTile = turn, moveAtNextTile = movement;
|
||||
int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo());
|
||||
int remains = moveAtNextTile - cost;
|
||||
if(remains < 0)
|
||||
{
|
||||
//occurs rarely, when hero with low movepoints tries to leave the road
|
||||
hlp->updateTurnInfo(++turnAtNextTile);
|
||||
int moveAtNextTile = hlp->getMaxMovePoints(i);
|
||||
moveAtNextTile = hlp->getMaxMovePoints(i);
|
||||
cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo()); //cost must be updated, movement points changed :(
|
||||
remains = moveAtNextTile - cost;
|
||||
}
|
||||
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
|
||||
{
|
||||
/// FREE_SHIP_BOARDING bonus only remove additional penalty
|
||||
/// land <-> sail transition still cost movement points as normal movement
|
||||
remains = hero->movementPointsAfterEmbark(moveAtNextTile, cost, destAction - 1, hlp->getTurnInfo());
|
||||
cost = moveAtNextTile - remains;
|
||||
}
|
||||
|
||||
if(isBetterWay(remains, turnAtNextTile) &&
|
||||
((cp->turns == turnAtNextTile && remains) || passOneTurnLimitCheck()))
|
||||
@ -189,14 +191,24 @@ void CPathfinder::calculatePaths()
|
||||
dp = out.getNode(neighbour, cp->layer);
|
||||
if(dp->locked)
|
||||
continue;
|
||||
/// TODO: We may consider use invisible exits on FoW border in future
|
||||
/// Useful for AI when at least one tile around exit is visible and passable
|
||||
/// Objects are usually visible on FoW border anyway so it's not cheating.
|
||||
///
|
||||
/// For now it's disabled as it's will cause crashes in movement code.
|
||||
if(dp->accessible == CGPathNode::BLOCKED)
|
||||
continue;
|
||||
|
||||
if(isBetterWay(movement, turn))
|
||||
{
|
||||
dtObj = gs->map->getTile(neighbour).topVisitableObj();
|
||||
|
||||
dp->moveRemains = movement;
|
||||
dp->turns = turn;
|
||||
dp->theNodeBefore = cp;
|
||||
dp->action = CGPathNode::NORMAL;
|
||||
pq.push(dp);
|
||||
dp->action = getTeleportDestAction();
|
||||
if(dp->action == CGPathNode::TELEPORT_NORMAL)
|
||||
pq.push(dp);
|
||||
}
|
||||
}
|
||||
} //queue loop
|
||||
@ -361,6 +373,16 @@ bool CPathfinder::isLayerTransitionPossible() const
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ELayer::WATER:
|
||||
if(dp->accessible != CGPathNode::ACCESSIBLE && dp->accessible != CGPathNode::VISITABLE)
|
||||
{
|
||||
/// Hero that walking on water can transit to accessible and visitable tiles
|
||||
/// Though hero can't interact with blocking visit objects while standing on water
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -443,7 +465,7 @@ bool CPathfinder::isMovementAfterDestPossible() const
|
||||
/// Transit over whirlpools only allowed when hero protected
|
||||
return true;
|
||||
}
|
||||
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2)
|
||||
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2 || dtObj->ID == Obj::BORDER_GATE)
|
||||
{
|
||||
/// Transit via unguarded garrisons is always possible
|
||||
return true;
|
||||
@ -507,18 +529,33 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
|
||||
else
|
||||
action = CGPathNode::BLOCKING_VISIT;
|
||||
}
|
||||
else if(dtObj->ID == Obj::TOWN && objRel == PlayerRelations::ENEMIES)
|
||||
else if(dtObj->ID == Obj::TOWN)
|
||||
{
|
||||
const CGTownInstance * townObj = dynamic_cast<const CGTownInstance *>(dtObj);
|
||||
if(townObj->armedGarrison())
|
||||
if(dtObj->passableFor(hero->tempOwner))
|
||||
action = CGPathNode::VISIT;
|
||||
else if(objRel == PlayerRelations::ENEMIES)
|
||||
action = CGPathNode::BATTLE;
|
||||
}
|
||||
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2)
|
||||
{
|
||||
const CGGarrison * garrisonObj = dynamic_cast<const CGGarrison *>(dtObj);
|
||||
if((garrisonObj->stacksCount() && objRel == PlayerRelations::ENEMIES) || isDestinationGuarded(true))
|
||||
if(dtObj->passableFor(hero->tempOwner))
|
||||
{
|
||||
if(isDestinationGuarded(true))
|
||||
action = CGPathNode::BATTLE;
|
||||
}
|
||||
else if(objRel == PlayerRelations::ENEMIES)
|
||||
action = CGPathNode::BATTLE;
|
||||
}
|
||||
else if(dtObj->ID == Obj::BORDER_GATE)
|
||||
{
|
||||
if(dtObj->passableFor(hero->tempOwner))
|
||||
{
|
||||
if(isDestinationGuarded(true))
|
||||
action = CGPathNode::BATTLE;
|
||||
}
|
||||
else
|
||||
action = CGPathNode::BLOCKING_VISIT;
|
||||
}
|
||||
else if(isDestinationGuardian())
|
||||
action = CGPathNode::BATTLE;
|
||||
else if(dtObj->blockVisit && !(options.useCastleGate && dtObj->ID == Obj::TOWN))
|
||||
@ -541,6 +578,21 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
|
||||
return action;
|
||||
}
|
||||
|
||||
CGPathNode::ENodeAction CPathfinder::getTeleportDestAction() const
|
||||
{
|
||||
CGPathNode::ENodeAction action = CGPathNode::TELEPORT_NORMAL;
|
||||
if(isDestVisitableObj() && dtObj->ID == Obj::HERO)
|
||||
{
|
||||
auto objRel = getPlayerRelations(dtObj->tempOwner, hero->tempOwner);
|
||||
if(objRel == PlayerRelations::ENEMIES)
|
||||
action = CGPathNode::TELEPORT_BATTLE;
|
||||
else
|
||||
action = CGPathNode::TELEPORT_BLOCKING_VISIT;
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
bool CPathfinder::isSourceInitialPosition() const
|
||||
{
|
||||
return cp->coord == out.hpos;
|
||||
@ -987,7 +1039,7 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
|
||||
}
|
||||
else if(dt->terType == ETerrainType::WATER)
|
||||
{
|
||||
if(h->boat && ct->hasFavourableWinds() && dt->hasFavourableWinds()) //Favourable Winds
|
||||
if(h->boat && ct->hasFavorableWinds() && dt->hasFavorableWinds())
|
||||
ret *= 0.666;
|
||||
else if(!h->boat && ti->hasBonusOfType(Bonus::WATER_WALKING))
|
||||
{
|
||||
|
@ -36,7 +36,10 @@ struct DLL_LINKAGE CGPathNode
|
||||
NORMAL,
|
||||
BATTLE,
|
||||
VISIT,
|
||||
BLOCKING_VISIT
|
||||
BLOCKING_VISIT,
|
||||
TELEPORT_NORMAL,
|
||||
TELEPORT_BLOCKING_VISIT,
|
||||
TELEPORT_BATTLE
|
||||
};
|
||||
|
||||
enum EAccessibility : ui8
|
||||
@ -159,7 +162,7 @@ private:
|
||||
CPathsInfo & out;
|
||||
const CGHeroInstance * hero;
|
||||
const std::vector<std::vector<std::vector<ui8> > > &FoW;
|
||||
unique_ptr<CPathfinderHelper> hlp;
|
||||
std::unique_ptr<CPathfinderHelper> hlp;
|
||||
|
||||
enum EPatrolState {
|
||||
PATROL_NONE = 0,
|
||||
@ -202,6 +205,7 @@ private:
|
||||
bool isMovementToDestPossible() const;
|
||||
bool isMovementAfterDestPossible() const;
|
||||
CGPathNode::ENodeAction getDestAction() const;
|
||||
CGPathNode::ENodeAction getTeleportDestAction() const;
|
||||
|
||||
bool isSourceInitialPosition() const;
|
||||
bool isSourceVisitableObj() const;
|
||||
@ -240,7 +244,7 @@ struct DLL_LINKAGE TurnInfo
|
||||
|
||||
BonusCache(TBonusListPtr bonusList);
|
||||
};
|
||||
unique_ptr<BonusCache> bonusCache;
|
||||
std::unique_ptr<BonusCache> bonusCache;
|
||||
|
||||
const CGHeroInstance * hero;
|
||||
TBonusListPtr bonuses;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* timeHandler.h, part of VCMI engine
|
||||
* CStopWatch.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -17,9 +17,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using namespace boost;
|
||||
using namespace boost::asio::ip;
|
||||
|
||||
extern template void registerTypes<CISer>(CISer & s);
|
||||
extern template void registerTypes<COSer>(COSer & s);
|
||||
extern template void registerTypes<CTypeList>(CTypeList & s);
|
||||
@ -70,13 +67,13 @@ void CConnection::init()
|
||||
}
|
||||
|
||||
CConnection::CConnection(std::string host, std::string port, std::string Name)
|
||||
:iser(this), oser(this), io_service(new asio::io_service), name(Name)
|
||||
:iser(this), oser(this), io_service(new boost::asio::io_service), name(Name)
|
||||
{
|
||||
int i;
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
socket = new tcp::socket(*io_service);
|
||||
tcp::resolver resolver(*io_service);
|
||||
tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(tcp::resolver::query(host,port),error);
|
||||
boost::system::error_code error = boost::asio::error::host_not_found;
|
||||
socket = new boost::asio::ip::tcp::socket(*io_service);
|
||||
boost::asio::ip::tcp::resolver resolver(*io_service);
|
||||
boost::asio::ip::tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(boost::asio::ip::tcp::resolver::query(host,port),error);
|
||||
if(error)
|
||||
{
|
||||
logNetwork->errorStream() << "Problem with resolving: \n" << error;
|
||||
@ -121,7 +118,7 @@ connerror1:
|
||||
else
|
||||
logNetwork->errorStream() << "No error info. ";
|
||||
delete io_service;
|
||||
//delete socket;
|
||||
//delete socket;
|
||||
throw std::runtime_error("Can't establish connection :(");
|
||||
}
|
||||
CConnection::CConnection(TSocket * Socket, std::string Name )
|
||||
@ -132,14 +129,14 @@ CConnection::CConnection(TSocket * Socket, std::string Name )
|
||||
CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name)
|
||||
: iser(this), oser(this), name(Name)//, send(this), rec(this)
|
||||
{
|
||||
boost::system::error_code error = asio::error::host_not_found;
|
||||
socket = new tcp::socket(*io_service);
|
||||
boost::system::error_code error = boost::asio::error::host_not_found;
|
||||
socket = new boost::asio::ip::tcp::socket(*io_service);
|
||||
acceptor->accept(*socket,error);
|
||||
if (error)
|
||||
{
|
||||
{
|
||||
logNetwork->errorStream() << "Error on accepting: " << error;
|
||||
delete socket;
|
||||
throw std::runtime_error("Can't establish connection :(");
|
||||
delete socket;
|
||||
throw std::runtime_error("Can't establish connection :(");
|
||||
}
|
||||
init();
|
||||
}
|
||||
@ -149,7 +146,7 @@ int CConnection::write(const void * data, unsigned size)
|
||||
try
|
||||
{
|
||||
int ret;
|
||||
ret = asio::write(*socket,asio::const_buffers_1(asio::const_buffer(data,size)));
|
||||
ret = boost::asio::write(*socket,boost::asio::const_buffers_1(boost::asio::const_buffer(data,size)));
|
||||
return ret;
|
||||
}
|
||||
catch(...)
|
||||
@ -164,7 +161,7 @@ int CConnection::read(void * data, unsigned size)
|
||||
//LOG("Receiving " << size << " byte(s) of data" <<std::endl);
|
||||
try
|
||||
{
|
||||
int ret = asio::read(*socket,asio::mutable_buffers_1(asio::mutable_buffer(data,size)));
|
||||
int ret = boost::asio::read(*socket,boost::asio::mutable_buffers_1(boost::asio::mutable_buffer(data,size)));
|
||||
return ret;
|
||||
}
|
||||
catch(...)
|
||||
@ -240,12 +237,12 @@ void CConnection::sendPackToServer(const CPack &pack, PlayerColor player, ui32 r
|
||||
|
||||
void CConnection::disableStackSendingByID()
|
||||
{
|
||||
CSerializer::sendStackInstanceByIds = false;
|
||||
CSerializer::sendStackInstanceByIds = false;
|
||||
}
|
||||
|
||||
void CConnection::enableStackSendingByID()
|
||||
{
|
||||
CSerializer::sendStackInstanceByIds = true;
|
||||
CSerializer::sendStackInstanceByIds = true;
|
||||
}
|
||||
|
||||
void CConnection::disableSmartPointerSerialization()
|
||||
@ -285,7 +282,7 @@ void CConnection::enableSmartVectorMemberSerializatoin()
|
||||
CSerializer::smartVectorMembersSerialization = true;
|
||||
}
|
||||
|
||||
CSaveFile::CSaveFile( const std::string &fname ): serializer(this)
|
||||
CSaveFile::CSaveFile( const std::string &fname ): serializer(this)
|
||||
{
|
||||
registerTypes(serializer);
|
||||
openNextFile(fname);
|
||||
@ -379,7 +376,7 @@ void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalV
|
||||
if(std::memcmp(buffer,"VCMI",4))
|
||||
THROW_FORMAT("Error: not a VCMI file(%s)!", fName);
|
||||
|
||||
serializer >> serializer.fileVersion;
|
||||
serializer >> serializer.fileVersion;
|
||||
if(serializer.fileVersion < minimalVersion)
|
||||
THROW_FORMAT("Error: too old file format (%s)!", fName);
|
||||
|
||||
@ -442,7 +439,7 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
|
||||
return typeDescr; //type found, return ptr to structure
|
||||
|
||||
//type not found - add it to the list and return given ID
|
||||
auto newType = make_shared<TypeDescriptor>();
|
||||
auto newType = std::make_shared<TypeDescriptor>();
|
||||
newType->typeID = typeInfos.size() + 1;
|
||||
newType->name = type->name();
|
||||
typeInfos[type] = newType;
|
||||
@ -450,18 +447,19 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
|
||||
return newType;
|
||||
}
|
||||
|
||||
ui16 CTypeList::getTypeID( const std::type_info *type )
|
||||
ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const
|
||||
{
|
||||
auto i = typeInfos.find(type);
|
||||
if(i != typeInfos.end())
|
||||
return i->second->typeID;
|
||||
else
|
||||
auto descriptor = getTypeDescriptor(type, throws);
|
||||
if (descriptor == nullptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return descriptor->typeID;
|
||||
}
|
||||
|
||||
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to)
|
||||
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
|
||||
{
|
||||
if(from == to)
|
||||
if(!strcmp(from->name, to->name))
|
||||
return std::vector<CTypeList::TypeInfoPtr>();
|
||||
|
||||
// Perform a simple BFS in the class hierarchy.
|
||||
@ -484,7 +482,7 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<TypeInfoPtr> ret;
|
||||
|
||||
if(!previous.count(from))
|
||||
@ -512,21 +510,21 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to)
|
||||
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
|
||||
{
|
||||
//This additional if is needed because getTypeDescriptor might fail if type is not registered
|
||||
// (and if casting is not needed, then registereing should no be required)
|
||||
if(*from == *to)
|
||||
if(!strcmp(from->name(), to->name()))
|
||||
return std::vector<CTypeList::TypeInfoPtr>();
|
||||
|
||||
return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
|
||||
}
|
||||
|
||||
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws)
|
||||
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) const
|
||||
{
|
||||
auto i = typeInfos.find(type);
|
||||
if(i != typeInfos.end())
|
||||
return i->second; //type found, return ptr to structure
|
||||
return i->second; //type found, return ptr to structure
|
||||
|
||||
if(!throws)
|
||||
return nullptr;
|
||||
@ -553,19 +551,19 @@ CSerializer::CSerializer()
|
||||
|
||||
void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
|
||||
{
|
||||
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
|
||||
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
|
||||
[](const CGObjectInstance &obj){ return obj.id; });
|
||||
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
|
||||
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
|
||||
[](const CHero &h){ return h.ID; });
|
||||
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
|
||||
[](const CGHeroInstance &h){ return h.type->ID; });
|
||||
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
|
||||
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
|
||||
[](const CCreature &cre){ return cre.idNumber; });
|
||||
registerVectoredType<CArtifact, ArtifactID>(&lib->arth->artifacts,
|
||||
[](const CArtifact &art){ return art.id; });
|
||||
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
|
||||
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
|
||||
[](const CArtifactInstance &artInst){ return artInst.id; });
|
||||
registerVectoredType<CQuest, si32>(&gs->map->quests,
|
||||
registerVectoredType<CQuest, si32>(&gs->map->quests,
|
||||
[](const CQuest &q){ return q.qid; });
|
||||
|
||||
smartVectorMembersSerialization = true;
|
||||
@ -606,7 +604,7 @@ int CLoadIntegrityValidator::read( void * data, unsigned size )
|
||||
return ret;
|
||||
}
|
||||
|
||||
unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
|
||||
std::unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
|
||||
{
|
||||
primaryFile->serializer.loadedPointers = this->serializer.loadedPointers;
|
||||
primaryFile->serializer.loadedPointersTypes = this->serializer.loadedPointersTypes;
|
||||
@ -646,4 +644,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this)
|
||||
registerTypes(iser);
|
||||
registerTypes(oser);
|
||||
}
|
||||
|
||||
|
232
lib/Connection.h
232
lib/Connection.h
@ -81,10 +81,14 @@ enum SerializationLvl
|
||||
|
||||
struct TypeComparer
|
||||
{
|
||||
bool operator()(const std::type_info *a, const std::type_info *b) const
|
||||
{
|
||||
return a->before(*b);
|
||||
}
|
||||
bool operator()(const std::type_info *a, const std::type_info *b) const
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
return a->before(*b);
|
||||
#else
|
||||
return strcmp(a->name(), b->name()) < 0;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct IPointerCaster
|
||||
@ -102,6 +106,11 @@ struct PointerCaster : IPointerCaster
|
||||
{
|
||||
From * from = (From*)boost::any_cast<void*>(ptr);
|
||||
To * ret = dynamic_cast<To*>(from);
|
||||
if (ret == nullptr)
|
||||
{
|
||||
// Last resort when RTTI goes mad
|
||||
ret = static_cast<To*>(from);
|
||||
}
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
@ -113,6 +122,11 @@ struct PointerCaster : IPointerCaster
|
||||
{
|
||||
auto from = boost::any_cast<SmartPt>(ptr);
|
||||
auto ret = std::dynamic_pointer_cast<To>(from);
|
||||
if (!ret)
|
||||
{
|
||||
// Last resort when RTTI goes mad
|
||||
ret = std::static_pointer_cast<To>(from);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
@ -136,7 +150,7 @@ struct PointerCaster : IPointerCaster
|
||||
// }
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CTypeList
|
||||
class DLL_LINKAGE CTypeList: public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
struct TypeDescriptor;
|
||||
@ -147,33 +161,53 @@ public:
|
||||
const char *name;
|
||||
std::vector<TypeInfoPtr> children, parents;
|
||||
};
|
||||
typedef boost::shared_mutex TMutex;
|
||||
typedef boost::unique_lock<TMutex> TUniqueLock;
|
||||
typedef boost::shared_lock<TMutex> TSharedLock;
|
||||
private:
|
||||
mutable TMutex mx;
|
||||
|
||||
std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
|
||||
std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
|
||||
|
||||
CTypeList(CTypeList &)
|
||||
{
|
||||
// This type is non-copyable.
|
||||
// Unfortunately on Windows it is required for DLL_EXPORT-ed type to provide copy c-tor, so we can't =delete it.
|
||||
assert(0);
|
||||
}
|
||||
CTypeList &operator=(CTypeList &)
|
||||
{
|
||||
// As above.
|
||||
assert(0);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
/// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
|
||||
/// Throws if there is no link registered.
|
||||
std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
|
||||
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
|
||||
|
||||
CTypeList();
|
||||
|
||||
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
|
||||
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
|
||||
{
|
||||
TSharedLock lock(mx);
|
||||
auto typesSequence = castSequence(fromArg, toArg);
|
||||
|
||||
boost::any ptr = inputPtr;
|
||||
for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
|
||||
{
|
||||
auto &from = typesSequence[i];
|
||||
auto &to = typesSequence[i + 1];
|
||||
auto castingPair = std::make_pair(from, to);
|
||||
if(!casters.count(castingPair))
|
||||
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
|
||||
|
||||
auto &caster = casters.at(castingPair);
|
||||
ptr = (*caster.*CastingFunction)(ptr); //Why does std::unique_ptr not have operator->* ..?
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
|
||||
|
||||
TypeInfoPtr registerType(const std::type_info *type);
|
||||
|
||||
public:
|
||||
CTypeList();
|
||||
|
||||
template <typename Base, typename Derived>
|
||||
void registerType(const Base * b = nullptr, const Derived * d = nullptr)
|
||||
{
|
||||
TUniqueLock lock(mx);
|
||||
static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
|
||||
static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
|
||||
static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two diffrenet types.");
|
||||
@ -187,77 +221,52 @@ public:
|
||||
casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>();
|
||||
}
|
||||
|
||||
ui16 getTypeID(const std::type_info *type);
|
||||
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true); //if not throws, failure returns nullptr
|
||||
ui16 getTypeID(const std::type_info *type, bool throws = false) const;
|
||||
|
||||
template <typename T>
|
||||
ui16 getTypeID(const T * t = nullptr)
|
||||
ui16 getTypeID(const T * t = nullptr, bool throws = false) const
|
||||
{
|
||||
return getTypeID(getTypeInfo(t));
|
||||
}
|
||||
|
||||
|
||||
// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
|
||||
// Throws if there is no link registered.
|
||||
std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to);
|
||||
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to);
|
||||
|
||||
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
|
||||
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg)
|
||||
{
|
||||
auto typesSequence = castSequence(fromArg, toArg);
|
||||
|
||||
boost::any ptr = inputPtr;
|
||||
for(int i = 0; i < (int)typesSequence.size() - 1; i++)
|
||||
{
|
||||
auto &from = typesSequence[i];
|
||||
auto &to = typesSequence[i + 1];
|
||||
auto castingPair = std::make_pair(from, to);
|
||||
if(!casters.count(castingPair))
|
||||
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
|
||||
|
||||
auto &caster = casters.at(castingPair);
|
||||
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr does not have operator->* ..?
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return getTypeID(getTypeInfo(t), throws);
|
||||
}
|
||||
|
||||
template<typename TInput>
|
||||
void *castToMostDerived(const TInput *inputPtr)
|
||||
void * castToMostDerived(const TInput * inputPtr) const
|
||||
{
|
||||
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
|
||||
auto derivedType = getTypeInfo(inputPtr);
|
||||
|
||||
if(baseType == *derivedType)
|
||||
return (void*)inputPtr;
|
||||
if (!strcmp(baseType.name(), derivedType->name()))
|
||||
{
|
||||
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
|
||||
}
|
||||
|
||||
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType));
|
||||
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
|
||||
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
|
||||
derivedType));
|
||||
}
|
||||
|
||||
template<typename TInput>
|
||||
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr)
|
||||
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
|
||||
{
|
||||
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
|
||||
auto derivedType = getTypeInfo(inputPtr.get());
|
||||
|
||||
if(baseType == *derivedType)
|
||||
if (!strcmp(baseType.name(), derivedType->name()))
|
||||
return inputPtr;
|
||||
|
||||
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType);
|
||||
}
|
||||
|
||||
void* castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to)
|
||||
void * castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) const
|
||||
{
|
||||
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
|
||||
}
|
||||
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to)
|
||||
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to) const
|
||||
{
|
||||
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
|
||||
}
|
||||
|
||||
|
||||
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr)
|
||||
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
|
||||
{
|
||||
if(t)
|
||||
return &typeid(*t);
|
||||
@ -444,13 +453,13 @@ public:
|
||||
virtual int write(const void * data, unsigned size) = 0;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CSaverBase
|
||||
class DLL_LINKAGE CSaverBase
|
||||
{
|
||||
protected:
|
||||
IBinaryWriter * writer;
|
||||
public:
|
||||
CSaverBase(IBinaryWriter * w): writer(w){};
|
||||
|
||||
|
||||
inline int write(const void * data, unsigned size)
|
||||
{
|
||||
return writer->write(data, size);
|
||||
@ -586,15 +595,15 @@ struct LoadIfStackInstance<Ser, CStackInstance *>
|
||||
class DLL_LINKAGE COSer : public CSaverBase
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
struct SaveBoolean
|
||||
{
|
||||
static void invoke(COSer &s, const bool &data)
|
||||
{
|
||||
s.saveBoolean(data);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
struct SaveBooleanVector
|
||||
{
|
||||
static void invoke(COSer &s, const std::vector<bool> &data)
|
||||
@ -629,7 +638,7 @@ public:
|
||||
s.saveEnum(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct SavePointer
|
||||
{
|
||||
@ -638,7 +647,7 @@ public:
|
||||
s.savePointer(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct SaveArray
|
||||
{
|
||||
@ -655,9 +664,9 @@ public:
|
||||
{
|
||||
throw std::runtime_error("Wrong save serialization call!");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CPointerSaver : public CBasicPointerSaver
|
||||
{
|
||||
public:
|
||||
@ -665,12 +674,11 @@ public:
|
||||
{
|
||||
COSer &s = static_cast<COSer&>(ar);
|
||||
const T *ptr = static_cast<const T*>(data);
|
||||
|
||||
//T is most derived known type, it's time to call actual serialize
|
||||
const_cast<T&>(*ptr).serialize(s,version);
|
||||
const_cast<T*>(ptr)->serialize(s,version);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
bool saving;
|
||||
std::map<ui16,CBasicPointerSaver*> savers; // typeID => CPointerSaver<serializer,type>
|
||||
|
||||
@ -841,13 +849,13 @@ public:
|
||||
const_cast<T&>(data).serialize(*this,version);
|
||||
}
|
||||
template <typename T>
|
||||
void saveSerializable(const shared_ptr<T> &data)
|
||||
void saveSerializable(const std::shared_ptr<T> &data)
|
||||
{
|
||||
T *internalPtr = data.get();
|
||||
*this << internalPtr;
|
||||
}
|
||||
template <typename T>
|
||||
void saveSerializable(const unique_ptr<T> &data)
|
||||
void saveSerializable(const std::unique_ptr<T> &data)
|
||||
{
|
||||
T *internalPtr = data.get();
|
||||
*this << internalPtr;
|
||||
@ -964,13 +972,13 @@ public:
|
||||
virtual int read(void * data, unsigned size) = 0;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CLoaderBase
|
||||
class DLL_LINKAGE CLoaderBase
|
||||
{
|
||||
protected:
|
||||
IBinaryReader * reader;
|
||||
public:
|
||||
CLoaderBase(IBinaryReader * r): reader(r){};
|
||||
|
||||
|
||||
inline int read(void * data, unsigned size)
|
||||
{
|
||||
return reader->read(data, size);
|
||||
@ -1015,15 +1023,15 @@ public:
|
||||
s.loadBoolean(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct LoadBooleanVector
|
||||
{
|
||||
static void invoke(CISer &s, std::vector<bool> &data)
|
||||
{
|
||||
s.loadBooleanVector(data);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LoadEnum
|
||||
{
|
||||
@ -1040,7 +1048,7 @@ public:
|
||||
{
|
||||
s.loadPrimitive(data);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LoadPointer
|
||||
@ -1049,8 +1057,8 @@ public:
|
||||
{
|
||||
s.loadPointer(data);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LoadArray
|
||||
{
|
||||
@ -1076,8 +1084,8 @@ public:
|
||||
{
|
||||
throw std::runtime_error("Wrong load serialization call!");
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <typename T> class CPointerLoader : public CBasicPointerLoader
|
||||
{
|
||||
public:
|
||||
@ -1094,8 +1102,8 @@ public:
|
||||
ptr->serialize(s,version);
|
||||
return &typeid(T);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
bool saving;
|
||||
std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
|
||||
si32 fileVersion;
|
||||
@ -1324,7 +1332,7 @@ public:
|
||||
|
||||
|
||||
template <typename T>
|
||||
void loadSerializable(shared_ptr<T> &data)
|
||||
void loadSerializable(std::shared_ptr<T> &data)
|
||||
{
|
||||
typedef typename boost::remove_const<T>::type NonConstT;
|
||||
NonConstT *internalPtr;
|
||||
@ -1345,7 +1353,7 @@ public:
|
||||
auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
|
||||
if(*actualType == *typeWeNeedToReturn)
|
||||
{
|
||||
// No casting needed, just unpack already stored shared_ptr and return it
|
||||
// No casting needed, just unpack already stored std::shared_ptr and return it
|
||||
data = boost::any_cast<std::shared_ptr<T>>(itr->second);
|
||||
}
|
||||
else
|
||||
@ -1375,7 +1383,7 @@ public:
|
||||
data.reset();
|
||||
}
|
||||
template <typename T>
|
||||
void loadSerializable(unique_ptr<T> &data)
|
||||
void loadSerializable(std::unique_ptr<T> &data)
|
||||
{
|
||||
T *internalPtr;
|
||||
*this >> internalPtr;
|
||||
@ -1539,11 +1547,11 @@ class DLL_LINKAGE CSaveFile
|
||||
:public IBinaryWriter
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
COSer serializer;
|
||||
|
||||
|
||||
std::string fName;
|
||||
unique_ptr<std::ofstream> sfile;
|
||||
std::unique_ptr<std::ofstream> sfile;
|
||||
|
||||
CSaveFile(const std::string &fname); //throws!
|
||||
~CSaveFile();
|
||||
@ -1554,13 +1562,13 @@ public:
|
||||
void reportState(CLogger * out) override;
|
||||
|
||||
void putMagicBytes(const std::string &text);
|
||||
|
||||
|
||||
template<class T>
|
||||
CSaveFile & operator<<(const T &t)
|
||||
{
|
||||
serializer << t;
|
||||
return * this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CLoadFile
|
||||
@ -1568,9 +1576,9 @@ class DLL_LINKAGE CLoadFile
|
||||
{
|
||||
public:
|
||||
CISer serializer;
|
||||
|
||||
|
||||
std::string fName;
|
||||
unique_ptr<boost::filesystem::ifstream> sfile;
|
||||
std::unique_ptr<boost::filesystem::ifstream> sfile;
|
||||
|
||||
CLoadFile(const boost::filesystem::path & fname, int minimalVersion = version); //throws!
|
||||
~CLoadFile();
|
||||
@ -1581,21 +1589,21 @@ public:
|
||||
void reportState(CLogger * out) override;
|
||||
|
||||
void checkMagicBytes(const std::string & text);
|
||||
|
||||
|
||||
template<class T>
|
||||
CLoadFile & operator>>(T &t)
|
||||
{
|
||||
serializer >> t;
|
||||
return * this;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CLoadIntegrityValidator
|
||||
class DLL_LINKAGE CLoadIntegrityValidator
|
||||
: public IBinaryReader
|
||||
{
|
||||
public:
|
||||
CISer serializer;
|
||||
unique_ptr<CLoadFile> primaryFile, controlFile;
|
||||
CISer serializer;
|
||||
std::unique_ptr<CLoadFile> primaryFile, controlFile;
|
||||
bool foundDesync;
|
||||
|
||||
CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws!
|
||||
@ -1603,7 +1611,7 @@ public:
|
||||
int read( void * data, unsigned size) override; //throws!
|
||||
void checkMagicBytes(const std::string &text);
|
||||
|
||||
unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
|
||||
std::unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
|
||||
};
|
||||
|
||||
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
|
||||
@ -1620,7 +1628,7 @@ class DLL_LINKAGE CConnection
|
||||
public:
|
||||
CISer iser;
|
||||
COSer oser;
|
||||
|
||||
|
||||
boost::mutex *rmx, *wmx; // read/write mutexes
|
||||
TSocket * socket;
|
||||
bool logging;
|
||||
@ -1658,14 +1666,14 @@ public:
|
||||
|
||||
void prepareForSendingHeroes(); //disables sending vectorised, enables smart pointer serialization, clears saved/loaded ptr cache
|
||||
void enterPregameConnectionMode();
|
||||
|
||||
|
||||
template<class T>
|
||||
CConnection & operator>>(T &t)
|
||||
{
|
||||
iser >> t;
|
||||
return * this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
CConnection & operator<<(const T &t)
|
||||
{
|
||||
@ -1687,19 +1695,19 @@ class DLL_LINKAGE CMemorySerializer
|
||||
public:
|
||||
CISer iser;
|
||||
COSer oser;
|
||||
|
||||
|
||||
int read(void * data, unsigned size) override; //throws!
|
||||
int write(const void * data, unsigned size) override;
|
||||
|
||||
CMemorySerializer();
|
||||
|
||||
template <typename T>
|
||||
static unique_ptr<T> deepCopy(const T &data)
|
||||
static std::unique_ptr<T> deepCopy(const T &data)
|
||||
{
|
||||
CMemorySerializer mem;
|
||||
mem.oser << &data;
|
||||
|
||||
unique_ptr<T> ret;
|
||||
std::unique_ptr<T> ret;
|
||||
mem.iser >> ret;
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ namespace GameConstants
|
||||
const int SPELL_SCHOOL_LEVELS = 4;
|
||||
const int CRE_LEVELS = 10; // number of creature experience levels
|
||||
|
||||
const int HERO_GOLD_COST = 2500;
|
||||
const int SPELLBOOK_GOLD_COST = 500;
|
||||
const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
|
||||
const int ARMY_SIZE = 7;
|
||||
@ -837,10 +838,10 @@ public:
|
||||
// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines
|
||||
//8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields
|
||||
//15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog
|
||||
//21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||
//21. "favorable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||
enum EBFieldType {NONE = -1, NONE2, SAND_SHORE, SAND_MESAS, DIRT_BIRCHES, DIRT_HILLS, DIRT_PINES, GRASS_HILLS,
|
||||
GRASS_PINES, LAVA, MAGIC_PLAINS, SNOW_MOUNTAINS, SNOW_TREES, SUBTERRANEAN, SWAMP_TREES, FIERY_FIELDS,
|
||||
ROCKLANDS, MAGIC_CLOUDS, LUCID_POOLS, HOLY_GROUND, CLOVER_FIELD, EVIL_FOG, FAVOURABLE_WINDS, CURSED_GROUND,
|
||||
ROCKLANDS, MAGIC_CLOUDS, LUCID_POOLS, HOLY_GROUND, CLOVER_FIELD, EVIL_FOG, FAVORABLE_WINDS, CURSED_GROUND,
|
||||
ROUGH, SHIP_TO_SHIP, SHIP
|
||||
};
|
||||
|
||||
|
@ -64,19 +64,19 @@ const std::map<std::string, Bonus::LimitEffect> bonusLimitEffect =
|
||||
|
||||
const std::map<std::string, TLimiterPtr> bonusLimiterMap =
|
||||
{
|
||||
{"SHOOTER_ONLY", make_shared<HasAnotherBonusLimiter>(Bonus::SHOOTER)},
|
||||
{"DRAGON_NATURE", make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
|
||||
{"IS_UNDEAD", make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}
|
||||
{"SHOOTER_ONLY", std::make_shared<HasAnotherBonusLimiter>(Bonus::SHOOTER)},
|
||||
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
|
||||
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}
|
||||
};
|
||||
|
||||
const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
|
||||
{
|
||||
{"BATTLE_WIDE", make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE)},
|
||||
{"VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR)},
|
||||
{"PLAYER_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)},
|
||||
{"HERO", make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)},
|
||||
{"TEAM_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested
|
||||
{"GLOBAL_EFFECT", make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
|
||||
{"BATTLE_WIDE", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE)},
|
||||
{"VISITED_TOWN_AND_VISITOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR)},
|
||||
{"PLAYER_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)},
|
||||
{"HERO", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)},
|
||||
{"TEAM_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested
|
||||
{"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
|
||||
}; //untested
|
||||
|
||||
|
||||
@ -651,7 +651,7 @@ const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, c
|
||||
|
||||
//We still don't have the bonuses (didn't returned them from cache)
|
||||
//Perform bonus selection
|
||||
auto ret = make_shared<BonusList>();
|
||||
auto ret = std::make_shared<BonusList>();
|
||||
cachedBonuses.getBonuses(*ret, selector, limit);
|
||||
|
||||
// Save the results in the cache
|
||||
@ -668,7 +668,7 @@ const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, c
|
||||
|
||||
const TBonusListPtr CBonusSystemNode::getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= nullptr*/) const
|
||||
{
|
||||
auto ret = make_shared<BonusList>();
|
||||
auto ret = std::make_shared<BonusList>();
|
||||
|
||||
// Get bonus results without caching enabled.
|
||||
BonusList beforeLimiting, afterLimiting;
|
||||
@ -995,11 +995,6 @@ CBonusSystemNode::ENodeTypes CBonusSystemNode::getNodeType() const
|
||||
return nodeType;
|
||||
}
|
||||
|
||||
BonusList& CBonusSystemNode::getBonusList()
|
||||
{
|
||||
return bonuses;
|
||||
}
|
||||
|
||||
const BonusList& CBonusSystemNode::getBonusList() const
|
||||
{
|
||||
return bonuses;
|
||||
@ -1072,7 +1067,7 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
|
||||
|
||||
TBonusListPtr CBonusSystemNode::limitBonuses(const BonusList &allBonuses) const
|
||||
{
|
||||
auto ret = make_shared<BonusList>();
|
||||
auto ret = std::make_shared<BonusList>();
|
||||
limitBonuses(allBonuses, *ret);
|
||||
return ret;
|
||||
}
|
||||
@ -1323,7 +1318,7 @@ Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
|
||||
if(!limiterList)
|
||||
{
|
||||
//Create a new limiter list with old limiter and the new one will be pushed later
|
||||
limiterList = make_shared<LimiterList>();
|
||||
limiterList = std::make_shared<LimiterList>();
|
||||
limiterList->add(limiter);
|
||||
limiter = limiterList;
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ class ILimiter;
|
||||
class IPropagator;
|
||||
class BonusList;
|
||||
|
||||
typedef shared_ptr<BonusList> TBonusListPtr;
|
||||
typedef shared_ptr<ILimiter> TLimiterPtr;
|
||||
typedef shared_ptr<IPropagator> TPropagatorPtr;
|
||||
typedef std::shared_ptr<BonusList> TBonusListPtr;
|
||||
typedef std::shared_ptr<ILimiter> TLimiterPtr;
|
||||
typedef std::shared_ptr<IPropagator> TPropagatorPtr;
|
||||
typedef std::set<CBonusSystemNode*> TNodes;
|
||||
typedef std::set<const CBonusSystemNode*> TCNodes;
|
||||
typedef std::vector<CBonusSystemNode *> TNodesVector;
|
||||
@ -694,7 +694,6 @@ public:
|
||||
void exportBonus(Bonus * b);
|
||||
void exportBonuses();
|
||||
|
||||
BonusList &getBonusList();
|
||||
const BonusList &getBonusList() const;
|
||||
BonusList &getExportedBonusList();
|
||||
CBonusSystemNode::ENodeTypes getNodeType() const;
|
||||
|
@ -483,10 +483,10 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
|
||||
break;
|
||||
case JsonNode::DATA_STRUCT: //customizable limiters
|
||||
{
|
||||
shared_ptr<ILimiter> l;
|
||||
std::shared_ptr<ILimiter> l;
|
||||
if (limiter["type"].String() == "CREATURE_TYPE_LIMITER")
|
||||
{
|
||||
shared_ptr<CCreatureTypeLimiter> l2 = make_shared<CCreatureTypeLimiter>(); //TODO: How the hell resolve pointer to creature?
|
||||
std::shared_ptr<CCreatureTypeLimiter> l2 = std::make_shared<CCreatureTypeLimiter>(); //TODO: How the hell resolve pointer to creature?
|
||||
const JsonVector vec = limiter["parameters"].Vector();
|
||||
VLC->modh->identifiers.requestIdentifier("creature", vec[0], [=](si32 creature)
|
||||
{
|
||||
@ -503,7 +503,7 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
|
||||
}
|
||||
if (limiter["type"].String() == "HAS_ANOTHER_BONUS_LIMITER")
|
||||
{
|
||||
shared_ptr<HasAnotherBonusLimiter> l2 = make_shared<HasAnotherBonusLimiter>();
|
||||
std::shared_ptr<HasAnotherBonusLimiter> l2 = std::make_shared<HasAnotherBonusLimiter>();
|
||||
const JsonVector vec = limiter["parameters"].Vector();
|
||||
std::string anotherBonusType = vec[0].String();
|
||||
|
||||
|
@ -331,9 +331,6 @@ struct SetAvailableHeroes : public CPackForClient //113
|
||||
for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++)
|
||||
army[i].clear();
|
||||
}
|
||||
~SetAvailableHeroes()
|
||||
{
|
||||
}
|
||||
void applyCl(CClient *cl);
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
@ -446,7 +443,7 @@ struct UpdateCampaignState : public CPackForClient //119
|
||||
type = 119;
|
||||
}
|
||||
|
||||
shared_ptr<CCampaignState> camp;
|
||||
std::shared_ptr<CCampaignState> camp;
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -1684,7 +1681,7 @@ struct BattleObstaclePlaced : public CPackForClient //3020
|
||||
DLL_LINKAGE void applyGs(CGameState *gs); //effect
|
||||
void applyCl(CClient *cl); //play animations & stuff
|
||||
|
||||
shared_ptr<CObstacleInstance> obstacle;
|
||||
std::shared_ptr<CObstacleInstance> obstacle;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -223,7 +223,7 @@ DLL_LINKAGE void FoWChange::applyGs( CGameState *gs )
|
||||
case Obj::TOWN:
|
||||
case Obj::ABANDONED_MINE:
|
||||
if(vstd::contains(team->players, o->tempOwner)) //check owned observators
|
||||
gs->getTilesInRange(tiles, o->getSightCenter(), o->getSightRadious(), o->tempOwner, 1);
|
||||
gs->getTilesInRange(tilesRevealed, o->getSightCenter(), o->getSightRadious(), o->tempOwner, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1010,6 +1010,13 @@ DLL_LINKAGE void SetAvailableArtifacts::applyGs( CGameState *gs )
|
||||
DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
|
||||
{
|
||||
gs->day = day;
|
||||
|
||||
// Update bonuses before doing anything else so hero don't get more MP than needed
|
||||
gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs
|
||||
gs->globalEffects.updateBonuses(Bonus::NDays);
|
||||
gs->globalEffects.updateBonuses(Bonus::OneWeek);
|
||||
//TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...]
|
||||
|
||||
for(NewTurn::Hero h : heroes) //give mana/movement point
|
||||
{
|
||||
CGHeroInstance *hero = gs->getHero(h.id);
|
||||
@ -1026,11 +1033,6 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
|
||||
for(auto creatureSet : cres) //set available creatures in towns
|
||||
creatureSet.second.applyGs(gs);
|
||||
|
||||
gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs
|
||||
gs->globalEffects.updateBonuses(Bonus::NDays);
|
||||
gs->globalEffects.updateBonuses(Bonus::OneWeek);
|
||||
//TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...]
|
||||
|
||||
for(CGTownInstance* t : gs->map->towns)
|
||||
t->builded = 0;
|
||||
|
||||
|
@ -82,9 +82,9 @@ struct StartInfo
|
||||
ui8 turnTime; //in minutes, 0=unlimited
|
||||
std::string mapname; // empty for random map, otherwise name of the map or savegame
|
||||
bool createRandomMap() const { return mapGenOptions.get() != nullptr; }
|
||||
shared_ptr<CMapGenOptions> mapGenOptions;
|
||||
std::shared_ptr<CMapGenOptions> mapGenOptions;
|
||||
|
||||
shared_ptr<CCampaignState> campState;
|
||||
std::shared_ptr<CCampaignState> campState;
|
||||
|
||||
PlayerSettings & getIthPlayersSettings(PlayerColor no)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "GameConstants.h"
|
||||
|
||||
/*
|
||||
* GameConstants.h, part of VCMI engine
|
||||
* StringConstants.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -293,8 +293,10 @@
|
||||
<ClInclude Include="Connection.h" />
|
||||
<ClInclude Include="ConstTransitivePtr.h" />
|
||||
<ClInclude Include="CPathfinder.h" />
|
||||
<ClInclude Include="CPlayerState.h" />
|
||||
<ClInclude Include="CRandomGenerator.h" />
|
||||
<ClInclude Include="CScriptingModule.h" />
|
||||
<ClInclude Include="CSoundBase.h" />
|
||||
<ClInclude Include="CStopWatch.h" />
|
||||
<ClInclude Include="CThreadHelper.h" />
|
||||
<ClInclude Include="CTownHandler.h" />
|
||||
@ -313,6 +315,7 @@
|
||||
<ClInclude Include="filesystem\ResourceID.h" />
|
||||
<ClInclude Include="FunctionList.h" />
|
||||
<ClInclude Include="IBonusTypeHandler.h" />
|
||||
<ClInclude Include="IHandlerBase.h" />
|
||||
<ClInclude Include="JsonDetail.h" />
|
||||
<ClInclude Include="LogicalExpression.h" />
|
||||
<ClInclude Include="mapObjects\CArmedInstance.h" />
|
||||
@ -332,12 +335,15 @@
|
||||
<ClInclude Include="mapObjects\MiscObjects.h" />
|
||||
<ClInclude Include="mapObjects\ObjectTemplate.h" />
|
||||
<ClInclude Include="mapping\CCampaignHandler.h" />
|
||||
<ClInclude Include="mapping\CDrawRoadsOperation.h" />
|
||||
<ClInclude Include="mapping\CMap.h" />
|
||||
<ClInclude Include="mapping\CMapDefines.h" />
|
||||
<ClInclude Include="mapping\CMapInfo.h" />
|
||||
<ClInclude Include="mapping\CMapService.h" />
|
||||
<ClInclude Include="mapping\CMapEditManager.h" />
|
||||
<ClInclude Include="mapping\MapFormatH3M.h" />
|
||||
<ClInclude Include="mapping\MapFormatJson.h" />
|
||||
<ClInclude Include="NetPacksBase.h" />
|
||||
<ClInclude Include="registerTypes\RegisterTypes.h" />
|
||||
<ClInclude Include="rmg\CMapGenerator.h" />
|
||||
<ClInclude Include="logging\CLogger.h" />
|
||||
@ -360,6 +366,7 @@
|
||||
<ClInclude Include="rmg\CZoneGraphGenerator.h" />
|
||||
<ClInclude Include="rmg\CZonePlacer.h" />
|
||||
<ClInclude Include="rmg\float3.h" />
|
||||
<ClInclude Include="ScopeGuard.h" />
|
||||
<ClInclude Include="spells\AdventureSpellMechanics.h" />
|
||||
<ClInclude Include="spells\BattleSpellMechanics.h" />
|
||||
<ClInclude Include="spells\CDefaultSpellMechanics.h" />
|
||||
@ -371,7 +378,9 @@
|
||||
<ClInclude Include="spells\ViewSpellInt.h" />
|
||||
<ClInclude Include="StartInfo.h" />
|
||||
<ClInclude Include="StdInc.h" />
|
||||
<ClInclude Include="StringConstants.h" />
|
||||
<ClInclude Include="UnlockGuard.h" />
|
||||
<ClInclude Include="vcmi_endian.h" />
|
||||
<ClInclude Include="VCMI_Lib.h" />
|
||||
<ClInclude Include="VCMIDirs.h" />
|
||||
</ItemGroup>
|
||||
|
@ -155,8 +155,6 @@
|
||||
<ClCompile Include="registerTypes\TypesClientPacks1.cpp">
|
||||
<Filter>registerTypes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="registerTypes\TypesMapObjects1.cpp" />
|
||||
<ClCompile Include="registerTypes\TypesMapObjects2.cpp" />
|
||||
<ClCompile Include="mapObjects\CArmedInstance.cpp">
|
||||
<Filter>mapObjects</Filter>
|
||||
</ClCompile>
|
||||
@ -202,7 +200,6 @@
|
||||
<ClCompile Include="mapObjects\ObjectTemplate.cpp">
|
||||
<Filter>mapObjects</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="registerTypes\TypesMapObjects3.cpp" />
|
||||
<ClCompile Include="IHandlerBase.cpp" />
|
||||
<ClCompile Include="spells\AdventureSpellMechanics.cpp">
|
||||
<Filter>spells</Filter>
|
||||
@ -227,6 +224,15 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="mapping\CDrawRoadsOperation.cpp" />
|
||||
<ClCompile Include="CPathfinder.cpp" />
|
||||
<ClCompile Include="registerTypes\TypesMapObjects1.cpp">
|
||||
<Filter>registerTypes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="registerTypes\TypesMapObjects2.cpp">
|
||||
<Filter>registerTypes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="registerTypes\TypesMapObjects3.cpp">
|
||||
<Filter>registerTypes</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CCreatureSet.h">
|
||||
@ -541,5 +547,32 @@
|
||||
<ClInclude Include="CPathfinder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CPlayerState.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mapping\CMapDefines.h">
|
||||
<Filter>mapping</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CSoundBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IHandlerBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NetPacksBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScopeGuard.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vcmi_endian.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mapping\CDrawRoadsOperation.h">
|
||||
<Filter>mapping</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* CLodStream.h, part of VCMI engine
|
||||
* CCompressedStream.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -134,7 +134,7 @@ void CLogger::setLevel(ELogLevel::ELogLevel level)
|
||||
|
||||
const CLoggerDomain & CLogger::getDomain() const { return domain; }
|
||||
|
||||
void CLogger::addTarget(unique_ptr<ILogTarget> && target)
|
||||
void CLogger::addTarget(std::unique_ptr<ILogTarget> && target)
|
||||
{
|
||||
TLockGuard _(mx);
|
||||
targets.push_back(std::move(target));
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
|
||||
inline void log(ELogLevel::ELogLevel level, const std::string & message) const;
|
||||
|
||||
void addTarget(unique_ptr<ILogTarget> && target);
|
||||
void addTarget(std::unique_ptr<ILogTarget> && target);
|
||||
void clearTargets();
|
||||
|
||||
/// Returns true if a debug/trace log message will be logged, false if not.
|
||||
@ -121,7 +121,7 @@ private:
|
||||
CLoggerDomain domain;
|
||||
CLogger * parent;
|
||||
ELogLevel::ELogLevel level;
|
||||
std::vector<unique_ptr<ILogTarget> > targets;
|
||||
std::vector<std::unique_ptr<ILogTarget> > targets;
|
||||
mutable boost::mutex mx;
|
||||
static boost::recursive_mutex smx;
|
||||
};
|
||||
@ -149,7 +149,7 @@ private:
|
||||
/// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled.
|
||||
///
|
||||
#define RAII_TRACE(logger, onEntry, onLeave) \
|
||||
unique_ptr<CTraceLogger> ctl00; \
|
||||
std::unique_ptr<CTraceLogger> ctl00; \
|
||||
if(logger->isTraceEnabled()) \
|
||||
ctl00 = make_unique<CTraceLogger>(logger, onEntry, onLeave);
|
||||
|
||||
|
@ -46,7 +46,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
if(!validTypes(false)) //object not randomized, don't bother
|
||||
return;
|
||||
|
||||
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
Bonus *b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
if(!b)
|
||||
{
|
||||
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
|
||||
@ -96,10 +96,11 @@ void CArmedInstance::updateMoraleBonusFromArmy()
|
||||
b->description = b->description.substr(0, b->description.size()-2);//trim value
|
||||
}
|
||||
boost::algorithm::trim(b->description);
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
|
||||
//-1 modifier for any Undead unit in army
|
||||
const ui8 UNDEAD_MODIFIER_ID = -2;
|
||||
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
|
||||
Bonus *undeadModifier = getExportedBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
|
||||
if(hasUndead)
|
||||
{
|
||||
if(!undeadModifier)
|
||||
|
@ -292,9 +292,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
loot.addReplacement(*elem.second);
|
||||
}
|
||||
|
||||
if (ourArmy.Slots().size())
|
||||
if(ourArmy.stacksCount())
|
||||
{
|
||||
if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
|
||||
if(ourArmy.stacksCount() == 1 && ourArmy.Slots().begin()->second->count == 1)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
|
||||
else
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 186);
|
||||
|
@ -43,7 +43,7 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16
|
||||
|
||||
static int lowestSpeed(const CGHeroInstance * chi)
|
||||
{
|
||||
if(!chi->Slots().size())
|
||||
if(!chi->stacksCount())
|
||||
{
|
||||
logGlobal->errorStream() << "Error! Hero " << chi->id.getNum() << " ("<<chi->name<<") has no army!";
|
||||
return 20;
|
||||
@ -818,7 +818,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
|
||||
|
||||
|
||||
Bonus::ValueType skillValType = skillVal ? Bonus::BASE_NUMBER : Bonus::INDEPENDENT_MIN;
|
||||
if(Bonus * b = getBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which)
|
||||
if(Bonus * b = getExportedBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which)
|
||||
.And(Selector::sourceType(Bonus::SECONDARY_SKILL)))) //only local hero bonus
|
||||
{
|
||||
b->val = skillVal;
|
||||
@ -831,6 +831,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
|
||||
addNewBonus(bonus);
|
||||
}
|
||||
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
|
||||
{
|
||||
@ -1365,6 +1366,7 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si
|
||||
{
|
||||
skill->val += value;
|
||||
}
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
else if(primarySkill == PrimarySkill::EXPERIENCE)
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & patrolling;
|
||||
if(version >= 755)
|
||||
if(version >= 755) //save format backward compatibility
|
||||
{
|
||||
h & initialPos;
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
|
||||
if (creatures.Slots().size())
|
||||
if(creatures.stacksCount())
|
||||
{ //this part is taken straight from creature bank
|
||||
MetaString loot;
|
||||
for(auto & elem : creatures.Slots())
|
||||
@ -245,7 +245,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
|
||||
loot.addReplacement(*elem.second);
|
||||
}
|
||||
|
||||
if (creatures.Slots().size() == 1 && creatures.Slots().begin()->second->count == 1)
|
||||
if(creatures.stacksCount() == 1 && creatures.Slots().begin()->second->count == 1)
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 185);
|
||||
else
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 186);
|
||||
@ -303,17 +303,17 @@ void CGPandoraBox::battleFinished(const CGHeroInstance *hero, const BattleResult
|
||||
|
||||
void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
||||
{
|
||||
if (answer)
|
||||
if(answer)
|
||||
{
|
||||
if (stacksCount() > 0) //if pandora's box is protected by army
|
||||
if(stacksCount() > 0) //if pandora's box is protected by army
|
||||
{
|
||||
showInfoDialog(hero,16,0);
|
||||
cb->startBattleI(hero, this); //grants things after battle
|
||||
}
|
||||
else if (message.size() == 0 && resources.size() == 0
|
||||
else if(message.size() == 0 && resources.size() == 0
|
||||
&& primskills.size() == 0 && abilities.size() == 0
|
||||
&& abilityLevels.size() == 0 && artifacts.size() == 0
|
||||
&& spells.size() == 0 && creatures.Slots().size() > 0
|
||||
&& abilityLevels.size() == 0 && artifacts.size() == 0
|
||||
&& spells.size() == 0 && creatures.stacksCount() > 0
|
||||
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
|
||||
{
|
||||
showInfoDialog(hero,15,0);
|
||||
|
@ -856,7 +856,7 @@ void CGTownInstance::deserializationFix()
|
||||
|
||||
void CGTownInstance::updateMoraleBonusFromArmy()
|
||||
{
|
||||
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
Bonus *b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
|
||||
if(!b)
|
||||
{
|
||||
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
|
||||
@ -864,7 +864,10 @@ void CGTownInstance::updateMoraleBonusFromArmy()
|
||||
}
|
||||
|
||||
if (garrisonHero)
|
||||
{
|
||||
b->val = 0;
|
||||
CBonusSystemNode::treeHasChanged();
|
||||
}
|
||||
else
|
||||
CArmedInstance::updateMoraleBonusFromArmy();
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ int3 IBoatGenerator::bestLocation() const
|
||||
{
|
||||
if (const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
|
||||
{
|
||||
if (tile->terType == ETerrainType::WATER && (!tile->blocked || tile->blockingObjects.front()->ID == 8)) //and is water and is not blocked or is blocked by boat
|
||||
if (tile->terType == ETerrainType::WATER && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
|
||||
return o->pos + offset;
|
||||
}
|
||||
}
|
||||
|
@ -325,10 +325,10 @@ void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRando
|
||||
}
|
||||
}
|
||||
|
||||
CBankInfo::CBankInfo(JsonVector config):
|
||||
config(config)
|
||||
CBankInfo::CBankInfo(const JsonVector & Config):
|
||||
config(Config)
|
||||
{
|
||||
assert(!config.empty());
|
||||
assert(!Config.empty());
|
||||
}
|
||||
|
||||
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "CObjectClassesHandler.h"
|
||||
#include "../CTownHandler.h" // for building ID-based filters
|
||||
#include "MapObjects.h"
|
||||
|
||||
/*
|
||||
* CommonConstructors.h, part of VCMI engine
|
||||
@ -155,9 +156,9 @@ typedef std::vector<std::pair<ui8, IObjectInfo::CArmyStructure>> TPossibleGuards
|
||||
|
||||
class DLL_LINKAGE CBankInfo : public IObjectInfo
|
||||
{
|
||||
JsonVector config;
|
||||
const JsonVector & config;
|
||||
public:
|
||||
CBankInfo(JsonVector config);
|
||||
CBankInfo(const JsonVector & Config);
|
||||
|
||||
TPossibleGuards getPossibleGuards() const;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* CRewardableObject.cpp, part of VCMI engine
|
||||
* JsonRandom.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
|
@ -640,7 +640,6 @@ std::string CGMine::getObjectName() const
|
||||
|
||||
std::string CGMine::getHoverText(PlayerColor player) const
|
||||
{
|
||||
|
||||
std::string hoverName = getObjectName(); // Sawmill
|
||||
|
||||
if (tempOwner != PlayerColor::NEUTRAL)
|
||||
@ -650,11 +649,12 @@ std::string CGMine::getHoverText(PlayerColor player) const
|
||||
hoverName += "\n(" + VLC->generaltexth->restypes[producedResource] + ")";
|
||||
}
|
||||
|
||||
for (auto & slot : Slots()) // guarded by a few Pikeman
|
||||
if(stacksCount())
|
||||
{
|
||||
hoverName += "\n";
|
||||
hoverName += getRoughAmount(slot.first);
|
||||
hoverName += getCreature(slot.first)->namePl;
|
||||
hoverName += VLC->generaltexth->allTexts[202]; //Guarded by
|
||||
hoverName += " ";
|
||||
hoverName += getArmyDescription();
|
||||
}
|
||||
return hoverName;
|
||||
}
|
||||
@ -907,12 +907,12 @@ std::vector<ObjectInstanceID> CGTeleport::getPassableExits(CGameState * gs, cons
|
||||
return exits;
|
||||
}
|
||||
|
||||
void CGTeleport::addToChannel(std::map<TeleportChannelID, shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj)
|
||||
void CGTeleport::addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj)
|
||||
{
|
||||
shared_ptr<TeleportChannel> tc;
|
||||
std::shared_ptr<TeleportChannel> tc;
|
||||
if(channelsList.find(obj->channel) == channelsList.end())
|
||||
{
|
||||
tc = make_shared<TeleportChannel>();
|
||||
tc = std::make_shared<TeleportChannel>();
|
||||
channelsList.insert(std::make_pair(obj->channel, tc));
|
||||
}
|
||||
else
|
||||
@ -973,17 +973,18 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
|
||||
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
|
||||
{
|
||||
int3 dPos;
|
||||
auto randomExit = getRandomExit(hero);
|
||||
auto realExits = getAllExits(true);
|
||||
if(!isEntrance() // Do nothing if hero visited exit only object
|
||||
|| (!exits.size() && !realExits.size()) // Do nothing if there no exits on this channel
|
||||
|| (!exits.size() && ObjectInstanceID() == getRandomExit(hero))) // Do nothing if all exits are blocked by friendly hero and it's not subterranean gate
|
||||
|| ObjectInstanceID() == randomExit) // Do nothing if all exits are blocked by friendly hero and it's not subterranean gate
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(vstd::isValidIndex(exits, answer))
|
||||
dPos = exits[answer].second;
|
||||
else
|
||||
dPos = CGHeroInstance::convertPosition(cb->getObj(getRandomExit(hero))->visitablePos(), true);
|
||||
dPos = CGHeroInstance::convertPosition(cb->getObj(randomExit)->visitablePos(), true);
|
||||
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
}
|
||||
@ -1158,10 +1159,10 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
}
|
||||
|
||||
bool CGWhirlpool::isProtected( const CGHeroInstance * h )
|
||||
bool CGWhirlpool::isProtected(const CGHeroInstance * h)
|
||||
{
|
||||
if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION)
|
||||
|| (h->Slots().size() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit
|
||||
if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION) ||
|
||||
(h->stacksCount() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1196,7 +1197,7 @@ std::string CGArtifact::getObjectName() const
|
||||
return VLC->arth->artifacts[subID]->Name();
|
||||
}
|
||||
|
||||
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
|
||||
void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
|
||||
{
|
||||
if(!stacksCount())
|
||||
{
|
||||
@ -1207,28 +1208,32 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
|
||||
case Obj::ARTIFACT:
|
||||
{
|
||||
iw.soundID = soundBase::treasure; //play sound only for non-scroll arts
|
||||
iw.components.push_back(Component(Component::ARTIFACT,subID,0,0));
|
||||
iw.components.push_back(Component(Component::ARTIFACT, subID, 0, 0));
|
||||
if(message.length())
|
||||
iw.text << message;
|
||||
iw.text << message;
|
||||
else
|
||||
{
|
||||
if (VLC->arth->artifacts[subID]->EventText().size())
|
||||
iw.text << std::pair<ui8, ui32> (MetaString::ART_EVNTS, subID);
|
||||
if(VLC->arth->artifacts[subID]->EventText().size())
|
||||
iw.text << std::pair<ui8, ui32>(MetaString::ART_EVNTS, subID);
|
||||
else //fix for mod artifacts with no event text
|
||||
{
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 183); //% has found treasure
|
||||
iw.text.addReplacement (h->name);
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure
|
||||
iw.text.addReplacement(h->name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Obj::SPELL_SCROLL:
|
||||
{
|
||||
int spellID = storedArtifact->getGivenSpellID();
|
||||
iw.components.push_back (Component(Component::SPELL, spellID,0,0));
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT,135);
|
||||
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
|
||||
iw.components.push_back(Component(Component::SPELL, spellID, 0, 0));
|
||||
if(message.length())
|
||||
iw.text << message;
|
||||
else
|
||||
{
|
||||
iw.text.addTxt(MetaString::ADVOB_TXT,135);
|
||||
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1237,16 +1242,38 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
else
|
||||
{
|
||||
if(message.size())
|
||||
switch(ID)
|
||||
{
|
||||
BlockingDialog ynd(true,false);
|
||||
ynd.player = h->getOwner();
|
||||
ynd.text << message;
|
||||
cb->showBlockingDialog(&ynd);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockingDialogAnswered(h, true);
|
||||
case Obj::ARTIFACT:
|
||||
{
|
||||
BlockingDialog ynd(true,false);
|
||||
ynd.player = h->getOwner();
|
||||
if(message.length())
|
||||
ynd.text << message;
|
||||
else
|
||||
{
|
||||
// TODO: Guard text is more complex in H3, see mantis issue 2325 for details
|
||||
ynd.text.addTxt(MetaString::GENERAL_TXT, 420);
|
||||
ynd.text.addReplacement("");
|
||||
ynd.text.addReplacement(getArmyDescription());
|
||||
ynd.text.addReplacement(MetaString::GENERAL_TXT, 43); // creatures
|
||||
}
|
||||
cb->showBlockingDialog(&ynd);
|
||||
}
|
||||
break;
|
||||
case Obj::SPELL_SCROLL:
|
||||
{
|
||||
if(message.length())
|
||||
{
|
||||
BlockingDialog ynd(true,false);
|
||||
ynd.player = h->getOwner();
|
||||
ynd.text << message;
|
||||
cb->showBlockingDialog(&ynd);
|
||||
}
|
||||
else
|
||||
blockingDialogAnswered(h, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ public:
|
||||
static bool isTeleport(const CGObjectInstance * dst);
|
||||
static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
|
||||
static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * dst);
|
||||
static void addToChannel(std::map<TeleportChannelID, shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
|
||||
static void addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
|
||||
static std::vector<ObjectInstanceID> getPassableExits(CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
|
||||
static bool isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj);
|
||||
|
||||
|
@ -40,7 +40,7 @@ CCampaignHeader CCampaignHandler::getHeader( const std::string & name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
|
||||
std::unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
|
||||
{
|
||||
auto ret = make_unique<CCampaign>();
|
||||
|
||||
@ -411,7 +411,7 @@ CCampaignState::CCampaignState()
|
||||
|
||||
}
|
||||
|
||||
CCampaignState::CCampaignState( unique_ptr<CCampaign> _camp ) : camp(std::move(_camp))
|
||||
CCampaignState::CCampaignState( std::unique_ptr<CCampaign> _camp ) : camp(std::move(_camp))
|
||||
{
|
||||
for(int i = 0; i < camp->scenarios.size(); i++)
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ public:
|
||||
class DLL_LINKAGE CCampaignState
|
||||
{
|
||||
public:
|
||||
unique_ptr<CCampaign> camp;
|
||||
std::unique_ptr<CCampaign> camp;
|
||||
std::string campaignName;
|
||||
std::vector<ui8> mapsConquered, mapsRemaining;
|
||||
boost::optional<si32> currentMap;
|
||||
@ -159,7 +159,7 @@ public:
|
||||
ui8 currentBonusID() const;
|
||||
|
||||
CCampaignState();
|
||||
CCampaignState(unique_ptr<CCampaign> _camp);
|
||||
CCampaignState(std::unique_ptr<CCampaign> _camp);
|
||||
~CCampaignState(){};
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -184,5 +184,5 @@ public:
|
||||
|
||||
static CCampaignHeader getHeader( const std::string & name); //name - name of appropriate file
|
||||
|
||||
static unique_ptr<CCampaign> getCampaign(const std::string & name); //name - name of appropriate file
|
||||
static std::unique_ptr<CCampaign> getCampaign(const std::string & name); //name - name of appropriate file
|
||||
};
|
||||
|
@ -153,7 +153,7 @@ EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
|
||||
return EDiggingStatus::CAN_DIG;
|
||||
}
|
||||
|
||||
bool TerrainTile::hasFavourableWinds() const
|
||||
bool TerrainTile::hasFavorableWinds() const
|
||||
{
|
||||
return extTileFlags & 128;
|
||||
}
|
||||
|
@ -319,12 +319,12 @@ public:
|
||||
|
||||
//Helper lists
|
||||
std::vector< ConstTransitivePtr<CGHeroInstance> > heroesOnMap;
|
||||
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > teleportChannels;
|
||||
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > teleportChannels;
|
||||
|
||||
/// associative list to identify which hero/creature id belongs to which object id(index for objects)
|
||||
std::map<si32, ObjectInstanceID> questIdentifierToId;
|
||||
|
||||
unique_ptr<CMapEditManager> editManager;
|
||||
std::unique_ptr<CMapEditManager> editManager;
|
||||
|
||||
int3 ***guardingCreaturePositions;
|
||||
|
||||
|
@ -71,7 +71,7 @@ struct DLL_LINKAGE TerrainTile
|
||||
CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
|
||||
bool isWater() const;
|
||||
EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
|
||||
bool hasFavourableWinds() const;
|
||||
bool hasFavorableWinds() const;
|
||||
|
||||
ETerrainType terType;
|
||||
ui8 terView;
|
||||
@ -80,7 +80,7 @@ struct DLL_LINKAGE TerrainTile
|
||||
ERoadType::ERoadType roadType;
|
||||
ui8 roadDir;
|
||||
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road);
|
||||
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favourable Winds effect
|
||||
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
|
||||
ui8 extTileFlags;
|
||||
bool visitable;
|
||||
bool blocked;
|
||||
|
@ -189,7 +189,7 @@ const CMapOperation * CMapUndoManager::peekUndo() const
|
||||
return peek(undoStack);
|
||||
}
|
||||
|
||||
void CMapUndoManager::addOperation(unique_ptr<CMapOperation> && operation)
|
||||
void CMapUndoManager::addOperation(std::unique_ptr<CMapOperation> && operation)
|
||||
{
|
||||
undoStack.push_front(std::move(operation));
|
||||
if(undoStack.size() > undoRedoLimit) undoStack.pop_back();
|
||||
@ -252,7 +252,7 @@ void CMapEditManager::insertObject(CGObjectInstance * obj, const int3 & pos)
|
||||
execute(make_unique<CInsertObjectOperation>(map, obj, pos));
|
||||
}
|
||||
|
||||
void CMapEditManager::execute(unique_ptr<CMapOperation> && operation)
|
||||
void CMapEditManager::execute(std::unique_ptr<CMapOperation> && operation)
|
||||
{
|
||||
operation->execute();
|
||||
undoManager.addOperation(std::move(operation));
|
||||
@ -302,7 +302,7 @@ void CComposedOperation::redo()
|
||||
}
|
||||
}
|
||||
|
||||
void CComposedOperation::addOperation(unique_ptr<CMapOperation> && operation)
|
||||
void CComposedOperation::addOperation(std::unique_ptr<CMapOperation> && operation)
|
||||
{
|
||||
operations.push_back(std::move(operation));
|
||||
}
|
||||
|
@ -144,10 +144,10 @@ public:
|
||||
const CMapOperation * peekRedo() const;
|
||||
const CMapOperation * peekUndo() const;
|
||||
|
||||
void addOperation(unique_ptr<CMapOperation> && operation); /// Client code does not need to call this method.
|
||||
void addOperation(std::unique_ptr<CMapOperation> && operation); /// Client code does not need to call this method.
|
||||
|
||||
private:
|
||||
typedef std::list<unique_ptr<CMapOperation> > TStack;
|
||||
typedef std::list<std::unique_ptr<CMapOperation> > TStack;
|
||||
|
||||
void doOperation(TStack & fromStack, TStack & toStack, bool doUndo);
|
||||
const CMapOperation * peek(const TStack & stack) const;
|
||||
@ -182,7 +182,7 @@ public:
|
||||
CMapUndoManager & getUndoManager();
|
||||
|
||||
private:
|
||||
void execute(unique_ptr<CMapOperation> && operation);
|
||||
void execute(std::unique_ptr<CMapOperation> && operation);
|
||||
|
||||
CMap * map;
|
||||
CMapUndoManager undoManager;
|
||||
@ -205,10 +205,10 @@ public:
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
void addOperation(unique_ptr<CMapOperation> && operation);
|
||||
void addOperation(std::unique_ptr<CMapOperation> && operation);
|
||||
|
||||
private:
|
||||
std::list<unique_ptr<CMapOperation> > operations;
|
||||
std::list<std::unique_ptr<CMapOperation> > operations;
|
||||
};
|
||||
|
||||
namespace ETerrainGroup
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Forward class declarations aren't enough here. The compiler
|
||||
// generated CMapInfo d-tor, generates the unique_ptr d-tor as well here
|
||||
// as a inline method. The unique_ptr d-tor requires a complete type. Defining
|
||||
// generated CMapInfo d-tor, generates the std::unique_ptr d-tor as well here
|
||||
// as a inline method. The std::unique_ptr d-tor requires a complete type. Defining
|
||||
// the CMapInfo d-tor to let the compiler add the d-tor stuff in the .cpp file
|
||||
// would work with one exception. It prevents the generation of the move
|
||||
// constructor which is needed. (Writing such a c-tor is nasty.) With the
|
||||
@ -20,8 +20,8 @@ struct StartInfo;
|
||||
class DLL_LINKAGE CMapInfo
|
||||
{
|
||||
public:
|
||||
unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
|
||||
unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario
|
||||
std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
|
||||
std::unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario
|
||||
StartInfo * scenarioOpts; //options with which scenario has been started (used only with saved games)
|
||||
std::string fileURI;
|
||||
std::string date;
|
||||
|
@ -52,7 +52,7 @@ class DLL_LINKAGE CMapGenerator
|
||||
{
|
||||
public:
|
||||
explicit CMapGenerator();
|
||||
~CMapGenerator(); // required due to unique_ptr
|
||||
~CMapGenerator(); // required due to std::unique_ptr
|
||||
|
||||
std::unique_ptr<CMap> generate(CMapGenOptions * mapGenOptions, int RandomSeed = std::time(nullptr));
|
||||
|
||||
|
@ -28,7 +28,7 @@ CZoneGraphGenerator::CZoneGraphGenerator()// : gen(nullptr)
|
||||
|
||||
}
|
||||
|
||||
unique_ptr<CZoneGraph> CZoneGraphGenerator::generate(const CMapGenOptions & options, CRandomGenerator * gen)
|
||||
std::unique_ptr<CZoneGraph> CZoneGraphGenerator::generate(const CMapGenOptions & options, CRandomGenerator * gen)
|
||||
{
|
||||
return make_unique<CZoneGraph>();
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user