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

Merge branch 'develop' into feature/VCMIMapFormat1

Conflicts:
	lib/CArtHandler.cpp
This commit is contained in:
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"
using boost::optional;
static shared_ptr<CBattleCallback> cbc;
static std::shared_ptr<CBattleCallback> cbc;
#define LOGL(text) print(text)
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl))
@ -91,7 +91,7 @@ CBattleAI::~CBattleAI(void)
}
}
void CBattleAI::init(shared_ptr<CBattleCallback> CB)
void CBattleAI::init(std::shared_ptr<CBattleCallback> CB)
{
print("init called, saving ptr to IBattleCallback");
cbc = cb = CB;
@ -610,7 +610,7 @@ ThreatMap::ThreatMap(const CStack *Endangered) : endangered(Endangered)
const TBonusListPtr StackWithBonuses::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= nullptr*/, const std::string &cachingStr /*= ""*/) const
{
TBonusListPtr ret = make_shared<BonusList>();
TBonusListPtr ret = std::make_shared<BonusList>();
const TBonusListPtr originalList = stack->getAllBonuses(selector, limit, root, cachingStr);
range::copy(*originalList, std::back_inserter(*ret));
for(auto &bonus : bonusesToAdd)

View File

@ -110,7 +110,7 @@ struct PotentialTargets
class CBattleAI : public CBattleGameInterface
{
int side;
shared_ptr<CBattleCallback> cb;
std::shared_ptr<CBattleCallback> cb;
//Previous setting of cb
bool wasWaitingForRealize, wasUnlockingGs;
@ -120,7 +120,7 @@ public:
CBattleAI(void);
~CBattleAI(void);
void init(shared_ptr<CBattleCallback> CB) override;
void init(std::shared_ptr<CBattleCallback> CB) override;
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack

View File

@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
}
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
{
out = make_shared<CBattleAI>();
out = std::make_shared<CBattleAI>();
}

View File

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

View File

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

View File

@ -13,7 +13,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy(name,NAME);
}
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
{
out = make_shared<CEmptyAI>();
out = std::make_shared<CEmptyAI>();
}

View File

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

View File

@ -5,14 +5,14 @@
class CStupidAI : public CBattleGameInterface
{
int side;
shared_ptr<CBattleCallback> cb;
std::shared_ptr<CBattleCallback> cb;
void print(const std::string &text) const;
public:
CStupidAI(void);
~CStupidAI(void);
void init(shared_ptr<CBattleCallback> CB) override;
void init(std::shared_ptr<CBattleCallback> CB) override;
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack

View File

@ -25,7 +25,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
}
extern "C" DLL_EXPORT void GetNewBattleAI(shared_ptr<CBattleGameInterface> &out)
extern "C" DLL_EXPORT void GetNewBattleAI(std::shared_ptr<CBattleGameInterface> &out)
{
out = make_shared<CStupidAI>();
out = std::make_shared<CStupidAI>();
}

View File

@ -23,7 +23,6 @@ class CCallback;
typedef const int3& crint3;
typedef const std::string& crstring;
const int HERO_GOLD_COST = 2500;
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7;
const int ALLOWED_ROAMING_HEROES = 8;

View File

@ -31,7 +31,6 @@ class Engine;
class InputVariable;
class CGTownInstance;
using namespace vstd;
//using namespace Goals;
FuzzyHelper *fh;
@ -85,7 +84,7 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
if (walker)
walkersStrenght += s.second->getPower();
amax (maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
}
armyStructure as;
as.walkers = walkersStrenght / totalStrenght;
@ -297,7 +296,7 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
delete threat;
}
//shared_ptr<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec)
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec)
Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{

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
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 FuzzyHelper * fh; //TODO: this logic should be moved inside VCAI
using namespace vstd;
using namespace Goals;
TSubgoal Goals::sptr(const AbstractGoal & tmp)
{
shared_ptr<AbstractGoal> ptr;
std::shared_ptr<AbstractGoal> ptr;
ptr.reset(tmp.clone());
return ptr;
}
@ -575,7 +574,7 @@ TGoalVec Explore::getAllPossibleSubgoals()
{
//heroes = ai->getUnblockedHeroes();
heroes = cb->getHeroesInfo();
erase_if (heroes, [](const HeroPtr h)
vstd::erase_if(heroes, [](const HeroPtr h)
{
if (ai->getGoal(h)->goalType == Goals::EXPLORE) //do not reassign hero who is already explorer
return true;
@ -693,8 +692,8 @@ TSubgoal RecruitHero::whatToDoToAchieve()
if(!t)
return sptr (Goals::BuildThis(BuildingID::TAVERN));
if(cb->getResourceAmount(Res::GOLD) < HERO_GOLD_COST)
return sptr (Goals::CollectRes(Res::GOLD, HERO_GOLD_COST));
if(cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST)
return sptr (Goals::CollectRes(Res::GOLD, GameConstants::HERO_GOLD_COST));
return iAmElementar();
}
@ -747,10 +746,10 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
if (ai->canRecruitAnyHero())
ret.push_back (sptr(Goals::RecruitHero()));
}
if (ret.empty())
if(ret.empty())
{
auto obj = frontOrNull(cb->getVisitableObjs(tile));
if (obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
auto obj = vstd::frontOrNull(cb->getVisitableObjs(tile));
if(obj && obj->ID == Obj::HERO && obj->tempOwner == ai->playerID) //our own hero stands on that tile
{
if (hero.get(true) && hero->id == obj->id) //if it's assigned hero, visit tile. If it's different hero, we can't visit tile now
ret.push_back(sptr(Goals::VisitTile(tile).sethero(dynamic_cast<const CGHeroInstance *>(obj)).setisElementar(true)));
@ -767,7 +766,7 @@ TGoalVec VisitTile::getAllPossibleSubgoals()
TSubgoal DigAtTile::whatToDoToAchieve()
{
const CGObjectInstance *firstObj = frontOrNull(cb->getVisitableObjs(tile));
const CGObjectInstance *firstObj = vstd::frontOrNull(cb->getVisitableObjs(tile));
if(firstObj && firstObj->ID == Obj::HERO && firstObj->tempOwner == ai->playerID) //we have hero at dest
{
const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(firstObj);
@ -1057,7 +1056,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
auto otherHeroes = cb->getHeroesInfo();
auto heroDummy = hero;
erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
vstd::erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
{
return (h == heroDummy.h || !ai->isAccessibleForHero(heroDummy->visitablePos(), h, true)
|| !ai->canGetArmy(heroDummy.h, h) || ai->getGoal(h)->goalType == Goals::GATHER_ARMY);

View File

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

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
*
@ -29,8 +29,6 @@ class CGVisitableOPW;
const double SAFE_ATTACK_CONSTANT = 1.5;
const int GOLD_RESERVE = 10000; //when buying creatures we want to keep at least this much gold (10000 so at least we'll be able to reach capitol)
using namespace vstd;
//one thread may be turn of AI and another will be handling a side effect for AI2
boost::thread_specific_ptr<CCallback> cb;
boost::thread_specific_ptr<VCAI> ai;
@ -124,8 +122,8 @@ void VCAI::heroMoved(const TryMoveHero & details)
{
const int3 from = CGHeroInstance::convertPosition(details.start, false),
to = CGHeroInstance::convertPosition(details.end, false);
const CGObjectInstance *o1 = frontOrNull(cb->getVisitableObjs(from)),
*o2 = frontOrNull(cb->getVisitableObjs(to));
const CGObjectInstance *o1 = vstd::frontOrNull(cb->getVisitableObjs(from)),
*o2 = vstd::frontOrNull(cb->getVisitableObjs(to));
auto t1 = dynamic_cast<const CGTeleport *>(o1);
auto t2 = dynamic_cast<const CGTeleport *>(o2);
@ -394,8 +392,8 @@ void VCAI::objectRemoved(const CGObjectInstance *obj)
LOG_TRACE(logAi);
NET_EVENT_HANDLER;
erase_if_present(visitableObjs, obj);
erase_if_present(alreadyVisited, obj);
vstd::erase_if_present(visitableObjs, obj);
vstd::erase_if_present(alreadyVisited, obj);
for (auto h : cb->getHeroesInfo())
unreserveObject(h, obj);
@ -518,15 +516,15 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
{
//we don't want to visit know object twice (do we really?)
if(sop->val == playerID.getNum())
erase_if_present(visitableObjs, myCb->getObj(sop->id));
else if (myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
vstd::erase_if_present(visitableObjs, myCb->getObj(sop->id));
else if(myCb->getPlayerRelations(playerID, (PlayerColor)sop->val) == PlayerRelations::ENEMIES)
{
//we want to visit objects owned by oppponents
auto obj = myCb->getObj(sop->id, false);
if (obj)
{
addVisitableObj(obj);
erase_if_present(alreadyVisited, obj);
vstd::erase_if_present(alreadyVisited, obj);
}
}
}
@ -557,7 +555,7 @@ void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions)
NET_EVENT_HANDLER;
}
void VCAI::init(shared_ptr<CCallback> CB)
void VCAI::init(std::shared_ptr<CCallback> CB)
{
LOG_TRACE(logAi);
myCb = CB;
@ -738,7 +736,7 @@ void VCAI::makeTurn()
if (isWeeklyRevisitable(obj))
{
addVisitableObj(obj);
erase_if_present (alreadyVisited, obj);
vstd::erase_if_present(alreadyVisited, obj);
}
}
}
@ -841,7 +839,7 @@ void VCAI::makeTurnInternal()
{
if (h->movement)
logAi->warnStream() << boost::format("hero %s has %d MP left") % h->name % h->movement;
}
}
}
catch(boost::thread_interrupted &e)
{
@ -910,7 +908,7 @@ bool VCAI::canGetArmy (const CGHeroInstance * army, const CGHeroInstance * sourc
const CArmedInstance *armies[] = {army, source};
//we calculate total strength for each creature type available in armies
std::map<const CCreature*, int> creToPower;
for(auto armyPtr : armies)
@ -945,7 +943,7 @@ bool VCAI::canGetArmy (const CGHeroInstance * army, const CGHeroInstance * sourc
if(armyPtr->getCreature(SlotID(j)) == bestArmy[i] && armyPtr != army) //it's a searched creature not in dst ARMY
{
//FIXME: line below is useless when simulating exchange between two non-singular armies
if (!(armyPtr->needsLastStack() && armyPtr->Slots().size() == 1)) //can't take away last creature
if(!(armyPtr->needsLastStack() && armyPtr->stacksCount() == 1)) //can't take away last creature
return true; //at least one exchange will be performed
else
return false; //no further exchange possible
@ -992,7 +990,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
for (int j = 0; j < GameConstants::ARMY_SIZE; j++)
{
if(armyPtr->getCreature(SlotID(j)) == bestArmy[i] && (i != j || armyPtr != army)) //it's a searched creature not in dst SLOT
if (!(armyPtr->needsLastStack() && armyPtr->Slots().size() == 1)) //can't take away last creature
if(!(armyPtr->needsLastStack() && armyPtr->stacksCount() == 1)) //can't take away last creature
cb->mergeOrSwapStacks(armyPtr, army, SlotID(j), SlotID(i));
}
}
@ -1007,7 +1005,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
}
void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other)
{
{
auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
{
bool changeMade = false;
@ -1052,6 +1050,9 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
continue; //don't reequip artifact we already wear
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
continue;
auto s = location.getSlot();
if (!s || s->locked) //we can't move locks
continue;
@ -1118,7 +1119,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit
// if(containsSavedRes(c->cost))
// continue;
amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
vstd::amin(count, freeResources() / VLC->creh->creatures[creID]->cost);
if(count > 0)
cb->recruitCreatures(d, recruiter, creID, count, i);
}
@ -1445,7 +1446,7 @@ bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
if (!t)
t = findTownWithTavern();
if (t)
return cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST &&
return cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST &&
cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES &&
cb->getAvailableHeroes(t).size();
else
@ -1481,7 +1482,7 @@ void VCAI::wander(HeroPtr h)
}
range::copy(getPossibleDestinations(h), std::back_inserter(dests));
erase_if(dests, [&](ObjectIdRef obj) -> bool
vstd::erase_if(dests, [&](ObjectIdRef obj) -> bool
{
return !isSafeToVisit(h, sm->firstTileToGet(h, obj->visitablePos()));
});
@ -1530,10 +1531,10 @@ void VCAI::wander(HeroPtr h)
}
break;
}
else if(cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST)
else if(cb->getResourceAmount(Res::GOLD) >= GameConstants::HERO_GOLD_COST)
{
std::vector<const CGTownInstance *> towns = cb->getTownsInfo();
erase_if(towns, [](const CGTownInstance *t) -> bool
vstd::erase_if(towns, [](const CGTownInstance *t) -> bool
{
for(const CGHeroInstance *h : cb->getHeroesInfo())
if(!t->getArmyStrength() || howManyReinforcementsCanGet(h, t))
@ -1584,8 +1585,8 @@ void VCAI::wander(HeroPtr h)
void VCAI::setGoal(HeroPtr h, Goals::TSubgoal goal)
{ //TODO: check for presence?
if (goal->invalid())
erase_if_present(lockedHeroes, h);
if(goal->invalid())
vstd::erase_if_present(lockedHeroes, h);
else
{
lockedHeroes[h] = goal;
@ -1626,7 +1627,7 @@ void VCAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int
NET_EVENT_HANDLER;
assert(playerID > PlayerColor::PLAYER_LIMIT || status.getBattle() == UPCOMING_BATTLE);
status.setBattle(ONGOING_BATTLE);
const CGObjectInstance *presumedEnemy = backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
const CGObjectInstance *presumedEnemy = vstd::backOrNull(cb->getVisitableObjs(tile)); //may be nullptr in some very are cases -> eg. visited monolith and fighting with an enemy at the FoW covered exit
battlename = boost::str(boost::format("Starting battle of %s attacking %s at %s") % (hero1 ? hero1->name : "a army") % (presumedEnemy ? presumedEnemy->getObjectName() : "unknown enemy") % tile);
CAdventureAI::battleStart(army1, army2, tile, hero1, hero2, side);
}
@ -1666,8 +1667,8 @@ void VCAI::reserveObject(HeroPtr h, const CGObjectInstance *obj)
void VCAI::unreserveObject(HeroPtr h, const CGObjectInstance *obj)
{
erase_if_present(reservedObjs, obj); //unreserve objects
erase_if_present(reservedHeroesMap[h], obj);
vstd::erase_if_present(reservedObjs, obj); //unreserve objects
vstd::erase_if_present(reservedHeroesMap[h], obj);
}
void VCAI::markHeroUnableToExplore (HeroPtr h)
@ -1676,7 +1677,7 @@ void VCAI::markHeroUnableToExplore (HeroPtr h)
}
void VCAI::markHeroAbleToExplore (HeroPtr h)
{
erase_if_present(heroesUnableToExplore, h);
vstd::erase_if_present(heroesUnableToExplore, h);
}
bool VCAI::isAbleToExplore (HeroPtr h)
{
@ -1697,7 +1698,7 @@ void VCAI::validateVisitableObjs()
auto shouldBeErased = [&](const CGObjectInstance *obj) -> bool
{
if (obj)
return !cb->getObj(obj->id);
return !cb->getObj(obj->id, false); // no verbose output needed as we check object visibility
else
return true;
@ -1713,25 +1714,25 @@ void VCAI::validateVisitableObjs()
//errorMsg is captured by ref so lambda will take the new text
errorMsg = " shouldn't be on the visitable objects list!";
erase_if(visitableObjs, shouldBeErased);
vstd::erase_if(visitableObjs, shouldBeErased);
//FIXME: how comes our own heroes become inaccessible?
erase_if(reservedHeroesMap, [](std::pair<HeroPtr, std::set<const CGObjectInstance *>> hp) -> bool
vstd::erase_if(reservedHeroesMap, [](std::pair<HeroPtr, std::set<const CGObjectInstance *>> hp) -> bool
{
return !hp.first.get(true);
});
for(auto &p : reservedHeroesMap)
{
errorMsg = " shouldn't be on list for hero " + p.first->name + "!";
erase_if(p.second, shouldBeErased);
vstd::erase_if(p.second, shouldBeErased);
}
errorMsg = " shouldn't be on the reserved objs list!";
erase_if(reservedObjs, shouldBeErased);
vstd::erase_if(reservedObjs, shouldBeErased);
//TODO overkill, hidden object should not be removed. However, we can't know if hidden object is erased from game.
errorMsg = " shouldn't be on the already visited objs list!";
erase_if(alreadyVisited, shouldBeErased);
vstd::erase_if(alreadyVisited, shouldBeErased);
}
void VCAI::retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned /*= false*/) const
@ -1762,7 +1763,7 @@ std::vector<const CGObjectInstance *> VCAI::getFlaggedObjects() const
{
std::vector<const CGObjectInstance *> ret;
retreiveVisitableObjs(ret, true);
erase_if(ret, [](const CGObjectInstance *obj)
vstd::erase_if(ret, [](const CGObjectInstance *obj)
{
return obj->tempOwner != ai->playerID;
});
@ -1784,7 +1785,7 @@ const CGObjectInstance * VCAI::lookForArt(int aid) const
{
for(const CGObjectInstance *obj : ai->visitableObjs)
{
if(obj->ID == 5 && obj->subID == aid)
if(obj->ID == Obj::ARTIFACT && obj->subID == aid)
return obj;
}
@ -1876,6 +1877,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst;
throw goalFulfilledException (sptr(Goals::VisitTile(dst).sethero(h)));
}
int i = path.nodes.size()-1;
auto getObj = [&](int3 coord, bool ignoreHero)
{
@ -1885,6 +1887,31 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
//return cb->getTile(coord,false)->topVisitableObj(ignoreHero);
};
auto isTeleportAction = [&](CGPathNode::ENodeAction action) -> bool
{
if(action != CGPathNode::TELEPORT_NORMAL &&
action != CGPathNode::TELEPORT_BLOCKING_VISIT &&
action != CGPathNode::TELEPORT_BATTLE)
{
return false;
}
return true;
};
auto getDestTeleportObj = [&](const CGObjectInstance * currentObject, const CGObjectInstance * nextObjectTop, const CGObjectInstance * nextObject) -> const CGObjectInstance *
{
if(CGTeleport::isConnected(currentObject, nextObjectTop))
return nextObjectTop;
if(nextObjectTop && nextObjectTop->ID == Obj::HERO &&
CGTeleport::isConnected(currentObject, nextObject))
{
return nextObject;
}
return nullptr;
};
auto doMovement = [&](int3 dst, bool transit)
{
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
@ -1915,17 +1942,18 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
doTeleportMovement(currentExit, currentPos);
};
int i=path.nodes.size()-1;
for(; i>0; i--)
{
int3 currentCoord = path.nodes[i].coord;
int3 nextCoord = path.nodes[i-1].coord;
auto currentObject = getObj(currentCoord, currentCoord == CGHeroInstance::convertPosition(h->pos,false));
auto nextObject = getObj(nextCoord, false);
if(CGTeleport::isConnected(currentObject, nextObject))
auto nextObjectTop = getObj(nextCoord, false);
auto nextObject = getObj(nextCoord, true);
auto destTeleportObj = getDestTeleportObj(currentObject, nextObjectTop, nextObject);
if(isTeleportAction(path.nodes[i-1].action) && destTeleportObj != nullptr)
{ //we use special login if hero standing on teleporter it's mean we need
doTeleportMovement(nextObject->id, nextCoord);
doTeleportMovement(destTeleportObj->id, nextCoord);
if(teleportChannelProbingList.size())
doChannelProbing();
@ -1944,8 +1972,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
continue;
if((i-2 >= 0) // Check there is node after next one; otherwise transit is pointless
&& (CGTeleport::isConnected(nextObject, getObj(path.nodes[i-2].coord, false))
|| CGTeleport::isTeleport(nextObject)))
&& (CGTeleport::isConnected(nextObjectTop, getObj(path.nodes[i-2].coord, false))
|| CGTeleport::isTeleport(nextObjectTop)))
{ // Hero should be able to go through object if it's allow transit
doMovement(endpos, true);
}
@ -1963,7 +1991,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
}
if (h)
{
if (auto visitedObject = frontOrNull(cb->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
if(auto visitedObject = vstd::frontOrNull(cb->getVisitableObjs(h->visitablePos()))) //we stand on something interesting
{
if (visitedObject != *h)
performObjectInteraction (visitedObject, h);
@ -1974,16 +2002,16 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
completeGoal (sptr(Goals::VisitTile(dst).sethero(h))); //we stepped on some tile, anyway
completeGoal (sptr(Goals::ClearWayTo(dst).sethero(h)));
if (!ret) //reserve object we are heading towards
if(!ret) //reserve object we are heading towards
{
auto obj = frontOrNull(cb->getVisitableObjs(dst));
if (obj && obj != *h)
auto obj = vstd::frontOrNull(cb->getVisitableObjs(dst));
if(obj && obj != *h)
reserveObject(h, obj);
}
if (startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target
if(startHpos == h->visitablePos() && !ret) //we didn't move and didn't reach the target
{
erase_if_present (lockedHeroes, h); //hero seemingly is confused
vstd::erase_if_present(lockedHeroes, h); //hero seemingly is confused
throw cannotFulfillGoalException("Invalid path found!"); //FIXME: should never happen
}
logAi->debugStream() << boost::format("Hero %s moved from %s to %s. Returning %d.") % h->name % startHpos % h->visitablePos() % ret;
@ -2101,7 +2129,7 @@ void VCAI::tryRealize(Goals::CollectRes & g)
cb->trade(obj, EMarketMode::RESOURCE_RESOURCE, i, g.resID, toGive);
if(cb->getResourceAmount(static_cast<Res::ERes>(g.resID)) >= g.value)
return;
}
}
throw cannotFulfillGoalException("I cannot get needed resources by trade!");
}
@ -2290,7 +2318,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
}
else
{
erase_if_present (lockedHeroes, goal->hero); // we seemingly don't know what to do with hero
vstd::erase_if_present (lockedHeroes, goal->hero); // we seemingly don't know what to do with hero
}
}
@ -2319,7 +2347,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
completeGoal (goal);
//completed goal was main goal //TODO: find better condition
if (ultimateGoal->fulfillsMe(goal) || maxGoals > searchDepth2)
return sptr(Goals::Invalid());
return sptr(Goals::Invalid());
}
catch(std::exception &e)
{
@ -2545,7 +2573,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
for (int i = 1; i < radius; i++)
{
getVisibleNeighbours(tiles[i-1], tiles[i]);
removeDuplicates(tiles[i]);
vstd::removeDuplicates(tiles[i]);
for(const int3 &tile : tiles[i])
{
@ -2575,7 +2603,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
{
auto sm = getCachedSectorMap(h);
int radius = h->getSightRadious();
std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow]
tiles.resize(radius);
@ -2590,10 +2618,10 @@ int3 VCAI::explorationDesperate(HeroPtr h)
ui64 lowestDanger = -1;
int3 bestTile(-1,-1,-1);
for (int i = 1; i < radius; i++)
for(int i = 1; i < radius; i++)
{
getVisibleNeighbours(tiles[i-1], tiles[i]);
removeDuplicates(tiles[i]);
vstd::removeDuplicates(tiles[i]);
for(const int3 &tile : tiles[i])
{
@ -2705,37 +2733,26 @@ void VCAI::finish()
void VCAI::requestActionASAP(std::function<void()> whatToDo)
{
boost::mutex mutex;
mutex.lock();
boost::thread newThread([&mutex,this,whatToDo]()
boost::thread newThread([this,whatToDo]()
{
setThreadName("VCAI::requestActionASAP::helper");
setThreadName("VCAI::requestActionASAP::whatToDo");
SET_GLOBAL_STATE(this);
boost::shared_lock<boost::shared_mutex> gsLock(cb->getGsMutex());
// unlock mutex and allow parent function to exit
mutex.unlock();
whatToDo();
});
// wait for mutex to unlock and for thread to initialize properly
mutex.lock();
// unlock mutex - boost dislikes destruction of locked mutexes
mutex.unlock();
}
void VCAI::lostHero(HeroPtr h)
{
logAi->debugStream() << boost::format("I lost my hero %s. It's best to forget and move on.") % h.name;
erase_if_present(lockedHeroes, h);
vstd::erase_if_present(lockedHeroes, h);
for(auto obj : reservedHeroesMap[h])
{
erase_if_present(reservedObjs, obj); //unreserve all objects for that hero
vstd::erase_if_present(reservedObjs, obj); //unreserve all objects for that hero
}
erase_if_present(reservedHeroesMap, h);
erase_if_present(cachedSectorMaps, h);
vstd::erase_if_present(reservedHeroesMap, h);
vstd::erase_if_present(cachedSectorMaps, h);
}
void VCAI::answerQuery(QueryID queryID, int selection)
@ -2776,15 +2793,15 @@ void VCAI::validateObject(const CGObjectInstance *obj)
void VCAI::validateObject(ObjectIdRef obj)
{
auto matchesId = [&] (const CGObjectInstance *hlpObj) -> bool { return hlpObj->id == obj.id; };
auto matchesId = [&](const CGObjectInstance *hlpObj) -> bool { return hlpObj->id == obj.id; };
if(!obj)
{
erase_if(visitableObjs, matchesId);
vstd::erase_if(visitableObjs, matchesId);
for(auto &p : reservedHeroesMap)
erase_if(p.second, matchesId);
vstd::erase_if(p.second, matchesId);
erase_if(reservedObjs, matchesId);
vstd::erase_if(reservedObjs, matchesId);
}
}
@ -2933,8 +2950,8 @@ void AIStatus::heroVisit(const CGObjectInstance *obj, bool started)
objectsBeingVisited.push_back(obj);
else
{
// There can be more than one object visited at the time (eg. hero visits Subterranean Gate
// causing visit to hero on the other side.
// There can be more than one object visited at the time (eg. hero visits Subterranean Gate
// causing visit to hero on the other side.
// However, we are guaranteed that start/end visit notification maintain stack order.
assert(!objectsBeingVisited.empty());
objectsBeingVisited.pop_back();
@ -3048,7 +3065,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp)
s.embarkmentPoints.push_back(neighPos);
}
});
if(t->visitable)
{
auto obj = t->visitableObjects.front();
@ -3062,7 +3079,7 @@ void SectorMap::exploreNewSector(crint3 pos, int num, CCallback * cbp)
}
}
removeDuplicates(s.embarkmentPoints);
vstd::removeDuplicates(s.embarkmentPoints);
}
void SectorMap::write(crstring fname)
@ -3104,7 +3121,7 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj)
bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
{
switch (obj->ID)
{
{
case Obj::TOWN:
case Obj::HERO: //never visit our heroes at random
return obj->tempOwner != h->tempOwner; //do not visit our towns at random
@ -3155,7 +3172,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
return canRecruitCreatures;
}
case Obj::HILL_FORT:
{
{
for (auto slot : h->Slots())
{
if (slot.second->type->upgrades.size())
@ -3241,21 +3258,6 @@ For ship construction etc, another function (goal?) is needed
sectorQueue.push(neigh);
}
}
for (auto gate : s->subterraneanGates)
{
auto gatePair = ai->knownSubterraneanGates.find(gate);
if (gatePair != ai->knownSubterraneanGates.end())
{
//check the other side of gate
Sector *neigh = &infoOnSectors[retreiveTile(gatePair->second->visitablePos())];
if(!preds[neigh]) //if we didn't come into this sector yet
{
preds[neigh] = s; //it becomes our new target sector
sectorQueue.push(neigh);
}
}
}
}
if(!preds[dest])
@ -3361,30 +3363,8 @@ For ship construction etc, another function (goal?) is needed
//disembark
return ret;
}
else //use subterranean gates
else //use subterranean gates - not needed since gates are now handled via Pathfinder
{
//auto t = findFirstVisitableTile (h, dst);
//if (t.valid())
// return t;
//TODO: pop sectors linked by Subterranean Gate in loop
auto firstGate = boost::find_if(src->subterraneanGates, [=](const CGObjectInstance * gate) -> bool
{
//make sure no hero block the way
auto pos = ai->knownSubterraneanGates[gate]->visitablePos();
const TerrainTile *t = getTile(pos);
return t && t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::SUBTERRANEAN_GATE
&& retreiveTile(pos) == sectorToReach->id;
});
if(firstGate != src->subterraneanGates.end())
{
//TODO: pahtfinder can find path through subterranean gates, but this function only reaches closest gate
return (*firstGate)->visitablePos();
}
//TODO
//Monolith? Whirlpool? ...
return ret;
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
}
@ -3455,7 +3435,7 @@ void SectorMap::makeParentBFS(crint3 source)
ui8 &sec = retreiveTile(curPos);
assert(sec == mySector); //consider only tiles from the same sector
UNUSED(sec);
foreach_neighbour(curPos, [&](crint3 neighPos)
{
if(retreiveTile(neighPos) == mySector && !vstd::contains(parent, neighPos))

View File

@ -93,7 +93,7 @@ struct SectorMap
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
std::map<int, Sector> infoOnSectors;
shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
SectorMap();
SectorMap(HeroPtr h);
@ -129,7 +129,7 @@ public:
friend class FuzzyHelper;
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > knownTeleportChannels;
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > knownTeleportChannels;
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
ObjectInstanceID destinationTeleport;
int3 destinationTeleportPos;
@ -153,9 +153,9 @@ public:
AIStatus status;
std::string battlename;
shared_ptr<CCallback> myCb;
std::shared_ptr<CCallback> myCb;
unique_ptr<boost::thread> makingTurn;
std::unique_ptr<boost::thread> makingTurn;
VCAI(void);
~VCAI(void);
@ -180,7 +180,7 @@ public:
virtual std::string getBattleAIName() const override;
virtual void init(shared_ptr<CCallback> CB) override;
virtual void init(std::shared_ptr<CCallback> CB) override;
virtual void yourTurn() override;
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id

View File

@ -23,7 +23,7 @@ extern "C" DLL_EXPORT void GetAiName(char* name)
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
}
extern "C" DLL_EXPORT void GetNewAI(shared_ptr<CGlobalAI> &out)
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out)
{
out = make_shared<VCAI>();
out = std::make_shared<VCAI>();
}

View File

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

View File

@ -333,22 +333,22 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance
return swapCreatures(s1, s2, p1, p2);
}
void CCallback::registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
void CCallback::registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
{
cl->additionalPlayerInts[*player].push_back(gameEvents);
}
void CCallback::registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
void CCallback::registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
{
cl->additionalBattleInts[*player].push_back(battleEvents);
}
void CCallback::unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents)
void CCallback::unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents)
{
cl->additionalPlayerInts[*player] -= gameEvents;
}
void CCallback::unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents)
void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents)
{
cl->additionalBattleInts[*player] -= battleEvents;
}

View File

@ -110,10 +110,10 @@ public:
virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out);
//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins.
void registerGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
void registerBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
void unregisterGameInterface(shared_ptr<IGameEventsReceiver> gameEvents);
void unregisterBattleInterface(shared_ptr<IBattleEventsReceiver> battleEvents);
void registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
void unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents);
void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents);
void unregisterAllInterfaces(); //stops delivering information about game events to player interfaces -> can be called ONLY after victory/loss

View File

@ -64,7 +64,7 @@ endif()
if (WIN32)
add_definitions(-DBOOST_THREAD_USE_LIB)
add_definitions(-D_WIN32_WINNT=0x0501)
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock)
set(SYSTEM_LIBS ${SYSTEM_LIBS} ole32 oleaut32 ws2_32 mswsock dbghelp)
#delete lib prefix for dlls (libvcmi -> vcmi)
set(CMAKE_SHARED_LIBRARY_PREFIX "")

View File

@ -93,6 +93,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
#ifdef VCMI_WINDOWS
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - delete this line if something is missing.
# define NOMINMAX // Exclude min/max macros from <Windows.h>. Use std::[min/max] from <algorithm> instead.
# define _NO_W32_PSEUDO_MODIFIERS // Exclude more macros for compiling with MinGW on Linux.
#endif
/* ---------------------------------------------------------------------------- */
@ -179,9 +180,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
/* ---------------------------------------------------------------------------- */
/* Usings */
/* ---------------------------------------------------------------------------- */
using std::shared_ptr;
using std::unique_ptr;
using std::make_shared;
using namespace std::placeholders;
namespace range = boost::range;

View File

@ -170,9 +170,9 @@ static void prog_version(void)
static void prog_help(const po::options_description &opts)
{
printf("%s - A Heroes of Might and Magic 3 clone\n", GameConstants::VCMI_VERSION.c_str());
printf("Copyright (C) 2007-2014 VCMI dev team - see AUTHORS file\n");
printf("This is free software; see the source for copying conditions. There is NO\n");
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
printf("Copyright (C) 2007-2016 VCMI dev team - see AUTHORS file\n");
printf("This is free software; see the source for copying conditions. There is NO\n");
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
printf("\n");
printf("Usage:\n");
std::cout << opts;
@ -244,7 +244,9 @@ int main(int argc, char** argv)
("loadhumanplayerindices",po::value<std::vector<int>>(),"Indexes of human players (0=Red, etc.)")
("loadplayer", po::value<int>(),"specifies which player we are in multiplayer loaded games (0=Red, etc.)")
("loadserverip",po::value<std::string>(),"IP for loaded game server")
("loadserverport",po::value<std::string>(),"port for loaded game server");
("loadserverport",po::value<std::string>(),"port for loaded game server")
("testingport",po::value<std::string>(),"port for testing, override specified in config file")
("testingfileprefix",po::value<std::string>(),"prefix for auto save files");
if(argc > 1)
{
@ -281,7 +283,7 @@ int main(int argc, char** argv)
// it may result in very small \ very fast mouse when game in fullscreen mode
putenv((char*)"SDL_VIDEO_X11_DGAMOUSE=0");
// Init old logging system and new (temporary) logging system
// Init old logging system and new (temporary) logging system
CStopWatch total, pomtime;
std::cout.flags(std::ios::unitbuf);
console = new CConsoleHandler;
@ -291,16 +293,25 @@ int main(int argc, char** argv)
const bfs::path logPath = VCMIDirs::get().userCachePath() / "VCMI_Client_log.txt";
CBasicLogConfigurator logConfig(logPath, console);
logConfig.configureDefault();
logConfig.configureDefault();
logGlobal->infoStream() << "Creating console and configuring logger: " << pomtime.getDiff();
logGlobal->infoStream() << "The log file will be saved to " << logPath;
// Init filesystem and settings
// Init filesystem and settings
preinitDLL(::console);
settings.init();
settings.init();
// Initialize logging based on settings
logConfig.configure();
// Init special testing settings
Settings testingSettings = settings.write["testing"];
if(vm.count("testingport") && vm.count("testingfileprefix"))
{
testingSettings["enabled"].Bool() = true;
testingSettings["port"].String() = vm["testingport"].as<std::string>();
testingSettings["prefix"].String() = vm["testingfileprefix"].as<std::string>();
}
// Initialize logging based on settings
logConfig.configure();
// Some basic data validation to produce better error messages in cases of incorrect install
auto testFile = [](std::string filename, std::string message) -> bool
@ -308,13 +319,15 @@ int main(int argc, char** argv)
if (CResourceHandler::get()->existsResource(ResourceID(filename)))
return true;
logGlobal->errorStream() << "Error: " << message << " was not found!";
logGlobal->errorStream() << "Error: " << message << " was not found!";
return false;
};
if (!testFile("DATA/HELP.TXT", "Heroes III data") ||
!testFile("MODS/VCMI/MOD.JSON", "VCMI data"))
!testFile("MODS/VCMI/MOD.JSON", "VCMI data"))
{
exit(1); // These are unrecoverable errors
}
// these two are optional + some installs have them on CD and not in data directory
testFile("VIDEO/GOOD1A.SMK", "campaign movies");

View File

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

View File

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

View File

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

View File

@ -105,7 +105,7 @@ public:
static CBattleInterface * battleInt; //nullptr if no battle
CInGameConsole * cingconsole;
shared_ptr<CCallback> cb; //to communicate with engine
std::shared_ptr<CCallback> cb; //to communicate with engine
const BattleAction *curAction; //during the battle - action currently performed by active stack (or nullptr)
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
@ -116,7 +116,7 @@ public:
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
//During battle is quick combat mode is used
shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
const CArmedInstance * getSelection();
@ -236,7 +236,7 @@ public:
void openTownWindow(const CGTownInstance * town); //shows townscreen
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
void updateInfo(const CGObjectInstance * specific);
void init(shared_ptr<CCallback> CB) override;
void init(std::shared_ptr<CCallback> CB) override;
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
// show dialogs

View File

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

View File

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

View File

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

View File

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

View File

@ -95,7 +95,7 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2,
const CGHeroInstance *hero1, const CGHeroInstance *hero2,
const SDL_Rect & myRect,
shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen)
std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen)
: background(nullptr), queue(nullptr), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
activeStack(nullptr), mouseHoveredStack(nullptr), stackToActivate(nullptr), selectedStack(nullptr), previouslyHoveredHex(-1),
currentlyHoveredHex(-1), attackingHex(-1), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(nullptr), sp(nullptr),
@ -3260,7 +3260,7 @@ void CBattleInterface::showStacks(SDL_Surface * to, std::vector<const CStack *>
}
}
void CBattleInterface::showObstacles(SDL_Surface *to, std::vector<shared_ptr<const CObstacleInstance> > &obstacles)
void CBattleInterface::showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance> > &obstacles)
{
for (auto & obstacle : obstacles)
{

View File

@ -79,7 +79,7 @@ struct BattleObjectsByHex
typedef std::vector<int> TWallList;
typedef std::vector<const CStack * > TStackList;
typedef std::vector<const BattleEffect *> TEffectList;
typedef std::vector<shared_ptr<const CObstacleInstance> > TObstacleList;
typedef std::vector<std::shared_ptr<const CObstacleInstance> > TObstacleList;
struct HexData
{
@ -153,7 +153,7 @@ private:
BattleHex currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
int attackingHex; //hex from which the stack would perform attack with current cursor
shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
std::shared_ptr<CPlayerInterface> tacticianInterface; //used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
bool tacticsMode;
bool stackCanCastSpell; //if true, active stack could possibly cast some target spell
bool creatureCasting; //if true, stack currently aims to cats a spell
@ -212,8 +212,8 @@ private:
friend class CBattleInterface;
} * siegeH;
shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
shared_ptr<CPlayerInterface> curInt; //current player interface
std::shared_ptr<CPlayerInterface> attackerInt, defenderInt; //because LOCPLINT is not enough in hotSeat
std::shared_ptr<CPlayerInterface> curInt; //current player interface
const CGHeroInstance * getActiveHero(); //returns hero that can currently cast a spell
/** Methods for displaying battle screen */
@ -229,7 +229,7 @@ private:
void showAliveStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
void showStacks(SDL_Surface * to, std::vector<const CStack *> stacks);
void showObstacles(SDL_Surface *to, std::vector<shared_ptr<const CObstacleInstance> > &obstacles);
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance> > &obstacles);
void showPiecesOfWall(SDL_Surface * to, std::vector<int> pieces);
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
@ -249,7 +249,7 @@ public:
ui32 animIDhelper; //for giving IDs for animations
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, shared_ptr<CPlayerInterface> att, shared_ptr<CPlayerInterface> defen); //c-tor
CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, const SDL_Rect & myRect, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen); //c-tor
~CBattleInterface(); //d-tor
//std::vector<TimeInterested*> timeinterested; //animation handling

View File

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

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);
else if(terName)
{

View File

@ -380,7 +380,16 @@ void MoraleLuckBox::set(const IBonusBearer *node)
if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD)
|| node->hasBonusOfType(Bonus::BLOCK_MORALE)
|| node->hasBonusOfType(Bonus::NON_LIVING)))
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
{
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
bonusValue = 0;
}
else if(!morale && node && node->hasBonusOfType(Bonus::BLOCK_LUCK))
{
// TODO: there is no text like "Unaffected by luck" so probably we need own text
text += CGI->generaltexth->arraytxt[noneTxtId];
bonusValue = 0;
}
else if(modifierList->empty())
text += CGI->generaltexth->arraytxt[noneTxtId];//no modifiers
else

View File

@ -55,16 +55,15 @@
*/
#define ADVOPT (conf.go()->ac)
using namespace boost::logic;
using namespace CSDL_Ext;
CAdvMapInt *adventureInt;
CTerrainRect::CTerrainRect()
: fadeSurface(nullptr),
: fadeSurface(nullptr),
fadeAnim(new CFadeAnimation()),
curHoveredTile(-1,-1,-1),
curHoveredTile(-1,-1,-1),
currentPath(nullptr)
{
tilesw=(ADVOPT.advmapW+31)/32;
@ -283,7 +282,7 @@ void CTerrainRect::show(SDL_Surface * to)
info.heroAnim = adventureInt->heroAnim;
if (ADVOPT.smoothMove)
info.movement = int3(moveX, moveY, 0);
lastRedrawStatus = CGI->mh->drawTerrainRectNew(to, &info);
if (fadeAnim->isFading())
{
@ -316,7 +315,7 @@ void CTerrainRect::showAll(SDL_Surface * to)
}
void CTerrainRect::showAnim(SDL_Surface * to)
{
{
if (fadeAnim->isFading())
show(to);
else if (lastRedrawStatus == EMapAnimRedrawStatus::REDRAW_REQUESTED)
@ -357,7 +356,7 @@ void CTerrainRect::fadeFromCurrentView()
return;
if (adventureInt->mode == EAdvMapMode::WORLD_VIEW)
return;
if (!fadeSurface)
fadeSurface = CSDL_Ext::newSurface(pos.w, pos.h);
SDL_BlitSurface(screen, &pos, fadeSurface, nullptr);
@ -502,10 +501,10 @@ CAdvMapInt::CAdvMapInt():
endTurn = makeButton(302, std::bind(&CAdvMapInt::fendTurn,this), ADVOPT.endTurn, SDLK_e);
int panelSpaceBottom = screen->h - resdatabar.pos.h - 4;
panelMain = new CAdvMapPanel(nullptr, Point(0, 0));
// TODO correct drawing position
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
panelWorldView = new CAdvMapWorldViewPanel(bgWorldView, Point(heroList.pos.x - 2, 195), panelSpaceBottom, LOCPLINT->playerID);
panelMain->addChildColorableButton(kingOverview);
panelMain->addChildColorableButton(underground);
@ -593,7 +592,7 @@ CAdvMapInt::CAdvMapInt():
Colors::WHITE, CGI->generaltexth->allTexts[618]));
activeMapPanel = panelMain;
changeMode(EAdvMapMode::NORMAL);
underground->block(!CGI->mh->map->twoLevel);
@ -767,6 +766,11 @@ void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
moveHero->block(!hasPath || (h->movement == 0));
}
void CAdvMapInt::updateSpellbook(const CGHeroInstance *h)
{
spellbook->block(!h);
}
int CAdvMapInt::getNextHeroIndex(int startIndex)
{
if (LOCPLINT->wanderingHeroes.size() == 0)
@ -966,7 +970,7 @@ void CAdvMapInt::show(SDL_Surface * to)
for(int i=0;i<4;i++)
blitAt(gems[i]->ourImages[LOCPLINT->playerID.getNum()].bitmap,ADVOPT.gemX[i],ADVOPT.gemY[i],to);
}
infoBar.show(to);
statusbar.showAll(to);
}
@ -981,7 +985,7 @@ void CAdvMapInt::selectionChanged()
void CAdvMapInt::centerOn(int3 on, bool fade /* = false */)
{
bool switchedLevels = on.z != position.z;
if (fade)
{
terrain.fadeFromCurrentView();
@ -1262,6 +1266,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
updateSleepWake(nullptr);
updateMoveHero(nullptr);
updateSpellbook(nullptr);
}
else //hero selected
{
@ -1275,6 +1280,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
updateSleepWake(hero);
updateMoveHero(hero);
updateSpellbook(hero);
}
townList.redraw();
heroList.redraw();
@ -1531,12 +1537,16 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
}
else if(const CGHeroInstance * h = curHero())
{
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPos);
int3 mapPosCopy = mapPos;
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPosCopy);
assert(pnode);
int turns = pnode->turns;
vstd::amin(turns, 3);
switch(pnode->action)
{
case CGPathNode::NORMAL:
case CGPathNode::TELEPORT_NORMAL:
if(pnode->layer == EPathfindingLayer::LAND)
CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
else
@ -1545,6 +1555,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
case CGPathNode::VISIT:
case CGPathNode::BLOCKING_VISIT:
case CGPathNode::TELEPORT_BLOCKING_VISIT:
if(objAtTile && objAtTile->ID == Obj::HERO)
{
if(selection == objAtTile)
@ -1559,6 +1570,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
break;
case CGPathNode::BATTLE:
case CGPathNode::TELEPORT_BATTLE:
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
break;
@ -1708,9 +1720,9 @@ void CAdvMapInt::changeMode(EAdvMapMode newMode, float newScale /* = 0.4f */)
townList.activate();
heroList.activate();
infoBar.activate();
worldViewOptions.clear();
break;
case EAdvMapMode::WORLD_VIEW:
panelMain->deactivate();
@ -1780,14 +1792,13 @@ CAdvMapInt::WorldViewOptions::WorldViewOptions()
void CAdvMapInt::WorldViewOptions::clear()
{
showAllTerrain = false;
iconPositions.clear();
}
void CAdvMapInt::WorldViewOptions::adjustDrawingInfo(MapDrawingInfo& info)
{
info.showAllTerrain = showAllTerrain;
info.additionalIcons = &iconPositions;
}
info.additionalIcons = &iconPositions;
}

View File

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

View File

@ -230,7 +230,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building
}
else
{
logGlobal->warnStream() << "Problem: dwelling with id " << bid << " offers no creatures!";
logGlobal->warnStream() << "Problem: dwelling with id " << bid << " offers no creatures!";
return "#ERROR#";
}
}
@ -501,7 +501,10 @@ void CCastleBuildings::recreate()
if(vstd::contains(town->builtBuildings, BuildingID::SHIPYARD))
{
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(town->bestLocation());
auto bayPos = town->bestLocation();
if(!bayPos.valid())
logGlobal->warnStream() << "Shipyard in non-coastal town!";
std::vector <const CGObjectInstance *> vobjs = LOCPLINT->cb->getVisitableObjs(bayPos, false);
//there is visitable obj at shipyard output tile and it's a boat or hero (on boat)
if(!vobjs.empty() && (vobjs.front()->ID == Obj::BOAT || vobjs.front()->ID == Obj::HERO))
{

View File

@ -86,7 +86,7 @@ void CQuestMinimap::addQuestMarks (const QuestInfo * q)
if (level != tile.z)
setLevel(tile.z);
auto pic = make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
auto pic = std::make_shared<CQuestIcon>("VwSymbol.def", 3, x, y);
pic->moveBy (Point ( -pic->pos.w/2, -pic->pos.h/2));
pic->callback = std::bind (&CQuestMinimap::iconClicked, this);
@ -179,7 +179,7 @@ void CQuestLog::recreateLabelList()
else
text.addReplacement(quests[i].obj->getObjectName()); //get name of the object
}
auto label = make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
auto label = std::make_shared<CQuestLabel>(Rect(13, 195, 149,31), FONT_SMALL, TOPLEFT, Colors::WHITE, text.toString());
label->disable();
label->callback = std::bind(&CQuestLog::selectQuest, this, i, currentLabel);

View File

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

View File

@ -861,7 +861,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
if(itemsType[1] == RESOURCE)
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<Res::ERes>(soldItemId));
else if(itemsType[1] == CREATURE)
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->Slots().size() == 1 && hero->needsLastStack());
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack());
else
assert(0);

View File

@ -704,7 +704,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
oldSelected = -1;
new CLabel(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]);
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, "2500");
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, boost::lexical_cast<std::string>(GameConstants::HERO_GOLD_COST));
auto rumorText = boost::str(boost::format(CGI->generaltexth->allTexts[216]) % LOCPLINT->cb->getTavernRumor(tavernObj));
new CTextBox(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
@ -714,7 +714,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
recruit = new CButton(Point(272, 355), "TPTAV01.DEF", CButton::tooltip(), std::bind(&CTavernWindow::recruitb, this), SDLK_RETURN);
thiefGuild = new CButton(Point(22, 428), "TPTAV02.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[5]), std::bind(&CTavernWindow::thievesguildb, this), SDLK_t);
if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < 2500) //not enough gold
if(LOCPLINT->cb->getResourceAmount(Res::GOLD) < GameConstants::HERO_GOLD_COST) //not enough gold
{
recruit->addHoverText(CButton::NORMAL, CGI->generaltexth->tavernInfo[0]); //Cannot afford a Hero
recruit->block(true);

View File

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

View File

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

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)
int3 tile; //for background and bonuses
std::vector<CStack*> stacks;
std::vector<shared_ptr<CObstacleInstance> > obstacles;
std::vector<std::shared_ptr<CObstacleInstance> > obstacles;
SiegeInfo si;
BFieldType battlefieldType; //like !!BA:B
@ -124,7 +124,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
//std::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = nullptr, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
shared_ptr<CObstacleInstance> getObstacleOnTile(BattleHex tile) const;
std::shared_ptr<CObstacleInstance> getObstacleOnTile(BattleHex tile) const;
std::set<BattleHex> getStoppers(bool whichSidePerspective) const;
ui32 calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand); //charge - number of hexes travelled before attack (for champion's jousting)

View File

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

View File

@ -258,8 +258,8 @@ private:
void loadComponents(CArtifact * art, const JsonNode & node);
void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalinfo = 0);
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator, int additionalinfo = 0);
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, std::shared_ptr<ILimiter> limiter = std::shared_ptr<ILimiter>(), int additionalinfo = 0);
void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, std::shared_ptr<IPropagator> propagator, int additionalinfo = 0);
void giveArtBonus(ArtifactID aid, Bonus *bonus);
void erasePickedArt(ArtifactID id);

View File

@ -130,9 +130,9 @@ BFieldType CBattleInfoEssentials::battleGetBattlefieldType() const
return getBattle()->battlefieldType;
}
std::vector<shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
std::vector<std::shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
{
std::vector<shared_ptr<const CObstacleInstance> > ret;
std::vector<std::shared_ptr<const CObstacleInstance> > ret;
RETURN_IF_NOT_BATTLE(ret);
if(!perspective)
@ -1100,9 +1100,9 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
return ret;
}
shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/) const
std::shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking /*= true*/) const
{
RETURN_IF_NOT_BATTLE(shared_ptr<const CObstacleInstance>());
RETURN_IF_NOT_BATTLE(std::shared_ptr<const CObstacleInstance>());
for(auto &obs : battleGetAllObstacles())
{
@ -1113,7 +1113,7 @@ shared_ptr<const CObstacleInstance> CBattleInfoCallback::battleGetObstacleOnPos(
}
}
return shared_ptr<const CObstacleInstance>();
return std::shared_ptr<const CObstacleInstance>();
}
AccessibilityInfo CBattleInfoCallback::getAccesibility() const

View File

@ -170,7 +170,7 @@ public:
ETerrainType battleTerrainType() const;
BFieldType battleGetBattlefieldType() const;
std::vector<shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
/** @brief Main method for getting battle stacks
*
@ -243,7 +243,7 @@ public:
//battle
boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
std::shared_ptr<const CObstacleInstance> battleGetObstacleOnPos(BattleHex tile, bool onlyBlocking = true) const; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
const CStack * battleGetStackByPos(BattleHex pos, bool onlyAlive = true) const; //returns stack info by given pos
void battleGetStackQueue(std::vector<const CStack *> &out, const int howMany, const int turn = 0, int lastMoved = -1) const;
void battleGetStackCountOutsideHexes(bool *ac) const; // returns hexes which when in front of a stack cause us to move the amount box back

View File

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

View File

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

View File

@ -225,14 +225,39 @@ ui64 CCreatureSet::getPower (SlotID slot) const
return getStack(slot).getPower();
}
std::string CCreatureSet::getRoughAmount (SlotID slot) const
std::string CCreatureSet::getRoughAmount(SlotID slot, int mode) const
{
/// Mode represent return string format
/// "Pack" - 0, "A pack of" - 1, "a pack of" - 2
int quantity = CCreature::getQuantityID(getStackCount(slot));
if (quantity)
return VLC->generaltexth->arraytxt[174 + 3*CCreature::getQuantityID(getStackCount(slot))];
if(quantity)
return VLC->generaltexth->arraytxt[(174 + mode) + 3*CCreature::getQuantityID(getStackCount(slot))];
return "";
}
std::string CCreatureSet::getArmyDescription() const
{
std::string text;
std::vector<std::string> guards;
for(auto & elem : stacks)
{
auto str = boost::str(boost::format("%s %s") % getRoughAmount(elem.first, 2) % getCreature(elem.first)->namePl);
guards.push_back(str);
}
if(guards.size())
{
for(int i = 0; i < guards.size(); i++)
{
text += guards[i];
if(i + 2 < guards.size())
text += ", ";
else if(i + 2 == guards.size())
text += VLC->generaltexth->allTexts[237];
}
}
return text;
}
int CCreatureSet::stacksCount() const
{
return stacks.size();

View File

@ -200,7 +200,8 @@ public:
virtual bool needsLastStack() const; //true if last stack cannot be taken
ui64 getArmyStrength() const; //sum of AI values of creatures
ui64 getPower (SlotID slot) const; //value of specific stack
std::string getRoughAmount (SlotID slot) const; //rough size of specific stack
std::string getRoughAmount(SlotID slot, int mode = 0) const; //rough size of specific stack
std::string getArmyDescription() const;
bool hasStackAtSlot(SlotID slot) const;
bool contains(const CStackInstance *stack) const;

View File

@ -475,7 +475,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
}
//TODO: typedef?
shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
{
assert(player.is_initialized());
auto team = getPlayerTeam(player.get());
@ -496,7 +496,7 @@ shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisible
else
tileArray[x][y][z] = nullptr;
}
return make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
return std::make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
}
EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
@ -577,7 +577,7 @@ EPlayerStatus::EStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bo
std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTavern) const
{
std::string text = "", extraText = "";
if(gs->rumor.type == RumorState::TYPE_NONE) // (version < 755 backward compatability
if(gs->rumor.type == RumorState::TYPE_NONE)
return text;
auto rumor = gs->rumor.last[gs->rumor.type];

View File

@ -91,7 +91,7 @@ public:
const CMapHeader * getMapHeader()const;
int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map
const TerrainTile * getTile(int3 tile, bool verbose = true) const;
shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> getAllVisibleTiles() const;
bool isInTheMap(const int3 &pos) const;
//town

View File

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

View File

@ -67,7 +67,7 @@ public:
std::string dllName;
virtual ~CBattleGameInterface() {};
virtual void init(shared_ptr<CBattleCallback> CB){};
virtual void init(std::shared_ptr<CBattleCallback> CB){};
//battle call-ins
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
@ -82,7 +82,7 @@ public:
class DLL_LINKAGE CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
{
public:
virtual void init(shared_ptr<CCallback> CB){};
virtual void init(std::shared_ptr<CCallback> CB){};
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
@ -105,9 +105,9 @@ public:
class DLL_LINKAGE CDynLibHandler
{
public:
static shared_ptr<CGlobalAI> getNewAI(std::string dllname);
static shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
static shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
static std::shared_ptr<CGlobalAI> getNewAI(std::string dllname);
static std::shared_ptr<CBattleGameInterface> getNewBattleAI(std::string dllname);
static std::shared_ptr<CScriptingModule> getNewScriptingModule(std::string dllname);
};
class DLL_LINKAGE CGlobalAI : public CGameInterface // AI class (to derivate)
@ -123,8 +123,8 @@ class DLL_LINKAGE CAdventureAI : public CGlobalAI
public:
CAdventureAI() {};
shared_ptr<CBattleGameInterface> battleAI;
shared_ptr<CBattleCallback> cbc;
std::shared_ptr<CBattleGameInterface> battleAI;
std::shared_ptr<CBattleCallback> cbc;
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used

View File

@ -675,8 +675,8 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
}
else
{
cur->setType(ran.first, ran.second);
}
cur->setType(ran.first, ran.second);
}
}
int CGameState::getDate(Date::EDateType mode) const
@ -1939,7 +1939,7 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile)
case Obj::EVIL_FOG:
return BFieldType::EVIL_FOG;
case Obj::FAVORABLE_WINDS:
return BFieldType::FAVOURABLE_WINDS;
return BFieldType::FAVORABLE_WINDS;
case Obj::FIERY_FIELDS:
return BFieldType::FIERY_FIELDS;
case Obj::HOLY_GROUNDS:
@ -3177,7 +3177,7 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
for(const JsonNode &n : duelData["obstacles"].Vector())
{
auto oi = make_shared<CObstacleInstance>();
auto oi = std::make_shared<CObstacleInstance>();
if(n.getType() == JsonNode::DATA_VECTOR)
{
oi->ID = n.Vector()[0].Float();

View File

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

View File

@ -150,22 +150,24 @@ void CPathfinder::calculatePaths()
continue;
destAction = getDestAction();
int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, movement, hlp->getTurnInfo());
int remains = movement - cost;
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
{
remains = hero->movementPointsAfterEmbark(movement, cost, destAction - 1, hlp->getTurnInfo());
cost = movement - remains;
}
int turnAtNextTile = turn;
int turnAtNextTile = turn, moveAtNextTile = movement;
int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo());
int remains = moveAtNextTile - cost;
if(remains < 0)
{
//occurs rarely, when hero with low movepoints tries to leave the road
hlp->updateTurnInfo(++turnAtNextTile);
int moveAtNextTile = hlp->getMaxMovePoints(i);
moveAtNextTile = hlp->getMaxMovePoints(i);
cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo()); //cost must be updated, movement points changed :(
remains = moveAtNextTile - cost;
}
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
{
/// FREE_SHIP_BOARDING bonus only remove additional penalty
/// land <-> sail transition still cost movement points as normal movement
remains = hero->movementPointsAfterEmbark(moveAtNextTile, cost, destAction - 1, hlp->getTurnInfo());
cost = moveAtNextTile - remains;
}
if(isBetterWay(remains, turnAtNextTile) &&
((cp->turns == turnAtNextTile && remains) || passOneTurnLimitCheck()))
@ -189,14 +191,24 @@ void CPathfinder::calculatePaths()
dp = out.getNode(neighbour, cp->layer);
if(dp->locked)
continue;
/// TODO: We may consider use invisible exits on FoW border in future
/// Useful for AI when at least one tile around exit is visible and passable
/// Objects are usually visible on FoW border anyway so it's not cheating.
///
/// For now it's disabled as it's will cause crashes in movement code.
if(dp->accessible == CGPathNode::BLOCKED)
continue;
if(isBetterWay(movement, turn))
{
dtObj = gs->map->getTile(neighbour).topVisitableObj();
dp->moveRemains = movement;
dp->turns = turn;
dp->theNodeBefore = cp;
dp->action = CGPathNode::NORMAL;
pq.push(dp);
dp->action = getTeleportDestAction();
if(dp->action == CGPathNode::TELEPORT_NORMAL)
pq.push(dp);
}
}
} //queue loop
@ -361,6 +373,16 @@ bool CPathfinder::isLayerTransitionPossible() const
return false;
}
break;
case ELayer::WATER:
if(dp->accessible != CGPathNode::ACCESSIBLE && dp->accessible != CGPathNode::VISITABLE)
{
/// Hero that walking on water can transit to accessible and visitable tiles
/// Though hero can't interact with blocking visit objects while standing on water
return false;
}
break;
}
@ -443,7 +465,7 @@ bool CPathfinder::isMovementAfterDestPossible() const
/// Transit over whirlpools only allowed when hero protected
return true;
}
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2)
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2 || dtObj->ID == Obj::BORDER_GATE)
{
/// Transit via unguarded garrisons is always possible
return true;
@ -507,18 +529,33 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
else
action = CGPathNode::BLOCKING_VISIT;
}
else if(dtObj->ID == Obj::TOWN && objRel == PlayerRelations::ENEMIES)
else if(dtObj->ID == Obj::TOWN)
{
const CGTownInstance * townObj = dynamic_cast<const CGTownInstance *>(dtObj);
if(townObj->armedGarrison())
if(dtObj->passableFor(hero->tempOwner))
action = CGPathNode::VISIT;
else if(objRel == PlayerRelations::ENEMIES)
action = CGPathNode::BATTLE;
}
else if(dtObj->ID == Obj::GARRISON || dtObj->ID == Obj::GARRISON2)
{
const CGGarrison * garrisonObj = dynamic_cast<const CGGarrison *>(dtObj);
if((garrisonObj->stacksCount() && objRel == PlayerRelations::ENEMIES) || isDestinationGuarded(true))
if(dtObj->passableFor(hero->tempOwner))
{
if(isDestinationGuarded(true))
action = CGPathNode::BATTLE;
}
else if(objRel == PlayerRelations::ENEMIES)
action = CGPathNode::BATTLE;
}
else if(dtObj->ID == Obj::BORDER_GATE)
{
if(dtObj->passableFor(hero->tempOwner))
{
if(isDestinationGuarded(true))
action = CGPathNode::BATTLE;
}
else
action = CGPathNode::BLOCKING_VISIT;
}
else if(isDestinationGuardian())
action = CGPathNode::BATTLE;
else if(dtObj->blockVisit && !(options.useCastleGate && dtObj->ID == Obj::TOWN))
@ -541,6 +578,21 @@ CGPathNode::ENodeAction CPathfinder::getDestAction() const
return action;
}
CGPathNode::ENodeAction CPathfinder::getTeleportDestAction() const
{
CGPathNode::ENodeAction action = CGPathNode::TELEPORT_NORMAL;
if(isDestVisitableObj() && dtObj->ID == Obj::HERO)
{
auto objRel = getPlayerRelations(dtObj->tempOwner, hero->tempOwner);
if(objRel == PlayerRelations::ENEMIES)
action = CGPathNode::TELEPORT_BATTLE;
else
action = CGPathNode::TELEPORT_BLOCKING_VISIT;
}
return action;
}
bool CPathfinder::isSourceInitialPosition() const
{
return cp->coord == out.hpos;
@ -987,7 +1039,7 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
}
else if(dt->terType == ETerrainType::WATER)
{
if(h->boat && ct->hasFavourableWinds() && dt->hasFavourableWinds()) //Favourable Winds
if(h->boat && ct->hasFavorableWinds() && dt->hasFavorableWinds())
ret *= 0.666;
else if(!h->boat && ti->hasBonusOfType(Bonus::WATER_WALKING))
{

View File

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

View File

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

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<COSer>(COSer & s);
extern template void registerTypes<CTypeList>(CTypeList & s);
@ -70,13 +67,13 @@ void CConnection::init()
}
CConnection::CConnection(std::string host, std::string port, std::string Name)
:iser(this), oser(this), io_service(new asio::io_service), name(Name)
:iser(this), oser(this), io_service(new boost::asio::io_service), name(Name)
{
int i;
boost::system::error_code error = asio::error::host_not_found;
socket = new tcp::socket(*io_service);
tcp::resolver resolver(*io_service);
tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(tcp::resolver::query(host,port),error);
boost::system::error_code error = boost::asio::error::host_not_found;
socket = new boost::asio::ip::tcp::socket(*io_service);
boost::asio::ip::tcp::resolver resolver(*io_service);
boost::asio::ip::tcp::resolver::iterator end, pom, endpoint_iterator = resolver.resolve(boost::asio::ip::tcp::resolver::query(host,port),error);
if(error)
{
logNetwork->errorStream() << "Problem with resolving: \n" << error;
@ -121,7 +118,7 @@ connerror1:
else
logNetwork->errorStream() << "No error info. ";
delete io_service;
//delete socket;
//delete socket;
throw std::runtime_error("Can't establish connection :(");
}
CConnection::CConnection(TSocket * Socket, std::string Name )
@ -132,14 +129,14 @@ CConnection::CConnection(TSocket * Socket, std::string Name )
CConnection::CConnection(TAcceptor * acceptor, boost::asio::io_service *Io_service, std::string Name)
: iser(this), oser(this), name(Name)//, send(this), rec(this)
{
boost::system::error_code error = asio::error::host_not_found;
socket = new tcp::socket(*io_service);
boost::system::error_code error = boost::asio::error::host_not_found;
socket = new boost::asio::ip::tcp::socket(*io_service);
acceptor->accept(*socket,error);
if (error)
{
{
logNetwork->errorStream() << "Error on accepting: " << error;
delete socket;
throw std::runtime_error("Can't establish connection :(");
delete socket;
throw std::runtime_error("Can't establish connection :(");
}
init();
}
@ -149,7 +146,7 @@ int CConnection::write(const void * data, unsigned size)
try
{
int ret;
ret = asio::write(*socket,asio::const_buffers_1(asio::const_buffer(data,size)));
ret = boost::asio::write(*socket,boost::asio::const_buffers_1(boost::asio::const_buffer(data,size)));
return ret;
}
catch(...)
@ -164,7 +161,7 @@ int CConnection::read(void * data, unsigned size)
//LOG("Receiving " << size << " byte(s) of data" <<std::endl);
try
{
int ret = asio::read(*socket,asio::mutable_buffers_1(asio::mutable_buffer(data,size)));
int ret = boost::asio::read(*socket,boost::asio::mutable_buffers_1(boost::asio::mutable_buffer(data,size)));
return ret;
}
catch(...)
@ -240,12 +237,12 @@ void CConnection::sendPackToServer(const CPack &pack, PlayerColor player, ui32 r
void CConnection::disableStackSendingByID()
{
CSerializer::sendStackInstanceByIds = false;
CSerializer::sendStackInstanceByIds = false;
}
void CConnection::enableStackSendingByID()
{
CSerializer::sendStackInstanceByIds = true;
CSerializer::sendStackInstanceByIds = true;
}
void CConnection::disableSmartPointerSerialization()
@ -285,7 +282,7 @@ void CConnection::enableSmartVectorMemberSerializatoin()
CSerializer::smartVectorMembersSerialization = true;
}
CSaveFile::CSaveFile( const std::string &fname ): serializer(this)
CSaveFile::CSaveFile( const std::string &fname ): serializer(this)
{
registerTypes(serializer);
openNextFile(fname);
@ -379,7 +376,7 @@ void CLoadFile::openNextFile(const boost::filesystem::path & fname, int minimalV
if(std::memcmp(buffer,"VCMI",4))
THROW_FORMAT("Error: not a VCMI file(%s)!", fName);
serializer >> serializer.fileVersion;
serializer >> serializer.fileVersion;
if(serializer.fileVersion < minimalVersion)
THROW_FORMAT("Error: too old file format (%s)!", fName);
@ -442,7 +439,7 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
return typeDescr; //type found, return ptr to structure
//type not found - add it to the list and return given ID
auto newType = make_shared<TypeDescriptor>();
auto newType = std::make_shared<TypeDescriptor>();
newType->typeID = typeInfos.size() + 1;
newType->name = type->name();
typeInfos[type] = newType;
@ -450,18 +447,19 @@ CTypeList::TypeInfoPtr CTypeList::registerType( const std::type_info *type )
return newType;
}
ui16 CTypeList::getTypeID( const std::type_info *type )
ui16 CTypeList::getTypeID( const std::type_info *type, bool throws ) const
{
auto i = typeInfos.find(type);
if(i != typeInfos.end())
return i->second->typeID;
else
auto descriptor = getTypeDescriptor(type, throws);
if (descriptor == nullptr)
{
return 0;
}
return descriptor->typeID;
}
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to)
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, TypeInfoPtr to) const
{
if(from == to)
if(!strcmp(from->name, to->name))
return std::vector<CTypeList::TypeInfoPtr>();
// Perform a simple BFS in the class hierarchy.
@ -484,7 +482,7 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
}
}
}
std::vector<TypeInfoPtr> ret;
if(!previous.count(from))
@ -512,21 +510,21 @@ std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(TypeInfoPtr from, Ty
return ret;
}
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to)
std::vector<CTypeList::TypeInfoPtr> CTypeList::castSequence(const std::type_info *from, const std::type_info *to) const
{
//This additional if is needed because getTypeDescriptor might fail if type is not registered
// (and if casting is not needed, then registereing should no be required)
if(*from == *to)
if(!strcmp(from->name(), to->name()))
return std::vector<CTypeList::TypeInfoPtr>();
return castSequence(getTypeDescriptor(from), getTypeDescriptor(to));
}
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws)
CTypeList::TypeInfoPtr CTypeList::getTypeDescriptor(const std::type_info *type, bool throws) const
{
auto i = typeInfos.find(type);
if(i != typeInfos.end())
return i->second; //type found, return ptr to structure
return i->second; //type found, return ptr to structure
if(!throws)
return nullptr;
@ -553,19 +551,19 @@ CSerializer::CSerializer()
void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
{
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->map->objects,
[](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
registerVectoredType<CHero, HeroTypeID>(&lib->heroh->heroes,
[](const CHero &h){ return h.ID; });
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->map->allHeroes,
[](const CGHeroInstance &h){ return h.type->ID; });
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
registerVectoredType<CCreature, CreatureID>(&lib->creh->creatures,
[](const CCreature &cre){ return cre.idNumber; });
registerVectoredType<CArtifact, ArtifactID>(&lib->arth->artifacts,
[](const CArtifact &art){ return art.id; });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->map->artInstances,
[](const CArtifactInstance &artInst){ return artInst.id; });
registerVectoredType<CQuest, si32>(&gs->map->quests,
registerVectoredType<CQuest, si32>(&gs->map->quests,
[](const CQuest &q){ return q.qid; });
smartVectorMembersSerialization = true;
@ -606,7 +604,7 @@ int CLoadIntegrityValidator::read( void * data, unsigned size )
return ret;
}
unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
std::unique_ptr<CLoadFile> CLoadIntegrityValidator::decay()
{
primaryFile->serializer.loadedPointers = this->serializer.loadedPointers;
primaryFile->serializer.loadedPointersTypes = this->serializer.loadedPointersTypes;
@ -646,4 +644,3 @@ CMemorySerializer::CMemorySerializer(): iser(this), oser(this)
registerTypes(iser);
registerTypes(oser);
}

View File

@ -81,10 +81,14 @@ enum SerializationLvl
struct TypeComparer
{
bool operator()(const std::type_info *a, const std::type_info *b) const
{
return a->before(*b);
}
bool operator()(const std::type_info *a, const std::type_info *b) const
{
#ifndef __APPLE__
return a->before(*b);
#else
return strcmp(a->name(), b->name()) < 0;
#endif
}
};
struct IPointerCaster
@ -102,6 +106,11 @@ struct PointerCaster : IPointerCaster
{
From * from = (From*)boost::any_cast<void*>(ptr);
To * ret = dynamic_cast<To*>(from);
if (ret == nullptr)
{
// Last resort when RTTI goes mad
ret = static_cast<To*>(from);
}
return (void*)ret;
}
@ -113,6 +122,11 @@ struct PointerCaster : IPointerCaster
{
auto from = boost::any_cast<SmartPt>(ptr);
auto ret = std::dynamic_pointer_cast<To>(from);
if (!ret)
{
// Last resort when RTTI goes mad
ret = std::static_pointer_cast<To>(from);
}
return ret;
}
catch(std::exception &e)
@ -136,7 +150,7 @@ struct PointerCaster : IPointerCaster
// }
};
class DLL_LINKAGE CTypeList
class DLL_LINKAGE CTypeList: public boost::noncopyable
{
public:
struct TypeDescriptor;
@ -147,33 +161,53 @@ public:
const char *name;
std::vector<TypeInfoPtr> children, parents;
};
typedef boost::shared_mutex TMutex;
typedef boost::unique_lock<TMutex> TUniqueLock;
typedef boost::shared_lock<TMutex> TSharedLock;
private:
mutable TMutex mx;
std::map<const std::type_info *, TypeInfoPtr, TypeComparer> typeInfos;
std::map<std::pair<TypeInfoPtr, TypeInfoPtr>, std::unique_ptr<const IPointerCaster>> casters; //for each pair <Base, Der> we provide a caster (each registered relations creates a single entry here)
CTypeList(CTypeList &)
{
// This type is non-copyable.
// Unfortunately on Windows it is required for DLL_EXPORT-ed type to provide copy c-tor, so we can't =delete it.
assert(0);
}
CTypeList &operator=(CTypeList &)
{
// As above.
assert(0);
return *this;
}
public:
/// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
/// Throws if there is no link registered.
std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to) const;
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to) const;
CTypeList();
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg) const
{
TSharedLock lock(mx);
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < static_cast<int>(typesSequence.size()) - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does std::unique_ptr not have operator->* ..?
}
return ptr;
}
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true) const; //if not throws, failure returns nullptr
TypeInfoPtr registerType(const std::type_info *type);
public:
CTypeList();
template <typename Base, typename Derived>
void registerType(const Base * b = nullptr, const Derived * d = nullptr)
{
TUniqueLock lock(mx);
static_assert(std::is_base_of<Base, Derived>::value, "First registerType template parameter needs to ba a base class of the second one.");
static_assert(std::has_virtual_destructor<Base>::value, "Base class needs to have a virtual destructor.");
static_assert(!std::is_same<Base, Derived>::value, "Parameters of registerTypes should be two diffrenet types.");
@ -187,77 +221,52 @@ public:
casters[std::make_pair(dti, bti)] = make_unique<const PointerCaster<Derived, Base>>();
}
ui16 getTypeID(const std::type_info *type);
TypeInfoPtr getTypeDescriptor(const std::type_info *type, bool throws = true); //if not throws, failure returns nullptr
ui16 getTypeID(const std::type_info *type, bool throws = false) const;
template <typename T>
ui16 getTypeID(const T * t = nullptr)
ui16 getTypeID(const T * t = nullptr, bool throws = false) const
{
return getTypeID(getTypeInfo(t));
}
// Returns sequence of types starting from "from" and ending on "to". Every next type is derived from the previous.
// Throws if there is no link registered.
std::vector<TypeInfoPtr> castSequence(TypeInfoPtr from, TypeInfoPtr to);
std::vector<TypeInfoPtr> castSequence(const std::type_info *from, const std::type_info *to);
template<boost::any(IPointerCaster::*CastingFunction)(const boost::any &) const>
boost::any castHelper(boost::any inputPtr, const std::type_info *fromArg, const std::type_info *toArg)
{
auto typesSequence = castSequence(fromArg, toArg);
boost::any ptr = inputPtr;
for(int i = 0; i < (int)typesSequence.size() - 1; i++)
{
auto &from = typesSequence[i];
auto &to = typesSequence[i + 1];
auto castingPair = std::make_pair(from, to);
if(!casters.count(castingPair))
THROW_FORMAT("Cannot find caster for conversion %s -> %s which is needed to cast %s -> %s", from->name % to->name % fromArg->name() % toArg->name());
auto &caster = casters.at(castingPair);
ptr = (*caster.*CastingFunction)(ptr); //Why does unique_ptr does not have operator->* ..?
}
return ptr;
return getTypeID(getTypeInfo(t), throws);
}
template<typename TInput>
void *castToMostDerived(const TInput *inputPtr)
void * castToMostDerived(const TInput * inputPtr) const
{
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr);
if(baseType == *derivedType)
return (void*)inputPtr;
if (!strcmp(baseType.name(), derivedType->name()))
{
return const_cast<void*>(reinterpret_cast<const void*>(inputPtr));
}
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>((void*)inputPtr, &baseType, derivedType));
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(
const_cast<void*>(reinterpret_cast<const void*>(inputPtr)), &baseType,
derivedType));
}
template<typename TInput>
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr)
boost::any castSharedToMostDerived(const std::shared_ptr<TInput> inputPtr) const
{
auto &baseType = typeid(typename std::remove_cv<TInput>::type);
auto derivedType = getTypeInfo(inputPtr.get());
if(baseType == *derivedType)
if (!strcmp(baseType.name(), derivedType->name()))
return inputPtr;
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, &baseType, derivedType);
}
void* castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to)
void * castRaw(void *inputPtr, const std::type_info *from, const std::type_info *to) const
{
return boost::any_cast<void*>(castHelper<&IPointerCaster::castRawPtr>(inputPtr, from, to));
}
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to)
boost::any castShared(boost::any inputPtr, const std::type_info *from, const std::type_info *to) const
{
return castHelper<&IPointerCaster::castSharedPtr>(inputPtr, from, to);
}
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr)
template <typename T> const std::type_info * getTypeInfo(const T * t = nullptr) const
{
if(t)
return &typeid(*t);
@ -444,13 +453,13 @@ public:
virtual int write(const void * data, unsigned size) = 0;
};
class DLL_LINKAGE CSaverBase
class DLL_LINKAGE CSaverBase
{
protected:
IBinaryWriter * writer;
public:
CSaverBase(IBinaryWriter * w): writer(w){};
inline int write(const void * data, unsigned size)
{
return writer->write(data, size);
@ -586,15 +595,15 @@ struct LoadIfStackInstance<Ser, CStackInstance *>
class DLL_LINKAGE COSer : public CSaverBase
{
public:
struct SaveBoolean
{
static void invoke(COSer &s, const bool &data)
{
s.saveBoolean(data);
}
};
};
struct SaveBooleanVector
{
static void invoke(COSer &s, const std::vector<bool> &data)
@ -629,7 +638,7 @@ public:
s.saveEnum(data);
}
};
template<typename T>
struct SavePointer
{
@ -638,7 +647,7 @@ public:
s.savePointer(data);
}
};
template<typename T>
struct SaveArray
{
@ -655,9 +664,9 @@ public:
{
throw std::runtime_error("Wrong save serialization call!");
}
};
template <typename T>
};
template <typename T>
class CPointerSaver : public CBasicPointerSaver
{
public:
@ -665,12 +674,11 @@ public:
{
COSer &s = static_cast<COSer&>(ar);
const T *ptr = static_cast<const T*>(data);
//T is most derived known type, it's time to call actual serialize
const_cast<T&>(*ptr).serialize(s,version);
const_cast<T*>(ptr)->serialize(s,version);
}
};
};
bool saving;
std::map<ui16,CBasicPointerSaver*> savers; // typeID => CPointerSaver<serializer,type>
@ -841,13 +849,13 @@ public:
const_cast<T&>(data).serialize(*this,version);
}
template <typename T>
void saveSerializable(const shared_ptr<T> &data)
void saveSerializable(const std::shared_ptr<T> &data)
{
T *internalPtr = data.get();
*this << internalPtr;
}
template <typename T>
void saveSerializable(const unique_ptr<T> &data)
void saveSerializable(const std::unique_ptr<T> &data)
{
T *internalPtr = data.get();
*this << internalPtr;
@ -964,13 +972,13 @@ public:
virtual int read(void * data, unsigned size) = 0;
};
class DLL_LINKAGE CLoaderBase
class DLL_LINKAGE CLoaderBase
{
protected:
IBinaryReader * reader;
public:
CLoaderBase(IBinaryReader * r): reader(r){};
inline int read(void * data, unsigned size)
{
return reader->read(data, size);
@ -1015,15 +1023,15 @@ public:
s.loadBoolean(data);
}
};
struct LoadBooleanVector
{
static void invoke(CISer &s, std::vector<bool> &data)
{
s.loadBooleanVector(data);
}
};
};
template<typename T>
struct LoadEnum
{
@ -1040,7 +1048,7 @@ public:
{
s.loadPrimitive(data);
}
};
};
template<typename T>
struct LoadPointer
@ -1049,8 +1057,8 @@ public:
{
s.loadPointer(data);
}
};
};
template<typename T>
struct LoadArray
{
@ -1076,8 +1084,8 @@ public:
{
throw std::runtime_error("Wrong load serialization call!");
}
};
};
template <typename T> class CPointerLoader : public CBasicPointerLoader
{
public:
@ -1094,8 +1102,8 @@ public:
ptr->serialize(s,version);
return &typeid(T);
}
};
};
bool saving;
std::map<ui16,CBasicPointerLoader*> loaders; // typeID => CPointerSaver<serializer,type>
si32 fileVersion;
@ -1324,7 +1332,7 @@ public:
template <typename T>
void loadSerializable(shared_ptr<T> &data)
void loadSerializable(std::shared_ptr<T> &data)
{
typedef typename boost::remove_const<T>::type NonConstT;
NonConstT *internalPtr;
@ -1345,7 +1353,7 @@ public:
auto typeWeNeedToReturn = typeList.getTypeInfo<T>();
if(*actualType == *typeWeNeedToReturn)
{
// No casting needed, just unpack already stored shared_ptr and return it
// No casting needed, just unpack already stored std::shared_ptr and return it
data = boost::any_cast<std::shared_ptr<T>>(itr->second);
}
else
@ -1375,7 +1383,7 @@ public:
data.reset();
}
template <typename T>
void loadSerializable(unique_ptr<T> &data)
void loadSerializable(std::unique_ptr<T> &data)
{
T *internalPtr;
*this >> internalPtr;
@ -1539,11 +1547,11 @@ class DLL_LINKAGE CSaveFile
:public IBinaryWriter
{
public:
COSer serializer;
std::string fName;
unique_ptr<std::ofstream> sfile;
std::unique_ptr<std::ofstream> sfile;
CSaveFile(const std::string &fname); //throws!
~CSaveFile();
@ -1554,13 +1562,13 @@ public:
void reportState(CLogger * out) override;
void putMagicBytes(const std::string &text);
template<class T>
CSaveFile & operator<<(const T &t)
{
serializer << t;
return * this;
}
}
};
class DLL_LINKAGE CLoadFile
@ -1568,9 +1576,9 @@ class DLL_LINKAGE CLoadFile
{
public:
CISer serializer;
std::string fName;
unique_ptr<boost::filesystem::ifstream> sfile;
std::unique_ptr<boost::filesystem::ifstream> sfile;
CLoadFile(const boost::filesystem::path & fname, int minimalVersion = version); //throws!
~CLoadFile();
@ -1581,21 +1589,21 @@ public:
void reportState(CLogger * out) override;
void checkMagicBytes(const std::string & text);
template<class T>
CLoadFile & operator>>(T &t)
{
serializer >> t;
return * this;
}
}
};
class DLL_LINKAGE CLoadIntegrityValidator
class DLL_LINKAGE CLoadIntegrityValidator
: public IBinaryReader
{
public:
CISer serializer;
unique_ptr<CLoadFile> primaryFile, controlFile;
CISer serializer;
std::unique_ptr<CLoadFile> primaryFile, controlFile;
bool foundDesync;
CLoadIntegrityValidator(const std::string &primaryFileName, const std::string &controlFileName, int minimalVersion = version); //throws!
@ -1603,7 +1611,7 @@ public:
int read( void * data, unsigned size) override; //throws!
void checkMagicBytes(const std::string &text);
unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
std::unique_ptr<CLoadFile> decay(); //returns primary file. CLoadIntegrityValidator stops being usable anymore
};
typedef boost::asio::basic_stream_socket < boost::asio::ip::tcp , boost::asio::stream_socket_service<boost::asio::ip::tcp> > TSocket;
@ -1620,7 +1628,7 @@ class DLL_LINKAGE CConnection
public:
CISer iser;
COSer oser;
boost::mutex *rmx, *wmx; // read/write mutexes
TSocket * socket;
bool logging;
@ -1658,14 +1666,14 @@ public:
void prepareForSendingHeroes(); //disables sending vectorised, enables smart pointer serialization, clears saved/loaded ptr cache
void enterPregameConnectionMode();
template<class T>
CConnection & operator>>(T &t)
{
iser >> t;
return * this;
}
}
template<class T>
CConnection & operator<<(const T &t)
{
@ -1687,19 +1695,19 @@ class DLL_LINKAGE CMemorySerializer
public:
CISer iser;
COSer oser;
int read(void * data, unsigned size) override; //throws!
int write(const void * data, unsigned size) override;
CMemorySerializer();
template <typename T>
static unique_ptr<T> deepCopy(const T &data)
static std::unique_ptr<T> deepCopy(const T &data)
{
CMemorySerializer mem;
mem.oser << &data;
unique_ptr<T> ret;
std::unique_ptr<T> ret;
mem.iser >> ret;
return ret;
}

View File

@ -33,6 +33,7 @@ namespace GameConstants
const int SPELL_SCHOOL_LEVELS = 4;
const int CRE_LEVELS = 10; // number of creature experience levels
const int HERO_GOLD_COST = 2500;
const int SPELLBOOK_GOLD_COST = 500;
const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
const int ARMY_SIZE = 7;
@ -837,10 +838,10 @@ public:
// 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines
//8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields
//15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog
//21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
//21. "favorable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
enum EBFieldType {NONE = -1, NONE2, SAND_SHORE, SAND_MESAS, DIRT_BIRCHES, DIRT_HILLS, DIRT_PINES, GRASS_HILLS,
GRASS_PINES, LAVA, MAGIC_PLAINS, SNOW_MOUNTAINS, SNOW_TREES, SUBTERRANEAN, SWAMP_TREES, FIERY_FIELDS,
ROCKLANDS, MAGIC_CLOUDS, LUCID_POOLS, HOLY_GROUND, CLOVER_FIELD, EVIL_FOG, FAVOURABLE_WINDS, CURSED_GROUND,
ROCKLANDS, MAGIC_CLOUDS, LUCID_POOLS, HOLY_GROUND, CLOVER_FIELD, EVIL_FOG, FAVORABLE_WINDS, CURSED_GROUND,
ROUGH, SHIP_TO_SHIP, SHIP
};

View File

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

View File

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

View File

@ -483,10 +483,10 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
break;
case JsonNode::DATA_STRUCT: //customizable limiters
{
shared_ptr<ILimiter> l;
std::shared_ptr<ILimiter> l;
if (limiter["type"].String() == "CREATURE_TYPE_LIMITER")
{
shared_ptr<CCreatureTypeLimiter> l2 = make_shared<CCreatureTypeLimiter>(); //TODO: How the hell resolve pointer to creature?
std::shared_ptr<CCreatureTypeLimiter> l2 = std::make_shared<CCreatureTypeLimiter>(); //TODO: How the hell resolve pointer to creature?
const JsonVector vec = limiter["parameters"].Vector();
VLC->modh->identifiers.requestIdentifier("creature", vec[0], [=](si32 creature)
{
@ -503,7 +503,7 @@ Bonus * JsonUtils::parseBonus (const JsonNode &ability)
}
if (limiter["type"].String() == "HAS_ANOTHER_BONUS_LIMITER")
{
shared_ptr<HasAnotherBonusLimiter> l2 = make_shared<HasAnotherBonusLimiter>();
std::shared_ptr<HasAnotherBonusLimiter> l2 = std::make_shared<HasAnotherBonusLimiter>();
const JsonVector vec = limiter["parameters"].Vector();
std::string anotherBonusType = vec[0].String();

View File

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

View File

@ -223,7 +223,7 @@ DLL_LINKAGE void FoWChange::applyGs( CGameState *gs )
case Obj::TOWN:
case Obj::ABANDONED_MINE:
if(vstd::contains(team->players, o->tempOwner)) //check owned observators
gs->getTilesInRange(tiles, o->getSightCenter(), o->getSightRadious(), o->tempOwner, 1);
gs->getTilesInRange(tilesRevealed, o->getSightCenter(), o->getSightRadious(), o->tempOwner, 1);
break;
}
}
@ -1010,6 +1010,13 @@ DLL_LINKAGE void SetAvailableArtifacts::applyGs( CGameState *gs )
DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
{
gs->day = day;
// Update bonuses before doing anything else so hero don't get more MP than needed
gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs
gs->globalEffects.updateBonuses(Bonus::NDays);
gs->globalEffects.updateBonuses(Bonus::OneWeek);
//TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...]
for(NewTurn::Hero h : heroes) //give mana/movement point
{
CGHeroInstance *hero = gs->getHero(h.id);
@ -1026,11 +1033,6 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
for(auto creatureSet : cres) //set available creatures in towns
creatureSet.second.applyGs(gs);
gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs
gs->globalEffects.updateBonuses(Bonus::NDays);
gs->globalEffects.updateBonuses(Bonus::OneWeek);
//TODO not really a single root hierarchy, what about bonuses placed elsewhere? [not an issue with H3 mechanics but in the future...]
for(CGTownInstance* t : gs->map->towns)
t->builded = 0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -105,7 +105,7 @@ public:
inline void log(ELogLevel::ELogLevel level, const std::string & message) const;
void addTarget(unique_ptr<ILogTarget> && target);
void addTarget(std::unique_ptr<ILogTarget> && target);
void clearTargets();
/// Returns true if a debug/trace log message will be logged, false if not.
@ -121,7 +121,7 @@ private:
CLoggerDomain domain;
CLogger * parent;
ELogLevel::ELogLevel level;
std::vector<unique_ptr<ILogTarget> > targets;
std::vector<std::unique_ptr<ILogTarget> > targets;
mutable boost::mutex mx;
static boost::recursive_mutex smx;
};
@ -149,7 +149,7 @@ private:
/// the first statement in the function. Logging traces via this macro have almost no impact when the trace is disabled.
///
#define RAII_TRACE(logger, onEntry, onLeave) \
unique_ptr<CTraceLogger> ctl00; \
std::unique_ptr<CTraceLogger> ctl00; \
if(logger->isTraceEnabled()) \
ctl00 = make_unique<CTraceLogger>(logger, onEntry, onLeave);

View File

@ -46,7 +46,7 @@ void CArmedInstance::updateMoraleBonusFromArmy()
if(!validTypes(false)) //object not randomized, don't bother
return;
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
Bonus *b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@ -96,10 +96,11 @@ void CArmedInstance::updateMoraleBonusFromArmy()
b->description = b->description.substr(0, b->description.size()-2);//trim value
}
boost::algorithm::trim(b->description);
CBonusSystemNode::treeHasChanged();
//-1 modifier for any Undead unit in army
const ui8 UNDEAD_MODIFIER_ID = -2;
Bonus *undeadModifier = getBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
Bonus *undeadModifier = getExportedBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
if(hasUndead)
{
if(!undeadModifier)

View File

@ -292,9 +292,9 @@ void CBank::doVisit(const CGHeroInstance * hero) const
loot.addReplacement(*elem.second);
}
if (ourArmy.Slots().size())
if(ourArmy.stacksCount())
{
if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1)
if(ourArmy.stacksCount() == 1 && ourArmy.Slots().begin()->second->count == 1)
iw.text.addTxt (MetaString::ADVOB_TXT, 185);
else
iw.text.addTxt (MetaString::ADVOB_TXT, 186);

View File

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

View File

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

View File

@ -235,7 +235,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
iw.components.clear();
iw.text.clear();
if (creatures.Slots().size())
if(creatures.stacksCount())
{ //this part is taken straight from creature bank
MetaString loot;
for(auto & elem : creatures.Slots())
@ -245,7 +245,7 @@ void CGPandoraBox::giveContentsAfterExp(const CGHeroInstance *h) const
loot.addReplacement(*elem.second);
}
if (creatures.Slots().size() == 1 && creatures.Slots().begin()->second->count == 1)
if(creatures.stacksCount() == 1 && creatures.Slots().begin()->second->count == 1)
iw.text.addTxt(MetaString::ADVOB_TXT, 185);
else
iw.text.addTxt(MetaString::ADVOB_TXT, 186);
@ -303,17 +303,17 @@ void CGPandoraBox::battleFinished(const CGHeroInstance *hero, const BattleResult
void CGPandoraBox::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
{
if (answer)
if(answer)
{
if (stacksCount() > 0) //if pandora's box is protected by army
if(stacksCount() > 0) //if pandora's box is protected by army
{
showInfoDialog(hero,16,0);
cb->startBattleI(hero, this); //grants things after battle
}
else if (message.size() == 0 && resources.size() == 0
else if(message.size() == 0 && resources.size() == 0
&& primskills.size() == 0 && abilities.size() == 0
&& abilityLevels.size() == 0 && artifacts.size() == 0
&& spells.size() == 0 && creatures.Slots().size() > 0
&& abilityLevels.size() == 0 && artifacts.size() == 0
&& spells.size() == 0 && creatures.stacksCount() > 0
&& gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle
{
showInfoDialog(hero,15,0);

View File

@ -856,7 +856,7 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::updateMoraleBonusFromArmy()
{
Bonus *b = getBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
Bonus *b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE)));
if(!b)
{
b = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
@ -864,7 +864,10 @@ void CGTownInstance::updateMoraleBonusFromArmy()
}
if (garrisonHero)
{
b->val = 0;
CBonusSystemNode::treeHasChanged();
}
else
CArmedInstance::updateMoraleBonusFromArmy();
}

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 (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;
}
}

View File

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

View File

@ -2,6 +2,7 @@
#include "CObjectClassesHandler.h"
#include "../CTownHandler.h" // for building ID-based filters
#include "MapObjects.h"
/*
* CommonConstructors.h, part of VCMI engine
@ -155,9 +156,9 @@ typedef std::vector<std::pair<ui8, IObjectInfo::CArmyStructure>> TPossibleGuards
class DLL_LINKAGE CBankInfo : public IObjectInfo
{
JsonVector config;
const JsonVector & config;
public:
CBankInfo(JsonVector config);
CBankInfo(const JsonVector & Config);
TPossibleGuards getPossibleGuards() const;

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
*

View File

@ -640,7 +640,6 @@ std::string CGMine::getObjectName() const
std::string CGMine::getHoverText(PlayerColor player) const
{
std::string hoverName = getObjectName(); // Sawmill
if (tempOwner != PlayerColor::NEUTRAL)
@ -650,11 +649,12 @@ std::string CGMine::getHoverText(PlayerColor player) const
hoverName += "\n(" + VLC->generaltexth->restypes[producedResource] + ")";
}
for (auto & slot : Slots()) // guarded by a few Pikeman
if(stacksCount())
{
hoverName += "\n";
hoverName += getRoughAmount(slot.first);
hoverName += getCreature(slot.first)->namePl;
hoverName += VLC->generaltexth->allTexts[202]; //Guarded by
hoverName += " ";
hoverName += getArmyDescription();
}
return hoverName;
}
@ -907,12 +907,12 @@ std::vector<ObjectInstanceID> CGTeleport::getPassableExits(CGameState * gs, cons
return exits;
}
void CGTeleport::addToChannel(std::map<TeleportChannelID, shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj)
void CGTeleport::addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj)
{
shared_ptr<TeleportChannel> tc;
std::shared_ptr<TeleportChannel> tc;
if(channelsList.find(obj->channel) == channelsList.end())
{
tc = make_shared<TeleportChannel>();
tc = std::make_shared<TeleportChannel>();
channelsList.insert(std::make_pair(obj->channel, tc));
}
else
@ -973,17 +973,18 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
{
int3 dPos;
auto randomExit = getRandomExit(hero);
auto realExits = getAllExits(true);
if(!isEntrance() // Do nothing if hero visited exit only object
|| (!exits.size() && !realExits.size()) // Do nothing if there no exits on this channel
|| (!exits.size() && ObjectInstanceID() == getRandomExit(hero))) // Do nothing if all exits are blocked by friendly hero and it's not subterranean gate
|| ObjectInstanceID() == randomExit) // Do nothing if all exits are blocked by friendly hero and it's not subterranean gate
{
return;
}
else if(vstd::isValidIndex(exits, answer))
dPos = exits[answer].second;
else
dPos = CGHeroInstance::convertPosition(cb->getObj(getRandomExit(hero))->visitablePos(), true);
dPos = CGHeroInstance::convertPosition(cb->getObj(randomExit)->visitablePos(), true);
cb->moveHero(hero->id, dPos, true);
}
@ -1158,10 +1159,10 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
cb->moveHero(hero->id, dPos, true);
}
bool CGWhirlpool::isProtected( const CGHeroInstance * h )
bool CGWhirlpool::isProtected(const CGHeroInstance * h)
{
if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION)
|| (h->Slots().size() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit
if(h->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION) ||
(h->stacksCount() == 1 && h->Slots().begin()->second->count == 1)) //we can't remove last unit
{
return true;
}
@ -1196,7 +1197,7 @@ std::string CGArtifact::getObjectName() const
return VLC->arth->artifacts[subID]->Name();
}
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
void CGArtifact::onHeroVisit(const CGHeroInstance * h) const
{
if(!stacksCount())
{
@ -1207,28 +1208,32 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
case Obj::ARTIFACT:
{
iw.soundID = soundBase::treasure; //play sound only for non-scroll arts
iw.components.push_back(Component(Component::ARTIFACT,subID,0,0));
iw.components.push_back(Component(Component::ARTIFACT, subID, 0, 0));
if(message.length())
iw.text << message;
iw.text << message;
else
{
if (VLC->arth->artifacts[subID]->EventText().size())
iw.text << std::pair<ui8, ui32> (MetaString::ART_EVNTS, subID);
if(VLC->arth->artifacts[subID]->EventText().size())
iw.text << std::pair<ui8, ui32>(MetaString::ART_EVNTS, subID);
else //fix for mod artifacts with no event text
{
iw.text.addTxt (MetaString::ADVOB_TXT, 183); //% has found treasure
iw.text.addReplacement (h->name);
iw.text.addTxt(MetaString::ADVOB_TXT, 183); //% has found treasure
iw.text.addReplacement(h->name);
}
}
}
break;
case Obj::SPELL_SCROLL:
{
int spellID = storedArtifact->getGivenSpellID();
iw.components.push_back (Component(Component::SPELL, spellID,0,0));
iw.text.addTxt (MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
iw.components.push_back(Component(Component::SPELL, spellID, 0, 0));
if(message.length())
iw.text << message;
else
{
iw.text.addTxt(MetaString::ADVOB_TXT,135);
iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
}
}
break;
}
@ -1237,16 +1242,38 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
}
else
{
if(message.size())
switch(ID)
{
BlockingDialog ynd(true,false);
ynd.player = h->getOwner();
ynd.text << message;
cb->showBlockingDialog(&ynd);
}
else
{
blockingDialogAnswered(h, true);
case Obj::ARTIFACT:
{
BlockingDialog ynd(true,false);
ynd.player = h->getOwner();
if(message.length())
ynd.text << message;
else
{
// TODO: Guard text is more complex in H3, see mantis issue 2325 for details
ynd.text.addTxt(MetaString::GENERAL_TXT, 420);
ynd.text.addReplacement("");
ynd.text.addReplacement(getArmyDescription());
ynd.text.addReplacement(MetaString::GENERAL_TXT, 43); // creatures
}
cb->showBlockingDialog(&ynd);
}
break;
case Obj::SPELL_SCROLL:
{
if(message.length())
{
BlockingDialog ynd(true,false);
ynd.player = h->getOwner();
ynd.text << message;
cb->showBlockingDialog(&ynd);
}
else
blockingDialogAnswered(h, true);
}
break;
}
}
}

View File

@ -317,7 +317,7 @@ public:
static bool isTeleport(const CGObjectInstance * dst);
static bool isConnected(const CGTeleport * src, const CGTeleport * dst);
static bool isConnected(const CGObjectInstance * src, const CGObjectInstance * dst);
static void addToChannel(std::map<TeleportChannelID, shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
static void addToChannel(std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > &channelsList, const CGTeleport * obj);
static std::vector<ObjectInstanceID> getPassableExits(CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
static bool isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj);

View File

@ -40,7 +40,7 @@ CCampaignHeader CCampaignHandler::getHeader( const std::string & name)
return ret;
}
unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
std::unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
{
auto ret = make_unique<CCampaign>();
@ -411,7 +411,7 @@ CCampaignState::CCampaignState()
}
CCampaignState::CCampaignState( unique_ptr<CCampaign> _camp ) : camp(std::move(_camp))
CCampaignState::CCampaignState( std::unique_ptr<CCampaign> _camp ) : camp(std::move(_camp))
{
for(int i = 0; i < camp->scenarios.size(); i++)
{

View File

@ -144,7 +144,7 @@ public:
class DLL_LINKAGE CCampaignState
{
public:
unique_ptr<CCampaign> camp;
std::unique_ptr<CCampaign> camp;
std::string campaignName;
std::vector<ui8> mapsConquered, mapsRemaining;
boost::optional<si32> currentMap;
@ -159,7 +159,7 @@ public:
ui8 currentBonusID() const;
CCampaignState();
CCampaignState(unique_ptr<CCampaign> _camp);
CCampaignState(std::unique_ptr<CCampaign> _camp);
~CCampaignState(){};
template <typename Handler> void serialize(Handler &h, const int version)
@ -184,5 +184,5 @@ public:
static CCampaignHeader getHeader( const std::string & name); //name - name of appropriate file
static unique_ptr<CCampaign> getCampaign(const std::string & name); //name - name of appropriate file
static std::unique_ptr<CCampaign> getCampaign(const std::string & name); //name - name of appropriate file
};

View File

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

View File

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

View File

@ -71,7 +71,7 @@ struct DLL_LINKAGE TerrainTile
CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
bool isWater() const;
EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
bool hasFavourableWinds() const;
bool hasFavorableWinds() const;
ETerrainType terType;
ui8 terView;
@ -80,7 +80,7 @@ struct DLL_LINKAGE TerrainTile
ERoadType::ERoadType roadType;
ui8 roadDir;
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road);
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favourable Winds effect
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
ui8 extTileFlags;
bool visitable;
bool blocked;

View File

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

View File

@ -144,10 +144,10 @@ public:
const CMapOperation * peekRedo() const;
const CMapOperation * peekUndo() const;
void addOperation(unique_ptr<CMapOperation> && operation); /// Client code does not need to call this method.
void addOperation(std::unique_ptr<CMapOperation> && operation); /// Client code does not need to call this method.
private:
typedef std::list<unique_ptr<CMapOperation> > TStack;
typedef std::list<std::unique_ptr<CMapOperation> > TStack;
void doOperation(TStack & fromStack, TStack & toStack, bool doUndo);
const CMapOperation * peek(const TStack & stack) const;
@ -182,7 +182,7 @@ public:
CMapUndoManager & getUndoManager();
private:
void execute(unique_ptr<CMapOperation> && operation);
void execute(std::unique_ptr<CMapOperation> && operation);
CMap * map;
CMapUndoManager undoManager;
@ -205,10 +205,10 @@ public:
void undo() override;
void redo() override;
void addOperation(unique_ptr<CMapOperation> && operation);
void addOperation(std::unique_ptr<CMapOperation> && operation);
private:
std::list<unique_ptr<CMapOperation> > operations;
std::list<std::unique_ptr<CMapOperation> > operations;
};
namespace ETerrainGroup

View File

@ -1,8 +1,8 @@
#pragma once
// Forward class declarations aren't enough here. The compiler
// generated CMapInfo d-tor, generates the unique_ptr d-tor as well here
// as a inline method. The unique_ptr d-tor requires a complete type. Defining
// generated CMapInfo d-tor, generates the std::unique_ptr d-tor as well here
// as a inline method. The std::unique_ptr d-tor requires a complete type. Defining
// the CMapInfo d-tor to let the compiler add the d-tor stuff in the .cpp file
// would work with one exception. It prevents the generation of the move
// constructor which is needed. (Writing such a c-tor is nasty.) With the
@ -20,8 +20,8 @@ struct StartInfo;
class DLL_LINKAGE CMapInfo
{
public:
unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario
std::unique_ptr<CMapHeader> mapHeader; //may be nullptr if campaign
std::unique_ptr<CCampaignHeader> campaignHeader; //may be nullptr if scenario
StartInfo * scenarioOpts; //options with which scenario has been started (used only with saved games)
std::string fileURI;
std::string date;

View File

@ -52,7 +52,7 @@ class DLL_LINKAGE CMapGenerator
{
public:
explicit CMapGenerator();
~CMapGenerator(); // required due to unique_ptr
~CMapGenerator(); // required due to std::unique_ptr
std::unique_ptr<CMap> generate(CMapGenOptions * mapGenOptions, int RandomSeed = std::time(nullptr));

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>();
}

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