1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Merge branch 'develop' into feature/VCMIMapFormat1

Conflicts:
	lib/CArtHandler.cpp
This commit is contained in:
AlexVinS 2016-01-01 20:28:52 +03:00
commit 37d0dad70a
114 changed files with 1077 additions and 813 deletions

View File

@ -8,7 +8,7 @@
#include "../../lib/VCMI_Lib.h" #include "../../lib/VCMI_Lib.h"
using boost::optional; using boost::optional;
static shared_ptr<CBattleCallback> cbc; static std::shared_ptr<CBattleCallback> cbc;
#define LOGL(text) print(text) #define LOGL(text) print(text)
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl)) #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"); print("init called, saving ptr to IBattleCallback");
cbc = cb = CB; 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 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); const TBonusListPtr originalList = stack->getAllBonuses(selector, limit, root, cachingStr);
range::copy(*originalList, std::back_inserter(*ret)); range::copy(*originalList, std::back_inserter(*ret));
for(auto &bonus : bonusesToAdd) for(auto &bonus : bonusesToAdd)

View File

@ -110,7 +110,7 @@ struct PotentialTargets
class CBattleAI : public CBattleGameInterface class CBattleAI : public CBattleGameInterface
{ {
int side; int side;
shared_ptr<CBattleCallback> cb; std::shared_ptr<CBattleCallback> cb;
//Previous setting of cb //Previous setting of cb
bool wasWaitingForRealize, wasUnlockingGs; bool wasWaitingForRealize, wasUnlockingGs;
@ -120,7 +120,7 @@ public:
CBattleAI(void); CBattleAI(void);
~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 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 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 BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack

View File

@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName); 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>();
} }

View File

@ -3,7 +3,7 @@
#include "../../lib/CRandomGenerator.h" #include "../../lib/CRandomGenerator.h"
void CEmptyAI::init(shared_ptr<CCallback> CB) void CEmptyAI::init(std::shared_ptr<CCallback> CB)
{ {
cb = CB; cb = CB;
human=false; human=false;

View File

@ -7,10 +7,10 @@ struct HeroMoveDetails;
class CEmptyAI : public CGlobalAI class CEmptyAI : public CGlobalAI
{ {
shared_ptr<CCallback> cb; std::shared_ptr<CCallback> cb;
public: public:
void init(shared_ptr<CCallback> CB) override; void init(std::shared_ptr<CCallback> CB) override;
void yourTurn() override; void yourTurn() override;
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) 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; void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;

View File

@ -13,7 +13,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy(name,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>();
} }

View File

@ -5,7 +5,7 @@
#include "../../CCallback.h" #include "../../CCallback.h"
#include "../../lib/CCreatureHandler.h" #include "../../lib/CCreatureHandler.h"
static shared_ptr<CBattleCallback> cbc; static std::shared_ptr<CBattleCallback> cbc;
CStupidAI::CStupidAI(void) CStupidAI::CStupidAI(void)
: side(-1) : side(-1)
@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void)
print("destroyed"); print("destroyed");
} }
void CStupidAI::init(shared_ptr<CBattleCallback> CB) void CStupidAI::init(std::shared_ptr<CBattleCallback> CB)
{ {
print("init called, saving ptr to IBattleCallback"); print("init called, saving ptr to IBattleCallback");
cbc = cb = CB; cbc = cb = CB;

View File

@ -5,14 +5,14 @@
class CStupidAI : public CBattleGameInterface class CStupidAI : public CBattleGameInterface
{ {
int side; int side;
shared_ptr<CBattleCallback> cb; std::shared_ptr<CBattleCallback> cb;
void print(const std::string &text) const; void print(const std::string &text) const;
public: public:
CStupidAI(void); CStupidAI(void);
~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 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 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 BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack

View File

@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName); 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>();
} }

View File

@ -23,7 +23,6 @@ class CCallback;
typedef const int3& crint3; typedef const int3& crint3;
typedef const std::string& crstring; 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 GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7; const int ACTUAL_RESOURCE_COUNT = 7;
const int ALLOWED_ROAMING_HEROES = 8; const int ALLOWED_ROAMING_HEROES = 8;

View File

@ -31,7 +31,6 @@ class Engine;
class InputVariable; class InputVariable;
class CGTownInstance; class CGTownInstance;
using namespace vstd;
//using namespace Goals; //using namespace Goals;
FuzzyHelper *fh; FuzzyHelper *fh;
@ -85,7 +84,7 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
if (walker) if (walker)
walkersStrenght += s.second->getPower(); 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; armyStructure as;
as.walkers = walkersStrenght / totalStrenght; as.walkers = walkersStrenght / totalStrenght;
@ -297,7 +296,7 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
delete threat; 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) Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{ {

View File

@ -83,5 +83,5 @@ public:
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec); 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);
}; };

View File

@ -19,12 +19,11 @@ extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai; extern boost::thread_specific_ptr<VCAI> ai;
extern FuzzyHelper * fh; //TODO: this logic should be moved inside VCAI extern FuzzyHelper * fh; //TODO: this logic should be moved inside VCAI
using namespace vstd;
using namespace Goals; using namespace Goals;
TSubgoal Goals::sptr(const AbstractGoal & tmp) TSubgoal Goals::sptr(const AbstractGoal & tmp)
{ {
shared_ptr<AbstractGoal> ptr; std::shared_ptr<AbstractGoal> ptr;
ptr.reset(tmp.clone()); ptr.reset(tmp.clone());
return ptr; return ptr;
} }
@ -575,7 +574,7 @@ TGoalVec Explore::getAllPossibleSubgoals()
{ {
//heroes = ai->getUnblockedHeroes(); //heroes = ai->getUnblockedHeroes();
heroes = cb->getHeroesInfo(); 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 if (ai->getGoal(h)->goalType == Goals::EXPLORE) //do not reassign hero who is already explorer
return true; return true;
@ -693,8 +692,8 @@ TSubgoal RecruitHero::whatToDoToAchieve()
if(!t) if(!t)
return sptr (Goals::BuildThis(BuildingID::TAVERN)); return sptr (Goals::BuildThis(BuildingID::TAVERN));
if(cb->getResourceAmount(Res::GOLD) < HERO_GOLD_COST) if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST)
return sptr (Goals::CollectRes(Res::GOLD, HERO_GOLD_COST)); return sptr (Goals::CollectRes(Res::GOLD, GameConstants::HERO_GOLD_COST));
return iAmElementar(); return iAmElementar();
} }
@ -749,7 +748,7 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
} }
if(ret.empty()) if(ret.empty())
{ {
auto obj = frontOrNull(cb->getVisitableObjs(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(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 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
@ -767,7 +766,7 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
TSubgoal DigAtTile::whatToDoToAchieve() 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 if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest
{ {
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj); const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj);
@ -1057,7 +1056,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
auto otherHeroes = cb->getHeroesInfo(); auto otherHeroes = cb->getHeroesInfo();
auto heroDummy = hero; 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) return (h == heroDummy.h || !ai->isAccessibleForHero(heroDummy->visitablePos(), h, true)
|| !ai->canGetArmy(heroDummy.h, h) || ai->getGoal(h)->goalType == Goals::GATHER_ARMY); || !ai->canGetArmy(heroDummy.h, h) || ai->getGoal(h)->goalType == Goals::GATHER_ARMY);

View File

@ -107,7 +107,7 @@ public:
static TSubgoal tryRecruitHero(); static TSubgoal tryRecruitHero();
///Visitor pattern ///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 void accept (VCAI * ai); //unhandled goal will report standard error
virtual float accept (FuzzyHelper * f); virtual float accept (FuzzyHelper * f);
@ -162,7 +162,7 @@ public:
TSubgoal iAmElementar() TSubgoal iAmElementar()
{ {
setisElementar(true); setisElementar(true);
shared_ptr<AbstractGoal> ptr; std::shared_ptr<AbstractGoal> ptr;
ptr.reset(clone()); ptr.reset(clone());
return ptr; return ptr;
} }

View File

@ -13,7 +13,7 @@
/* /*
* CCreatureHandler.h, part of VCMI engine * VCAI.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -29,8 +29,6 @@ class CGVisitableOPW;
const double SAFE_ATTACK_CONSTANT = 1.5; 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) 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 //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<CCallback> cb;
boost::thread_specific_ptr<VCAI> ai; boost::thread_specific_ptr<VCAI> ai;
@ -124,8 +122,8 @@ void VCAI::heroMoved(const TryMoveHero & details)
{ {
const int3 from = CGHeroInstance::convertPosition(details.start, false), const int3 from = CGHeroInstance::convertPosition(details.start, false),
to = CGHeroInstance::convertPosition(details.end, false); to = CGHeroInstance::convertPosition(details.end, false);
const CGObjectInstance *o1 = frontOrNull(cb->getVisitableObjs(from)), const CGObjectInstance *o1 = vstd::frontOrNull(cb->getVisitableObjs(from)),
*o2 = frontOrNull(cb->getVisitableObjs(to)); *o2 = vstd::frontOrNull(cb->getVisitableObjs(to));
auto t1 = dynamic_cast<const CGTeleport *>(o1); auto t1 = dynamic_cast<const CGTeleport *>(o1);
auto t2 = dynamic_cast<const CGTeleport *>(o2); auto t2 = dynamic_cast<const CGTeleport *>(o2);
@ -394,8 +392,8 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
LOG_TRACE(logAi); LOG_TRACE(logAi);
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
erase_if_present(visitableObjs, obj); vstd::erase_if_present(visitableObjs, obj);
erase_if_present(alreadyVisited, obj); vstd::erase_if_present(alreadyVisited, obj);
for (auto h : cb->getHeroesInfo()) for (auto h : cb->getHeroesInfo())
unreserveObject(h, obj); unreserveObject(h, obj);
@ -518,7 +516,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
{ {
//we don't want to visit know object twice (do we really?) //we don't want to visit know object twice (do we really?)
if(sop->val == playerID.getNum()) if(sop->val == playerID.getNum())
erase_if_present(visitableObjs, myCb->getObj(sop->id)); vstd::erase_if_present(visitableObjs, myCb->getObj(sop->id));
else if(myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES) else if(myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
{ {
//we want to visit objects owned by oppponents //we want to visit objects owned by oppponents
@ -526,7 +524,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
if (obj) if (obj)
{ {
addVisitableObj(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; NET_EVENT_HANDLER;
} }
void VCAI::init(shared_ptr<CCallback> CB) void VCAI::init(std::shared_ptr<CCallback> CB)
{ {
LOG_TRACE(logAi); LOG_TRACE(logAi);
myCb = CB; myCb = CB;
@ -738,7 +736,7 @@ void VCAI::makeTurn()
if (isWeeklyRevisitable(obj)) if (isWeeklyRevisitable(obj))
{ {
addVisitableObj(obj); addVisitableObj(obj);
erase_if_present (alreadyVisited, obj); vstd::erase_if_present(alreadyVisited, obj);
} }
} }
} }
@ -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 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 //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 return true; //at least one exchange will be performed
else else
return false; //no further exchange possible 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++) 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->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)); cb->mergeOrSwapStacks(armyPtr, army, SlotID(j), SlotID(i));
} }
} }
@ -1052,6 +1050,9 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST) if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
continue; //don't reequip artifact we already wear continue; //don't reequip artifact we already wear
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
continue;
auto s = location.getSlot(); auto s = location.getSlot();
if (!s || s->locked) //we can't move locks if (!s || s->locked) //we can't move locks
continue; continue;
@ -1118,7 +1119,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit
// if(containsSavedRes(c->cost)) // if(containsSavedRes(c->cost))
// continue; // continue;
amin(count, freeResources() / VLC->creh->creatures[creID]->cost); vstd::amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
if(count > 0) if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i); cb->recruitCreatures(d, recruiter, creID, count, i);
} }
@ -1445,7 +1446,7 @@ bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
if (!t) if (!t)
t = findTownWithTavern(); t = findTownWithTavern();
if (t) 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->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES &&
cb->getAvailableHeroes(t).size(); cb->getAvailableHeroes(t).size();
else else
@ -1481,7 +1482,7 @@ void VCAI::wander(HeroPtr h)
} }
range::copy(getPossibleDestinations(h), std::back_inserter(dests)); 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())); return !isSafeToVisit(h, sm->firstTileToGet(h, obj->visitablePos()));
}); });
@ -1530,10 +1531,10 @@ void VCAI::wander(HeroPtr h)
} }
break; 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(); 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()) for(const CGHeroInstance *h : cb->getHeroesInfo())
if(!t->getArmyStrength() || howManyReinforcementsCanGet(h, t)) if(!t->getArmyStrength() || howManyReinforcementsCanGet(h, t))
@ -1585,7 +1586,7 @@ void VCAI::wander(HeroPtr h)
void VCAI::setGoal(HeroPtr h, Goals::TSubgoal goal) void VCAI::setGoal(HeroPtr h, Goals::TSubgoal goal)
{ //TODO: check for presence? { //TODO: check for presence?
if(goal->invalid()) if(goal->invalid())
erase_if_present(lockedHeroes, h); vstd::erase_if_present(lockedHeroes, h);
else else
{ {
lockedHeroes[h] = goal; lockedHeroes[h] = goal;
@ -1626,7 +1627,7 @@ void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int
NET_EVENT_HANDLER; NET_EVENT_HANDLER;
assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE); assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE);
status.setBattle(ONGOING_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); 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); 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) void VCAI::unreserveObject(HeroPtr h, const CGObjectInstance *obj)
{ {
erase_if_present(reservedObjs, obj); //unreserve objects vstd::erase_if_present(reservedObjs, obj); //unreserve objects
erase_if_present(reservedHeroesMap[h], obj); vstd::erase_if_present(reservedHeroesMap[h], obj);
} }
void VCAI::markHeroUnableToExplore (HeroPtr h) void VCAI::markHeroUnableToExplore (HeroPtr h)
@ -1676,7 +1677,7 @@ void VCAI::markHeroUnableToExplore (HeroPtr h)
} }
void VCAI::markHeroAbleToExplore (HeroPtr h) void VCAI::markHeroAbleToExplore (HeroPtr h)
{ {
erase_if_present(heroesUnableToExplore, h); vstd::erase_if_present(heroesUnableToExplore, h);
} }
bool VCAI::isAbleToExplore (HeroPtr h) bool VCAI::isAbleToExplore (HeroPtr h)
{ {
@ -1697,7 +1698,7 @@ void VCAI::validateVisitableObjs()
auto shouldBeErased = [&](const CGObjectInstance *obj) -> bool auto shouldBeErased = [&](const CGObjectInstance *obj) -> bool
{ {
if (obj) if (obj)
return !cb->getObj(obj->id); return !cb->getObj(obj->id, false); // no verbose output needed as we check object visibility
else else
return true; return true;
@ -1713,25 +1714,25 @@ void VCAI::validateVisitableObjs()
//errorMsg is captured by ref so lambda will take the new text //errorMsg is captured by ref so lambda will take the new text
errorMsg = " shouldn't be on the visitable objects list!"; 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? //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); return !hp.first.get(true);
}); });
for(auto &p : reservedHeroesMap) for(auto &p : reservedHeroesMap)
{ {
errorMsg = " shouldn't be on list for hero " + p.first->name + "!"; 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!"; 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. //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!"; 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 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; std::vector<const CGObjectInstance *> ret;
retreiveVisitableObjs(ret, true); retreiveVisitableObjs(ret, true);
erase_if(ret, [](const CGObjectInstance *obj) vstd::erase_if(ret, [](const CGObjectInstance *obj)
{ {
return obj->tempOwner != ai->playerID; return obj->tempOwner != ai->playerID;
}); });
@ -1784,7 +1785,7 @@ const CGObjectInstance * VCAI::lookForArt(int aid) const
{ {
for(const CGObjectInstance *obj : ai->visitableObjs) for(const CGObjectInstance *obj : ai->visitableObjs)
{ {
if(obj->ID == 5 && obj->subID == aid) if(obj->ID == Obj::ARTIFACT && obj->subID == aid)
return obj; return obj;
} }
@ -1876,6 +1877,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst; logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst;
throw goalFulfilledException (sptr(Goals::VisitTile(dst).sethero(h))); throw goalFulfilledException (sptr(Goals::VisitTile(dst).sethero(h)));
} }
int i = path.nodes.size()-1;
auto getObj = [&](int3 coord, bool ignoreHero) auto getObj = [&](int3 coord, bool ignoreHero)
{ {
@ -1885,6 +1887,31 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
//return cb->getTile(coord,false)->topVisitableObj(ignoreHero); //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) auto doMovement = [&](int3 dst, bool transit)
{ {
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit); cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
@ -1915,17 +1942,18 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
doTeleportMovement(currentExit, currentPos); doTeleportMovement(currentExit, currentPos);
}; };
int i=path.nodes.size()-1;
for(; i>0; i--) for(; i>0; i--)
{ {
int3 currentCoord = path.nodes[i].coord; int3 currentCoord = path.nodes[i].coord;
int3 nextCoord = path.nodes[i-1].coord; int3 nextCoord = path.nodes[i-1].coord;
auto currentObject = getObj(currentCoord, currentCoord == CGHeroInstance::convertPosition(h->pos,false)); auto currentObject = getObj(currentCoord, currentCoord == CGHeroInstance::convertPosition(h->pos,false));
auto nextObject = getObj(nextCoord, false); auto nextObjectTop = getObj(nextCoord, false);
if(CGTeleport::isConnected(currentObject, nextObject)) 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 { //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()) if(teleportChannelProbingList.size())
doChannelProbing(); doChannelProbing();
@ -1944,8 +1972,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
continue; continue;
if((i-2 >= 0) // Check there is node after next one; otherwise transit is pointless 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::isConnected(nextObjectTop, getObj(path.nodes[i-2].coord, false))
|| CGTeleport::isTeleport(nextObject))) || CGTeleport::isTeleport(nextObjectTop)))
{ // Hero should be able to go through object if it's allow transit { // Hero should be able to go through object if it's allow transit
doMovement(endpos, true); doMovement(endpos, true);
} }
@ -1963,7 +1991,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
} }
if (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) if (visitedObject != *h)
performObjectInteraction (visitedObject, h); performObjectInteraction (visitedObject, h);
@ -1976,14 +2004,14 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
if(!ret) //reserve object we are heading towards if(!ret) //reserve object we are heading towards
{ {
auto obj = frontOrNull(cb->getVisitableObjs(dst)); auto obj = vstd::frontOrNull(cb->getVisitableObjs(dst));
if(obj && obj != *h) if(obj && obj != *h)
reserveObject(h, obj); 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 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; logAi->debugStream() << boost::format("Hero %s moved from %s to %s. Returning %d.") % h->name % startHpos % h->visitablePos() % ret;
@ -2290,7 +2318,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
} }
else 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
} }
} }
@ -2545,7 +2573,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
for (int i = 1; i < radius; i++) for (int i = 1; i < radius; i++)
{ {
getVisibleNeighbours(tiles[i-1], tiles[i]); getVisibleNeighbours(tiles[i-1], tiles[i]);
removeDuplicates(tiles[i]); vstd::removeDuplicates(tiles[i]);
for(const int3 &tile : tiles[i]) for(const int3 &tile : tiles[i])
{ {
@ -2593,7 +2621,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
for(int i = 1; i < radius; i++) for(int i = 1; i < radius; i++)
{ {
getVisibleNeighbours(tiles[i-1], tiles[i]); getVisibleNeighbours(tiles[i-1], tiles[i]);
removeDuplicates(tiles[i]); vstd::removeDuplicates(tiles[i]);
for(const int3 &tile : tiles[i]) for(const int3 &tile : tiles[i])
{ {
@ -2705,37 +2733,26 @@ void VCAI::finish()
void VCAI::requestActionASAP(std::function<void()> whatToDo) void VCAI::requestActionASAP(std::function<void()> whatToDo)
{ {
boost::mutex mutex; boost::thread newThread([this,whatToDo]()
mutex.lock();
boost::thread newThread([&mutex,this,whatToDo]()
{ {
setThreadName("VCAI::requestActionASAP::helper"); setThreadName("VCAI::requestActionASAP::whatToDo");
SET_GLOBAL_STATE(this); SET_GLOBAL_STATE(this);
boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex()); boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
// unlock mutex and allow parent function to exit
mutex.unlock();
whatToDo(); 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) void VCAI::lostHero(HeroPtr h)
{ {
logAi->debugStream() << boost::format("I lost my hero %s. It's best to forget and move on.") % h.name; 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]) 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); vstd::erase_if_present(reservedHeroesMap, h);
erase_if_present(cachedSectorMaps, h); vstd::erase_if_present(cachedSectorMaps, h);
} }
void VCAI::answerQuery(QueryID queryID, int selection) void VCAI::answerQuery(QueryID queryID, int selection)
@ -2779,12 +2796,12 @@ 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) if(!obj)
{ {
erase_if(visitableObjs, matchesId); vstd::erase_if(visitableObjs, matchesId);
for(auto &p : reservedHeroesMap) for(auto &p : reservedHeroesMap)
erase_if(p.second, matchesId); vstd::erase_if(p.second, matchesId);
erase_if(reservedObjs, matchesId); vstd::erase_if(reservedObjs, matchesId);
} }
} }
@ -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) void SectorMap::write(crstring fname)
@ -3241,21 +3258,6 @@ For ship construction etc, another function (goal?) is needed
sectorQueue.push(neigh); 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]) if(!preds[dest])
@ -3361,30 +3363,8 @@ For ship construction etc, another function (goal?) is needed
//disembark //disembark
return ret; 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; return ret;
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!"); //throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
} }

View File

@ -93,7 +93,7 @@ struct SectorMap
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector; //std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
std::map<int, Sector> infoOnSectors; std::map<int, Sector> infoOnSectors;
shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles; std::shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
SectorMap(); SectorMap();
SectorMap(HeroPtr h); SectorMap(HeroPtr h);
@ -129,7 +129,7 @@ public:
friend class FuzzyHelper; 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; std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
ObjectInstanceID destinationTeleport; ObjectInstanceID destinationTeleport;
int3 destinationTeleportPos; int3 destinationTeleportPos;
@ -153,9 +153,9 @@ public:
AIStatus status; AIStatus status;
std::string battlename; 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);
~VCAI(void); ~VCAI(void);
@ -180,7 +180,7 @@ public:
virtual std::string getBattleAIName() const override; 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 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 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

View File

@ -23,7 +23,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName); 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>();
} }

View File

@ -52,5 +52,5 @@ Alexey aka Macron1Robot, <>
Alexander Shishkin aka alexvins, Alexander Shishkin aka alexvins,
* MinGW platform support, modding related programming * MinGW platform support, modding related programming
Arseniy Shestakov aka SXX, Arseniy Shestakov aka SXX, <me@arseniyshestakov.com>
* pathfinding improvements, programming * pathfinding improvements, programming

View File

@ -333,22 +333,22 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
return swapCreatures(s1, s2, p1, p2); 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); 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); 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; cl->additionalPlayerInts[*player] -= gameEvents;
} }
void CCallback::unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents) void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
{ {
cl->additionalBattleInts[*player] -= battleEvents; cl->additionalBattleInts[*player] -= battleEvents;
} }

View File

@ -110,10 +110,10 @@ public:
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out); 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. //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 registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
void registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents); void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
void unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents); void unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
void unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents); 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 void unregisterAllInterfaces(); //stops delivering information about game events to player interfaces -> can be called ONLY after victory/loss

View File

@ -64,7 +64,7 @@ endif()
if (WIN32) if (WIN32)
add_definitions(-DBOOST_THREAD_USE_LIB) add_definitions(-DBOOST_THREAD_USE_LIB)
add_definitions(-D_WIN32_WINNT=0x0501) 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) #delete lib prefix for dlls (libvcmi -> vcmi)
set(CMAKE_SHARED_LIBRARY_PREFIX "") set(CMAKE_SHARED_LIBRARY_PREFIX "")

View File

@ -93,6 +93,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
#ifdef VCMI_WINDOWS #ifdef VCMI_WINDOWS
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - delete this line if something is missing. # 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 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 #endif
/* ---------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- */
@ -179,9 +180,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
/* ---------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- */
/* Usings */ /* Usings */
/* ---------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- */
using std::shared_ptr;
using std::unique_ptr;
using std::make_shared;
using namespace std::placeholders; using namespace std::placeholders;
namespace range = boost::range; namespace range = boost::range;

View File

@ -170,7 +170,7 @@ static void prog_version(void)
static void prog_help(const po::options_description &opts) 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("%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("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("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("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
printf("\n"); printf("\n");
@ -244,7 +244,9 @@ int main(int argc, char** argv)
("loadhumanplayerindices",po::value<std::vector<int>>(),"Indexes of human players (0=Red, etc.)") ("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.)") ("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") ("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) if(argc > 1)
{ {
@ -299,6 +301,15 @@ int main(int argc, char** argv)
preinitDLL(::console); preinitDLL(::console);
settings.init(); settings.init();
// 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 // Initialize logging based on settings
logConfig.configure(); logConfig.configure();
@ -314,7 +325,9 @@ int main(int argc, char** argv)
if (!testFile("DATA/HELP.TXT", "Heroes III data") || 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 exit(1); // These are unrecoverable errors
}
// these two are optional + some installs have them on CD and not in data directory // these two are optional + some installs have them on CD and not in data directory
testFile("VIDEO/GOOD1A.SMK", "campaign movies"); testFile("VIDEO/GOOD1A.SMK", "campaign movies");

View File

@ -349,7 +349,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
queueNext(this, "", selectedEntry->second, loop); queueNext(this, "", selectedEntry->second, loop);
} }
void CMusicHandler::queueNext(unique_ptr<MusicEntry> queued) void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
{ {
if (!initialized) if (!initialized)
return; return;

View File

@ -114,11 +114,11 @@ private:
SettingsListener listener; SettingsListener listener;
void onVolumeChange(const JsonNode &volumeNode); void onVolumeChange(const JsonNode &volumeNode);
unique_ptr<MusicEntry> current; std::unique_ptr<MusicEntry> current;
unique_ptr<MusicEntry> next; std::unique_ptr<MusicEntry> next;
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped); 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; std::map<std::string, std::map<int, std::string> > musicsSet;
public: public:

View File

@ -133,7 +133,7 @@ CPlayerInterface::~CPlayerInterface()
if(LOCPLINT == this) if(LOCPLINT == this)
LOCPLINT = nullptr; LOCPLINT = nullptr;
} }
void CPlayerInterface::init(shared_ptr<CCallback> CB) void CPlayerInterface::init(std::shared_ptr<CCallback> CB)
{ {
cb = CB; cb = CB;
if(observerInDuelMode) if(observerInDuelMode)
@ -157,24 +157,30 @@ void CPlayerInterface::yourTurn()
GH.curInt = this; GH.curInt = this;
adventureInt->selection = nullptr; adventureInt->selection = nullptr;
std::string prefix = "";
if(settings["testing"]["enabled"].Bool())
{
prefix = settings["testing"]["prefix"].String();
}
if(firstCall) if(firstCall)
{ {
if(howManyPeople == 1) if(howManyPeople == 1)
adventureInt->setPlayer(playerID); adventureInt->setPlayer(playerID);
autosaveCount = getLastIndex("Autosave_"); autosaveCount = getLastIndex(prefix + "Autosave_");
if(firstCall > 0) //new game, not loaded if(firstCall > 0) //new game, not loaded
{ {
int index = getLastIndex("Newgame_Autosave_"); int index = getLastIndex(prefix + "Newgame_");
index %= SAVES_COUNT; 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; firstCall = 0;
} }
else 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; autosaveCount %= 5;
} }
@ -2242,8 +2248,10 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
void CPlayerInterface::acceptTurn() void CPlayerInterface::acceptTurn()
{ {
bool centerView = true;
if(settings["session"]["autoSkip"].Bool()) if(settings["session"]["autoSkip"].Bool())
{ {
centerView = false;
while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt())) while(CInfoWindow *iw = dynamic_cast<CInfoWindow *>(GH.topInt()))
iw->close(); iw->close();
} }
@ -2270,10 +2278,10 @@ void CPlayerInterface::acceptTurn()
//select first hero if available. //select first hero if available.
if(heroToSelect != nullptr) if(heroToSelect != nullptr)
{ {
adventureInt->select(heroToSelect); adventureInt->select(heroToSelect, centerView);
} }
else else
adventureInt->select(towns.front()); adventureInt->select(towns.front(), centerView);
//show new day animation and sound on infobar //show new day animation and sound on infobar
adventureInt->infoBar.showDate(); adventureInt->infoBar.showDate();
@ -2629,6 +2637,31 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
return cb->getTile(CGHeroInstance::convertPosition(coord,false))->topVisitableObj(ignoreHero); 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); boost::unique_lock<boost::mutex> un(stillMoveHero.mx);
stillMoveHero.data = CONTINUE_MOVE; stillMoveHero.data = CONTINUE_MOVE;
auto doMovement = [&](int3 dst, bool transit) 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 currentCoord = path.nodes[i].coord;
int3 nextCoord = path.nodes[i-1].coord; int3 nextCoord = path.nodes[i-1].coord;
auto nextObject = getObj(nextCoord, nextCoord == h->pos); auto currentObject = getObj(currentCoord, currentCoord == h->pos);
if(CGTeleport::isConnected(getObj(currentCoord, currentCoord == h->pos), 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)
{ {
CCS->soundh->stopSound(sh); CCS->soundh->stopSound(sh);
destinationTeleport = nextObject->id; destinationTeleport = destTeleportObj->id;
destinationTeleportPos = nextCoord; destinationTeleportPos = nextCoord;
doMovement(h->pos, false); 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); sh = CCS->soundh->playSound(CCS->soundh->horseSounds[currentTerrain], -1);
continue; continue;
} }
@ -2700,8 +2741,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
bool useTransit = false; bool useTransit = false;
if((i-2 >= 0) // Check there is node after next one; otherwise transit is pointless 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::isConnected(nextObjectTop, getObj(path.nodes[i-2].coord, false))
|| CGTeleport::isTeleport(nextObject))) || CGTeleport::isTeleport(nextObjectTop)))
{ // Hero should be able to go through object if it's allow transit { // Hero should be able to go through object if it's allow transit
useTransit = true; useTransit = true;
} }

View File

@ -105,7 +105,7 @@ public:
static CBattleInterface * battleInt; //nullptr if no battle static CBattleInterface * battleInt; //nullptr if no battle
CInGameConsole * cingconsole; 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) 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!) 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 std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
//During battle is quick combat mode is used //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. bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
const CArmedInstance * getSelection(); const CArmedInstance * getSelection();
@ -236,7 +236,7 @@ public:
void openTownWindow(const CGTownInstance * town); //shows townscreen void openTownWindow(const CGTownInstance * town); //shows townscreen
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
void updateInfo(const CGObjectInstance * specific); 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 int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
// show dialogs // show dialogs

View File

@ -1918,7 +1918,7 @@ const CMapGenOptions & CRandomMapTab::getMapGenOptions() const
return mapGenOptions; 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())); mapSizeBtnGroup->setSelected(vstd::find_pos(getPossibleMapSizes(), opts->getWidth()));
twoLevelsBtn->setSelected(opts->getHasTwoLevels()); twoLevelsBtn->setSelected(opts->getHasTwoLevels());
@ -3291,14 +3291,14 @@ void CBonusSelection::init()
sFlags = CDefHandler::giveDef("ITGFLAGS.DEF"); sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
} }
CBonusSelection::CBonusSelection(shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign) CBonusSelection::CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign) : ourCampaign(_ourCampaign)
{ {
init(); init();
} }
CBonusSelection::CBonusSelection(const std::string & campaignFName) CBonusSelection::CBonusSelection(const std::string & campaignFName)
{ {
ourCampaign = make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName)); ourCampaign = std::make_shared<CCampaignState>(CCampaignHandler::getCampaign(campaignFName));
init(); init();
} }

View File

@ -300,7 +300,7 @@ public:
CFunctionList<void (const CMapInfo *)> & getMapInfoChanged(); CFunctionList<void (const CMapInfo *)> & getMapInfoChanged();
const CMapInfo * getMapInfo() const; const CMapInfo * getMapInfo() const;
const CMapGenOptions & getMapGenOptions() const; const CMapGenOptions & getMapGenOptions() const;
void setMapGenOptions(shared_ptr<CMapGenOptions> opts); void setMapGenOptions(std::shared_ptr<CMapGenOptions> opts);
private: private:
void addButtonsToGroup(CToggleGroup * group, const std::vector<std::string> & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const; 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; * compOnlyTeamsCntGroup, * waterContentGroup, * monsterStrengthGroup;
CButton * showRandMaps; CButton * showRandMaps;
CMapGenOptions mapGenOptions; CMapGenOptions mapGenOptions;
unique_ptr<CMapInfo> mapInfo; std::unique_ptr<CMapInfo> mapInfo;
CFunctionList<void(const CMapInfo *)> mapInfoChanged; CFunctionList<void(const CMapInfo *)> mapInfoChanged;
}; };
@ -463,7 +463,7 @@ class CBonusSelection : public CIntObject
{ {
public: public:
CBonusSelection(const std::string & campaignFName); CBonusSelection(const std::string & campaignFName);
CBonusSelection(shared_ptr<CCampaignState> _ourCampaign); CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign);
~CBonusSelection(); ~CBonusSelection();
void showAll(SDL_Surface * to) override; void showAll(SDL_Surface * to) override;
@ -532,7 +532,7 @@ private:
CDefHandler * sFlags; CDefHandler * sFlags;
// Data // Data
shared_ptr<CCampaignState> ourCampaign; std::shared_ptr<CCampaignState> ourCampaign;
int selectedMap; int selectedMap;
boost::optional<int> selectedBonus; boost::optional<int> selectedBonus;
StartInfo startInfo; StartInfo startInfo;

View File

@ -247,17 +247,24 @@ void CClient::endGame( bool closeConnection /*= true*/ )
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) 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; CServerHandler sh;
if(server) if(server)
sh.startServer(); sh.startServer();
else else
serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port); serv = sh.justConnectToServer(ipaddr, realPort);
CStopWatch tmh; CStopWatch tmh;
unique_ptr<CLoadFile> loader; std::unique_ptr<CLoadFile> loader;
try try
{ {
std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME)); std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
@ -454,7 +461,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
} }
else else
{ {
installNewPlayerInterface(make_shared<CPlayerInterface>(color), color); installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
humanPlayers++; humanPlayers++;
} }
} }
@ -470,7 +477,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
if(!gNoGUI) if(!gNoGUI)
{ {
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim); 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; p->observerInDuelMode = true;
installNewPlayerInterface(p, boost::none); installNewPlayerInterface(p, boost::none);
GH.curInt = p.get(); GH.curInt = p.get();
@ -535,7 +542,7 @@ void CClient::serialize(CISer & h, const int version)
h & pid & dllname & isHuman; h & pid & dllname & isHuman;
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid); LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
shared_ptr<CGameInterface> nInt; std::shared_ptr<CGameInterface> nInt;
if(dllname.length()) if(dllname.length())
{ {
if(pid == PlayerColor::NEUTRAL) if(pid == PlayerColor::NEUTRAL)
@ -553,7 +560,7 @@ void CClient::serialize(CISer & h, const int version)
else else
{ {
assert(isHuman); assert(isHuman);
nInt = make_shared<CPlayerInterface>(pid); nInt = std::make_shared<CPlayerInterface>(pid);
} }
nInt->dllName = dllname; nInt->dllName = dllname;
@ -604,7 +611,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
h & pid & dllname & isHuman; h & pid & dllname & isHuman;
LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid); LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
shared_ptr<CGameInterface> nInt; std::shared_ptr<CGameInterface> nInt;
if(dllname.length()) if(dllname.length())
{ {
if(pid == PlayerColor::NEUTRAL) if(pid == PlayerColor::NEUTRAL)
@ -623,7 +630,7 @@ void CClient::serialize(CISer & h, const int version, const std::set<PlayerColor
else else
{ {
assert(isHuman); assert(isHuman);
nInt = make_shared<CPlayerInterface>(pid); nInt = std::make_shared<CPlayerInterface>(pid);
} }
nInt->dllName = dllname; nInt->dllName = dllname;
@ -661,11 +668,11 @@ void CClient::handlePack( CPack * pack )
delete 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)); GH.pushInt(new CBonusSelection(camp));
} }
@ -717,7 +724,7 @@ void CClient::battleStarted(const BattleInfo * info)
// if(battleCallbacks.count(side)) // if(battleCallbacks.count(side))
// battleCallbacks[side]->setBattle(info); // battleCallbacks[side]->setBattle(info);
shared_ptr<CPlayerInterface> att, def; std::shared_ptr<CPlayerInterface> att, def;
auto &leftSide = info->sides[0], &rightSide = info->sides[1]; auto &leftSide = info->sides[0], &rightSide = info->sides[1];
@ -783,7 +790,7 @@ PlayerColor CClient::getLocalPlayer() const
return getCurrentPlayer(); return getCurrentPlayer();
} }
void CClient::commenceTacticPhaseForInt(shared_ptr<CBattleGameInterface> battleInt) void CClient::commenceTacticPhaseForInt(std::shared_ptr<CBattleGameInterface> battleInt)
{ {
setThreadName("CClient::commenceTacticPhaseForInt"); setThreadName("CClient::commenceTacticPhaseForInt");
try try
@ -835,7 +842,7 @@ int CClient::sendRequest(const CPack *request, PlayerColor player)
return requestID; return requestID;
} }
void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp ) void CClient::campaignMapFinished( std::shared_ptr<CCampaignState> camp )
{ {
endGame(false); 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); boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
@ -869,7 +876,7 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
playerint[colorUsed] = gameInterface; playerint[colorUsed] = gameInterface;
logGlobal->traceStream() << boost::format("\tInitializing the interface for player %s") % colorUsed; 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; callbacks[colorUsed] = cb;
battleCallbacks[colorUsed] = cb; battleCallbacks[colorUsed] = cb;
gameInterface->init(cb); gameInterface->init(cb);
@ -877,7 +884,7 @@ void CClient::installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface
installNewBattleInterface(gameInterface, color, false); 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); boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
@ -890,7 +897,7 @@ void CClient::installNewBattleInterface(shared_ptr<CBattleGameInterface> battleI
if(needCallback) if(needCallback)
{ {
logGlobal->traceStream() << boost::format("\tInitializing the battle interface for player %s") % *color; 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; battleCallbacks[colorUsed] = cbc;
battleInterface->init(cbc); battleInterface->init(cbc);
} }
@ -967,6 +974,9 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
{ {
serverThread = nullptr; serverThread = nullptr;
shared = nullptr; shared = nullptr;
if(settings["testing"]["enabled"].Bool())
port = settings["testing"]["port"].String();
else
port = boost::lexical_cast<std::string>(settings["server"]["port"].Float()); port = boost::lexical_cast<std::string>(settings["server"]["port"].Float());
verbose = true; verbose = true;
@ -1009,6 +1019,14 @@ void CServerHandler::callServer()
CConnection * CServerHandler::justConnectToServer(const std::string &host, const std::string &port) 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; CConnection *ret = nullptr;
while(!ret) while(!ret)
{ {
@ -1016,7 +1034,7 @@ CConnection * CServerHandler::justConnectToServer(const std::string &host, const
{ {
logNetwork->infoStream() << "Establishing connection..."; logNetwork->infoStream() << "Establishing connection...";
ret = new CConnection( host.size() ? host : settings["server"]["server"].String(), ret = new CConnection( host.size() ? host : settings["server"]["server"].String(),
port.size() ? port : boost::lexical_cast<std::string>(settings["server"]["port"].Float()), realPort,
NAME); NAME);
} }
catch(...) catch(...)

View File

@ -115,17 +115,17 @@ public:
/// Class which handles client - server logic /// Class which handles client - server logic
class CClient : public IGameCallback class CClient : public IGameCallback
{ {
unique_ptr<CPathsInfo> pathInfo; std::unique_ptr<CPathsInfo> pathInfo;
public: public:
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces std::map<PlayerColor,std::shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces std::map<PlayerColor,std::shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
std::vector<shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces std::vector<std::shared_ptr<IGameEventsReceiver>> privilagedGameEventReceivers; //scripting modules, spectator interfaces
std::vector<shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces std::vector<std::shared_ptr<IBattleEventsReceiver>> privilagedBattleEventReceivers; //scripting modules, spectator interfaces
std::map<PlayerColor, shared_ptr<CGameInterface>> playerint; std::map<PlayerColor, std::shared_ptr<CGameInterface>> playerint;
std::map<PlayerColor, shared_ptr<CBattleGameInterface>> battleints; std::map<PlayerColor, std::shared_ptr<CBattleGameInterface>> battleints;
std::map<PlayerColor,std::vector<shared_ptr<IGameEventsReceiver>>> additionalPlayerInts; std::map<PlayerColor,std::vector<std::shared_ptr<IGameEventsReceiver>>> additionalPlayerInts;
std::map<PlayerColor,std::vector<shared_ptr<IBattleEventsReceiver>>> additionalBattleInts; std::map<PlayerColor,std::vector<std::shared_ptr<IBattleEventsReceiver>>> additionalBattleInts;
bool hotSeat; bool hotSeat;
CConnection *serv; CConnection *serv;
@ -146,8 +146,8 @@ public:
void newGame(CConnection *con, StartInfo *si); //con - connection to server void newGame(CConnection *con, StartInfo *si); //con - connection to server
void loadNeutralBattleAI(); void loadNeutralBattleAI();
void installNewPlayerInterface(shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color); void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color);
void installNewBattleInterface(shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true); 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 std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human
void endGame(bool closeConnection = true); void endGame(bool closeConnection = true);
@ -155,9 +155,9 @@ public:
void save(const std::string & fname); 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 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 run();
void campaignMapFinished( shared_ptr<CCampaignState> camp ); void campaignMapFinished( std::shared_ptr<CCampaignState> camp );
void finishCampaign( shared_ptr<CCampaignState> camp ); void finishCampaign( std::shared_ptr<CCampaignState> camp );
void proposeNextMission(shared_ptr<CCampaignState> camp); void proposeNextMission(std::shared_ptr<CCampaignState> camp);
void invalidatePaths(); void invalidatePaths();
const CPathsInfo * getPathsInfo(const CGHeroInstance *h); const CPathsInfo * getPathsInfo(const CGHeroInstance *h);
@ -233,7 +233,7 @@ public:
void handlePack( CPack * pack ); //applies the given pack and deletes it void handlePack( CPack * pack ); //applies the given pack and deletes it
void battleStarted(const BattleInfo * info); 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; void commitPackage(CPackForClient *pack) override;

View File

@ -95,7 +95,7 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2,
const CGHeroInstance *hero1, const CGHeroInstance *hero2, const CGHeroInstance *hero1, const CGHeroInstance *hero2,
const SDL_Rect & myRect, 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), : background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1), 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), 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) for (auto & obstacle : obstacles)
{ {

View File

@ -79,7 +79,7 @@ struct BattleObjectsByHex
typedef std::vector<int> TWallList; typedef std::vector<int> TWallList;
typedef std::vector<const CStack * > TStackList; typedef std::vector<const CStack * > TStackList;
typedef std::vector<const BattleEffect *> TEffectList; 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 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) 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 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 tacticsMode;
bool stackCanCastSpell; //if true, active stack could possibly cast some target spell bool stackCanCastSpell; //if true, active stack could possibly cast some target spell
bool creatureCasting; //if true, stack currently aims to cats a spell bool creatureCasting; //if true, stack currently aims to cats a spell
@ -212,8 +212,8 @@ private:
friend class CBattleInterface; friend class CBattleInterface;
} * siegeH; } * siegeH;
shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat std::shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
shared_ptr<CPlayerInterface> curInt; //current player interface std::shared_ptr<CPlayerInterface> curInt; //current player interface
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
/** Methods for displaying battle screen */ /** Methods for displaying battle screen */
@ -229,7 +229,7 @@ private:
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks); void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
void showStacks(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 showPiecesOfWall(SDL_Surface * to, std::vector<int> pieces);
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects); void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
@ -249,7 +249,7 @@ public:
ui32 animIDhelper; //for giving IDs for animations ui32 animIDhelper; //for giving IDs for animations
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims 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 ~CBattleInterface(); //d-tor
//std::vector<TimeInterested*> timeinterested; //animation handling //std::vector<TimeInterested*> timeinterested; //animation handling

View File

@ -66,7 +66,7 @@ private:
//animation raw data //animation raw data
//TODO: use vector instead? //TODO: use vector instead?
unique_ptr<ui8[]> pixelData; std::unique_ptr<ui8[]> pixelData;
size_t pixelDataSize; size_t pixelDataSize;
// speed of animation, measure in frames per second // speed of animation, measure in frames per second

View File

@ -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); out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
else if(terName) else if(terName)
{ {

View File

@ -380,7 +380,16 @@ void MoraleLuckBox::set(const IBonusBearer *node)
if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD) if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD)
|| node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::BLOCK_MORALE)
|| node->hasBonusOfType(Bonus::NON_LIVING))) || 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()) else if(modifierList->empty())
text += CGI->generaltexth->arraytxt[noneTxtId];//no modifiers text += CGI->generaltexth->arraytxt[noneTxtId];//no modifiers
else else

View File

@ -55,7 +55,6 @@
*/ */
#define ADVOPT (conf.go()->ac) #define ADVOPT (conf.go()->ac)
using namespace boost::logic;
using namespace CSDL_Ext; using namespace CSDL_Ext;
CAdvMapInt *adventureInt; CAdvMapInt *adventureInt;
@ -767,6 +766,11 @@ void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
moveHero->block(!hasPath || (h->movement == 0)); moveHero->block(!hasPath || (h->movement == 0));
} }
void CAdvMapInt::updateSpellbook(const CGHeroInstance *h)
{
spellbook->block(!h);
}
int CAdvMapInt::getNextHeroIndex(int startIndex) int CAdvMapInt::getNextHeroIndex(int startIndex)
{ {
if (LOCPLINT->wanderingHeroes.size() == 0) if (LOCPLINT->wanderingHeroes.size() == 0)
@ -1262,6 +1266,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
updateSleepWake(nullptr); updateSleepWake(nullptr);
updateMoveHero(nullptr); updateMoveHero(nullptr);
updateSpellbook(nullptr);
} }
else //hero selected else //hero selected
{ {
@ -1275,6 +1280,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
updateSleepWake(hero); updateSleepWake(hero);
updateMoveHero(hero); updateMoveHero(hero);
updateSpellbook(hero);
} }
townList.redraw(); townList.redraw();
heroList.redraw(); heroList.redraw();
@ -1531,12 +1537,16 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
} }
else if(const CGHeroInstance * h = curHero()) 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; int turns = pnode->turns;
vstd::amin(turns, 3); vstd::amin(turns, 3);
switch(pnode->action) switch(pnode->action)
{ {
case CGPathNode::NORMAL: case CGPathNode::NORMAL:
case CGPathNode::TELEPORT_NORMAL:
if(pnode->layer == EPathfindingLayer::LAND) if(pnode->layer == EPathfindingLayer::LAND)
CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6); CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
else else
@ -1545,6 +1555,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
case CGPathNode::VISIT: case CGPathNode::VISIT:
case CGPathNode::BLOCKING_VISIT: case CGPathNode::BLOCKING_VISIT:
case CGPathNode::TELEPORT_BLOCKING_VISIT:
if(objAtTile && objAtTile->ID == Obj::HERO) if(objAtTile && objAtTile->ID == Obj::HERO)
{ {
if(selection == objAtTile) if(selection == objAtTile)
@ -1559,6 +1570,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
break; break;
case CGPathNode::BATTLE: case CGPathNode::BATTLE:
case CGPathNode::TELEPORT_BATTLE:
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6); CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
break; break;
@ -1790,4 +1802,3 @@ void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
info.additionalIcons = &iconPositions; info.additionalIcons = &iconPositions;
} }

View File

@ -235,6 +235,7 @@ public:
//button updates //button updates
void updateSleepWake(const CGHeroInstance *h); void updateSleepWake(const CGHeroInstance *h);
void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate); void updateMoveHero(const CGHeroInstance *h, tribool hasPath = boost::logic::indeterminate);
void updateSpellbook(const CGHeroInstance *h);
void updateNextHero(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 /// changes current adventure map mode; used to switch between default view and world view; scale is ignored if EAdvMapMode == NORMAL

View File

@ -501,7 +501,10 @@ void CCastleBuildings::recreate()
if(vstd::contains(town->builtBuildings, BuildingID::SHIPYARD)) 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) //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)) if(!vobjs.empty() && (vobjs.front()->ID == Obj::BOAT || vobjs.front()->ID == Obj::HERO))
{ {

View File

@ -86,7 +86,7 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
if (level != tile.z) if (level != tile.z)
setLevel(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->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
pic->callback = std::bind (&CQuestMinimap::iconClicked, this); pic->callback = std::bind (&CQuestMinimap::iconClicked, this);
@ -179,7 +179,7 @@ void CQuestLog::recreateLabelList()
else else
text.addReplacement(quests[i].obj->getObjectName()); //get name of the object 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->disable();
label->callback = std::bind(&CQuestLog::selectQuest, this, i, currentLabel); label->callback = std::bind(&CQuestLog::selectQuest, this, i, currentLabel);

View File

@ -58,7 +58,7 @@ public:
class CQuestMinimap : public CMinimap 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 clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface
void iconClicked(); void iconClicked();
@ -86,7 +86,7 @@ class CQuestLog : public CWindowObject
CLabel * hideCompleteLabel; CLabel * hideCompleteLabel;
const std::vector<QuestInfo> quests; const std::vector<QuestInfo> quests;
std::vector <shared_ptr<CQuestLabel>> labels; std::vector <std::shared_ptr<CQuestLabel>> labels;
CTextBox * description; CTextBox * description;
CQuestMinimap * minimap; CQuestMinimap * minimap;
CSlider * slider; //scrolls quests CSlider * slider; //scrolls quests

View File

@ -861,7 +861,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
if(itemsType[1] == RESOURCE) if(itemsType[1] == RESOURCE)
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId)); newAmount = LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId));
else if(itemsType[1] == CREATURE) 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 else
assert(0); assert(0);

View File

@ -704,7 +704,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
oldSelected = -1; oldSelected = -1;
new CLabel(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]); 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)); 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); 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); 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); 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->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
recruit->block(true); recruit->block(true);

View File

@ -4,7 +4,7 @@
#include "BattleState.h" #include "BattleState.h"
/* /*
* BattleAction.h, part of VCMI engine * BattleAction.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -201,9 +201,7 @@ void BattleInfo::localInitStack(CStack * s)
namespace CGH namespace CGH
{ {
using namespace std; static void readBattlePositions(const JsonNode &node, std::vector< std::vector<int> > & dest)
static void readBattlePositions(const JsonNode &node, vector< vector<int> > & dest)
{ {
for(const JsonNode &level : node.Vector()) for(const JsonNode &level : node.Vector())
{ {
@ -375,7 +373,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
try try
{ {
auto obstPtr = make_shared<CObstacleInstance>(); auto obstPtr = std::make_shared<CObstacleInstance>();
obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE; obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE;
obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle); obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle);
obstPtr->uniqueID = curB->obstacles.size(); obstPtr->uniqueID = curB->obstacles.size();
@ -424,7 +422,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
RangeGenerator posgenerator(18, 168, ourRand); RangeGenerator posgenerator(18, 168, ourRand);
auto obstPtr = make_shared<CObstacleInstance>(); auto obstPtr = std::make_shared<CObstacleInstance>();
obstPtr->ID = obid; obstPtr->ID = obid;
obstPtr->pos = posgenerator.getSuchNumber(validPosition); obstPtr->pos = posgenerator.getSuchNumber(validPosition);
obstPtr->uniqueID = curB->obstacles.size(); obstPtr->uniqueID = curB->obstacles.size();
@ -541,7 +539,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
} }
//moat //moat
auto moat = make_shared<MoatObstacle>(); auto moat = std::make_shared<MoatObstacle>();
moat->ID = curB->town->subID; moat->ID = curB->town->subID;
moat->obstacleType = CObstacleInstance::MOAT; moat->obstacleType = CObstacleInstance::MOAT;
moat->uniqueID = curB->obstacles.size(); moat->uniqueID = curB->obstacles.size();
@ -586,19 +584,19 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
case BFieldType::HOLY_GROUND: 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(std::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::EVIL)));
break; break;
} }
case BFieldType::CLOVER_FIELD: case BFieldType::CLOVER_FIELD:
{ //+2 luck bonus for neutral creatures { //+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; break;
} }
case BFieldType::EVIL_FOG: 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(std::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::EVIL)));
break; break;
} }
case BFieldType::CURSED_GROUND: case BFieldType::CURSED_GROUND:
@ -614,7 +612,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
//overlay premies given //overlay premies given
//native terrain bonuses //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::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::ATTACK, 1, Bonus::TERRAIN_NATIVE)->addLimiter(nativeTerrain));
curB->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 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; return 0;
} }
shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile) const std::shared_ptr<CObstacleInstance> BattleInfo::getObstacleOnTile(BattleHex tile) const
{ {
for(auto &obs : obstacles) for(auto &obs : obstacles)
if(vstd::contains(obs->getAffectedTiles(), tile)) if(vstd::contains(obs->getAffectedTiles(), tile))
return obs; return obs;
return shared_ptr<CObstacleInstance>(); return std::shared_ptr<CObstacleInstance>();
} }
BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType) BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldType)
@ -719,7 +717,7 @@ BattlefieldBI::BattlefieldBI BattleInfo::battlefieldTypeToBI(BFieldType bfieldTy
{BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD}, {BFieldType::CLOVER_FIELD, BattlefieldBI::CLOVER_FIELD},
{BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND}, {BFieldType::CURSED_GROUND, BattlefieldBI::CURSED_GROUND},
{BFieldType::EVIL_FOG, BattlefieldBI::EVIL_FOG}, {BFieldType::EVIL_FOG, BattlefieldBI::EVIL_FOG},
{BFieldType::FAVOURABLE_WINDS, BattlefieldBI::NONE}, {BFieldType::FAVORABLE_WINDS, BattlefieldBI::NONE},
{BFieldType::FIERY_FIELDS, BattlefieldBI::FIERY_FIELDS}, {BFieldType::FIERY_FIELDS, BattlefieldBI::FIERY_FIELDS},
{BFieldType::HOLY_GROUND, BattlefieldBI::HOLY_GROUND}, {BFieldType::HOLY_GROUND, BattlefieldBI::HOLY_GROUND},
{BFieldType::LUCID_POOLS, BattlefieldBI::LUCID_POOLS}, {BFieldType::LUCID_POOLS, BattlefieldBI::LUCID_POOLS},

View File

@ -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) 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 int3 tile; //for background and bonuses
std::vector<CStack*> stacks; std::vector<CStack*> stacks;
std::vector<shared_ptr<CObstacleInstance> > obstacles; std::vector<std::shared_ptr<CObstacleInstance> > obstacles;
SiegeInfo si; SiegeInfo si;
BFieldType battlefieldType; //like !!BA:B 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) //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; //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; 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) 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)

View File

@ -545,7 +545,7 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
return pickRandomArtifact(rand, flags, [](ArtifactID){ return true;}); 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); auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
added->additionalInfo = additionalInfo; added->additionalInfo = additionalInfo;
@ -554,7 +554,7 @@ Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType
return added; 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); auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
added->additionalInfo = additionalInfo; added->additionalInfo = additionalInfo;
@ -563,12 +563,12 @@ Bonus *createBonus(Bonus::BonusType type, int val, int subtype, shared_ptr<IProp
return added; 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)); 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)); giveArtBonus(aid, createBonus(type, val, subtype, propagator, additionalInfo));
} }
@ -737,6 +737,7 @@ void CArtHandler::afterLoadFinalization()
bonus->sid = art->id; bonus->sid = art->id;
} }
} }
CBonusSystemNode::treeHasChanged();
} }
CArtifactInstance::CArtifactInstance() CArtifactInstance::CArtifactInstance()

View File

@ -258,8 +258,8 @@ private:
void loadComponents(CArtifact * art, const JsonNode & node); void loadComponents(CArtifact * art, const JsonNode & node);
void loadGrowingArt(CGrowingArtifact * 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 = -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, shared_ptr<IPropagator> propagator, 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 giveArtBonus(ArtifactID aid, Bonus *bonus);
void erasePickedArt(ArtifactID id); void erasePickedArt(ArtifactID id);

View File

@ -130,9 +130,9 @@ BFieldType CBattleInfoEssentials::battleGetBattlefieldType() const
return getBattle()->battlefieldType; 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); RETURN_IF_NOT_BATTLE(ret);
if(!perspective) if(!perspective)
@ -1100,9 +1100,9 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
return ret; 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()) 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 AccessibilityInfo CBattleInfoCallback::getAccesibility() const

View File

@ -170,7 +170,7 @@ public:
ETerrainType battleTerrainType() const; ETerrainType battleTerrainType() const;
BFieldType battleGetBattlefieldType() 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 /** @brief Main method for getting battle stacks
* *
@ -243,7 +243,7 @@ public:
//battle //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 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 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 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 void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back

View File

@ -3,7 +3,7 @@
#include "../lib/JsonNode.h" #include "../lib/JsonNode.h"
/* /*
* CConfighandler.h, part of VCMI engine * CConfigHandler.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -140,6 +140,7 @@ void CCreature::setId(CreatureID ID)
if(bonus->source == Bonus::CREATURE_ABILITY) if(bonus->source == Bonus::CREATURE_ABILITY)
bonus->sid = ID; bonus->sid = ID;
} }
CBonusSystemNode::treeHasChanged();
} }
static void AddAbility(CCreature *cre, const JsonVector &ability_vec) static void AddAbility(CCreature *cre, const JsonVector &ability_vec)
@ -488,8 +489,14 @@ void CCreatureHandler::loadCrExpBon()
} }
do //parse everything that's left do //parse everything that's left
{ {
b.sid = parser.readNumber(); //id = this particular creature ID auto sid = parser.readNumber(); //id = this particular creature ID
loadStackExp(b, creatures[b.sid]->getBonusList(), parser); //add directly to CCreature Node 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()); while (parser.endLine());
@ -753,7 +760,7 @@ void CCreatureHandler::loadStackExperience(CCreature * creature, const JsonNode
{ {
if (val.Bool() == true) 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 creature->addNewBonus (new Bonus(*bonus)); //bonuses must be unique objects
break; //TODO: allow bonuses to turn off? break; //TODO: allow bonuses to turn off?
} }

View File

@ -225,14 +225,39 @@ ui64 CCreatureSet::getPower (SlotID slot) const
return getStack(slot).getPower(); 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)); int quantity = CCreature::getQuantityID(getStackCount(slot));
if(quantity) if(quantity)
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))]; return VLC->generaltexth->arraytxt[(174 + mode) + 3*CCreature::getQuantityID(getStackCount(slot))];
return ""; 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 int CCreatureSet::stacksCount() const
{ {
return stacks.size(); return stacks.size();

View File

@ -200,7 +200,8 @@ public:
virtual bool needsLastStack() const; //true if last stack cannot be taken virtual bool needsLastStack() const; //true if last stack cannot be taken
ui64 getArmyStrength() const; //sum of AI values of creatures ui64 getArmyStrength() const; //sum of AI values of creatures
ui64 getPower (SlotID slot) const; //value of specific stack 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 hasStackAtSlot(SlotID slot) const;
bool contains(const CStackInstance *stack) const; bool contains(const CStackInstance *stack) const;

View File

@ -475,7 +475,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
} }
//TODO: typedef? //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()); assert(player.is_initialized());
auto team = getPlayerTeam(player.get()); auto team = getPlayerTeam(player.get());
@ -496,7 +496,7 @@ shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisible
else else
tileArray[x][y][z] = nullptr; 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 ) 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 CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTavern) const
{ {
std::string text = "", extraText = ""; std::string text = "", extraText = "";
if(gs->rumor.type == RumorState::TYPE_NONE) // (version < 755 backward compatability if(gs->rumor.type == RumorState::TYPE_NONE)
return text; return text;
auto rumor = gs->rumor.last[gs->rumor.type]; auto rumor = gs->rumor.last[gs->rumor.type];

View File

@ -91,7 +91,7 @@ public:
const CMapHeader * getMapHeader()const; const CMapHeader * getMapHeader()const;
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map 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; 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; bool isInTheMap(const int3 &pos) const;
//town //town

View File

@ -24,19 +24,19 @@
#ifdef VCMI_ANDROID #ifdef VCMI_ANDROID
// we can't use shared libraries on Android so here's a hack // 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_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_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_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 #endif
template<typename rett> 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*); typedef void(*TGetNameFun)(char*);
char temp[150]; char temp[150];
@ -102,7 +102,7 @@ shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::st
getName(temp); getName(temp);
logGlobal->infoStream() << "Loaded " << temp; logGlobal->infoStream() << "Loaded " << temp;
shared_ptr<rett> ret; std::shared_ptr<rett> ret;
getAI(ret); getAI(ret);
if(!ret) if(!ret)
logGlobal->errorStream() << "Cannot get AI!"; logGlobal->errorStream() << "Cannot get AI!";
@ -111,7 +111,7 @@ shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::st
} }
template<typename rett> 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; logGlobal->infoStream() << "Opening " << dllname;
const boost::filesystem::path filePath = const boost::filesystem::path filePath =
@ -121,17 +121,17 @@ shared_ptr<rett> createAnyAI(std::string dllname, const std::string& methodName)
return ret; return ret;
} }
shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname) std::shared_ptr<CGlobalAI> CDynLibHandler::getNewAI(std::string dllname)
{ {
return createAnyAI<CGlobalAI>(dllname, "GetNewAI"); 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"); 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"); return createAny<CScriptingModule>(dllname, "GetNewModule");
} }

View File

@ -67,7 +67,7 @@ public:
std::string dllName; std::string dllName;
virtual ~CBattleGameInterface() {}; virtual ~CBattleGameInterface() {};
virtual void init(shared_ptr<CBattleCallback> CB){}; virtual void init(std::shared_ptr<CBattleCallback> CB){};
//battle call-ins //battle call-ins
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack 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 class DLL_LINKAGE CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
{ {
public: public:
virtual void init(shared_ptr<CCallback> CB){}; virtual void init(std::shared_ptr<CCallback> CB){};
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player) 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 //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 class DLL_LINKAGE CDynLibHandler
{ {
public: public:
static shared_ptr<CGlobalAI> getNewAI(std::string dllname); static std::shared_ptr<CGlobalAI> getNewAI(std::string dllname);
static shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname); static std::shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
static shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname); static std::shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
}; };
class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate) class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
@ -123,8 +123,8 @@ class DLL_LINKAGE CAdventureAI : public CGlobalAI
public: public:
CAdventureAI() {}; CAdventureAI() {};
shared_ptr<CBattleGameInterface> battleAI; std::shared_ptr<CBattleGameInterface> battleAI;
shared_ptr<CBattleCallback> cbc; std::shared_ptr<CBattleCallback> cbc;
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used

View File

@ -1939,7 +1939,7 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile)
case Obj::EVIL_FOG: case Obj::EVIL_FOG:
return BFieldType::EVIL_FOG; return BFieldType::EVIL_FOG;
case Obj::FAVORABLE_WINDS: case Obj::FAVORABLE_WINDS:
return BFieldType::FAVOURABLE_WINDS; return BFieldType::FAVORABLE_WINDS;
case Obj::FIERY_FIELDS: case Obj::FIERY_FIELDS:
return BFieldType::FIERY_FIELDS; return BFieldType::FIERY_FIELDS;
case Obj::HOLY_GROUNDS: case Obj::HOLY_GROUNDS:
@ -3177,7 +3177,7 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
for(const JsonNode &n : duelData["obstacles"].Vector()) for(const JsonNode &n : duelData["obstacles"].Vector())
{ {
auto oi = make_shared<CObstacleInstance>(); auto oi = std::make_shared<CObstacleInstance>();
if(n.getType() == JsonNode::DATA_VECTOR) if(n.getType() == JsonNode::DATA_VECTOR)
{ {
oi->ID = n.Vector()[0].Float(); oi->ID = n.Vector()[0].Float();

View File

@ -100,7 +100,7 @@ struct DLL_LINKAGE RumorState
ERumorType type; ERumorType type;
std::map<ERumorType, std::pair<int, int>> last; std::map<ERumorType, std::pair<int, int>> last;
RumorState(){type = TYPE_NONE; last = {};}; RumorState(){type = TYPE_NONE;};
bool update(int id, int extra); bool update(int id, int extra);
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
@ -149,7 +149,7 @@ struct DLL_EXPORT DuelParameters
} }
} sides[2]; } sides[2];
std::vector<shared_ptr<CObstacleInstance> > obstacles; std::vector<std::shared_ptr<CObstacleInstance> > obstacles;
static DuelParameters fromJSON(const std::string &fname); static DuelParameters fromJSON(const std::string &fname);
@ -249,7 +249,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects & rand; h & scenarioOps & initialOpts & currentPlayer & day & map & players & teams & hpool & globalEffects & rand;
if(version >= 755) if(version >= 755) //save format backward compatibility
{ {
h & rumor; h & rumor;
} }

View File

@ -150,22 +150,24 @@ void CPathfinder::calculatePaths()
continue; continue;
destAction = getDestAction(); destAction = getDestAction();
int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, movement, hlp->getTurnInfo()); int turnAtNextTile = turn, moveAtNextTile = movement;
int remains = movement - cost; int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo());
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK) int remains = moveAtNextTile - cost;
{
remains = hero->movementPointsAfterEmbark(movement, cost, destAction - 1, hlp->getTurnInfo());
cost = movement - remains;
}
int turnAtNextTile = turn;
if(remains < 0) if(remains < 0)
{ {
//occurs rarely, when hero with low movepoints tries to leave the road //occurs rarely, when hero with low movepoints tries to leave the road
hlp->updateTurnInfo(++turnAtNextTile); 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 :( cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo()); //cost must be updated, movement points changed :(
remains = moveAtNextTile - cost; 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) && if(isBetterWay(remains, turnAtNextTile) &&
((cp->turns == turnAtNextTile && remains) || passOneTurnLimitCheck())) ((cp->turns == turnAtNextTile && remains) || passOneTurnLimitCheck()))
@ -189,13 +191,23 @@ void CPathfinder::calculatePaths()
dp = out.getNode(neighbour, cp->layer); dp = out.getNode(neighbour, cp->layer);
if(dp->locked) if(dp->locked)
continue; 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)) if(isBetterWay(movement, turn))
{ {
dtObj = gs->map->getTile(neighbour).topVisitableObj();
dp->moveRemains = movement; dp->moveRemains = movement;
dp->turns = turn; dp->turns = turn;
dp->theNodeBefore = cp; dp->theNodeBefore = cp;
dp->action = CGPathNode::NORMAL; dp->action = getTeleportDestAction();
if(dp->action == CGPathNode::TELEPORT_NORMAL)
pq.push(dp); pq.push(dp);
} }
} }
@ -361,6 +373,16 @@ bool CPathfinder::isLayerTransitionPossible() const
return false; 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; break;
} }
@ -443,7 +465,7 @@ bool CPathfinder::isMovementAfterDestPossible() const
/// Transit over whirlpools only allowed when hero protected /// Transit over whirlpools only allowed when hero protected
return true; 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 /// Transit via unguarded garrisons is always possible
return true; return true;
@ -507,18 +529,33 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
else else
action = CGPathNode::BLOCKING_VISIT; 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(dtObj->passableFor(hero->tempOwner))
if(townObj->armedGarrison()) action = CGPathNode::VISIT;
else if(objRel == PlayerRelations::ENEMIES)
action = CGPathNode::BATTLE; action = CGPathNode::BATTLE;
} }
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2) else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2)
{ {
const CGGarrison * garrisonObj = dynamic_cast<const CGGarrison *>(dtObj); if(dtObj->passableFor(hero->tempOwner))
if((garrisonObj->stacksCount() && objRel == PlayerRelations::ENEMIES) || isDestinationGuarded(true)) {
if(isDestinationGuarded(true))
action = CGPathNode::BATTLE; 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()) else if(isDestinationGuardian())
action = CGPathNode::BATTLE; action = CGPathNode::BATTLE;
else if(dtObj->blockVisit && !(options.useCastleGate && dtObj->ID == Obj::TOWN)) else if(dtObj->blockVisit && !(options.useCastleGate && dtObj->ID == Obj::TOWN))
@ -541,6 +578,21 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
return action; 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 bool CPathfinder::isSourceInitialPosition() const
{ {
return cp->coord == out.hpos; return cp->coord == out.hpos;
@ -987,7 +1039,7 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
} }
else if(dt->terType == ETerrainType::WATER) 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; ret *= 0.666;
else if(!h->boat && ti->hasBonusOfType(Bonus::WATER_WALKING)) else if(!h->boat && ti->hasBonusOfType(Bonus::WATER_WALKING))
{ {

View File

@ -36,7 +36,10 @@ struct DLL_LINKAGE CGPathNode
NORMAL, NORMAL,
BATTLE, BATTLE,
VISIT, VISIT,
BLOCKING_VISIT BLOCKING_VISIT,
TELEPORT_NORMAL,
TELEPORT_BLOCKING_VISIT,
TELEPORT_BATTLE
}; };
enum EAccessibility : ui8 enum EAccessibility : ui8
@ -159,7 +162,7 @@ private:
CPathsInfo & out; CPathsInfo & out;
const CGHeroInstance * hero; const CGHeroInstance * hero;
const std::vector<std::vector<std::vector<ui8> > > &FoW; const std::vector<std::vector<std::vector<ui8> > > &FoW;
unique_ptr<CPathfinderHelper> hlp; std::unique_ptr<CPathfinderHelper> hlp;
enum EPatrolState { enum EPatrolState {
PATROL_NONE = 0, PATROL_NONE = 0,
@ -202,6 +205,7 @@ private:
bool isMovementToDestPossible() const; bool isMovementToDestPossible() const;
bool isMovementAfterDestPossible() const; bool isMovementAfterDestPossible() const;
CGPathNode::ENodeAction getDestAction() const; CGPathNode::ENodeAction getDestAction() const;
CGPathNode::ENodeAction getTeleportDestAction() const;
bool isSourceInitialPosition() const; bool isSourceInitialPosition() const;
bool isSourceVisitableObj() const; bool isSourceVisitableObj() const;
@ -240,7 +244,7 @@ struct DLL_LINKAGE TurnInfo
BonusCache(TBonusListPtr bonusList); BonusCache(TBonusListPtr bonusList);
}; };
unique_ptr<BonusCache> bonusCache; std::unique_ptr<BonusCache> bonusCache;
const CGHeroInstance * hero; const CGHeroInstance * hero;
TBonusListPtr bonuses; TBonusListPtr bonuses;

View File

@ -11,7 +11,7 @@
#endif #endif
/* /*
* timeHandler.h, part of VCMI engine * CStopWatch.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -17,9 +17,6 @@
* *
*/ */
using namespace boost;
using namespace boost::asio::ip;
extern template void registerTypes<CISer>(CISer & s); extern template void registerTypes<CISer>(CISer & s);
extern template void registerTypes<COSer>(COSer & s); extern template void registerTypes<COSer>(COSer & s);
extern template void registerTypes<CTypeList>(CTypeList & 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) 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; int i;
boost::system::error_code error = asio::error::host_not_found; boost::system::error_code error = boost::asio::error::host_not_found;
socket = new tcp::socket(*io_service); socket = new boost::asio::ip::tcp::socket(*io_service);
tcp::resolver resolver(*io_service); boost::asio::ip::tcp::resolver resolver(*io_service);
tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(tcp::resolver::query(host,port),error); boost::asio::ip::tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(boost::asio::ip::tcp::resolver::query(host,port),error);
if(error) if(error)
{ {
logNetwork->errorStream() << "Problem with resolving: \n" << error; logNetwork->errorStream() << "Problem with resolving: \n" << error;
@ -132,8 +129,8 @@ CConnection::CConnection(TSocket * Socket, std::string Name )
CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, 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) : iser(this), oser(this), name(Name)//, send(this), rec(this)
{ {
boost::system::error_code error = asio::error::host_not_found; boost::system::error_code error = boost::asio::error::host_not_found;
socket = new tcp::socket(*io_service); socket = new boost::asio::ip::tcp::socket(*io_service);
acceptor->accept(*socket,error); acceptor->accept(*socket,error);
if (error) if (error)
{ {
@ -149,7 +146,7 @@ int CConnection::write(const void * data, unsigned size)
try try
{ {
int ret; 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; return ret;
} }
catch(...) catch(...)
@ -164,7 +161,7 @@ int CConnection::read(void * data, unsigned size)
//LOG("Receiving " << size << " byte(s) of data" <<std::endl); //LOG("Receiving " << size << " byte(s) of data" <<std::endl);
try 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; return ret;
} }
catch(...) catch(...)
@ -442,7 +439,7 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
return typeDescr; //type found, return ptr to structure return typeDescr; //type found, return ptr to structure
//type not found - add it to the list and return given ID //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->typeID = typeInfos.size() + 1;
newType->name = type->name(); newType->name = type->name();
typeInfos[type] = newType; typeInfos[type] = newType;
@ -450,18 +447,19 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
return newType; return newType;
} }
ui16 CTypeList::getTypeID( const std::type_info *type ) ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const
{
auto descriptor = getTypeDescriptor(type, throws);
if (descriptor == nullptr)
{ {
auto i = typeInfos.find(type);
if(i != typeInfos.end())
return i->second->typeID;
else
return 0; 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>(); return std::vector<CTypeList::TypeInfoPtr>();
// Perform a simple BFS in the class hierarchy. // Perform a simple BFS in the class hierarchy.
@ -512,17 +510,17 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
return ret; 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 //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) // (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 std::vector<CTypeList::TypeInfoPtr>();
return castSequence(getTypeDescriptor(from), getTypeDescriptor(to)); 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); auto i = typeInfos.find(type);
if(i != typeInfos.end()) if(i != typeInfos.end())
@ -606,7 +604,7 @@ int CLoadIntegrityValidator::read( void * data, unsigned size )
return ret; return ret;
} }
unique_ptr<CLoadFile> CLoadIntegrityValidator::decay() std::unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
{ {
primaryFile->serializer.loadedPointers = this->serializer.loadedPointers; primaryFile->serializer.loadedPointers = this->serializer.loadedPointers;
primaryFile->serializer.loadedPointersTypes = this->serializer.loadedPointersTypes; primaryFile->serializer.loadedPointersTypes = this->serializer.loadedPointersTypes;
@ -646,4 +644,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this)
registerTypes(iser); registerTypes(iser);
registerTypes(oser); registerTypes(oser);
} }

View File

@ -83,7 +83,11 @@ struct TypeComparer
{ {
bool operator()(const std::type_info *a, const std::type_info *b) const bool operator()(const std::type_info *a, const std::type_info *b) const
{ {
#ifndef __APPLE__
return a->before(*b); return a->before(*b);
#else
return strcmp(a->name(), b->name()) < 0;
#endif
} }
}; };
@ -102,6 +106,11 @@ struct PointerCaster : IPointerCaster
{ {
From * from = (From*)boost::any_cast<void*>(ptr); From * from = (From*)boost::any_cast<void*>(ptr);
To * ret = dynamic_cast<To*>(from); To * ret = dynamic_cast<To*>(from);
if (ret == nullptr)
{
// Last resort when RTTI goes mad
ret = static_cast<To*>(from);
}
return (void*)ret; return (void*)ret;
} }
@ -113,6 +122,11 @@ struct PointerCaster : IPointerCaster
{ {
auto from = boost::any_cast<SmartPt>(ptr); auto from = boost::any_cast<SmartPt>(ptr);
auto ret = std::dynamic_pointer_cast<To>(from); 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; return ret;
} }
catch(std::exception &e) catch(std::exception &e)
@ -136,7 +150,7 @@ struct PointerCaster : IPointerCaster
// } // }
}; };
class DLL_LINKAGE CTypeList class DLL_LINKAGE CTypeList: public boost::noncopyable
{ {
public: public:
struct TypeDescriptor; struct TypeDescriptor;
@ -147,33 +161,53 @@ public:
const char *name; const char *name;
std::vector<TypeInfoPtr> children, parents; std::vector<TypeInfoPtr> children, parents;
}; };
typedef boost::shared_mutex TMutex;
typedef boost::unique_lock<TMutex> TUniqueLock;
typedef boost::shared_lock<TMutex> TSharedLock;
private: private:
mutable TMutex mx;
std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos; 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) 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 &) /// 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.
// This type is non-copyable. std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
// Unfortunately on Windows it is required for DLL_EXPORT-ed type to provide copy c-tor, so we can't =delete it. std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
assert(0);
}
CTypeList &operator=(CTypeList &)
{
// As above.
assert(0);
return *this;
}
public:
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); TypeInfoPtr registerType(const std::type_info *type);
public:
CTypeList();
template <typename Base, typename Derived> template <typename Base, typename Derived>
void registerType(const Base * b = nullptr, const Derived * d = nullptr) 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::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::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."); 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>>(); casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>();
} }
ui16 getTypeID(const std::type_info *type); ui16 getTypeID(const std::type_info *type, bool throws = false) const;
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true); //if not throws, failure returns nullptr
template <typename T> template <typename T>
ui16 getTypeID(const T * t = nullptr) ui16 getTypeID(const T * t = nullptr, bool throws = false) const
{ {
return getTypeID(getTypeInfo(t)); return getTypeID(getTypeInfo(t), throws);
}
// 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;
} }
template<typename TInput> template<typename TInput>
void *castToMostDerived(const TInput *inputPtr) void * castToMostDerived(const TInput * inputPtr) const
{ {
auto &baseType = typeid(typename std::remove_cv<TInput>::type); auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr); auto derivedType = getTypeInfo(inputPtr);
if(baseType == *derivedType) if (!strcmp(baseType.name(), derivedType->name()))
return (void*)inputPtr; {
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> 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 &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr.get()); auto derivedType = getTypeInfo(inputPtr.get());
if(baseType == *derivedType) if (!strcmp(baseType.name(), derivedType->name()))
return inputPtr; return inputPtr;
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType); 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)); 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); return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
} }
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr)
{ {
if(t) if(t)
return &typeid(*t); return &typeid(*t);
@ -665,9 +674,8 @@ public:
{ {
COSer &s = static_cast<COSer&>(ar); COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data); const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize //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);
} }
}; };
@ -841,13 +849,13 @@ public:
const_cast<T&>(data).serialize(*this,version); const_cast<T&>(data).serialize(*this,version);
} }
template <typename T> template <typename T>
void saveSerializable(const shared_ptr<T> &data) void saveSerializable(const std::shared_ptr<T> &data)
{ {
T *internalPtr = data.get(); T *internalPtr = data.get();
*this << internalPtr; *this << internalPtr;
} }
template <typename T> template <typename T>
void saveSerializable(const unique_ptr<T> &data) void saveSerializable(const std::unique_ptr<T> &data)
{ {
T *internalPtr = data.get(); T *internalPtr = data.get();
*this << internalPtr; *this << internalPtr;
@ -1324,7 +1332,7 @@ public:
template <typename T> template <typename T>
void loadSerializable(shared_ptr<T> &data) void loadSerializable(std::shared_ptr<T> &data)
{ {
typedef typename boost::remove_const<T>::type NonConstT; typedef typename boost::remove_const<T>::type NonConstT;
NonConstT *internalPtr; NonConstT *internalPtr;
@ -1345,7 +1353,7 @@ public:
auto typeWeNeedToReturn = typeList.getTypeInfo<T>(); auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
if(*actualType == *typeWeNeedToReturn) 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); data = boost::any_cast<std::shared_ptr<T>>(itr->second);
} }
else else
@ -1375,7 +1383,7 @@ public:
data.reset(); data.reset();
} }
template <typename T> template <typename T>
void loadSerializable(unique_ptr<T> &data) void loadSerializable(std::unique_ptr<T> &data)
{ {
T *internalPtr; T *internalPtr;
*this >> internalPtr; *this >> internalPtr;
@ -1543,7 +1551,7 @@ public:
COSer serializer; COSer serializer;
std::string fName; std::string fName;
unique_ptr<std::ofstream> sfile; std::unique_ptr<std::ofstream> sfile;
CSaveFile(const std::string &fname); //throws! CSaveFile(const std::string &fname); //throws!
~CSaveFile(); ~CSaveFile();
@ -1570,7 +1578,7 @@ public:
CISer serializer; CISer serializer;
std::string fName; 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(const boost::filesystem::path & fname, int minimalVersion = version); //throws!
~CLoadFile(); ~CLoadFile();
@ -1595,7 +1603,7 @@ class DLL_LINKAGE CLoadIntegrityValidator
{ {
public: public:
CISer serializer; CISer serializer;
unique_ptr<CLoadFile> primaryFile, controlFile; std::unique_ptr<CLoadFile> primaryFile, controlFile;
bool foundDesync; bool foundDesync;
CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws! 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! int read( void * data, unsigned size) override; //throws!
void checkMagicBytes(const std::string &text); 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; typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
@ -1694,12 +1702,12 @@ public:
CMemorySerializer(); CMemorySerializer();
template <typename T> template <typename T>
static unique_ptr<T> deepCopy(const T &data) static std::unique_ptr<T> deepCopy(const T &data)
{ {
CMemorySerializer mem; CMemorySerializer mem;
mem.oser << &data; mem.oser << &data;
unique_ptr<T> ret; std::unique_ptr<T> ret;
mem.iser >> ret; mem.iser >> ret;
return ret; return ret;
} }

View File

@ -33,6 +33,7 @@ namespace GameConstants
const int SPELL_SCHOOL_LEVELS = 4; const int SPELL_SCHOOL_LEVELS = 4;
const int CRE_LEVELS = 10; // number of creature experience levels const int CRE_LEVELS = 10; // number of creature experience levels
const int HERO_GOLD_COST = 2500;
const int SPELLBOOK_GOLD_COST = 500; 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 BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
const int ARMY_SIZE = 7; 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 // 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 //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 //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, 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, 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 ROUGH, SHIP_TO_SHIP, SHIP
}; };

View File

@ -64,19 +64,19 @@ const std::map<std::string, Bonus::LimitEffect> bonusLimitEffect =
const std::map<std::string, TLimiterPtr> bonusLimiterMap = const std::map<std::string, TLimiterPtr> bonusLimiterMap =
{ {
{"SHOOTER_ONLY", make_shared<HasAnotherBonusLimiter>(Bonus::SHOOTER)}, {"SHOOTER_ONLY", std::make_shared<HasAnotherBonusLimiter>(Bonus::SHOOTER)},
{"DRAGON_NATURE", make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)}, {"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
{"IS_UNDEAD", make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)} {"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}
}; };
const std::map<std::string, TPropagatorPtr> bonusPropagatorMap = const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
{ {
{"BATTLE_WIDE", make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE)}, {"BATTLE_WIDE", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE)},
{"VISITED_TOWN_AND_VISITOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR)}, {"VISITED_TOWN_AND_VISITOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TOWN_AND_VISITOR)},
{"PLAYER_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)}, {"PLAYER_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::PLAYER)},
{"HERO", make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)}, {"HERO", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::HERO)},
{"TEAM_PROPAGATOR", make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested {"TEAM_PROPAGATOR", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::TEAM)}, //untested
{"GLOBAL_EFFECT", make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)} {"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
}; //untested }; //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) //We still don't have the bonuses (didn't returned them from cache)
//Perform bonus selection //Perform bonus selection
auto ret = make_shared<BonusList>(); auto ret = std::make_shared<BonusList>();
cachedBonuses.getBonuses(*ret, selector, limit); cachedBonuses.getBonuses(*ret, selector, limit);
// Save the results in the cache // 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 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. // Get bonus results without caching enabled.
BonusList beforeLimiting, afterLimiting; BonusList beforeLimiting, afterLimiting;
@ -995,11 +995,6 @@ CBonusSystemNode::ENodeTypes CBonusSystemNode::getNodeType() const
return nodeType; return nodeType;
} }
BonusList& CBonusSystemNode::getBonusList()
{
return bonuses;
}
const BonusList& CBonusSystemNode::getBonusList() const const BonusList& CBonusSystemNode::getBonusList() const
{ {
return bonuses; return bonuses;
@ -1072,7 +1067,7 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
TBonusListPtr CBonusSystemNode::limitBonuses(const BonusList &allBonuses) const TBonusListPtr CBonusSystemNode::limitBonuses(const BonusList &allBonuses) const
{ {
auto ret = make_shared<BonusList>(); auto ret = std::make_shared<BonusList>();
limitBonuses(allBonuses, *ret); limitBonuses(allBonuses, *ret);
return ret; return ret;
} }
@ -1323,7 +1318,7 @@ Bonus * Bonus::addLimiter(TLimiterPtr Limiter)
if(!limiterList) if(!limiterList)
{ {
//Create a new limiter list with old limiter and the new one will be pushed later //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); limiterList->add(limiter);
limiter = limiterList; limiter = limiterList;
} }

View File

@ -20,9 +20,9 @@ class ILimiter;
class IPropagator; class IPropagator;
class BonusList; class BonusList;
typedef shared_ptr<BonusList> TBonusListPtr; typedef std::shared_ptr<BonusList> TBonusListPtr;
typedef shared_ptr<ILimiter> TLimiterPtr; typedef std::shared_ptr<ILimiter> TLimiterPtr;
typedef shared_ptr<IPropagator> TPropagatorPtr; typedef std::shared_ptr<IPropagator> TPropagatorPtr;
typedef std::set<CBonusSystemNode*> TNodes; typedef std::set<CBonusSystemNode*> TNodes;
typedef std::set<const CBonusSystemNode*> TCNodes; typedef std::set<const CBonusSystemNode*> TCNodes;
typedef std::vector<CBonusSystemNode *> TNodesVector; typedef std::vector<CBonusSystemNode *> TNodesVector;
@ -694,7 +694,6 @@ public:
void exportBonus(Bonus * b); void exportBonus(Bonus * b);
void exportBonuses(); void exportBonuses();
BonusList &getBonusList();
const BonusList &getBonusList() const; const BonusList &getBonusList() const;
BonusList &getExportedBonusList(); BonusList &getExportedBonusList();
CBonusSystemNode::ENodeTypes getNodeType() const; CBonusSystemNode::ENodeTypes getNodeType() const;

View File

@ -483,10 +483,10 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
break; break;
case JsonNode::DATA_STRUCT: //customizable limiters case JsonNode::DATA_STRUCT: //customizable limiters
{ {
shared_ptr<ILimiter> l; std::shared_ptr<ILimiter> l;
if (limiter["type"].String() == "CREATURE_TYPE_LIMITER") 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(); const JsonVector vec = limiter["parameters"].Vector();
VLC->modh->identifiers.requestIdentifier("creature", vec[0], [=](si32 creature) 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") 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(); const JsonVector vec = limiter["parameters"].Vector();
std::string anotherBonusType = vec[0].String(); std::string anotherBonusType = vec[0].String();

View File

@ -331,9 +331,6 @@ struct SetAvailableHeroes : public CPackForClient //113
for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++) for (int i = 0; i < GameConstants::AVAILABLE_HEROES_PER_PLAYER; i++)
army[i].clear(); army[i].clear();
} }
~SetAvailableHeroes()
{
}
void applyCl(CClient *cl); void applyCl(CClient *cl);
DLL_LINKAGE void applyGs(CGameState *gs); DLL_LINKAGE void applyGs(CGameState *gs);
@ -446,7 +443,7 @@ struct UpdateCampaignState : public CPackForClient //119
type = 119; type = 119;
} }
shared_ptr<CCampaignState> camp; std::shared_ptr<CCampaignState> camp;
void applyCl(CClient *cl); void applyCl(CClient *cl);
template <typename Handler> void serialize(Handler &h, const int version) 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 DLL_LINKAGE void applyGs(CGameState *gs); //effect
void applyCl(CClient *cl); //play animations & stuff 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) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@ -223,7 +223,7 @@ DLL_LINKAGE void FoWChange::applyGs( CGameState *gs )
case Obj::TOWN: case Obj::TOWN:
case Obj::ABANDONED_MINE: case Obj::ABANDONED_MINE:
if(vstd::contains(team->players, o->tempOwner)) //check owned observators 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; break;
} }
} }
@ -1010,6 +1010,13 @@ DLL_LINKAGE void SetAvailableArtifacts::applyGs( CGameState *gs )
DLL_LINKAGE void NewTurn::applyGs( CGameState *gs ) DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
{ {
gs->day = day; 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 for(NewTurn::Hero h : heroes) //give mana/movement point
{ {
CGHeroInstance *hero = gs->getHero(h.id); 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 for(auto creatureSet : cres) //set available creatures in towns
creatureSet.second.applyGs(gs); 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) for(CGTownInstance* t : gs->map->towns)
t->builded = 0; t->builded = 0;

View File

@ -82,9 +82,9 @@ struct StartInfo
ui8 turnTime; //in minutes, 0=unlimited ui8 turnTime; //in minutes, 0=unlimited
std::string mapname; // empty for random map, otherwise name of the map or savegame std::string mapname; // empty for random map, otherwise name of the map or savegame
bool createRandomMap() const { return mapGenOptions.get() != nullptr; } 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) PlayerSettings & getIthPlayersSettings(PlayerColor no)
{ {

View File

@ -3,7 +3,7 @@
#include "GameConstants.h" #include "GameConstants.h"
/* /*
* GameConstants.h, part of VCMI engine * StringConstants.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -293,8 +293,10 @@
<ClInclude Include="Connection.h" /> <ClInclude Include="Connection.h" />
<ClInclude Include="ConstTransitivePtr.h" /> <ClInclude Include="ConstTransitivePtr.h" />
<ClInclude Include="CPathfinder.h" /> <ClInclude Include="CPathfinder.h" />
<ClInclude Include="CPlayerState.h" />
<ClInclude Include="CRandomGenerator.h" /> <ClInclude Include="CRandomGenerator.h" />
<ClInclude Include="CScriptingModule.h" /> <ClInclude Include="CScriptingModule.h" />
<ClInclude Include="CSoundBase.h" />
<ClInclude Include="CStopWatch.h" /> <ClInclude Include="CStopWatch.h" />
<ClInclude Include="CThreadHelper.h" /> <ClInclude Include="CThreadHelper.h" />
<ClInclude Include="CTownHandler.h" /> <ClInclude Include="CTownHandler.h" />
@ -313,6 +315,7 @@
<ClInclude Include="filesystem\ResourceID.h" /> <ClInclude Include="filesystem\ResourceID.h" />
<ClInclude Include="FunctionList.h" /> <ClInclude Include="FunctionList.h" />
<ClInclude Include="IBonusTypeHandler.h" /> <ClInclude Include="IBonusTypeHandler.h" />
<ClInclude Include="IHandlerBase.h" />
<ClInclude Include="JsonDetail.h" /> <ClInclude Include="JsonDetail.h" />
<ClInclude Include="LogicalExpression.h" /> <ClInclude Include="LogicalExpression.h" />
<ClInclude Include="mapObjects\CArmedInstance.h" /> <ClInclude Include="mapObjects\CArmedInstance.h" />
@ -332,12 +335,15 @@
<ClInclude Include="mapObjects\MiscObjects.h" /> <ClInclude Include="mapObjects\MiscObjects.h" />
<ClInclude Include="mapObjects\ObjectTemplate.h" /> <ClInclude Include="mapObjects\ObjectTemplate.h" />
<ClInclude Include="mapping\CCampaignHandler.h" /> <ClInclude Include="mapping\CCampaignHandler.h" />
<ClInclude Include="mapping\CDrawRoadsOperation.h" />
<ClInclude Include="mapping\CMap.h" /> <ClInclude Include="mapping\CMap.h" />
<ClInclude Include="mapping\CMapDefines.h" />
<ClInclude Include="mapping\CMapInfo.h" /> <ClInclude Include="mapping\CMapInfo.h" />
<ClInclude Include="mapping\CMapService.h" /> <ClInclude Include="mapping\CMapService.h" />
<ClInclude Include="mapping\CMapEditManager.h" /> <ClInclude Include="mapping\CMapEditManager.h" />
<ClInclude Include="mapping\MapFormatH3M.h" /> <ClInclude Include="mapping\MapFormatH3M.h" />
<ClInclude Include="mapping\MapFormatJson.h" /> <ClInclude Include="mapping\MapFormatJson.h" />
<ClInclude Include="NetPacksBase.h" />
<ClInclude Include="registerTypes\RegisterTypes.h" /> <ClInclude Include="registerTypes\RegisterTypes.h" />
<ClInclude Include="rmg\CMapGenerator.h" /> <ClInclude Include="rmg\CMapGenerator.h" />
<ClInclude Include="logging\CLogger.h" /> <ClInclude Include="logging\CLogger.h" />
@ -360,6 +366,7 @@
<ClInclude Include="rmg\CZoneGraphGenerator.h" /> <ClInclude Include="rmg\CZoneGraphGenerator.h" />
<ClInclude Include="rmg\CZonePlacer.h" /> <ClInclude Include="rmg\CZonePlacer.h" />
<ClInclude Include="rmg\float3.h" /> <ClInclude Include="rmg\float3.h" />
<ClInclude Include="ScopeGuard.h" />
<ClInclude Include="spells\AdventureSpellMechanics.h" /> <ClInclude Include="spells\AdventureSpellMechanics.h" />
<ClInclude Include="spells\BattleSpellMechanics.h" /> <ClInclude Include="spells\BattleSpellMechanics.h" />
<ClInclude Include="spells\CDefaultSpellMechanics.h" /> <ClInclude Include="spells\CDefaultSpellMechanics.h" />
@ -371,7 +378,9 @@
<ClInclude Include="spells\ViewSpellInt.h" /> <ClInclude Include="spells\ViewSpellInt.h" />
<ClInclude Include="StartInfo.h" /> <ClInclude Include="StartInfo.h" />
<ClInclude Include="StdInc.h" /> <ClInclude Include="StdInc.h" />
<ClInclude Include="StringConstants.h" />
<ClInclude Include="UnlockGuard.h" /> <ClInclude Include="UnlockGuard.h" />
<ClInclude Include="vcmi_endian.h" />
<ClInclude Include="VCMI_Lib.h" /> <ClInclude Include="VCMI_Lib.h" />
<ClInclude Include="VCMIDirs.h" /> <ClInclude Include="VCMIDirs.h" />
</ItemGroup> </ItemGroup>

View File

@ -155,8 +155,6 @@
<ClCompile Include="registerTypes\TypesClientPacks1.cpp"> <ClCompile Include="registerTypes\TypesClientPacks1.cpp">
<Filter>registerTypes</Filter> <Filter>registerTypes</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="registerTypes\TypesMapObjects1.cpp" />
<ClCompile Include="registerTypes\TypesMapObjects2.cpp" />
<ClCompile Include="mapObjects\CArmedInstance.cpp"> <ClCompile Include="mapObjects\CArmedInstance.cpp">
<Filter>mapObjects</Filter> <Filter>mapObjects</Filter>
</ClCompile> </ClCompile>
@ -202,7 +200,6 @@
<ClCompile Include="mapObjects\ObjectTemplate.cpp"> <ClCompile Include="mapObjects\ObjectTemplate.cpp">
<Filter>mapObjects</Filter> <Filter>mapObjects</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="registerTypes\TypesMapObjects3.cpp" />
<ClCompile Include="IHandlerBase.cpp" /> <ClCompile Include="IHandlerBase.cpp" />
<ClCompile Include="spells\AdventureSpellMechanics.cpp"> <ClCompile Include="spells\AdventureSpellMechanics.cpp">
<Filter>spells</Filter> <Filter>spells</Filter>
@ -227,6 +224,15 @@
</ClCompile> </ClCompile>
<ClCompile Include="mapping\CDrawRoadsOperation.cpp" /> <ClCompile Include="mapping\CDrawRoadsOperation.cpp" />
<ClCompile Include="CPathfinder.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>
<ItemGroup> <ItemGroup>
<ClInclude Include="CCreatureSet.h"> <ClInclude Include="CCreatureSet.h">
@ -541,5 +547,32 @@
<ClInclude Include="CPathfinder.h"> <ClInclude Include="CPathfinder.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </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> </ItemGroup>
</Project> </Project>

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/* /*
* CLodStream.h, part of VCMI engine * CCompressedStream.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -134,7 +134,7 @@ void CLogger::setLevel(ELogLevel::ELogLevel level)
const CLoggerDomain & CLogger::getDomain() const { return domain; } const CLoggerDomain & CLogger::getDomain() const { return domain; }
void CLogger::addTarget(unique_ptr<ILogTarget> && target) void CLogger::addTarget(std::unique_ptr<ILogTarget> && target)
{ {
TLockGuard _(mx); TLockGuard _(mx);
targets.push_back(std::move(target)); targets.push_back(std::move(target));

View File

@ -105,7 +105,7 @@ public:
inline void log(ELogLevel::ELogLevel level, const std::string & message) const; 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(); void clearTargets();
/// Returns true if a debug/trace log message will be logged, false if not. /// Returns true if a debug/trace log message will be logged, false if not.
@ -121,7 +121,7 @@ private:
CLoggerDomain domain; CLoggerDomain domain;
CLogger * parent; CLogger * parent;
ELogLevel::ELogLevel level; ELogLevel::ELogLevel level;
std::vector<unique_ptr<ILogTarget> > targets; std::vector<std::unique_ptr<ILogTarget> > targets;
mutable boost::mutex mx; mutable boost::mutex mx;
static boost::recursive_mutex smx; 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. /// 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) \ #define RAII_TRACE(logger, onEntry, onLeave) \
unique_ptr<CTraceLogger> ctl00; \ std::unique_ptr<CTraceLogger> ctl00; \
if(logger->isTraceEnabled()) \ if(logger->isTraceEnabled()) \
ctl00 = make_unique<CTraceLogger>(logger, onEntry, onLeave); ctl00 = make_unique<CTraceLogger>(logger, onEntry, onLeave);

View File

@ -46,7 +46,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
if(!validTypes(false)) //object not randomized, don't bother if(!validTypes(false)) //object not randomized, don't bother
return; 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) if(!b)
{ {
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1); 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 b->description = b->description.substr(0, b->description.size()-2);//trim value
} }
boost::algorithm::trim(b->description); boost::algorithm::trim(b->description);
CBonusSystemNode::treeHasChanged();
//-1 modifier for any Undead unit in army //-1 modifier for any Undead unit in army
const ui8 UNDEAD_MODIFIER_ID = -2; 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(hasUndead)
{ {
if(!undeadModifier) if(!undeadModifier)

View File

@ -292,9 +292,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
loot.addReplacement(*elem.second); 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); iw.text.addTxt (MetaString::ADVOB_TXT, 185);
else else
iw.text.addTxt (MetaString::ADVOB_TXT, 186); iw.text.addTxt (MetaString::ADVOB_TXT, 186);

View File

@ -43,7 +43,7 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16
static int lowestSpeed(const CGHeroInstance * chi) 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!"; logGlobal->errorStream() << "Error! Hero " << chi->id.getNum() << " ("<<chi->name<<") has no army!";
return 20; return 20;
@ -818,7 +818,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
Bonus::ValueType skillValType = skillVal ? Bonus::BASE_NUMBER : Bonus::INDEPENDENT_MIN; 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 .And(Selector::sourceType(Bonus::SECONDARY_SKILL)))) //only local hero bonus
{ {
b->val = skillVal; b->val = skillVal;
@ -831,6 +831,7 @@ void CGHeroInstance::updateSkill(SecondarySkill which, int val)
addNewBonus(bonus); addNewBonus(bonus);
} }
CBonusSystemNode::treeHasChanged();
} }
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val ) void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
{ {
@ -1365,6 +1366,7 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill::PrimarySkill primarySkill, si
{ {
skill->val += value; skill->val += value;
} }
CBonusSystemNode::treeHasChanged();
} }
else if(primarySkill == PrimarySkill::EXPERIENCE) else if(primarySkill == PrimarySkill::EXPERIENCE)
{ {

View File

@ -79,7 +79,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & patrolling; h & patrolling;
if(version >= 755) if(version >= 755) //save format backward compatibility
{ {
h & initialPos; h & initialPos;
} }

View File

@ -235,7 +235,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
iw.components.clear(); iw.components.clear();
iw.text.clear(); iw.text.clear();
if (creatures.Slots().size()) if(creatures.stacksCount())
{ //this part is taken straight from creature bank { //this part is taken straight from creature bank
MetaString loot; MetaString loot;
for(auto & elem : creatures.Slots()) for(auto & elem : creatures.Slots())
@ -245,7 +245,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
loot.addReplacement(*elem.second); 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); iw.text.addTxt(MetaString::ADVOB_TXT, 185);
else else
iw.text.addTxt(MetaString::ADVOB_TXT, 186); iw.text.addTxt(MetaString::ADVOB_TXT, 186);
@ -313,7 +313,7 @@ void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answe
else if(message.size() == 0 && resources.size() == 0 else if(message.size() == 0 && resources.size() == 0
&& primskills.size() == 0 && abilities.size() == 0 && primskills.size() == 0 && abilities.size() == 0
&& abilityLevels.size() == 0 && artifacts.size() == 0 && abilityLevels.size() == 0 && artifacts.size() == 0
&& spells.size() == 0 && creatures.Slots().size() > 0 && spells.size() == 0 && creatures.stacksCount() > 0
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle && gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
{ {
showInfoDialog(hero,15,0); showInfoDialog(hero,15,0);

View File

@ -856,7 +856,7 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::updateMoraleBonusFromArmy() 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) if(!b)
{ {
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1); b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@ -864,7 +864,10 @@ void CGTownInstance::updateMoraleBonusFromArmy()
} }
if (garrisonHero) if (garrisonHero)
{
b->val = 0; b->val = 0;
CBonusSystemNode::treeHasChanged();
}
else else
CArmedInstance::updateMoraleBonusFromArmy(); CArmedInstance::updateMoraleBonusFromArmy();
} }

View File

@ -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 (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; return o->pos + offset;
} }
} }

View File

@ -325,10 +325,10 @@ void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRando
} }
} }
CBankInfo::CBankInfo(JsonVector config): CBankInfo::CBankInfo(const JsonVector & Config):
config(config) config(Config)
{ {
assert(!config.empty()); assert(!Config.empty());
} }
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount) static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)

View File

@ -2,6 +2,7 @@
#include "CObjectClassesHandler.h" #include "CObjectClassesHandler.h"
#include "../CTownHandler.h" // for building ID-based filters #include "../CTownHandler.h" // for building ID-based filters
#include "MapObjects.h"
/* /*
* CommonConstructors.h, part of VCMI engine * 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 class DLL_LINKAGE CBankInfo : public IObjectInfo
{ {
JsonVector config; const JsonVector & config;
public: public:
CBankInfo(JsonVector config); CBankInfo(const JsonVector & Config);
TPossibleGuards getPossibleGuards() const; TPossibleGuards getPossibleGuards() const;

View File

@ -1,6 +1,6 @@
/* /*
* *
* CRewardableObject.cpp, part of VCMI engine * JsonRandom.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -640,7 +640,6 @@ std::string CGMine::getObjectName() const
std::string CGMine::getHoverText(PlayerColor player) const std::string CGMine::getHoverText(PlayerColor player) const
{ {
std::string hoverName = getObjectName(); // Sawmill std::string hoverName = getObjectName(); // Sawmill
if (tempOwner != PlayerColor::NEUTRAL) if (tempOwner != PlayerColor::NEUTRAL)
@ -650,11 +649,12 @@ std::string CGMine::getHoverText(PlayerColor player) const
hoverName += "\n(" + VLC->generaltexth->restypes[producedResource] + ")"; hoverName += "\n(" + VLC->generaltexth->restypes[producedResource] + ")";
} }
for (auto & slot : Slots()) // guarded by a few Pikeman if(stacksCount())
{ {
hoverName += "\n"; hoverName += "\n";
hoverName += getRoughAmount(slot.first); hoverName += VLC->generaltexth->allTexts[202]; //Guarded by
hoverName += getCreature(slot.first)->namePl; hoverName += " ";
hoverName += getArmyDescription();
} }
return hoverName; return hoverName;
} }
@ -907,12 +907,12 @@ std::vector<ObjectInstanceID> CGTeleport::getPassableExits(CGameState * gs, cons
return exits; 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()) if(channelsList.find(obj->channel) == channelsList.end())
{ {
tc = make_shared<TeleportChannel>(); tc = std::make_shared<TeleportChannel>();
channelsList.insert(std::make_pair(obj->channel, tc)); channelsList.insert(std::make_pair(obj->channel, tc));
} }
else else
@ -973,17 +973,18 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
{ {
int3 dPos; int3 dPos;
auto randomExit = getRandomExit(hero);
auto realExits = getAllExits(true); auto realExits = getAllExits(true);
if(!isEntrance() // Do nothing if hero visited exit only object 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() && !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; return;
} }
else if(vstd::isValidIndex(exits, answer)) else if(vstd::isValidIndex(exits, answer))
dPos = exits[answer].second; dPos = exits[answer].second;
else else
dPos = CGHeroInstance::convertPosition(cb->getObj(getRandomExit(hero))->visitablePos(), true); dPos = CGHeroInstance::convertPosition(cb->getObj(randomExit)->visitablePos(), true);
cb->moveHero(hero->id, dPos, true); cb->moveHero(hero->id, dPos, true);
} }
@ -1160,8 +1161,8 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
bool CGWhirlpool::isProtected(const CGHeroInstance * h) bool CGWhirlpool::isProtected(const CGHeroInstance * h)
{ {
if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION) if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION) ||
|| (h->Slots().size() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit
{ {
return true; return true;
} }
@ -1219,7 +1220,6 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure
iw.text.addReplacement(h->name); iw.text.addReplacement(h->name);
} }
} }
} }
break; break;
@ -1227,9 +1227,14 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
{ {
int spellID = storedArtifact->getGivenSpellID(); int spellID = storedArtifact->getGivenSpellID();
iw.components.push_back(Component(Component::SPELL, spellID, 0, 0)); 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.addTxt(MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID); iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
} }
}
break; break;
} }
cb->showInfoDialog(&iw); cb->showInfoDialog(&iw);
@ -1237,7 +1242,28 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
} }
else else
{ {
if(message.size()) switch(ID)
{
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); BlockingDialog ynd(true,false);
ynd.player = h->getOwner(); ynd.player = h->getOwner();
@ -1245,9 +1271,10 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
cb->showBlockingDialog(&ynd); cb->showBlockingDialog(&ynd);
} }
else else
{
blockingDialogAnswered(h, true); blockingDialogAnswered(h, true);
} }
break;
}
} }
} }

View File

@ -317,7 +317,7 @@ public:
static bool isTeleport(const CGObjectInstance * dst); static bool isTeleport(const CGObjectInstance * dst);
static bool isConnected(const CGTeleport * src, const CGTeleport * dst); static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * 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 std::vector<ObjectInstanceID> getPassableExits(CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
static bool isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj); static bool isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj);

View File

@ -40,7 +40,7 @@ CCampaignHeader CCampaignHandler::getHeader( const std::string & name)
return ret; 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>(); 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++) for(int i = 0; i < camp->scenarios.size(); i++)
{ {

View File

@ -144,7 +144,7 @@ public:
class DLL_LINKAGE CCampaignState class DLL_LINKAGE CCampaignState
{ {
public: public:
unique_ptr<CCampaign> camp; std::unique_ptr<CCampaign> camp;
std::string campaignName; std::string campaignName;
std::vector<ui8> mapsConquered, mapsRemaining; std::vector<ui8> mapsConquered, mapsRemaining;
boost::optional<si32> currentMap; boost::optional<si32> currentMap;
@ -159,7 +159,7 @@ public:
ui8 currentBonusID() const; ui8 currentBonusID() const;
CCampaignState(); CCampaignState();
CCampaignState(unique_ptr<CCampaign> _camp); CCampaignState(std::unique_ptr<CCampaign> _camp);
~CCampaignState(){}; ~CCampaignState(){};
template <typename Handler> void serialize(Handler &h, const int version) 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 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
}; };

View File

@ -153,7 +153,7 @@ EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
return EDiggingStatus::CAN_DIG; return EDiggingStatus::CAN_DIG;
} }
bool TerrainTile::hasFavourableWinds() const bool TerrainTile::hasFavorableWinds() const
{ {
return extTileFlags & 128; return extTileFlags & 128;
} }

View File

@ -319,12 +319,12 @@ public:
//Helper lists //Helper lists
std::vector< ConstTransitivePtr<CGHeroInstance> > heroesOnMap; 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) /// associative list to identify which hero/creature id belongs to which object id(index for objects)
std::map<si32, ObjectInstanceID> questIdentifierToId; std::map<si32, ObjectInstanceID> questIdentifierToId;
unique_ptr<CMapEditManager> editManager; std::unique_ptr<CMapEditManager> editManager;
int3 ***guardingCreaturePositions; int3 ***guardingCreaturePositions;

View File

@ -71,7 +71,7 @@ struct DLL_LINKAGE TerrainTile
CGObjectInstance * topVisitableObj(bool excludeTop = false) const; CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
bool isWater() const; bool isWater() const;
EDiggingStatus getDiggingStatus(const bool excludeTop = true) const; EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
bool hasFavourableWinds() const; bool hasFavorableWinds() const;
ETerrainType terType; ETerrainType terType;
ui8 terView; ui8 terView;
@ -80,7 +80,7 @@ struct DLL_LINKAGE TerrainTile
ERoadType::ERoadType roadType; ERoadType::ERoadType roadType;
ui8 roadDir; ui8 roadDir;
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road); /// 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; ui8 extTileFlags;
bool visitable; bool visitable;
bool blocked; bool blocked;

View File

@ -189,7 +189,7 @@ const CMapOperation * CMapUndoManager::peekUndo() const
return peek(undoStack); return peek(undoStack);
} }
void CMapUndoManager::addOperation(unique_ptr<CMapOperation> && operation) void CMapUndoManager::addOperation(std::unique_ptr<CMapOperation> && operation)
{ {
undoStack.push_front(std::move(operation)); undoStack.push_front(std::move(operation));
if(undoStack.size() > undoRedoLimit) undoStack.pop_back(); 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)); execute(make_unique<CInsertObjectOperation>(map, obj, pos));
} }
void CMapEditManager::execute(unique_ptr<CMapOperation> && operation) void CMapEditManager::execute(std::unique_ptr<CMapOperation> && operation)
{ {
operation->execute(); operation->execute();
undoManager.addOperation(std::move(operation)); 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)); operations.push_back(std::move(operation));
} }

View File

@ -144,10 +144,10 @@ public:
const CMapOperation * peekRedo() const; const CMapOperation * peekRedo() const;
const CMapOperation * peekUndo() 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: private:
typedef std::list<unique_ptr<CMapOperation> > TStack; typedef std::list<std::unique_ptr<CMapOperation> > TStack;
void doOperation(TStack & fromStack, TStack & toStack, bool doUndo); void doOperation(TStack & fromStack, TStack & toStack, bool doUndo);
const CMapOperation * peek(const TStack & stack) const; const CMapOperation * peek(const TStack & stack) const;
@ -182,7 +182,7 @@ public:
CMapUndoManager & getUndoManager(); CMapUndoManager & getUndoManager();
private: private:
void execute(unique_ptr<CMapOperation> && operation); void execute(std::unique_ptr<CMapOperation> && operation);
CMap * map; CMap * map;
CMapUndoManager undoManager; CMapUndoManager undoManager;
@ -205,10 +205,10 @@ public:
void undo() override; void undo() override;
void redo() override; void redo() override;
void addOperation(unique_ptr<CMapOperation> && operation); void addOperation(std::unique_ptr<CMapOperation> && operation);
private: private:
std::list<unique_ptr<CMapOperation> > operations; std::list<std::unique_ptr<CMapOperation> > operations;
}; };
namespace ETerrainGroup namespace ETerrainGroup

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
// Forward class declarations aren't enough here. The compiler // Forward class declarations aren't enough here. The compiler
// generated CMapInfo d-tor, generates the unique_ptr d-tor as well here // generated CMapInfo d-tor, generates the std::unique_ptr d-tor as well here
// as a inline method. The unique_ptr d-tor requires a complete type. Defining // 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 // 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 // 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 // constructor which is needed. (Writing such a c-tor is nasty.) With the
@ -20,8 +20,8 @@ struct StartInfo;
class DLL_LINKAGE CMapInfo class DLL_LINKAGE CMapInfo
{ {
public: public:
unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario std::unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario
StartInfo * scenarioOpts; //options with which scenario has been started (used only with saved games) StartInfo * scenarioOpts; //options with which scenario has been started (used only with saved games)
std::string fileURI; std::string fileURI;
std::string date; std::string date;

View File

@ -52,7 +52,7 @@ class DLL_LINKAGE CMapGenerator
{ {
public: public:
explicit CMapGenerator(); 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)); std::unique_ptr<CMap> generate(CMapGenOptions * mapGenOptions, int RandomSeed = std::time(nullptr));

View File

@ -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>(); return make_unique<CZoneGraph>();
} }

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