mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge remote-tracking branch 'remotes/origin/develop' into issue/2306
s reverts commit fa8a282696
.
Conflicts:
AI/VCAI/VCAI.cpp
Conflicts:
AI/VCAI/VCAI.cpp
client/windows/CAdvmapInterface.cpp
lib/CPathfinder.cpp
lib/CPathfinder.h
This commit is contained in:
commit
0fab319c73
3
.gitignore
vendored
3
.gitignore
vendored
@ -32,3 +32,6 @@ build-*
|
||||
CMakeLists.txt.user.*
|
||||
Doxyfile
|
||||
doc/*
|
||||
VCMI_VS11.sdf
|
||||
*.ipch
|
||||
VCMI_VS11.opensdf
|
||||
|
@ -30,7 +30,7 @@ void CEmptyAI::showBlockingDialog(const std::string &text, const std::vector<Com
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void CEmptyAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
cb->selectionMade(0, askID);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
};
|
||||
|
||||
|
@ -153,6 +153,12 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto & enemy : enemiesReachable )
|
||||
enemy.calcDmg( stack );
|
||||
|
||||
for ( auto & enemy : enemiesShootable )
|
||||
enemy.calcDmg( stack );
|
||||
|
||||
if(enemiesShootable.size())
|
||||
{
|
||||
const EnemyInfo &ei= *std::max_element(enemiesShootable.begin(), enemiesShootable.end(), isMoreProfitable);
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/mapObjects/CBank.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
#include "../../lib/mapObjects/CQuest.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/mapping/CMapDefines.h"
|
||||
|
||||
/*
|
||||
* AIUtility.cpp, part of VCMI engine
|
||||
@ -150,7 +154,7 @@ void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo
|
||||
{
|
||||
CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer
|
||||
|
||||
for(const int3 &dir : dirs)
|
||||
for(const int3 &dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
@ -160,7 +164,7 @@ void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo
|
||||
|
||||
void foreach_neighbour(CCallback * cbp, const int3 &pos, std::function<void(CCallback * cbp, const int3& pos)> foo)
|
||||
{
|
||||
for(const int3 &dir : dirs)
|
||||
for(const int3 &dir : int3::getDirs())
|
||||
{
|
||||
const int3 n = pos + dir;
|
||||
if(cbp->isInTheMap(n))
|
||||
@ -359,7 +363,7 @@ int3 whereToExplore(HeroPtr h)
|
||||
int radius = h->getSightRadious();
|
||||
int3 hpos = h->visitablePos();
|
||||
|
||||
SectorMap &sm = ai->getCachedSectorMap(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
//look for nearby objs -> visit them if they're close enouh
|
||||
const int DIST_LIMIT = 3;
|
||||
@ -372,9 +376,9 @@ int3 whereToExplore(HeroPtr h)
|
||||
{
|
||||
int3 op = obj->visitablePos();
|
||||
CGPath p;
|
||||
ai->myCb->getPathsInfo(h.get())->getPath(op, p);
|
||||
ai->myCb->getPathsInfo(h.get())->getPath(p, op);
|
||||
if (p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
|
||||
if (ai->isGoodForVisit(obj, h, sm))
|
||||
if (ai->isGoodForVisit(obj, h, *sm))
|
||||
nearbyVisitableObjs.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,6 @@
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CStopWatch.h"
|
||||
|
||||
/*
|
||||
@ -21,6 +18,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class CCallback;
|
||||
|
||||
typedef const int3& crint3;
|
||||
typedef const std::string& crstring;
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/mapObjects/CommonConstructors.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CPathfinder.h"
|
||||
#include "../../lib/CGameStateFwd.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../CCallback.h"
|
||||
#include "VCAI.h"
|
||||
@ -421,7 +423,7 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
|
||||
|
||||
//assert(cb->isInTheMap(g.tile));
|
||||
float turns = 0;
|
||||
float distance = cb->getMovementCost(g.hero.h, g.tile);
|
||||
float distance = CPathfinderHelper::getMovementCost(g.hero.h, g.tile);
|
||||
if (!distance) //we stand on that tile
|
||||
turns = 0;
|
||||
else
|
||||
@ -482,7 +484,7 @@ float FuzzyHelper::evaluate (Goals::ClearWayTo & g)
|
||||
if (!g.hero.h)
|
||||
throw cannotFulfillGoalException("ClearWayTo called without hero!");
|
||||
|
||||
int3 t = ai->getCachedSectorMap(g.hero).firstTileToGet(g.hero, g.tile);
|
||||
int3 t = ai->getCachedSectorMap(g.hero)->firstTileToGet(g.hero, g.tile);
|
||||
|
||||
if (t.valid())
|
||||
{
|
||||
@ -530,4 +532,4 @@ float FuzzyHelper::evaluate (Goals::AbstractGoal & g)
|
||||
void FuzzyHelper::setPriority (Goals::TSubgoal & g)
|
||||
{
|
||||
g->setpriority(g->accept(this)); //this enforces returned value is set
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "VCAI.h"
|
||||
#include "Fuzzy.h"
|
||||
#include "../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../lib/CPathfinder.h"
|
||||
|
||||
/*
|
||||
* Goals.cpp, part of VCMI engine
|
||||
@ -483,9 +484,9 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
|
||||
//if our hero is trapped, make sure we request clearing the way from OUR perspective
|
||||
|
||||
SectorMap &sm = ai->getCachedSectorMap(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
int3 tileToHit = sm.firstTileToGet(h, tile);
|
||||
int3 tileToHit = sm->firstTileToGet(h, tile);
|
||||
if (!tileToHit.valid())
|
||||
continue;
|
||||
|
||||
@ -633,11 +634,11 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
||||
|
||||
for (auto h : heroes)
|
||||
{
|
||||
SectorMap &sm = ai->getCachedSectorMap(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
|
||||
for (auto obj : objs) //double loop, performance risk?
|
||||
{
|
||||
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||
auto t = sm->firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||
if (ai->isTileNotReserved(h, t))
|
||||
ret.push_back (sptr(Goals::ClearWayTo(obj->visitablePos(), h).setisAbstract(true)));
|
||||
}
|
||||
@ -963,7 +964,7 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
||||
|
||||
for (auto h : cb->getHeroesInfo())
|
||||
{
|
||||
SectorMap &sm = ai->getCachedSectorMap(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
||||
|
||||
for (auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
||||
@ -974,7 +975,7 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
||||
for (auto obj : ourObjs)
|
||||
{
|
||||
int3 dest = obj->visitablePos();
|
||||
auto t = sm.firstTileToGet(h, dest); //we assume that no more than one tile on the way is guarded
|
||||
auto t = sm->firstTileToGet(h, dest); //we assume that no more than one tile on the way is guarded
|
||||
if (t.valid()) //we know any path at all
|
||||
{
|
||||
if (ai->isTileNotReserved(h, t)) //no other hero wants to conquer that tile
|
||||
@ -1027,6 +1028,10 @@ TSubgoal GatherArmy::whatToDoToAchieve()
|
||||
|
||||
return fh->chooseSolution (getAllPossibleSubgoals()); //find dwelling. use current hero to prevent him from doing nothing.
|
||||
}
|
||||
|
||||
static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||
|
||||
TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
{
|
||||
//get all possible towns, heroes and dwellings we may use
|
||||
@ -1093,11 +1098,11 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
}
|
||||
for(auto h : cb->getHeroesInfo())
|
||||
{
|
||||
SectorMap &sm = ai->getCachedSectorMap(h);
|
||||
auto sm = ai->getCachedSectorMap(h);
|
||||
for (auto obj : objs)
|
||||
{ //find safe dwelling
|
||||
auto pos = obj->visitablePos();
|
||||
if (ai->isGoodForVisit(obj, h, sm))
|
||||
if (ai->isGoodForVisit(obj, h, *sm))
|
||||
ret.push_back (sptr (Goals::VisitTile(pos).sethero(h)));
|
||||
}
|
||||
}
|
||||
|
120
AI/VCAI/VCAI.cpp
120
AI/VCAI/VCAI.cpp
@ -8,6 +8,8 @@
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -96,6 +98,7 @@ VCAI::VCAI(void)
|
||||
LOG_TRACE(logAi);
|
||||
makingTurn = nullptr;
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
}
|
||||
|
||||
VCAI::~VCAI(void)
|
||||
@ -614,33 +617,46 @@ void VCAI::showBlockingDialog(const std::string &text, const std::vector<Compone
|
||||
});
|
||||
}
|
||||
|
||||
void VCAI::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void VCAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
LOG_TRACE_PARAMS(logAi, "askID '%i', exits '%s'", askID % exits);
|
||||
// LOG_TRACE_PARAMS(logAi, "askID '%i', exits '%s'", askID % exits);
|
||||
NET_EVENT_HANDLER;
|
||||
status.addQuery(askID, boost::str(boost::format("Teleport dialog query with %d exits")
|
||||
% exits.size()));
|
||||
|
||||
ObjectInstanceID choosenExit;
|
||||
int choosenExit = -1;
|
||||
if(impassable)
|
||||
knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
|
||||
else
|
||||
else if(destinationTeleport != ObjectInstanceID() && destinationTeleportPos.valid())
|
||||
{
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, destinationTeleport))
|
||||
choosenExit = destinationTeleport;
|
||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
}
|
||||
|
||||
if(!status.channelProbing())
|
||||
for(auto exit : exits)
|
||||
{
|
||||
if(status.channelProbing() && exit.first == destinationTeleport)
|
||||
{
|
||||
vstd::copy_if(exits, vstd::set_inserter(teleportChannelProbingList), [&](ObjectInstanceID id) -> bool
|
||||
choosenExit = vstd::find_pos(exits, exit);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Implement checking if visiting that teleport will uncovert any FoW
|
||||
// So far this is the best option to handle decision about probing
|
||||
auto obj = cb->getObj(exit.first, false);
|
||||
if(obj == nullptr && !vstd::contains(teleportChannelProbingList, exit.first) &&
|
||||
exit.first != destinationTeleport)
|
||||
{
|
||||
return !(vstd::contains(visitableObjs, cb->getObj(id)) || id == choosenExit);
|
||||
});
|
||||
teleportChannelProbingList.push_back(exit.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requestActionASAP([=]()
|
||||
{
|
||||
answerQuery(askID, choosenExit.getNum());
|
||||
answerQuery(askID, choosenExit);
|
||||
});
|
||||
}
|
||||
|
||||
@ -843,9 +859,9 @@ void VCAI::makeTurnInternal()
|
||||
bool VCAI::goVisitObj(const CGObjectInstance * obj, HeroPtr h)
|
||||
{
|
||||
int3 dst = obj->visitablePos();
|
||||
SectorMap &sm = getCachedSectorMap(h);
|
||||
auto sm = getCachedSectorMap(h);
|
||||
logAi->debugStream() << boost::format("%s will try to visit %s at (%s)") % h->name % obj->getObjectName() % strFromInt3(dst);
|
||||
int3 pos = sm.firstTileToGet(h, dst);
|
||||
int3 pos = sm->firstTileToGet(h, dst);
|
||||
if (!pos.valid()) //rare case when we are already standing on one of potential objects
|
||||
return false;
|
||||
return moveHeroToTile(pos, h);
|
||||
@ -1301,6 +1317,20 @@ bool VCAI::tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingI
|
||||
return false;//Nothing to build
|
||||
}
|
||||
|
||||
//Set of buildings for different goals. Does not include any prerequisites.
|
||||
static const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
|
||||
static const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
|
||||
static const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||
static const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
|
||||
BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP};
|
||||
static const BuildingID unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
|
||||
BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR};
|
||||
static const BuildingID spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
|
||||
BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
|
||||
static const BuildingID extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
|
||||
BuildingID::SPECIAL_4, BuildingID::SHIPYARD}; // all remaining buildings
|
||||
|
||||
void VCAI::buildStructure(const CGTownInstance * t)
|
||||
{
|
||||
//TODO make *real* town development system
|
||||
@ -1381,10 +1411,10 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
||||
{
|
||||
validateVisitableObjs();
|
||||
std::vector<const CGObjectInstance *> possibleDestinations;
|
||||
SectorMap &sm = getCachedSectorMap(h);
|
||||
auto sm = getCachedSectorMap(h);
|
||||
for(const CGObjectInstance *obj : visitableObjs)
|
||||
{
|
||||
if (isGoodForVisit(obj, h, sm))
|
||||
if (isGoodForVisit(obj, h, *sm))
|
||||
{
|
||||
possibleDestinations.push_back(obj);
|
||||
}
|
||||
@ -1439,12 +1469,12 @@ void VCAI::wander(HeroPtr h)
|
||||
validateVisitableObjs();
|
||||
std::vector <ObjectIdRef> dests, tmp;
|
||||
|
||||
SectorMap &sm = getCachedSectorMap(h);
|
||||
auto sm = getCachedSectorMap(h);
|
||||
|
||||
range::copy(reservedHeroesMap[h], std::back_inserter(tmp)); //also visit our reserved objects - but they are not prioritized to avoid running back and forth
|
||||
for (auto obj : tmp)
|
||||
{
|
||||
int3 pos = sm.firstTileToGet(h, obj->visitablePos());
|
||||
int3 pos = sm->firstTileToGet(h, obj->visitablePos());
|
||||
if (pos.valid())
|
||||
if (isAccessibleForHero (pos, h)) //even nearby objects could be blocked by other heroes :(
|
||||
dests.push_back(obj); //can't use lambda for member function :(
|
||||
@ -1453,7 +1483,7 @@ void VCAI::wander(HeroPtr h)
|
||||
range::copy(getPossibleDestinations(h), std::back_inserter(dests));
|
||||
erase_if(dests, [&](ObjectIdRef obj) -> bool
|
||||
{
|
||||
return !isSafeToVisit(h, sm.firstTileToGet(h, obj->visitablePos()));
|
||||
return !isSafeToVisit(h, sm->firstTileToGet(h, obj->visitablePos()));
|
||||
});
|
||||
|
||||
if(!dests.size())
|
||||
@ -1840,7 +1870,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
else
|
||||
{
|
||||
CGPath path;
|
||||
cb->getPathsInfo(h.get())->getPath(dst, path);
|
||||
cb->getPathsInfo(h.get())->getPath(path, dst);
|
||||
if(path.nodes.empty())
|
||||
{
|
||||
logAi->errorStream() << "Hero " << h->name << " cannot reach " << dst;
|
||||
@ -1860,25 +1890,29 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
|
||||
};
|
||||
|
||||
auto doTeleportMovement = [&](int3 dst, ObjectInstanceID exitId)
|
||||
auto doTeleportMovement = [&](ObjectInstanceID exitId, int3 exitPos)
|
||||
{
|
||||
destinationTeleport = exitId;
|
||||
cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true));
|
||||
if(exitPos.valid())
|
||||
destinationTeleportPos = CGHeroInstance::convertPosition(exitPos, true);
|
||||
cb->moveHero(*h, h->pos);
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
afterMovementCheck();
|
||||
};
|
||||
|
||||
auto doChannelProbing = [&]() -> void
|
||||
{
|
||||
auto currentExit = getObj(CGHeroInstance::convertPosition(h->pos,false), false);
|
||||
assert(currentExit);
|
||||
auto currentPos = CGHeroInstance::convertPosition(h->pos,false);
|
||||
auto currentExit = getObj(currentPos, true)->id;
|
||||
|
||||
status.setChannelProbing(true);
|
||||
for(auto exit : teleportChannelProbingList)
|
||||
doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), exit);
|
||||
doTeleportMovement(exit, int3(-1));
|
||||
teleportChannelProbingList.clear();
|
||||
doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), currentExit->id);
|
||||
status.setChannelProbing(false);
|
||||
|
||||
doTeleportMovement(currentExit, currentPos);
|
||||
};
|
||||
|
||||
int i=path.nodes.size()-1;
|
||||
@ -1891,7 +1925,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
auto nextObject = getObj(nextCoord, false);
|
||||
if(CGTeleport::isConnected(currentObject, nextObject))
|
||||
{ //we use special login if hero standing on teleporter it's mean we need
|
||||
doTeleportMovement(currentCoord, nextObject->id);
|
||||
doTeleportMovement(nextObject->id, nextCoord);
|
||||
if(teleportChannelProbingList.size())
|
||||
doChannelProbing();
|
||||
|
||||
@ -1915,6 +1949,8 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
|
||||
{ // Hero should be able to go through object if it's allow transit
|
||||
doMovement(endpos, true);
|
||||
}
|
||||
else if(path.nodes[i-1].layer == EPathfindingLayer::AIR)
|
||||
doMovement(endpos, true);
|
||||
else
|
||||
doMovement(endpos, false);
|
||||
|
||||
@ -2034,7 +2070,7 @@ void VCAI::tryRealize(Goals::BuildThis & g)
|
||||
void VCAI::tryRealize(Goals::DigAtTile & g)
|
||||
{
|
||||
assert(g.hero->visitablePos() == g.tile); //surely we want to crash here?
|
||||
if (g.hero->diggingStatus() == CGHeroInstance::CAN_DIG)
|
||||
if (g.hero->diggingStatus() == EDiggingStatus::CAN_DIG)
|
||||
{
|
||||
cb->dig(g.hero.get());
|
||||
completeGoal(sptr(g)); // finished digging
|
||||
@ -2463,7 +2499,7 @@ int3 VCAI::explorationBestNeighbour(int3 hpos, int radius, HeroPtr h)
|
||||
{
|
||||
int3 ourPos = h->convertPosition(h->pos, false);
|
||||
std::map<int3, int> dstToRevealedTiles;
|
||||
for(crint3 dir : dirs)
|
||||
for(crint3 dir : int3::getDirs())
|
||||
if(cb->isInTheMap(hpos+dir))
|
||||
if (ourPos != dir) //don't stand in place
|
||||
if (isSafeToVisit(h, hpos + dir) && isAccessibleForHero (hpos + dir, h))
|
||||
@ -2519,7 +2555,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
|
||||
continue;
|
||||
|
||||
CGPath path;
|
||||
cb->getPathsInfo(hero)->getPath(tile, path);
|
||||
cb->getPathsInfo(hero)->getPath(path, tile);
|
||||
float ourValue = (float)howManyTilesWillBeDiscovered(tile, radius, cbp) / (path.nodes.size() + 1); //+1 prevents erratic jumps
|
||||
|
||||
if (ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||
@ -2537,7 +2573,7 @@ int3 VCAI::explorationNewPoint(HeroPtr h)
|
||||
|
||||
int3 VCAI::explorationDesperate(HeroPtr h)
|
||||
{
|
||||
SectorMap &sm = getCachedSectorMap(h);
|
||||
auto sm = getCachedSectorMap(h);
|
||||
int radius = h->getSightRadious();
|
||||
|
||||
std::vector<std::vector<int3> > tiles; //tiles[distance_to_fow]
|
||||
@ -2566,7 +2602,7 @@ int3 VCAI::explorationDesperate(HeroPtr h)
|
||||
if (!howManyTilesWillBeDiscovered(tile, radius, cbp)) //avoid costly checks of tiles that don't reveal much
|
||||
continue;
|
||||
|
||||
auto t = sm.firstTileToGet(h, tile);
|
||||
auto t = sm->firstTileToGet(h, tile);
|
||||
if (t.valid())
|
||||
{
|
||||
ui64 ourDanger = evaluateDanger(t, h.h);
|
||||
@ -2669,13 +2705,24 @@ void VCAI::finish()
|
||||
|
||||
void VCAI::requestActionASAP(std::function<void()> whatToDo)
|
||||
{
|
||||
boost::thread newThread([this, whatToDo]()
|
||||
boost::mutex mutex;
|
||||
mutex.lock();
|
||||
|
||||
boost::thread newThread([&mutex,this,whatToDo]()
|
||||
{
|
||||
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)
|
||||
@ -2749,14 +2796,14 @@ TResources VCAI::freeResources() const
|
||||
return myRes;
|
||||
}
|
||||
|
||||
SectorMap& VCAI::getCachedSectorMap(HeroPtr h)
|
||||
std::shared_ptr<SectorMap> VCAI::getCachedSectorMap(HeroPtr h)
|
||||
{
|
||||
auto it = cachedSectorMaps.find(h);
|
||||
if (it != cachedSectorMaps.end())
|
||||
return it->second;
|
||||
else
|
||||
{
|
||||
cachedSectorMaps.insert(std::make_pair(h, SectorMap(h)));
|
||||
cachedSectorMaps[h] = std::make_shared<SectorMap>(h);
|
||||
return cachedSectorMaps[h];
|
||||
}
|
||||
}
|
||||
@ -2905,7 +2952,7 @@ void AIStatus::setMove(bool ongoing)
|
||||
void AIStatus::setChannelProbing(bool ongoing)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(mx);
|
||||
ongoingHeroMovement = ongoing;
|
||||
ongoingChannelProbing = ongoing;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
@ -3366,7 +3413,8 @@ int3 SectorMap::findFirstVisitableTile (HeroPtr h, crint3 dst)
|
||||
while(curtile != h->visitablePos())
|
||||
{
|
||||
auto topObj = cb->getTopObj(curtile);
|
||||
if (topObj && topObj->ID == Obj::HERO && h->tempOwner == topObj->tempOwner && topObj != h.h)
|
||||
if(topObj && topObj->ID == Obj::HERO && topObj != h.h &&
|
||||
cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
|
||||
{
|
||||
logAi->warnStream() << ("Another allied hero stands in our way");
|
||||
return ret;
|
||||
|
@ -12,11 +12,9 @@
|
||||
#include "../../lib/CBuildingHandler.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/mapObjects/MiscObjects.h"
|
||||
#include "../../lib/spells/CSpellHandler.h"
|
||||
#include "../../lib/Connection.h"
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/mapping/CMap.h"
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
|
||||
struct QuestInfo;
|
||||
@ -115,20 +113,6 @@ struct SectorMap
|
||||
int3 findFirstVisitableTile(HeroPtr h, crint3 dst);
|
||||
};
|
||||
|
||||
//Set of buildings for different goals. Does not include any prerequisites.
|
||||
const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
|
||||
const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
|
||||
const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
|
||||
BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
|
||||
const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
|
||||
BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP};
|
||||
const BuildingID unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
|
||||
BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR};
|
||||
const BuildingID spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
|
||||
BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
|
||||
const BuildingID extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
|
||||
BuildingID::SPECIAL_4, BuildingID::SHIPYARD}; // all remaining buildings
|
||||
|
||||
class VCAI : public CAdventureAI
|
||||
{
|
||||
public:
|
||||
@ -148,6 +132,7 @@ public:
|
||||
std::map<TeleportChannelID, shared_ptr<TeleportChannel> > knownTeleportChannels;
|
||||
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
|
||||
ObjectInstanceID destinationTeleport;
|
||||
int3 destinationTeleportPos;
|
||||
std::vector<ObjectInstanceID> teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored
|
||||
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
|
||||
std::map<HeroPtr, std::set<const CGTownInstance *> > townVisitsThisWeek;
|
||||
@ -161,7 +146,7 @@ public:
|
||||
std::set<const CGObjectInstance *> alreadyVisited;
|
||||
std::set<const CGObjectInstance *> reservedObjs; //to be visited by specific hero
|
||||
|
||||
std::map <HeroPtr, SectorMap> cachedSectorMaps; //TODO: serialize? not necessary
|
||||
std::map <HeroPtr, std::shared_ptr<SectorMap>> cachedSectorMaps; //TODO: serialize? not necessary
|
||||
|
||||
TResources saving;
|
||||
|
||||
@ -202,7 +187,7 @@ public:
|
||||
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO
|
||||
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
virtual void saveGame(COSer & h, const int version) override; //saving
|
||||
virtual void loadGame(CISer & h, const int version) override; //loading
|
||||
virtual void finish() override;
|
||||
@ -314,7 +299,7 @@ public:
|
||||
const CGObjectInstance *getUnvisitedObj(const std::function<bool(const CGObjectInstance *)> &predicate);
|
||||
bool isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies = false) const;
|
||||
//optimization - use one SM for every hero call
|
||||
SectorMap& getCachedSectorMap(HeroPtr h);
|
||||
std::shared_ptr<SectorMap> getCachedSectorMap(HeroPtr h);
|
||||
|
||||
const CGTownInstance *findTownWithTavern() const;
|
||||
bool canRecruitAnyHero(const CGTownInstance * t = NULL) const;
|
||||
|
@ -18,12 +18,7 @@
|
||||
#include "lib/spells/CSpellHandler.h"
|
||||
#include "lib/CArtHandler.h"
|
||||
#include "lib/GameConstants.h"
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#include "lib/CPlayerState.h"
|
||||
#include "lib/UnlockGuard.h"
|
||||
|
||||
/*
|
||||
@ -290,11 +285,6 @@ bool CCallback::canMoveBetween(const int3 &a, const int3 &b)
|
||||
return gs->checkForVisitableDir(a, b) && gs->checkForVisitableDir(b, a);
|
||||
}
|
||||
|
||||
int CCallback::getMovementCost(const CGHeroInstance * hero, int3 dest)
|
||||
{
|
||||
return gs->getMovementCost(hero, hero->visitablePos(), dest, hero->movement);
|
||||
}
|
||||
|
||||
const CPathsInfo * CCallback::getPathsInfo(const CGHeroInstance *h)
|
||||
{
|
||||
return cl->getPathsInfo(h);
|
||||
|
@ -104,7 +104,6 @@ public:
|
||||
|
||||
//client-specific functionalities (pathfinding)
|
||||
virtual bool canMoveBetween(const int3 &a, const int3 &b);
|
||||
virtual int getMovementCost(const CGHeroInstance * hero, int3 dest);
|
||||
virtual int3 getGuardingCreaturePosition(int3 tile);
|
||||
virtual const CPathsInfo * getPathsInfo(const CGHeroInstance *h);
|
||||
|
||||
|
10
ChangeLog
10
ChangeLog
@ -1,9 +1,19 @@
|
||||
0.98 -> 0.next
|
||||
|
||||
GENERAL:
|
||||
* New Bonus NO_TERRAIN_PENALTY
|
||||
* Nomads will remove Sand movement penalty from army
|
||||
* Flying and water walking is now supported in pathfinder
|
||||
* New artifacts supported
|
||||
- Angel Wings
|
||||
- Boots of Levitation
|
||||
* Implemented rumors in tavern window
|
||||
|
||||
ADVETURE AI:
|
||||
* Fixed AI trying to go through underground rock
|
||||
* Fixed several cases causing AI wandering aimlessly
|
||||
* AI can again pick best artifacts and exchange artifacts between heroes
|
||||
* AI heroes with patrol enabled won't leave patrol area anymore
|
||||
|
||||
RANDOM MAP GENERATOR:
|
||||
* Changed fractalization algorithm so it can create cycles
|
||||
|
12
Global.h
12
Global.h
@ -95,6 +95,18 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
# define NOMINMAX // Exclude min/max macros from <Windows.h>. Use std::[min/max] from <algorithm> instead.
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* A macro to force inlining some of our functions */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
// Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
|
||||
#ifdef _MSC_VER
|
||||
# define STRONG_INLINE __forceinline
|
||||
#elif __GNUC__
|
||||
# define STRONG_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# define STRONG_INLINE inline
|
||||
#endif
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cstdio>
|
||||
|
@ -529,8 +529,9 @@ void processCommand(const std::string &message)
|
||||
std::string cn; //command name
|
||||
readed >> cn;
|
||||
|
||||
if(LOCPLINT && LOCPLINT->cingconsole)
|
||||
LOCPLINT->cingconsole->print(message);
|
||||
// Check mantis issue 2292 for details
|
||||
// if(LOCPLINT && LOCPLINT->cingconsole)
|
||||
// LOCPLINT->cingconsole->print(message);
|
||||
|
||||
if(ermInteractiveMode)
|
||||
{
|
||||
@ -789,11 +790,12 @@ void processCommand(const std::string &message)
|
||||
Settings session = settings.write["session"];
|
||||
session["autoSkip"].Bool() = !session["autoSkip"].Bool();
|
||||
}
|
||||
else if(client && client->serv && client->serv->connected && LOCPLINT) //send to server
|
||||
// Check mantis issue 2292 for details
|
||||
/* else if(client && client->serv && client->serv->connected && LOCPLINT) //send to server
|
||||
{
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
LOCPLINT->cb->sendMessage(message);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//plays intro, ends when intro is over or button has been pressed (handles events)
|
||||
@ -1071,6 +1073,15 @@ static void handleEvent(SDL_Event & ev)
|
||||
|
||||
return;
|
||||
}
|
||||
else if(ev.type == SDL_WINDOWEVENT)
|
||||
{
|
||||
switch (ev.window.event) {
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
fullScreenChanged();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(eventsM);
|
||||
events.push(ev);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/StartInfo.h"
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "windows/InfoWindows.h"
|
||||
@ -97,6 +98,7 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player)
|
||||
{
|
||||
logGlobal->traceStream() << "\tHuman player interface for player " << Player << " being constructed";
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
observerInDuelMode = false;
|
||||
howManyPeople++;
|
||||
GH.defActionsDef = 0;
|
||||
@ -1147,14 +1149,15 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
|
||||
|
||||
}
|
||||
|
||||
void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID)
|
||||
void CPlayerInterface::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
ObjectInstanceID choosenExit;
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, destinationTeleport))
|
||||
choosenExit = destinationTeleport;
|
||||
int choosenExit = -1;
|
||||
auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
|
||||
if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
|
||||
choosenExit = vstd::find_pos(exits, neededExit);
|
||||
|
||||
cb->selectionMade(choosenExit.getNum(), askID);
|
||||
cb->selectionMade(choosenExit, askID);
|
||||
}
|
||||
|
||||
void CPlayerInterface::tileRevealed(const std::unordered_set<int3, ShashInt3> &pos)
|
||||
@ -1288,7 +1291,7 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
|
||||
for(auto &p : pathsMap)
|
||||
{
|
||||
CGPath path;
|
||||
cb->getPathsInfo(p.first)->getPath(p.second, path);
|
||||
cb->getPathsInfo(p.first)->getPath(path, p.second);
|
||||
paths[p.first] = path;
|
||||
logGlobal->traceStream() << boost::format("Restored path for hero %s leading to %s with %d nodes")
|
||||
% p.first->nodeName() % p.second % path.nodes.size();
|
||||
@ -1414,6 +1417,7 @@ void CPlayerInterface::requestRealized( PackageApplied *pa )
|
||||
&& stillMoveHero.get() == DURING_MOVE)
|
||||
{ // After teleportation via CGTeleport object is finished
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
stillMoveHero.setn(CONTINUE_MOVE);
|
||||
}
|
||||
}
|
||||
@ -2226,7 +2230,7 @@ CGPath * CPlayerInterface::getAndVerifyPath(const CGHeroInstance * h)
|
||||
{
|
||||
assert(h->getPosition(false) == path.startPos());
|
||||
//update the hero path in case of something has changed on map
|
||||
if(LOCPLINT->cb->getPathsInfo(h)->getPath(path.endPos(), path))
|
||||
if(LOCPLINT->cb->getPathsInfo(h)->getPath(path, path.endPos()))
|
||||
return &path;
|
||||
else
|
||||
paths.erase(h);
|
||||
@ -2315,23 +2319,22 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
|
||||
{
|
||||
std::string hlp;
|
||||
CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
|
||||
auto isDiggingPossible = h->diggingStatus();
|
||||
if(hlp.length())
|
||||
isDiggingPossible = EDiggingStatus::TILE_OCCUPIED; //TODO integrate with canDig
|
||||
|
||||
int msgToShow = -1;
|
||||
CGHeroInstance::ECanDig isDiggingPossible = h->diggingStatus();
|
||||
if(hlp.length())
|
||||
isDiggingPossible = CGHeroInstance::TILE_OCCUPIED; //TODO integrate with canDig
|
||||
|
||||
switch(isDiggingPossible)
|
||||
{
|
||||
case CGHeroInstance::CAN_DIG:
|
||||
case EDiggingStatus::CAN_DIG:
|
||||
break;
|
||||
case CGHeroInstance::LACK_OF_MOVEMENT:
|
||||
case EDiggingStatus::LACK_OF_MOVEMENT:
|
||||
msgToShow = 56; //"Digging for artifacts requires a whole day, try again tomorrow."
|
||||
break;
|
||||
case CGHeroInstance::TILE_OCCUPIED:
|
||||
case EDiggingStatus::TILE_OCCUPIED:
|
||||
msgToShow = 97; //Try searching on clear ground.
|
||||
break;
|
||||
case CGHeroInstance::WRONG_TERRAIN:
|
||||
case EDiggingStatus::WRONG_TERRAIN:
|
||||
msgToShow = 60; ////Try looking on land!
|
||||
break;
|
||||
default:
|
||||
@ -2642,7 +2645,18 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
ETerrainType newTerrain;
|
||||
int sh = -1;
|
||||
|
||||
for(i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE); i--)
|
||||
auto canStop = [&](CGPathNode * node) -> bool
|
||||
{
|
||||
if(node->layer == EPathfindingLayer::LAND || node->layer == EPathfindingLayer::SAIL)
|
||||
return true;
|
||||
|
||||
if(node->accessible == CGPathNode::ACCESSIBLE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
for(i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || !canStop(&path.nodes[i])); i--)
|
||||
{
|
||||
int3 currentCoord = path.nodes[i].coord;
|
||||
int3 nextCoord = path.nodes[i-1].coord;
|
||||
@ -2652,6 +2666,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
{
|
||||
CCS->soundh->stopSound(sh);
|
||||
destinationTeleport = nextObject->id;
|
||||
destinationTeleportPos = nextCoord;
|
||||
doMovement(h->pos, false);
|
||||
sh = CCS->soundh->playSound(CCS->soundh->horseSounds[currentTerrain], -1);
|
||||
continue;
|
||||
@ -2683,18 +2698,21 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
int3 endpos(nextCoord.x, nextCoord.y, h->pos.z);
|
||||
logGlobal->traceStream() << "Requesting hero movement to " << endpos;
|
||||
|
||||
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)))
|
||||
{ // Hero should be able to go through object if it's allow transit
|
||||
doMovement(endpos, true);
|
||||
useTransit = true;
|
||||
}
|
||||
else
|
||||
doMovement(endpos, false);
|
||||
else if(path.nodes[i-1].layer == EPathfindingLayer::AIR)
|
||||
useTransit = true;
|
||||
|
||||
doMovement(endpos, useTransit);
|
||||
|
||||
logGlobal->traceStream() << "Resuming " << __FUNCTION__;
|
||||
bool guarded = cb->isInTheMap(cb->getGuardingCreaturePosition(endpos - int3(1, 0, 0)));
|
||||
if(guarded || showingDialog->get() == true) // Abort movement if a guard was fought or there is a dialog to display (Mantis #1136)
|
||||
if((!useTransit && guarded) || showingDialog->get() == true) // Abort movement if a guard was fought or there is a dialog to display (Mantis #1136)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "../lib/CGameInterface.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "gui/CIntObject.h"
|
||||
//#include "../lib/CGameState.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define sprintf_s snprintf
|
||||
@ -90,6 +89,7 @@ class CPlayerInterface : public CGameInterface, public IUpdateable
|
||||
public:
|
||||
bool observerInDuelMode;
|
||||
ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation
|
||||
int3 destinationTeleportPos;
|
||||
|
||||
//minor interfaces
|
||||
CondSh<bool> *showingDialog; //indicates if dialog box is displayed
|
||||
@ -168,7 +168,7 @@ public:
|
||||
void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override;
|
||||
void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
|
||||
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
|
||||
void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) override;
|
||||
void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
|
||||
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override;
|
||||
void showPuzzleMap() override;
|
||||
void viewWorldMap() override;
|
||||
|
@ -1875,9 +1875,9 @@ void CRandomMapTab::updateMapInfo()
|
||||
|
||||
// Generate player information
|
||||
mapInfo->mapHeader->players.clear();
|
||||
int playersToGen = (mapGenOptions.getPlayerCount() == CMapGenOptions::RANDOM_SIZE
|
||||
|| mapGenOptions.getCompOnlyPlayerCount() == CMapGenOptions::RANDOM_SIZE)
|
||||
? 8 : mapGenOptions.getPlayerCount() + mapGenOptions.getCompOnlyPlayerCount();
|
||||
int playersToGen = PlayerColor::PLAYER_LIMIT_I;
|
||||
if(mapGenOptions.getPlayerCount() != CMapGenOptions::RANDOM_SIZE)
|
||||
playersToGen = mapGenOptions.getPlayerCount();
|
||||
mapInfo->mapHeader->howManyTeams = playersToGen;
|
||||
|
||||
for(int i = 0; i < playersToGen; ++i)
|
||||
@ -1885,7 +1885,8 @@ void CRandomMapTab::updateMapInfo()
|
||||
PlayerInfo player;
|
||||
player.isFactionRandom = true;
|
||||
player.canComputerPlay = true;
|
||||
if(i >= mapGenOptions.getPlayerCount() && mapGenOptions.getPlayerCount() != CMapGenOptions::RANDOM_SIZE)
|
||||
if(mapGenOptions.getCompOnlyPlayerCount() != CMapGenOptions::RANDOM_SIZE &&
|
||||
i >= mapGenOptions.getHumanOnlyPlayerCount())
|
||||
{
|
||||
player.canHumanPlay = false;
|
||||
}
|
||||
|
@ -104,11 +104,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
return false;
|
||||
}
|
||||
// Retrieve stream information
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
if (av_find_stream_info(format) < 0)
|
||||
#else
|
||||
if (avformat_find_stream_info(format, nullptr) < 0)
|
||||
#endif
|
||||
return false;
|
||||
|
||||
// Find the first video stream
|
||||
@ -139,22 +135,16 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
}
|
||||
|
||||
// Open codec
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 6, 0)
|
||||
if ( avcodec_open(codecContext, codec) < 0 )
|
||||
#else
|
||||
if ( avcodec_open2(codecContext, codec, nullptr) < 0 )
|
||||
#endif
|
||||
{
|
||||
// Could not open codec
|
||||
codec = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate video frame
|
||||
frame = avcodec_alloc_frame();
|
||||
frame = av_frame_alloc();
|
||||
|
||||
//setup scaling
|
||||
|
||||
if(scale)
|
||||
{
|
||||
pos.w = screen->w;
|
||||
@ -185,21 +175,21 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
if (texture)
|
||||
{ // Convert the image into YUV format that SDL uses
|
||||
sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
|
||||
pos.w, pos.h, PIX_FMT_YUV420P,
|
||||
pos.w, pos.h,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
SWS_BICUBIC, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
PixelFormat screenFormat = PIX_FMT_NONE;
|
||||
AVPixelFormat screenFormat = AV_PIX_FMT_NONE;
|
||||
if (screen->format->Bshift > screen->format->Rshift)
|
||||
{
|
||||
// this a BGR surface
|
||||
switch (screen->format->BytesPerPixel)
|
||||
{
|
||||
case 2: screenFormat = PIX_FMT_BGR565; break;
|
||||
case 3: screenFormat = PIX_FMT_BGR24; break;
|
||||
case 4: screenFormat = PIX_FMT_BGR32; break;
|
||||
case 2: screenFormat = AV_PIX_FMT_BGR565; break;
|
||||
case 3: screenFormat = AV_PIX_FMT_BGR24; break;
|
||||
case 4: screenFormat = AV_PIX_FMT_BGR32; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -208,9 +198,9 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
|
||||
// this a RGB surface
|
||||
switch (screen->format->BytesPerPixel)
|
||||
{
|
||||
case 2: screenFormat = PIX_FMT_RGB565; break;
|
||||
case 3: screenFormat = PIX_FMT_RGB24; break;
|
||||
case 4: screenFormat = PIX_FMT_RGB32; break;
|
||||
case 2: screenFormat = AV_PIX_FMT_RGB565; break;
|
||||
case 3: screenFormat = AV_PIX_FMT_RGB24; break;
|
||||
case 4: screenFormat = AV_PIX_FMT_RGB32; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
@ -367,8 +357,7 @@ void CVideoPlayer::close()
|
||||
|
||||
if (frame)
|
||||
{
|
||||
av_free(frame);
|
||||
frame = nullptr;
|
||||
av_frame_free(&frame);//will be set to null
|
||||
}
|
||||
|
||||
if (codec)
|
||||
@ -380,12 +369,7 @@ void CVideoPlayer::close()
|
||||
|
||||
if (format)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
av_close_input_file(format);
|
||||
format = nullptr;
|
||||
#else
|
||||
avformat_close_input(&format);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (context)
|
||||
|
@ -51,27 +51,42 @@ public:
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
// compatibility with different versions od libavutil
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 42, 0)) || \
|
||||
(LIBAVUTIL_VERSION_INT == AV_VERSION_INT(51, 73, 101))
|
||||
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_NV12 PIX_FMT_NV12
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422
|
||||
#define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//compatibility for libav 9.18 in ubuntu 14.04, 52.66.100 is ffmpeg 2.2.3
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 66, 100))
|
||||
inline AVFrame * av_frame_alloc()
|
||||
{
|
||||
return avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
inline void av_frame_free(AVFrame ** frame)
|
||||
{
|
||||
av_free(*frame);
|
||||
*frame = nullptr;
|
||||
}
|
||||
#endif // VCMI_USE_OLD_AVUTIL
|
||||
|
||||
//fix for travis-ci
|
||||
#if (LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 0, 0))
|
||||
#define AVPixelFormat PixelFormat
|
||||
#define AV_PIX_FMT_NONE PIX_FMT_NONE
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#define AV_PIX_FMT_BGR565 PIX_FMT_BGR565
|
||||
#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
|
||||
#define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
|
||||
#define AV_PIX_FMT_RGB565 PIX_FMT_RGB565
|
||||
#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
|
||||
#define AV_PIX_FMT_RGB32 PIX_FMT_RGB32
|
||||
#endif
|
||||
|
||||
class CVideoPlayer : public IMainVideoPlayer
|
||||
{
|
||||
int stream; // stream index in video
|
||||
AVFormatContext *format;
|
||||
AVCodecContext *codecContext; // codec context for stream
|
||||
AVCodec *codec;
|
||||
AVFrame *frame;
|
||||
AVFrame *frame;
|
||||
struct SwsContext *sws;
|
||||
|
||||
AVIOContext * context;
|
||||
@ -102,7 +117,7 @@ public:
|
||||
void show(int x, int y, SDL_Surface *dst, bool update = true) override; //blit current frame
|
||||
void redraw(int x, int y, SDL_Surface *dst, bool update = true) override; //reblits buffer
|
||||
void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true) override; //moves to next frame if appropriate, and blits it or blits only if redraw parameter is set true
|
||||
|
||||
|
||||
// Opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played)
|
||||
bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false, bool scale = false) override;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CStopWatch.h"
|
||||
#include "../lib/mapObjects/CObjectClassesHandler.h"
|
||||
#include "../lib/mapObjects/CObjectHandler.h"
|
||||
|
||||
using namespace CSDL_Ext;
|
||||
#ifdef min
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/BattleState.h"
|
||||
#include "../lib/GameConstants.h"
|
||||
#include "../lib/CPlayerState.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "widgets/AdventureMapClasses.h"
|
||||
@ -819,10 +820,10 @@ void SaveGame::applyCl(CClient *cl)
|
||||
|
||||
void PlayerMessage::applyCl(CClient *cl)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "Player "<< player <<" sends a message: " << text;
|
||||
logNetwork->debugStream() << "Player "<< player <<" sends a message: " << text;
|
||||
|
||||
logNetwork->debugStream() << str.str();
|
||||
std::ostringstream str;
|
||||
str << cl->getPlayer(player)->nodeName() <<": " << text;
|
||||
if(LOCPLINT)
|
||||
LOCPLINT->cingconsole->print(str.str());
|
||||
}
|
||||
|
@ -233,8 +233,9 @@ std::string CDefenceAnimation::getMySound()
|
||||
if(killed)
|
||||
return battle_sound(stack->getCreature(), killed);
|
||||
|
||||
if (stack->valOfBonuses(Bonus::UntilGetsTurn))
|
||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
return battle_sound(stack->getCreature(), defend);
|
||||
|
||||
return battle_sound(stack->getCreature(), wince);
|
||||
}
|
||||
|
||||
@ -243,10 +244,9 @@ CCreatureAnim::EAnimType CDefenceAnimation::getMyAnimType()
|
||||
if(killed)
|
||||
return CCreatureAnim::DEATH;
|
||||
|
||||
auto selector = CSelector(Bonus::UntilGetsTurn).And(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
|
||||
|
||||
if(stack->valOfBonuses(selector))
|
||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||
return CCreatureAnim::DEFENCE;
|
||||
|
||||
return CCreatureAnim::HITTED;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../../lib/NetPacks.h"
|
||||
#include "../../lib/StartInfo.h"
|
||||
#include "../../lib/CondSh.h"
|
||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||
|
||||
/*
|
||||
* CBattleInterfaceClasses.cpp, part of VCMI engine
|
||||
|
@ -13,13 +13,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
struct SDL_MouseMotionEvent;
|
||||
|
||||
// A point with x/y coordinate, used mostly for graphic rendering
|
||||
|
@ -18,15 +18,6 @@
|
||||
#include "../../lib/GameConstants.h"
|
||||
|
||||
|
||||
//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
|
||||
#ifdef _MSC_VER
|
||||
#define STRONG_INLINE __forceinline
|
||||
#elif __GNUC__
|
||||
#define STRONG_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
#define STRONG_INLINE inline
|
||||
#endif
|
||||
|
||||
extern SDL_Window * mainWindow;
|
||||
extern SDL_Renderer * mainRenderer;
|
||||
extern SDL_Texture * screenTexture;
|
||||
|
@ -1579,7 +1579,13 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
|
||||
if(t.hasFavourableWinds())
|
||||
out = CGI->objtypeh->getObjectName(Obj::FAVORABLE_WINDS);
|
||||
else if(terName)
|
||||
{
|
||||
out = CGI->generaltexth->terrainNames[t.terType];
|
||||
if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG)
|
||||
{
|
||||
out = boost::str(boost::format("%s %s") % out % CGI->generaltexth->allTexts[330]); /// digging ok
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMapHandler::discardWorldViewCache()
|
||||
|
@ -114,7 +114,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
|
||||
adventureInt->tileRClicked(mp);
|
||||
}
|
||||
|
||||
void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
||||
void CTerrainRect::mouseMoved(const SDL_MouseMotionEvent & sEvent)
|
||||
{
|
||||
int3 tHovered = whichTileIsIt(sEvent.x,sEvent.y);
|
||||
int3 pom = adventureInt->verifyPos(tHovered);
|
||||
@ -126,11 +126,11 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
||||
}
|
||||
|
||||
if (pom != curHoveredTile)
|
||||
curHoveredTile=pom;
|
||||
curHoveredTile = pom;
|
||||
else
|
||||
return;
|
||||
|
||||
adventureInt->tileHovered(curHoveredTile);
|
||||
adventureInt->tileHovered(pom);
|
||||
}
|
||||
void CTerrainRect::hover(bool on)
|
||||
{
|
||||
@ -188,7 +188,7 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
|
||||
* is id1=7, id2=5 (pns[7][5])
|
||||
*/
|
||||
bool pathContinuous = curPos.areNeighbours(nextPos) && curPos.areNeighbours(prevPos);
|
||||
if(pathContinuous && cv[i].land == cv[i+1].land)
|
||||
if(pathContinuous && cv[i].action != CGPathNode::EMBARK && cv[i].action != CGPathNode::DISEMBARK)
|
||||
{
|
||||
int id1=(curPos.x-nextPos.x+1)+3*(curPos.y-nextPos.y+1); //Direction of entering vector
|
||||
int id2=(cv[i-1].coord.x-curPos.x+1)+3*(cv[i-1].coord.y-curPos.y+1); //Direction of exiting vector
|
||||
@ -881,7 +881,7 @@ void CAdvMapInt::showAll(SDL_Surface * to)
|
||||
|
||||
statusbar.show(to);
|
||||
|
||||
LOCPLINT->cingconsole->showAll(to);
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
}
|
||||
|
||||
bool CAdvMapInt::isHeroSleeping(const CGHeroInstance *hero)
|
||||
@ -958,7 +958,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);
|
||||
updateScreen=false;
|
||||
LOCPLINT->cingconsole->showAll(to);
|
||||
LOCPLINT->cingconsole->show(to);
|
||||
}
|
||||
else if (terrain.needsAnimUpdate())
|
||||
{
|
||||
@ -1190,7 +1190,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
|
||||
CGPath &path = LOCPLINT->paths[h];
|
||||
terrain.currentPath = &path;
|
||||
int3 dst = h->getPosition(false) + dir;
|
||||
if(dst != verifyPos(dst) || !LOCPLINT->cb->getPathsInfo(h)->getPath(dst, path))
|
||||
if(dst != verifyPos(dst) || !LOCPLINT->cb->getPathsInfo(h)->getPath(path, dst))
|
||||
{
|
||||
terrain.currentPath = nullptr;
|
||||
return;
|
||||
@ -1445,7 +1445,7 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
|
||||
{
|
||||
CGPath &path = LOCPLINT->paths[currentHero];
|
||||
terrain.currentPath = &path;
|
||||
bool gotPath = LOCPLINT->cb->getPathsInfo(currentHero)->getPath(mapPos, path); //try getting path, erase if failed
|
||||
bool gotPath = LOCPLINT->cb->getPathsInfo(currentHero)->getPath(path, mapPos); //try getting path, erase if failed
|
||||
updateMoveHero(currentHero);
|
||||
if (!gotPath)
|
||||
LOCPLINT->eraseCurrentPathOf(currentHero);
|
||||
@ -1467,7 +1467,8 @@ void CAdvMapInt::tileLClicked(const int3 &mapPos)
|
||||
|
||||
void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
{
|
||||
if(mode != EAdvMapMode::NORMAL)
|
||||
if(mode != EAdvMapMode::NORMAL //disable in world view
|
||||
|| !selection) //may occur just at the start of game (fake move before full intiialization)
|
||||
return;
|
||||
if(!LOCPLINT->cb->isVisible(mapPos))
|
||||
{
|
||||
@ -1475,10 +1476,11 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
statusbar.clear();
|
||||
return;
|
||||
}
|
||||
auto objRelations = PlayerRelations::ALLIES;
|
||||
const CGObjectInstance *objAtTile = getActiveObject(mapPos);
|
||||
|
||||
if (objAtTile)
|
||||
if(objAtTile)
|
||||
{
|
||||
objRelations = LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner);
|
||||
std::string text = curHero() ? objAtTile->getHoverText(curHero()) : objAtTile->getHoverText(LOCPLINT->playerID);
|
||||
boost::replace_all(text,"\n"," ");
|
||||
statusbar.setText(text);
|
||||
@ -1490,9 +1492,6 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
statusbar.setText(hlp);
|
||||
}
|
||||
|
||||
if(!selection) //may occur just at the start of game (fake move before full intiialization)
|
||||
return;
|
||||
|
||||
if(spellBeingCasted)
|
||||
{
|
||||
switch(spellBeingCasted->id)
|
||||
@ -1505,9 +1504,9 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
return;
|
||||
case SpellID::DIMENSION_DOOR:
|
||||
{
|
||||
const TerrainTile *t = LOCPLINT->cb->getTile(mapPos, false);
|
||||
const TerrainTile * t = LOCPLINT->cb->getTile(mapPos, false);
|
||||
int3 hpos = selection->getSightCenter();
|
||||
if((!t || t->isClear(LOCPLINT->cb->getTile(hpos))) && isInScreenRange(hpos, mapPos))
|
||||
if((!t || t->isClear(LOCPLINT->cb->getTile(hpos))) && isInScreenRange(hpos, mapPos))
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 41);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
@ -1516,15 +1515,13 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
}
|
||||
}
|
||||
|
||||
const bool guardingCreature = CGI->mh->map->isInTheMap(LOCPLINT->cb->getGuardingCreaturePosition(mapPos));
|
||||
|
||||
if(selection->ID == Obj::TOWN)
|
||||
{
|
||||
if(objAtTile)
|
||||
{
|
||||
if(objAtTile->ID == Obj::TOWN && LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner) != PlayerRelations::ENEMIES)
|
||||
if(objAtTile->ID == Obj::TOWN && objRelations != PlayerRelations::ENEMIES)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 3);
|
||||
else if(objAtTile->ID == Obj::HERO && objAtTile->tempOwner == LOCPLINT->playerID)
|
||||
else if(objAtTile->ID == Obj::HERO && objRelations == PlayerRelations::SAME_PLAYER)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
@ -1532,129 +1529,61 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
else if(const CGHeroInstance *h = curHero())
|
||||
else if(const CGHeroInstance * h = curHero())
|
||||
{
|
||||
int3 mapPosCopy = mapPos;
|
||||
const CGPathNode *pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPosCopy);
|
||||
const CGPathNode * pnode = LOCPLINT->cb->getPathsInfo(h)->getPathInfo(mapPosCopy);
|
||||
assert(pnode);
|
||||
|
||||
int turns = pnode->turns;
|
||||
vstd::amin(turns, 3);
|
||||
bool accessible = pnode->turns < 255;
|
||||
|
||||
if(objAtTile)
|
||||
switch(pnode->action)
|
||||
{
|
||||
if(objAtTile->ID == Obj::HERO)
|
||||
{
|
||||
if(!LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, objAtTile->tempOwner)) //enemy hero
|
||||
{
|
||||
if(accessible)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
else //our or ally hero
|
||||
{
|
||||
if(selection == objAtTile)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
|
||||
else if(accessible)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 8 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
|
||||
}
|
||||
}
|
||||
else if(objAtTile->ID == Obj::TOWN)
|
||||
{
|
||||
if(!LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, objAtTile->tempOwner)) //enemy town
|
||||
{
|
||||
if(accessible)
|
||||
{
|
||||
const CGTownInstance* townObj = dynamic_cast<const CGTownInstance*>(objAtTile);
|
||||
|
||||
// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
|
||||
if (townObj && !townObj->armedGarrison())
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
}
|
||||
else //our or ally town
|
||||
{
|
||||
if(accessible)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 3);
|
||||
}
|
||||
}
|
||||
else if(objAtTile->ID == Obj::BOAT)
|
||||
{
|
||||
if(accessible)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 6 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
else if (objAtTile->ID == Obj::GARRISON || objAtTile->ID == Obj::GARRISON2)
|
||||
{
|
||||
if (accessible)
|
||||
{
|
||||
const CGGarrison* garrObj = dynamic_cast<const CGGarrison*>(objAtTile); //TODO evil evil cast!
|
||||
|
||||
// Show battle cursor for guarded enemy garrisons or garrisons have guarding creature behind, otherwise movement cursor.
|
||||
if (garrObj && ((garrObj->stacksCount()
|
||||
&& !LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, garrObj->tempOwner))
|
||||
|| guardingCreature))
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
|
||||
}
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
}
|
||||
else if (guardingCreature && accessible) //(objAtTile->ID == 54) //monster
|
||||
{
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
}
|
||||
case CGPathNode::NORMAL:
|
||||
if(pnode->layer == EPathfindingLayer::LAND)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 28 + turns);
|
||||
break;
|
||||
|
||||
case CGPathNode::VISIT:
|
||||
case CGPathNode::BLOCKING_VISIT:
|
||||
if(objAtTile && objAtTile->ID == Obj::HERO)
|
||||
{
|
||||
if(accessible)
|
||||
{
|
||||
if(pnode->land)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 28 + turns);
|
||||
}
|
||||
if(selection == objAtTile)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 8 + turns*6);
|
||||
}
|
||||
}
|
||||
else //no objs
|
||||
{
|
||||
if(accessible/* && pnode->accessible != CGPathNode::FLYABLE*/)
|
||||
else if(pnode->layer == EPathfindingLayer::LAND)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 28 + turns);
|
||||
break;
|
||||
|
||||
case CGPathNode::BATTLE:
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
break;
|
||||
|
||||
case CGPathNode::EMBARK:
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 6 + turns*6);
|
||||
break;
|
||||
|
||||
case CGPathNode::DISEMBARK:
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 7 + turns*6);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(objAtTile && objRelations != PlayerRelations::ENEMIES)
|
||||
{
|
||||
if (guardingCreature)
|
||||
{
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pnode->land)
|
||||
{
|
||||
if(LOCPLINT->cb->getTile(h->getPosition(false))->terType != ETerrainType::WATER)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 7 + turns*6); //anchor
|
||||
}
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 6 + turns*6);
|
||||
}
|
||||
if(objAtTile->ID == Obj::TOWN)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 3);
|
||||
else if(objAtTile->ID == Obj::HERO && objRelations == PlayerRelations::SAME_PLAYER)
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
|
||||
}
|
||||
else
|
||||
CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "../../lib/CGameState.h"
|
||||
#include "../../lib/CGeneralTextHandler.h"
|
||||
#include "../../lib/NetPacksBase.h"
|
||||
|
||||
#include "../../lib/mapObjects/CQuest.h"
|
||||
/*
|
||||
* CQuestLog.cpp, part of VCMI engine
|
||||
*
|
||||
|
@ -705,7 +705,9 @@ CTavernWindow::CTavernWindow(const CGObjectInstance *TavernObj):
|
||||
|
||||
new CLabel(200, 35, FONT_BIG, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[37]);
|
||||
new CLabel(320, 328, FONT_SMALL, CENTER, Colors::WHITE, "2500");
|
||||
new CTextBox(LOCPLINT->cb->getTavernGossip(tavernObj), Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
|
||||
|
||||
auto rumorText = boost::str(boost::format(CGI->generaltexth->allTexts[216]) % LOCPLINT->cb->getTavernRumor(tavernObj));
|
||||
new CTextBox(rumorText, Rect(32, 190, 330, 68), 0, FONT_SMALL, CENTER, Colors::WHITE);
|
||||
|
||||
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||
cancel = new CButton(Point(310, 428), "ICANCEL.DEF", CButton::tooltip(CGI->generaltexth->tavernInfo[7]), std::bind(&CTavernWindow::close, this), SDLK_ESCAPE);
|
||||
@ -1628,9 +1630,9 @@ CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner):
|
||||
int counter = 0;
|
||||
for(auto & iter : tgi.colorToBestHero)
|
||||
{
|
||||
new CPicture(colorToBox[iter.first.getNum()], 253 + 66 * counter, 334);
|
||||
if(iter.second.portrait >= 0)
|
||||
{
|
||||
new CPicture(colorToBox[iter.first.getNum()], 253 + 66 * counter, 334);
|
||||
new CAnimImage("PortraitsSmall", iter.second.portrait, 0, 260 + 66 * counter, 360);
|
||||
//TODO: r-click info:
|
||||
// - r-click on hero
|
||||
|
@ -3,7 +3,7 @@
|
||||
[
|
||||
{
|
||||
"resolution": { "x": 800, "y": 600 },
|
||||
"InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 39 },
|
||||
"InGameConsole": { "maxInputPerLine": 60, "maxOutputPerLine": 60 },
|
||||
"AdvMap": { "x": 7, "y": 7, "width": 594, "height": 546, "smoothMove": 1, "puzzleSepia": 1, "objectFading" : 1, "screenFading" : 1 },
|
||||
"InfoBox": { "x": 605, "y": 389 },
|
||||
"gem0": { "x": 6, "y": 508, "graphic": "agemLL.def" },
|
||||
|
@ -3,7 +3,7 @@
|
||||
{
|
||||
"type" : "object",
|
||||
"$schema": "http://json-schema.org/draft-04/schema",
|
||||
"required" : [ "general", "video", "adventure", "battle", "server", "logging", "launcher" ],
|
||||
"required" : [ "general", "video", "adventure", "pathfinder", "battle", "server", "logging", "launcher" ],
|
||||
"definitions" : {
|
||||
"logLevelEnum" : {
|
||||
"type" : "string",
|
||||
@ -108,6 +108,74 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pathfinder" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"default": {},
|
||||
"required" : [ "teleports", "layers", "oneTurnSpecialLayersLimit", "originalMovementRules", "lightweightFlyingMode" ],
|
||||
"properties" : {
|
||||
"layers" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"default": {},
|
||||
"required" : [ "sailing", "waterWalking", "flying" ],
|
||||
"properties" : {
|
||||
"sailing" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"waterWalking" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"flying" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
}
|
||||
}
|
||||
},
|
||||
"teleports" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"default": {},
|
||||
"required" : [ "twoWay", "oneWay", "oneWayRandom", "whirlpool", "castleGate" ],
|
||||
"properties" : {
|
||||
"twoWay" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"oneWay" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"oneWayRandom" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
},
|
||||
"whirlpool" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"castleGate" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
"oneTurnSpecialLayersLimit" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"originalMovementRules" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
},
|
||||
"lightweightFlyingMode" : {
|
||||
"type" : "boolean",
|
||||
"default" : false
|
||||
}
|
||||
}
|
||||
},
|
||||
"battle" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
/// CModListContainer overrides
|
||||
void resetRepositories() override;
|
||||
void addRepository(QVariantMap data) override;
|
||||
void modChanged(QString modID);
|
||||
void modChanged(QString modID) override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* BattleState.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -22,6 +22,7 @@
|
||||
#include "JsonNode.h"
|
||||
#include "filesystem/Filesystem.h"
|
||||
#include "CRandomGenerator.h"
|
||||
#include "mapObjects/CGTownInstance.h"
|
||||
|
||||
const CStack * BattleInfo::getNextStack() const
|
||||
{
|
||||
|
@ -11,12 +11,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "BattleHex.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "CCreatureSet.h"
|
||||
#include "mapObjects/CArmedInstance.h" // for army serialization
|
||||
#include "mapObjects/CGHeroInstance.h" // for commander serialization
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CObstacleInstance.h"
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "GameConstants.h"
|
||||
#include "CBattleCallback.h"
|
||||
|
@ -738,8 +738,8 @@ std::string CArtifactInstance::nodeName() const
|
||||
|
||||
CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
|
||||
{
|
||||
auto ret = new CArtifactInstance(VLC->arth->artifacts[1]);
|
||||
auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, 1, s->id);
|
||||
auto ret = new CArtifactInstance(VLC->arth->artifacts[ArtifactID::SPELL_SCROLL]);
|
||||
auto b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, ArtifactID::SPELL_SCROLL, s->id);
|
||||
ret->addNewBonus(b);
|
||||
return ret;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "spells/CSpellHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "mapObjects/CGTownInstance.h"
|
||||
|
||||
/*
|
||||
* CBattleCallback.cpp, part of VCMI engine
|
||||
@ -2245,6 +2246,7 @@ BattleAttackInfo::BattleAttackInfo(const CStack *Attacker, const CStack *Defende
|
||||
chargedFields = 0;
|
||||
|
||||
luckyHit = false;
|
||||
unluckyHit = false;
|
||||
deathBlow = false;
|
||||
ballistaDoubleDamage = false;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ DLL_LINKAGE CConsoleHandler * console = nullptr;
|
||||
#define CONSOLE_GRAY "\x1b[1;30m"
|
||||
#define CONSOLE_TEAL "\x1b[1;36m"
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#ifndef __MINGW32__
|
||||
#pragma comment(lib, "dbghelp.lib")
|
||||
|
@ -12,12 +12,15 @@
|
||||
#include "CGameInfoCallback.h"
|
||||
|
||||
#include "CGameState.h" // PlayerState
|
||||
#include "CGeneralTextHandler.h"
|
||||
#include "mapObjects/CObjectHandler.h" // for CGObjectInstance
|
||||
#include "StartInfo.h" // for StartInfo
|
||||
#include "BattleState.h" // for BattleInfo
|
||||
#include "NetPacks.h" // for InfoWindow
|
||||
#include "CModHandler.h"
|
||||
#include "spells/CSpellHandler.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "CPlayerState.h"
|
||||
|
||||
//TODO make clean
|
||||
#define ERROR_VERBOSE_OR_NOT_RET_VAL_IF(cond, verbose, txt, retVal) do {if(cond){if(verbose)logGlobal->errorStream() << BOOST_CURRENT_FUNCTION << ": " << txt; return retVal;}} while(0)
|
||||
@ -196,7 +199,14 @@ void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObj
|
||||
|
||||
if(obj->ID == Obj::TOWN || obj->ID == Obj::TAVERN)
|
||||
{
|
||||
gs->obtainPlayersStats(thi, gs->players[obj->tempOwner].towns.size());
|
||||
int taverns = 0;
|
||||
for(auto town : gs->players[*player].towns)
|
||||
{
|
||||
if(town->hasBuilt(BuildingID::TAVERN))
|
||||
taverns++;
|
||||
}
|
||||
|
||||
gs->obtainPlayersStats(thi, taverns);
|
||||
}
|
||||
else if(obj->ID == Obj::DEN_OF_THIEVES)
|
||||
{
|
||||
@ -564,9 +574,34 @@ EPlayerStatus::EStatus CGameInfoCallback::getPlayerStatus(PlayerColor player, bo
|
||||
return ps->status;
|
||||
}
|
||||
|
||||
std::string CGameInfoCallback::getTavernGossip(const CGObjectInstance * townOrTavern) const
|
||||
std::string CGameInfoCallback::getTavernRumor(const CGObjectInstance * townOrTavern) const
|
||||
{
|
||||
return "GOSSIP TEST";
|
||||
std::string text = "", extraText = "";
|
||||
if(gs->rumor.type == RumorState::TYPE_NONE) // (version < 755 backward compatability
|
||||
return text;
|
||||
|
||||
auto rumor = gs->rumor.last[gs->rumor.type];
|
||||
switch(gs->rumor.type)
|
||||
{
|
||||
case RumorState::TYPE_SPECIAL:
|
||||
if(rumor.first == RumorState::RUMOR_GRAIL)
|
||||
extraText = VLC->generaltexth->arraytxt[158 + rumor.second];
|
||||
else
|
||||
extraText = VLC->generaltexth->capColors[rumor.second];
|
||||
|
||||
text = boost::str(boost::format(VLC->generaltexth->allTexts[rumor.first]) % extraText);
|
||||
|
||||
break;
|
||||
case RumorState::TYPE_MAP:
|
||||
text = gs->map->rumors[rumor.first].text;
|
||||
break;
|
||||
|
||||
case RumorState::TYPE_RAND:
|
||||
text = VLC->generaltexth->tavernRumors[rumor.first];
|
||||
break;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
PlayerRelations::PlayerRelations CGameInfoCallback::getPlayerRelations( PlayerColor color1, PlayerColor color2 ) const
|
||||
@ -853,7 +888,7 @@ std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::
|
||||
{
|
||||
vstd::erase_if(ids, [&](ObjectInstanceID id) -> bool
|
||||
{
|
||||
auto obj = getObj(id);
|
||||
auto obj = getObj(id, false);
|
||||
return player != PlayerColor::UNFLAGGABLE && (!obj || !isVisible(obj->pos, player));
|
||||
});
|
||||
return ids;
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
int howManyTowns(PlayerColor Player) const;
|
||||
const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
|
||||
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
|
||||
std::string getTavernGossip(const CGObjectInstance * townOrTavern) const;
|
||||
std::string getTavernRumor(const CGObjectInstance * townOrTavern) const;
|
||||
EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||
virtual bool getTownInfo(const CGObjectInstance * town, InfoAboutTown & dest, const CGObjectInstance * selectedObject = nullptr) const;
|
||||
const CTown *getNativeTown(PlayerColor color) const;
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "spells/ViewSpellInt.h"
|
||||
|
||||
#include "mapObjects/CObjectHandler.h"
|
||||
|
||||
/*
|
||||
* CGameInterface.h, part of VCMI engine
|
||||
*
|
||||
@ -94,7 +96,7 @@ public:
|
||||
|
||||
// all stacks operations between these objects become allowed, interface has to call onEnd when done
|
||||
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) = 0;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, std::vector<ObjectInstanceID> exits, bool impassable, QueryID askID) = 0;
|
||||
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) = 0;
|
||||
virtual void finish(){}; //if for some reason we want to end
|
||||
|
||||
virtual void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions){};
|
||||
|
@ -907,7 +907,7 @@ void CGameState::initDuel()
|
||||
|
||||
if(!ss.spells.empty())
|
||||
{
|
||||
h->putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0));
|
||||
h->putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(ArtifactID::SPELLBOOK));
|
||||
boost::copy(ss.spells, std::inserter(h->spells, h->spells.begin()));
|
||||
}
|
||||
|
||||
@ -1383,7 +1383,8 @@ void CGameState::placeStartingHeroes()
|
||||
}
|
||||
|
||||
int heroTypeId = pickNextHeroType(playerColor);
|
||||
if(playerSettingPair.second.hero == -1) playerSettingPair.second.hero = heroTypeId;
|
||||
if(playerSettingPair.second.hero == -1)
|
||||
playerSettingPair.second.hero = heroTypeId;
|
||||
|
||||
placeStartingHero(playerColor, HeroTypeID(heroTypeId), playerInfo.posOfMainTown);
|
||||
}
|
||||
@ -2061,101 +2062,6 @@ PlayerRelations::PlayerRelations CGameState::getPlayerRelations( PlayerColor col
|
||||
return PlayerRelations::ENEMIES;
|
||||
}
|
||||
|
||||
void CGameState::getNeighbours(const TerrainTile &srct, int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand, bool limitCoastSailing)
|
||||
{
|
||||
static const int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
|
||||
int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) };
|
||||
|
||||
//vec.reserve(8); //optimization
|
||||
for (auto & dir : dirs)
|
||||
{
|
||||
const int3 hlp = tile + dir;
|
||||
if(!map->isInTheMap(hlp))
|
||||
continue;
|
||||
|
||||
const TerrainTile &hlpt = map->getTile(hlp);
|
||||
|
||||
// //we cannot visit things from blocked tiles
|
||||
// if(srct.blocked && !srct.visitable && hlpt.visitable && srct.blockingObjects.front()->ID != HEROI_TYPE)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if(srct.terType == ETerrainType::WATER && limitCoastSailing && hlpt.terType == ETerrainType::WATER && dir.x && dir.y) //diagonal move through water
|
||||
{
|
||||
int3 hlp1 = tile,
|
||||
hlp2 = tile;
|
||||
hlp1.x += dir.x;
|
||||
hlp2.y += dir.y;
|
||||
|
||||
if(map->getTile(hlp1).terType != ETerrainType::WATER || map->getTile(hlp2).terType != ETerrainType::WATER)
|
||||
continue;
|
||||
}
|
||||
|
||||
if((indeterminate(onLand) || onLand == (hlpt.terType!=ETerrainType::WATER) )
|
||||
&& hlpt.terType != ETerrainType::ROCK)
|
||||
{
|
||||
vec.push_back(hlp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, int remainingMovePoints, bool checkLast)
|
||||
{
|
||||
if(src == dest) //same tile
|
||||
return 0;
|
||||
|
||||
TerrainTile &s = map->getTile(src),
|
||||
&d = map->getTile(dest);
|
||||
|
||||
//get basic cost
|
||||
int ret = h->getTileCost(d,s);
|
||||
|
||||
if(d.blocked && h->canFly())
|
||||
{
|
||||
ret *= (100.0 + h->valOfBonuses(Bonus::FLYING_MOVEMENT)) / 100.0;
|
||||
}
|
||||
else if(d.terType == ETerrainType::WATER)
|
||||
{
|
||||
if(h->boat && s.hasFavourableWinds() && d.hasFavourableWinds()) //Favourable Winds
|
||||
ret *= 0.666;
|
||||
else if(!h->boat && h->canWalkOnSea())
|
||||
{
|
||||
ret *= (100.0 + h->valOfBonuses(Bonus::WATER_WALKING)) / 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if(src.x != dest.x && src.y != dest.y) //it's diagonal move
|
||||
{
|
||||
int old = ret;
|
||||
ret *= 1.414213;
|
||||
//diagonal move costs too much but normal move is possible - allow diagonal move for remaining move points
|
||||
if(ret > remainingMovePoints && remainingMovePoints >= old)
|
||||
{
|
||||
return remainingMovePoints;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int left = remainingMovePoints-ret;
|
||||
if(checkLast && left > 0 && remainingMovePoints-ret < 250) //it might be the last tile - if no further move possible we take all move points
|
||||
{
|
||||
std::vector<int3> vec;
|
||||
vec.reserve(8); //optimization
|
||||
getNeighbours(d, dest, vec, s.terType != ETerrainType::WATER, true);
|
||||
for(auto & elem : vec)
|
||||
{
|
||||
int fcost = getMovementCost(h, dest, elem, left, false);
|
||||
if(fcost <= left)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = remainingMovePoints;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CGameState::apply(CPack *pack)
|
||||
{
|
||||
ui16 typ = typeList.getTypeID(pack);
|
||||
@ -2228,6 +2134,76 @@ int3 CGameState::guardingCreaturePosition (int3 pos) const
|
||||
return gs->map->guardingCreaturePositions[pos.x][pos.y][pos.z];
|
||||
}
|
||||
|
||||
void CGameState::updateRumor()
|
||||
{
|
||||
static std::vector<RumorState::ERumorType> rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND};
|
||||
std::vector<RumorState::ERumorTypeSpecial> sRumorTypes = {
|
||||
RumorState::RUMOR_OBELISKS, RumorState::RUMOR_ARTIFACTS, RumorState::RUMOR_ARMY, RumorState::RUMOR_INCOME};
|
||||
if(map->grailPos.valid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce
|
||||
sRumorTypes.push_back(RumorState::RUMOR_GRAIL);
|
||||
|
||||
int rumorId = -1, rumorExtra = -1;
|
||||
auto & rand = getRandomGenerator();
|
||||
rumor.type = *RandomGeneratorUtil::nextItem(rumorTypes, rand);
|
||||
if(!map->rumors.size() && rumor.type == RumorState::TYPE_MAP)
|
||||
rumor.type = RumorState::TYPE_RAND;
|
||||
|
||||
do
|
||||
{
|
||||
switch(rumor.type)
|
||||
{
|
||||
case RumorState::TYPE_SPECIAL:
|
||||
{
|
||||
SThievesGuildInfo tgi;
|
||||
obtainPlayersStats(tgi, 20);
|
||||
rumorId = *RandomGeneratorUtil::nextItem(sRumorTypes, rand);
|
||||
if(rumorId == RumorState::RUMOR_GRAIL)
|
||||
{
|
||||
rumorExtra = getTile(map->grailPos)->terType;
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<PlayerColor> players = {};
|
||||
switch(rumorId)
|
||||
{
|
||||
case RumorState::RUMOR_OBELISKS:
|
||||
players = tgi.obelisks[0];
|
||||
break;
|
||||
|
||||
case RumorState::RUMOR_ARTIFACTS:
|
||||
players = tgi.artifacts[0];
|
||||
break;
|
||||
|
||||
case RumorState::RUMOR_ARMY:
|
||||
players = tgi.army[0];
|
||||
break;
|
||||
|
||||
case RumorState::RUMOR_INCOME:
|
||||
players = tgi.income[0];
|
||||
break;
|
||||
}
|
||||
rumorExtra = RandomGeneratorUtil::nextItem(players, rand)->getNum();
|
||||
|
||||
break;
|
||||
}
|
||||
case RumorState::TYPE_MAP:
|
||||
rumorId = rand.nextInt(map->rumors.size() - 1);
|
||||
|
||||
break;
|
||||
|
||||
case RumorState::TYPE_RAND:
|
||||
do
|
||||
{
|
||||
rumorId = rand.nextInt(VLC->generaltexth->tavernRumors.size() - 1);
|
||||
}
|
||||
while(!VLC->generaltexth->tavernRumors[rumorId].length());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!rumor.update(rumorId, rumorExtra));
|
||||
}
|
||||
|
||||
bool CGameState::isVisible(int3 pos, PlayerColor player)
|
||||
{
|
||||
if(player == PlayerColor::NEUTRAL)
|
||||
@ -2549,6 +2525,58 @@ struct statsHLP
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// get total gold income
|
||||
static int getIncome(const PlayerState * ps)
|
||||
{
|
||||
int totalIncome = 0;
|
||||
const CGObjectInstance * heroOrTown = nullptr;
|
||||
|
||||
//Heroes can produce gold as well - skill, specialty or arts
|
||||
for(auto & h : ps->heroes)
|
||||
{
|
||||
totalIncome += h->valOfBonuses(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::ESTATES));
|
||||
totalIncome += h->valOfBonuses(Selector::typeSubtype(Bonus::GENERATE_RESOURCE, Res::GOLD));
|
||||
|
||||
if(!heroOrTown)
|
||||
heroOrTown = h;
|
||||
}
|
||||
|
||||
//Add town income of all towns
|
||||
for(auto & t : ps->towns)
|
||||
{
|
||||
totalIncome += t->dailyIncome()[Res::GOLD];
|
||||
|
||||
if(!heroOrTown)
|
||||
heroOrTown = t;
|
||||
}
|
||||
|
||||
/// FIXME: Dirty dirty hack
|
||||
/// Stats helper need some access to gamestate.
|
||||
std::vector<const CGObjectInstance *> ownedObjects;
|
||||
for(const CGObjectInstance * obj : heroOrTown->cb->gameState()->map->objects)
|
||||
{
|
||||
if(obj && obj->tempOwner == ps->color)
|
||||
ownedObjects.push_back(obj);
|
||||
}
|
||||
/// This is code from CPlayerSpecificInfoCallback::getMyObjects
|
||||
/// I'm really need to find out about callback interface design...
|
||||
|
||||
for(auto object : ownedObjects)
|
||||
{
|
||||
//Mines
|
||||
if ( object->ID == Obj::MINE )
|
||||
{
|
||||
const CGMine *mine = dynamic_cast<const CGMine*>(object);
|
||||
assert(mine);
|
||||
|
||||
if (mine->producedResource == Res::GOLD)
|
||||
totalIncome += mine->producedQuantity;
|
||||
}
|
||||
}
|
||||
|
||||
return totalIncome;
|
||||
}
|
||||
};
|
||||
|
||||
void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
|
||||
@ -2579,20 +2607,22 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
|
||||
tgi.playerColors.push_back(elem.second.color);
|
||||
}
|
||||
|
||||
if(level >= 1) //num of towns & num of heroes
|
||||
if(level >= 0) //num of towns & num of heroes
|
||||
{
|
||||
//num of towns
|
||||
FILL_FIELD(numOfTowns, g->second.towns.size())
|
||||
//num of heroes
|
||||
FILL_FIELD(numOfHeroes, g->second.heroes.size())
|
||||
//best hero's portrait
|
||||
}
|
||||
if(level >= 1) //best hero's portrait
|
||||
{
|
||||
for(auto g = players.cbegin(); g != players.cend(); ++g)
|
||||
{
|
||||
if(playerInactive(g->second.color))
|
||||
continue;
|
||||
const CGHeroInstance * best = statsHLP::findBestHero(this, g->second.color);
|
||||
InfoAboutHero iah;
|
||||
iah.initFromHero(best, level >= 8);
|
||||
iah.initFromHero(best, level >= 2);
|
||||
iah.army.clear();
|
||||
tgi.colorToBestHero[g->second.color] = iah;
|
||||
}
|
||||
@ -2609,27 +2639,27 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
|
||||
{
|
||||
FILL_FIELD(mercSulfCrystGems, g->second.resources[Res::MERCURY] + g->second.resources[Res::SULFUR] + g->second.resources[Res::CRYSTAL] + g->second.resources[Res::GEMS])
|
||||
}
|
||||
if(level >= 4) //obelisks found
|
||||
if(level >= 3) //obelisks found
|
||||
{
|
||||
FILL_FIELD(obelisks, CGObelisk::visited[gs->getPlayerTeam(g->second.color)->id])
|
||||
}
|
||||
if(level >= 5) //artifacts
|
||||
if(level >= 4) //artifacts
|
||||
{
|
||||
FILL_FIELD(artifacts, statsHLP::getNumberOfArts(&g->second))
|
||||
}
|
||||
if(level >= 6) //army strength
|
||||
if(level >= 4) //army strength
|
||||
{
|
||||
FILL_FIELD(army, statsHLP::getArmyStrength(&g->second))
|
||||
}
|
||||
if(level >= 7) //income
|
||||
if(level >= 5) //income
|
||||
{
|
||||
//TODO:obtainPlayersStats - income
|
||||
FILL_FIELD(income, statsHLP::getIncome(&g->second))
|
||||
}
|
||||
if(level >= 8) //best hero's stats
|
||||
if(level >= 2) //best hero's stats
|
||||
{
|
||||
//already set in lvl 1 handling
|
||||
}
|
||||
if(level >= 9) //personality
|
||||
if(level >= 3) //personality
|
||||
{
|
||||
for(auto g = players.cbegin(); g != players.cend(); ++g)
|
||||
{
|
||||
@ -2646,7 +2676,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
|
||||
|
||||
}
|
||||
}
|
||||
if(level >= 10) //best creature
|
||||
if(level >= 4) //best creature
|
||||
{
|
||||
//best creatures belonging to player (highest AI value)
|
||||
for(auto g = players.cbegin(); g != players.cend(); ++g)
|
||||
@ -2865,7 +2895,7 @@ CGHeroInstance * CGameState::getUsedHero(HeroTypeID hid) const
|
||||
{
|
||||
for(auto hero : map->heroesOnMap) //heroes instances initialization
|
||||
{
|
||||
if(hero->subID == hid.getNum())
|
||||
if(hero->type && hero->type->ID == hid)
|
||||
{
|
||||
return hero;
|
||||
}
|
||||
@ -2873,9 +2903,12 @@ CGHeroInstance * CGameState::getUsedHero(HeroTypeID hid) const
|
||||
|
||||
for(auto obj : map->objects) //prisons
|
||||
{
|
||||
if(obj && obj->ID == Obj::PRISON && obj->subID == hid.getNum())
|
||||
if(obj && obj->ID == Obj::PRISON )
|
||||
{
|
||||
return dynamic_cast<CGHeroInstance *>(obj.get());
|
||||
auto hero = dynamic_cast<CGHeroInstance *>(obj.get());
|
||||
assert(hero);
|
||||
if ( hero->type && hero->type->ID == hid )
|
||||
return hero;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2894,6 +2927,25 @@ std::string PlayerState::nodeName() const
|
||||
return "Player " + (color.getNum() < VLC->generaltexth->capColors.size() ? VLC->generaltexth->capColors[color.getNum()] : boost::lexical_cast<std::string>(color));
|
||||
}
|
||||
|
||||
|
||||
bool RumorState::update(int id, int extra)
|
||||
{
|
||||
if(vstd::contains(last, type))
|
||||
{
|
||||
if(last[type].first != id)
|
||||
{
|
||||
last[type].first = id;
|
||||
last[type].second = extra;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
last[type] = std::make_pair(id, extra);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
InfoAboutArmy::InfoAboutArmy():
|
||||
owner(PlayerColor::NEUTRAL)
|
||||
{}
|
||||
|
149
lib/CGameState.h
149
lib/CGameState.h
@ -1,12 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
//#ifndef _MSC_VER
|
||||
#include "CCreatureHandler.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "mapping/CMap.h"
|
||||
//#endif
|
||||
|
||||
#include "HeroBonus.h"
|
||||
#include "CCreatureSet.h"
|
||||
@ -67,79 +62,6 @@ namespace boost
|
||||
class shared_mutex;
|
||||
}
|
||||
|
||||
//numbers of creatures are exact numbers if detailed else they are quantity ids (1 - a few, 2 - several and so on; additionally 0 - unknown)
|
||||
struct ArmyDescriptor : public std::map<SlotID, CStackBasicDescriptor>
|
||||
{
|
||||
bool isDetailed;
|
||||
DLL_LINKAGE ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count
|
||||
DLL_LINKAGE ArmyDescriptor();
|
||||
|
||||
DLL_LINKAGE int getStrength() const;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE InfoAboutArmy
|
||||
{
|
||||
PlayerColor owner;
|
||||
std::string name;
|
||||
|
||||
ArmyDescriptor army;
|
||||
|
||||
InfoAboutArmy();
|
||||
InfoAboutArmy(const CArmedInstance *Army, bool detailed);
|
||||
|
||||
void initFromArmy(const CArmedInstance *Army, bool detailed);
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE InfoAboutHero : public InfoAboutArmy
|
||||
{
|
||||
private:
|
||||
void assign(const InfoAboutHero & iah);
|
||||
public:
|
||||
struct DLL_LINKAGE Details
|
||||
{
|
||||
std::vector<si32> primskills;
|
||||
si32 mana, luck, morale;
|
||||
} *details;
|
||||
|
||||
const CHeroClass *hclass;
|
||||
int portrait;
|
||||
|
||||
InfoAboutHero();
|
||||
InfoAboutHero(const InfoAboutHero & iah);
|
||||
InfoAboutHero(const CGHeroInstance *h, bool detailed);
|
||||
~InfoAboutHero();
|
||||
|
||||
InfoAboutHero & operator=(const InfoAboutHero & iah);
|
||||
|
||||
void initFromHero(const CGHeroInstance *h, bool detailed);
|
||||
};
|
||||
|
||||
/// Struct which holds a int information about a town
|
||||
struct DLL_LINKAGE InfoAboutTown : public InfoAboutArmy
|
||||
{
|
||||
struct DLL_LINKAGE Details
|
||||
{
|
||||
si32 hallLevel, goldIncome;
|
||||
bool customRes;
|
||||
bool garrisonedHero;
|
||||
|
||||
} *details;
|
||||
|
||||
const CTown *tType;
|
||||
|
||||
si32 built;
|
||||
si32 fortLevel; //0 - none
|
||||
|
||||
InfoAboutTown();
|
||||
InfoAboutTown(const CGTownInstance *t, bool detailed);
|
||||
~InfoAboutTown();
|
||||
void initFromTown(const CGTownInstance *t, bool detailed);
|
||||
};
|
||||
|
||||
// typedef si32 TResourceUnit;
|
||||
// typedef std::vector<si32> TResourceVector;
|
||||
// typedef std::set<si32> TResourceSet;
|
||||
|
||||
struct DLL_LINKAGE SThievesGuildInfo
|
||||
{
|
||||
std::vector<PlayerColor> playerColors; //colors of players that are in-game
|
||||
@ -159,55 +81,34 @@ struct DLL_LINKAGE SThievesGuildInfo
|
||||
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE PlayerState : public CBonusSystemNode
|
||||
struct DLL_LINKAGE RumorState
|
||||
{
|
||||
public:
|
||||
PlayerColor color;
|
||||
bool human; //true if human controlled player, false for AI
|
||||
TeamID team;
|
||||
TResources resources;
|
||||
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
|
||||
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns
|
||||
std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth
|
||||
std::vector<QuestInfo> quests; //store info about all received quests
|
||||
enum ERumorType : ui8
|
||||
{
|
||||
TYPE_NONE = 0, TYPE_RAND, TYPE_SPECIAL, TYPE_MAP
|
||||
};
|
||||
|
||||
bool enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory
|
||||
EPlayerStatus::EStatus status;
|
||||
boost::optional<ui8> daysWithoutCastle;
|
||||
enum ERumorTypeSpecial : ui8
|
||||
{
|
||||
RUMOR_OBELISKS = 208,
|
||||
RUMOR_ARTIFACTS = 209,
|
||||
RUMOR_ARMY = 210,
|
||||
RUMOR_INCOME = 211,
|
||||
RUMOR_GRAIL = 212
|
||||
};
|
||||
|
||||
PlayerState();
|
||||
std::string nodeName() const override;
|
||||
ERumorType type;
|
||||
std::map<ERumorType, std::pair<int, int>> last;
|
||||
|
||||
RumorState(){type = TYPE_NONE; last = {};};
|
||||
bool update(int id, int extra);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & color & human & team & resources & status;
|
||||
h & heroes & towns & availableHeroes & dwellings & quests & visitedObjects;
|
||||
h & getBonusList(); //FIXME FIXME FIXME
|
||||
h & status & daysWithoutCastle;
|
||||
h & enteredLosingCheatCode & enteredWinningCheatCode;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
h & type & last;
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE TeamState : public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
TeamID id; //position in gameState::teams
|
||||
std::set<PlayerColor> players; // members of this team
|
||||
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
|
||||
|
||||
TeamState();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & id & players & fogOfWarMap;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct UpgradeInfo
|
||||
{
|
||||
CreatureID oldID; //creature to be upgraded
|
||||
@ -276,7 +177,6 @@ struct DLL_EXPORT DuelParameters
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct BattleInfo;
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EVictoryLossCheckResult & victoryLossCheckResult);
|
||||
@ -311,6 +211,7 @@ public:
|
||||
std::map<PlayerColor, PlayerState> players;
|
||||
std::map<TeamID, TeamState> teams;
|
||||
CBonusSystemNode globalEffects;
|
||||
RumorState rumor;
|
||||
|
||||
boost::shared_mutex *mx;
|
||||
|
||||
@ -324,6 +225,7 @@ public:
|
||||
void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out); //calculates possible paths for hero, by default uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
|
||||
int3 guardingCreaturePosition (int3 pos) const;
|
||||
std::vector<CGObjectInstance*> guardingCreatures (int3 pos) const;
|
||||
void updateRumor();
|
||||
|
||||
// ----- victory, loss condition checks -----
|
||||
|
||||
@ -339,8 +241,6 @@ public:
|
||||
bool isVisible(int3 pos, PlayerColor player);
|
||||
bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> player);
|
||||
|
||||
void getNeighbours(const TerrainTile &srct, int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand, bool limitCoastSailing);
|
||||
int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, int remainingMovePoints=-1, bool checkLast=true);
|
||||
int getDate(Date::EDateType mode=Date::DAY) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
|
||||
|
||||
// ----- getters, setters -----
|
||||
@ -349,6 +249,13 @@ 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)
|
||||
{
|
||||
h & rumor;
|
||||
}
|
||||
else if(!h.saving)
|
||||
rumor = RumorState();
|
||||
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,81 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CCreatureSet.h"
|
||||
|
||||
class CQuest;
|
||||
class CGObjectInstance;
|
||||
class CHeroClass;
|
||||
class CTown;
|
||||
|
||||
//numbers of creatures are exact numbers if detailed else they are quantity ids (1 - a few, 2 - several and so on; additionally 0 - unknown)
|
||||
struct ArmyDescriptor : public std::map<SlotID, CStackBasicDescriptor>
|
||||
{
|
||||
bool isDetailed;
|
||||
DLL_LINKAGE ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count
|
||||
DLL_LINKAGE ArmyDescriptor();
|
||||
|
||||
DLL_LINKAGE int getStrength() const;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE InfoAboutArmy
|
||||
{
|
||||
PlayerColor owner;
|
||||
std::string name;
|
||||
|
||||
ArmyDescriptor army;
|
||||
|
||||
InfoAboutArmy();
|
||||
InfoAboutArmy(const CArmedInstance *Army, bool detailed);
|
||||
|
||||
void initFromArmy(const CArmedInstance *Army, bool detailed);
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE InfoAboutHero : public InfoAboutArmy
|
||||
{
|
||||
private:
|
||||
void assign(const InfoAboutHero & iah);
|
||||
public:
|
||||
struct DLL_LINKAGE Details
|
||||
{
|
||||
std::vector<si32> primskills;
|
||||
si32 mana, luck, morale;
|
||||
} *details;
|
||||
|
||||
const CHeroClass *hclass;
|
||||
int portrait;
|
||||
|
||||
InfoAboutHero();
|
||||
InfoAboutHero(const InfoAboutHero & iah);
|
||||
InfoAboutHero(const CGHeroInstance *h, bool detailed);
|
||||
~InfoAboutHero();
|
||||
|
||||
InfoAboutHero & operator=(const InfoAboutHero & iah);
|
||||
|
||||
void initFromHero(const CGHeroInstance *h, bool detailed);
|
||||
};
|
||||
|
||||
/// Struct which holds a int information about a town
|
||||
struct DLL_LINKAGE InfoAboutTown : public InfoAboutArmy
|
||||
{
|
||||
struct DLL_LINKAGE Details
|
||||
{
|
||||
si32 hallLevel, goldIncome;
|
||||
bool customRes;
|
||||
bool garrisonedHero;
|
||||
|
||||
} *details;
|
||||
|
||||
const CTown *tType;
|
||||
|
||||
si32 built;
|
||||
si32 fortLevel; //0 - none
|
||||
|
||||
InfoAboutTown();
|
||||
InfoAboutTown(const CGTownInstance *t, bool detailed);
|
||||
~InfoAboutTown();
|
||||
void initFromTown(const CGTownInstance *t, bool detailed);
|
||||
};
|
||||
|
||||
class DLL_LINKAGE EVictoryLossCheckResult
|
||||
{
|
||||
|
@ -327,6 +327,7 @@ CGeneralTextHandler::CGeneralTextHandler()
|
||||
readToVector("DATA/PRISKILL.TXT", primarySkillNames);
|
||||
readToVector("DATA/JKTEXT.TXT", jktexts);
|
||||
readToVector("DATA/TVRNINFO.TXT", tavernInfo);
|
||||
readToVector("DATA/RANDTVRN.TXT", tavernRumors);
|
||||
readToVector("DATA/TURNDUR.TXT", turnDurations);
|
||||
readToVector("DATA/HEROSCRN.TXT", heroscrn);
|
||||
readToVector("DATA/TENTCOLR.TXT", tentColors);
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
//towns
|
||||
std::vector<std::string> tcommands, hcommands, fcommands; //texts for town screen, town hall screen and fort screen
|
||||
std::vector<std::string> tavernInfo;
|
||||
std::vector<std::string> tavernRumors;
|
||||
|
||||
std::vector<std::pair<std::string,std::string> > zelp;
|
||||
std::vector<std::string> lossCondtions;
|
||||
|
@ -117,6 +117,7 @@ set(lib_HEADERS
|
||||
filesystem/ISimpleResourceLoader.h
|
||||
|
||||
mapObjects/MapObjects.h
|
||||
mapping/CMapDefines.h
|
||||
|
||||
CSoundBase.h
|
||||
AI_Base.h
|
||||
@ -131,6 +132,7 @@ set(lib_HEADERS
|
||||
IGameEventsReceiver.h
|
||||
int3.h
|
||||
CGameStateFwd.h
|
||||
CPlayerState.h
|
||||
Interprocess.h
|
||||
NetPacks.h
|
||||
NetPacksBase.h
|
||||
|
@ -467,7 +467,7 @@ static JsonNode loadModSettings(std::string path)
|
||||
JsonNode addMeta(JsonNode config, std::string meta)
|
||||
{
|
||||
config.setMeta(meta);
|
||||
return std::move(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
CModInfo::CModInfo(std::string identifier,const JsonNode & local, const JsonNode & config):
|
||||
|
1124
lib/CPathfinder.cpp
1124
lib/CPathfinder.cpp
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "VCMI_Lib.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "IGameCallback.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "int3.h"
|
||||
|
||||
#include <boost/heap/priority_queue.hpp>
|
||||
|
||||
/*
|
||||
* CPathfinder.h, part of VCMI engine
|
||||
*
|
||||
@ -18,26 +20,47 @@
|
||||
class CGHeroInstance;
|
||||
class CGObjectInstance;
|
||||
struct TerrainTile;
|
||||
class CPathfinderHelper;
|
||||
class CMap;
|
||||
class CGWhirlpool;
|
||||
|
||||
struct DLL_LINKAGE CGPathNode
|
||||
{
|
||||
enum EAccessibility
|
||||
typedef EPathfindingLayer ELayer;
|
||||
|
||||
enum ENodeAction : ui8
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
EMBARK = 1,
|
||||
DISEMBARK,
|
||||
NORMAL,
|
||||
BATTLE,
|
||||
VISIT,
|
||||
BLOCKING_VISIT
|
||||
};
|
||||
|
||||
enum EAccessibility : ui8
|
||||
{
|
||||
NOT_SET = 0,
|
||||
ACCESSIBLE = 1, //tile can be entered and passed
|
||||
VISITABLE, //tile can be entered as the last tile in path
|
||||
BLOCKVIS, //visitable from neighbouring tile but not passable
|
||||
FLYABLE, //can only be accessed in air layer
|
||||
BLOCKED //tile can't be entered nor visited
|
||||
};
|
||||
|
||||
EAccessibility accessible;
|
||||
ui8 land;
|
||||
ui8 turns; //how many turns we have to wait before reachng the tile - 0 means current turn
|
||||
ui32 moveRemains; //remaining tiles after hero reaches the tile
|
||||
CGPathNode * theNodeBefore;
|
||||
int3 coord; //coordinates
|
||||
ui32 moveRemains; //remaining tiles after hero reaches the tile
|
||||
ui8 turns; //how many turns we have to wait before reachng the tile - 0 means current turn
|
||||
ELayer layer;
|
||||
EAccessibility accessible;
|
||||
ENodeAction action;
|
||||
bool locked;
|
||||
|
||||
CGPathNode();
|
||||
void reset();
|
||||
void update(const int3 & Coord, const ELayer Layer, const EAccessibility Accessible);
|
||||
bool reachable() const;
|
||||
};
|
||||
|
||||
@ -52,27 +75,36 @@ struct DLL_LINKAGE CGPath
|
||||
|
||||
struct DLL_LINKAGE CPathsInfo
|
||||
{
|
||||
typedef EPathfindingLayer ELayer;
|
||||
|
||||
mutable boost::mutex pathMx;
|
||||
|
||||
const CGHeroInstance *hero;
|
||||
const CGHeroInstance * hero;
|
||||
int3 hpos;
|
||||
int3 sizes;
|
||||
CGPathNode ***nodes; //[w][h][level]
|
||||
boost::multi_array<CGPathNode, 4> nodes; //[w][h][level][layer]
|
||||
|
||||
CPathsInfo(const int3 &Sizes);
|
||||
CPathsInfo(const int3 & Sizes);
|
||||
~CPathsInfo();
|
||||
const CGPathNode * getPathInfo(const int3& tile) const;
|
||||
bool getPath(const int3 &dst, CGPath &out) const;
|
||||
int getDistance( int3 tile ) const;
|
||||
const CGPathNode * getPathInfo(const int3 & tile) const;
|
||||
bool getPath(CGPath & out, const int3 & dst) const;
|
||||
int getDistance(const int3 & tile) const;
|
||||
const CGPathNode * getNode(const int3 & coord) const;
|
||||
|
||||
CGPathNode * getNode(const int3 & coord, const ELayer layer);
|
||||
};
|
||||
|
||||
class CPathfinder : private CGameInfoCallback
|
||||
{
|
||||
public:
|
||||
CPathfinder(CPathsInfo &_out, CGameState *_gs, const CGHeroInstance *_hero);
|
||||
friend class CPathfinderHelper;
|
||||
|
||||
CPathfinder(CPathsInfo & _out, CGameState * _gs, const CGHeroInstance * _hero);
|
||||
void calculatePaths(); //calculates possible paths for hero, uses current hero position and movement left; returns pointer to newly allocated CPath or nullptr if path does not exists
|
||||
|
||||
private:
|
||||
typedef EPathfindingLayer ELayer;
|
||||
|
||||
struct PathfinderOptions
|
||||
{
|
||||
bool useFlying;
|
||||
@ -83,42 +115,164 @@ private:
|
||||
bool useTeleportOneWayRandom; // One-way monoliths with more than one known exit
|
||||
bool useTeleportWhirlpool; // Force enabled if hero protected or unaffected (have one stack of one creature)
|
||||
|
||||
/// TODO: Find out with client and server code, merge with normal teleporters.
|
||||
/// Likely proper implementation would require some refactoring of CGTeleport.
|
||||
/// So for now this is unfinished and disabled by default.
|
||||
bool useCastleGate;
|
||||
|
||||
/// If true transition into air layer only possible from initial node.
|
||||
/// This is drastically decrease path calculation complexity (and time).
|
||||
/// Downside is less MP effective paths calculation.
|
||||
///
|
||||
/// TODO: If this option end up useful for slow devices it's can be improved:
|
||||
/// - Allow transition into air layer not only from initial position, but also from teleporters.
|
||||
/// Movement into air can be also allowed when hero disembarked.
|
||||
/// - Other idea is to allow transition into air within certain radius of N tiles around hero.
|
||||
/// Patrol support need similar functionality so it's won't be ton of useless code.
|
||||
/// Such limitation could be useful as it's can be scaled depend on device performance.
|
||||
bool lightweightFlyingMode;
|
||||
|
||||
/// This option enable one turn limitation for flying and water walking.
|
||||
/// So if we're out of MP while cp is blocked or water tile we won't add dest tile to queue.
|
||||
///
|
||||
/// Following imitation is default H3 mechanics, but someone may want to disable it in mods.
|
||||
/// After all this limit should benefit performance on maps with tons of water or blocked tiles.
|
||||
///
|
||||
/// TODO:
|
||||
/// - Behavior when option is disabled not implemented and will lead to crashes.
|
||||
bool oneTurnSpecialLayersLimit;
|
||||
|
||||
/// VCMI have different movement rules to solve flaws original engine has.
|
||||
/// If this option enabled you'll able to do following things in fly:
|
||||
/// - Move from blocked tiles to visitable one
|
||||
/// - Move from guarded tiles to blockvis tiles without being attacked
|
||||
/// - Move from guarded tiles to guarded visitable tiles with being attacked after
|
||||
/// TODO:
|
||||
/// - Option should also allow same tile land <-> air layer transitions.
|
||||
/// Current implementation only allow go into (from) air layer only to neighbour tiles.
|
||||
/// I find it's reasonable limitation, but it's will make some movements more expensive than in H3.
|
||||
bool originalMovementRules;
|
||||
|
||||
PathfinderOptions();
|
||||
} options;
|
||||
|
||||
CPathsInfo &out;
|
||||
const CGHeroInstance *hero;
|
||||
CPathsInfo & out;
|
||||
const CGHeroInstance * hero;
|
||||
const std::vector<std::vector<std::vector<ui8> > > &FoW;
|
||||
unique_ptr<CPathfinderHelper> hlp;
|
||||
|
||||
std::list<CGPathNode*> mq; //BFS queue -> nodes to be checked
|
||||
enum EPatrolState {
|
||||
PATROL_NONE = 0,
|
||||
PATROL_LOCKED = 1,
|
||||
PATROL_RADIUS
|
||||
} patrolState;
|
||||
std::unordered_set<int3, ShashInt3> patrolTiles;
|
||||
|
||||
struct NodeComparer
|
||||
{
|
||||
bool operator()(const CGPathNode * lhs, const CGPathNode * rhs) const
|
||||
{
|
||||
if(rhs->turns > lhs->turns)
|
||||
return false;
|
||||
else if(rhs->turns == lhs->turns && rhs->moveRemains < lhs->moveRemains)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
boost::heap::priority_queue<CGPathNode *, boost::heap::compare<NodeComparer> > pq;
|
||||
|
||||
std::vector<int3> neighbourTiles;
|
||||
std::vector<int3> neighbours;
|
||||
|
||||
CGPathNode *cp; //current (source) path node -> we took it from the queue
|
||||
CGPathNode *dp; //destination node -> it's a neighbour of cp that we consider
|
||||
const TerrainTile *ct, *dt; //tile info for both nodes
|
||||
const CGObjectInstance *sTileObj;
|
||||
ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark
|
||||
CGPathNode * cp; //current (source) path node -> we took it from the queue
|
||||
CGPathNode * dp; //destination node -> it's a neighbour of cp that we consider
|
||||
const TerrainTile * ct, * dt; //tile info for both nodes
|
||||
const CGObjectInstance * ctObj, * dtObj;
|
||||
CGPathNode::ENodeAction destAction;
|
||||
|
||||
void addNeighbours(const int3 &coord);
|
||||
void addTeleportExits(bool noTeleportExcludes = false);
|
||||
void addNeighbours();
|
||||
void addTeleportExits();
|
||||
|
||||
bool isMovementPossible(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost
|
||||
bool checkDestinationTile();
|
||||
bool isHeroPatrolLocked() const;
|
||||
bool isPatrolMovementAllowed(const int3 & dst) const;
|
||||
|
||||
int3 getSourceGuardPosition();
|
||||
bool isSourceGuarded();
|
||||
bool isDestinationGuarded();
|
||||
bool isDestinationGuardian();
|
||||
bool isLayerTransitionPossible(const ELayer dstLayer) const;
|
||||
bool isLayerTransitionPossible() const;
|
||||
bool isMovementToDestPossible() const;
|
||||
bool isMovementAfterDestPossible() const;
|
||||
CGPathNode::ENodeAction getDestAction() const;
|
||||
|
||||
bool isSourceInitialPosition() const;
|
||||
bool isSourceVisitableObj() const;
|
||||
bool isSourceGuarded() const;
|
||||
bool isDestVisitableObj() const;
|
||||
bool isDestinationGuarded(const bool ignoreAccessibility = true) const;
|
||||
bool isDestinationGuardian() const;
|
||||
|
||||
void initializePatrol();
|
||||
void initializeGraph();
|
||||
|
||||
CGPathNode *getNode(const int3 &coord);
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 &pos, const TerrainTile *tinfo) const;
|
||||
bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) const;
|
||||
bool isVisitableObj(const CGObjectInstance * obj, const ELayer layer) const;
|
||||
bool canSeeObj(const CGObjectInstance * obj) const;
|
||||
bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
||||
|
||||
bool isAllowedTeleportEntrance(const CGTeleport * obj) const;
|
||||
bool addTeleportTwoWay(const CGTeleport * obj) const;
|
||||
bool addTeleportOneWay(const CGTeleport * obj) const;
|
||||
bool addTeleportOneWayRandom(const CGTeleport * obj) const;
|
||||
bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
|
||||
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE TurnInfo
|
||||
{
|
||||
/// This is certainly not the best design ever and certainly can be improved
|
||||
/// Unfortunately for pathfinder that do hundreds of thousands calls onus system add too big overhead
|
||||
struct BonusCache {
|
||||
std::vector<bool> noTerrainPenalty;
|
||||
bool freeShipBoarding;
|
||||
bool flyingMovement;
|
||||
int flyingMovementVal;
|
||||
bool waterWalking;
|
||||
int waterWalkingVal;
|
||||
|
||||
BonusCache(TBonusListPtr bonusList);
|
||||
};
|
||||
unique_ptr<BonusCache> bonusCache;
|
||||
|
||||
const CGHeroInstance * hero;
|
||||
TBonusListPtr bonuses;
|
||||
mutable int maxMovePointsLand;
|
||||
mutable int maxMovePointsWater;
|
||||
int nativeTerrain;
|
||||
|
||||
TurnInfo(const CGHeroInstance * Hero, const int Turn = 0);
|
||||
bool isLayerAvailable(const EPathfindingLayer layer) const;
|
||||
bool hasBonusOfType(const Bonus::BonusType type, const int subtype = -1) const;
|
||||
int valOfBonuses(const Bonus::BonusType type, const int subtype = -1) const;
|
||||
int getMaxMovePoints(const EPathfindingLayer layer) const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CPathfinderHelper
|
||||
{
|
||||
public:
|
||||
CPathfinderHelper(const CGHeroInstance * Hero, const CPathfinder::PathfinderOptions & Options);
|
||||
void updateTurnInfo(const int turn = 0);
|
||||
bool isLayerAvailable(const EPathfindingLayer layer) const;
|
||||
const TurnInfo * getTurnInfo() const;
|
||||
bool hasBonusOfType(const Bonus::BonusType type, const int subtype = -1) const;
|
||||
int getMaxMovePoints(const EPathfindingLayer layer) const;
|
||||
|
||||
static void getNeighbours(const CMap * map, const TerrainTile & srct, const int3 & tile, std::vector<int3> & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing);
|
||||
|
||||
static int getMovementCost(const CGHeroInstance * h, const int3 & src, const int3 & dst, const TerrainTile * ct, const TerrainTile * dt, const int remainingMovePoints =- 1, const TurnInfo * ti = nullptr, const bool checkLast = true);
|
||||
static int getMovementCost(const CGHeroInstance * h, const int3 & dst);
|
||||
|
||||
private:
|
||||
int turn;
|
||||
const CGHeroInstance * hero;
|
||||
std::vector<TurnInfo *> turnsInfo;
|
||||
const CPathfinder::PathfinderOptions & options;
|
||||
};
|
||||
|
66
lib/CPlayerState.h
Normal file
66
lib/CPlayerState.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* CPlayerState.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "HeroBonus.h"
|
||||
|
||||
class CGHeroInstance;
|
||||
class CGTownInstance;
|
||||
class CGDwelling;
|
||||
|
||||
struct DLL_LINKAGE PlayerState : public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
PlayerColor color;
|
||||
bool human; //true if human controlled player, false for AI
|
||||
TeamID team;
|
||||
TResources resources;
|
||||
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
|
||||
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
|
||||
std::vector<ConstTransitivePtr<CGHeroInstance> > availableHeroes; //heroes available in taverns
|
||||
std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth
|
||||
std::vector<QuestInfo> quests; //store info about all received quests
|
||||
|
||||
bool enteredWinningCheatCode, enteredLosingCheatCode; //if true, this player has entered cheat codes for loss / victory
|
||||
EPlayerStatus::EStatus status;
|
||||
boost::optional<ui8> daysWithoutCastle;
|
||||
|
||||
PlayerState();
|
||||
std::string nodeName() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & color & human & team & resources & status;
|
||||
h & heroes & towns & availableHeroes & dwellings & quests & visitedObjects;
|
||||
h & getBonusList(); //FIXME FIXME FIXME
|
||||
h & status & daysWithoutCastle;
|
||||
h & enteredLosingCheatCode & enteredWinningCheatCode;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE TeamState : public CBonusSystemNode
|
||||
{
|
||||
public:
|
||||
TeamID id; //position in gameState::teams
|
||||
std::set<PlayerColor> players; // members of this team
|
||||
std::vector<std::vector<std::vector<ui8> > > fogOfWarMap; //true - visible, false - hidden
|
||||
|
||||
TeamState();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & id & players & fogOfWarMap;
|
||||
h & static_cast<CBonusSystemNode&>(*this);
|
||||
}
|
||||
|
||||
};
|
@ -774,12 +774,8 @@ std::set<TFaction> CTownHandler::getAllowedFactions(bool withTown /*=true*/) con
|
||||
if (withTown)
|
||||
allowed = getDefaultAllowed();
|
||||
else
|
||||
{
|
||||
for (auto town : factions)
|
||||
{
|
||||
allowed.push_back (true);
|
||||
}
|
||||
}
|
||||
allowed.resize( factions.size(), true);
|
||||
|
||||
for (size_t i=0; i<allowed.size(); i++)
|
||||
if (allowed[i])
|
||||
allowedFactions.insert(i);
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "Connection.h"
|
||||
|
||||
#include "registerTypes/RegisterTypes.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "CGameState.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <typeinfo> //XXX this is in namespace std if you want w/o use typeinfo.h?
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
@ -27,7 +27,7 @@
|
||||
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
||||
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
||||
|
||||
const ui32 version = 754;
|
||||
const ui32 version = 755;
|
||||
const ui32 minSupportedVersion = 753;
|
||||
|
||||
class CISer;
|
||||
|
@ -25,56 +25,6 @@ const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255);
|
||||
const PlayerColor PlayerColor::PLAYER_LIMIT = PlayerColor(PLAYER_LIMIT_I);
|
||||
const TeamID TeamID::NO_TEAM = TeamID(255);
|
||||
|
||||
#define ID_LIKE_OPERATORS_INTERNAL(A, B, AN, BN) \
|
||||
bool operator==(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN == BN ; \
|
||||
} \
|
||||
bool operator!=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN != BN ; \
|
||||
} \
|
||||
bool operator<(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN < BN ; \
|
||||
} \
|
||||
bool operator<=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN <= BN ; \
|
||||
} \
|
||||
bool operator>(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN > BN ; \
|
||||
} \
|
||||
bool operator>=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN >= BN ; \
|
||||
}
|
||||
|
||||
#define ID_LIKE_OPERATORS(CLASS_NAME, ENUM_NAME) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(CLASS_NAME, CLASS_NAME, a.num, b.num) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(CLASS_NAME, ENUM_NAME, a.num, b) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(ENUM_NAME, CLASS_NAME, a, b.num)
|
||||
|
||||
|
||||
ID_LIKE_OPERATORS(SecondarySkill, SecondarySkill::ESecondarySkill)
|
||||
|
||||
ID_LIKE_OPERATORS(Obj, Obj::EObj)
|
||||
|
||||
ID_LIKE_OPERATORS(ETerrainType, ETerrainType::EETerrainType)
|
||||
|
||||
ID_LIKE_OPERATORS(ArtifactID, ArtifactID::EArtifactID)
|
||||
|
||||
ID_LIKE_OPERATORS(ArtifactPosition, ArtifactPosition::EArtifactPosition)
|
||||
|
||||
ID_LIKE_OPERATORS(CreatureID, CreatureID::ECreatureID)
|
||||
|
||||
ID_LIKE_OPERATORS(SpellID, SpellID::ESpellID)
|
||||
|
||||
ID_LIKE_OPERATORS(BuildingID, BuildingID::EBuildingID)
|
||||
|
||||
ID_LIKE_OPERATORS(BFieldType, BFieldType::EBFieldType)
|
||||
|
||||
CArtifact * ArtifactID::toArtifact() const
|
||||
{
|
||||
return VLC->arth->artifacts[*this];
|
||||
@ -130,7 +80,7 @@ std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType
|
||||
else return os << it->second;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const ETerrainType actionType)
|
||||
std::ostream & operator<<(std::ostream & os, const ETerrainType terrainType)
|
||||
{
|
||||
static const std::map<ETerrainType::EETerrainType, std::string> terrainTypeToString =
|
||||
{
|
||||
@ -147,9 +97,10 @@ std::ostream & operator<<(std::ostream & os, const ETerrainType actionType)
|
||||
DEFINE_ELEMENT(LAVA),
|
||||
DEFINE_ELEMENT(WATER),
|
||||
DEFINE_ELEMENT(ROCK)
|
||||
#undef DEFINE_ELEMENT
|
||||
};
|
||||
|
||||
auto it = terrainTypeToString.find(actionType.num);
|
||||
auto it = terrainTypeToString.find(terrainType.num);
|
||||
if (it == terrainTypeToString.end()) return os << "<Unknown type>";
|
||||
else return os << it->second;
|
||||
}
|
||||
@ -160,3 +111,23 @@ std::string ETerrainType::toString() const
|
||||
ss << *this;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const EPathfindingLayer pathfindingLayer)
|
||||
{
|
||||
static const std::map<EPathfindingLayer::EEPathfindingLayer, std::string> pathfinderLayerToString
|
||||
{
|
||||
#define DEFINE_ELEMENT(element) {EPathfindingLayer::element, #element}
|
||||
DEFINE_ELEMENT(WRONG),
|
||||
DEFINE_ELEMENT(AUTO),
|
||||
DEFINE_ELEMENT(LAND),
|
||||
DEFINE_ELEMENT(SAIL),
|
||||
DEFINE_ELEMENT(WATER),
|
||||
DEFINE_ELEMENT(AIR),
|
||||
DEFINE_ELEMENT(NUM_LAYERS)
|
||||
#undef DEFINE_ELEMENT
|
||||
};
|
||||
|
||||
auto it = pathfinderLayerToString.find(pathfindingLayer.num);
|
||||
if (it == pathfinderLayerToString.end()) return os << "<Unknown type>";
|
||||
else return os << it->second;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace GameConstants
|
||||
{
|
||||
const std::string VCMI_VERSION = "VCMI 0.98e";
|
||||
const std::string VCMI_VERSION = "VCMI 0.98f";
|
||||
|
||||
const int BFIELD_WIDTH = 17;
|
||||
const int BFIELD_HEIGHT = 11;
|
||||
@ -93,18 +93,37 @@ CLASS_NAME & advance(int i) \
|
||||
}
|
||||
|
||||
|
||||
#define ID_LIKE_OPERATORS_INTERNAL_DECLS(A, B) \
|
||||
bool DLL_LINKAGE operator==(const A & a, const B & b); \
|
||||
bool DLL_LINKAGE operator!=(const A & a, const B & b); \
|
||||
bool DLL_LINKAGE operator<(const A & a, const B & b); \
|
||||
bool DLL_LINKAGE operator<=(const A & a, const B & b); \
|
||||
bool DLL_LINKAGE operator>(const A & a, const B & b); \
|
||||
bool DLL_LINKAGE operator>=(const A & a, const B & b);
|
||||
// Operators are performance-critical and to be inlined they must be in header
|
||||
#define ID_LIKE_OPERATORS_INTERNAL(A, B, AN, BN) \
|
||||
STRONG_INLINE bool operator==(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN == BN ; \
|
||||
} \
|
||||
STRONG_INLINE bool operator!=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN != BN ; \
|
||||
} \
|
||||
STRONG_INLINE bool operator<(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN < BN ; \
|
||||
} \
|
||||
STRONG_INLINE bool operator<=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN <= BN ; \
|
||||
} \
|
||||
STRONG_INLINE bool operator>(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN > BN ; \
|
||||
} \
|
||||
STRONG_INLINE bool operator>=(const A & a, const B & b) \
|
||||
{ \
|
||||
return AN >= BN ; \
|
||||
}
|
||||
|
||||
#define ID_LIKE_OPERATORS_DECLS(CLASS_NAME, ENUM_NAME) \
|
||||
ID_LIKE_OPERATORS_INTERNAL_DECLS(CLASS_NAME, CLASS_NAME) \
|
||||
ID_LIKE_OPERATORS_INTERNAL_DECLS(CLASS_NAME, ENUM_NAME) \
|
||||
ID_LIKE_OPERATORS_INTERNAL_DECLS(ENUM_NAME, CLASS_NAME)
|
||||
#define ID_LIKE_OPERATORS(CLASS_NAME, ENUM_NAME) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(CLASS_NAME, CLASS_NAME, a.num, b.num) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(CLASS_NAME, ENUM_NAME, a.num, b) \
|
||||
ID_LIKE_OPERATORS_INTERNAL(ENUM_NAME, CLASS_NAME, a, b.num)
|
||||
|
||||
|
||||
#define OP_DECL_INT(CLASS_NAME, OP) \
|
||||
@ -296,7 +315,7 @@ public:
|
||||
ESecondarySkill num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(SecondarySkill, SecondarySkill::ESecondarySkill)
|
||||
ID_LIKE_OPERATORS(SecondarySkill, SecondarySkill::ESecondarySkill)
|
||||
|
||||
namespace EAlignment
|
||||
{
|
||||
@ -384,7 +403,19 @@ public:
|
||||
EBuildingID num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(BuildingID, BuildingID::EBuildingID)
|
||||
ID_LIKE_OPERATORS(BuildingID, BuildingID::EBuildingID)
|
||||
|
||||
namespace EAiTactic
|
||||
{
|
||||
enum EAiTactic
|
||||
{
|
||||
NONE = -1,
|
||||
RANDOM,
|
||||
WARRIOR,
|
||||
BUILDER,
|
||||
EXPLORER
|
||||
};
|
||||
}
|
||||
|
||||
namespace EBuildingState
|
||||
{
|
||||
@ -432,8 +463,21 @@ namespace EMarketMode
|
||||
|
||||
namespace EBattleStackState
|
||||
{
|
||||
enum EBattleStackState{ALIVE = 180, SUMMONED, CLONED, DEAD_CLONE, HAD_MORALE, WAITING, MOVED, DEFENDING, FEAR,
|
||||
DRAINED_MANA /*remember to drain mana only once per turn*/};
|
||||
enum EBattleStackState
|
||||
{
|
||||
ALIVE = 180,
|
||||
SUMMONED, CLONED,
|
||||
DEAD_CLONE,
|
||||
HAD_MORALE,
|
||||
WAITING,
|
||||
MOVED,
|
||||
DEFENDING,
|
||||
FEAR,
|
||||
//remember to drain mana only once per turn
|
||||
DRAINED_MANA,
|
||||
//only for defending animation
|
||||
DEFENDING_ANIM
|
||||
};
|
||||
}
|
||||
|
||||
namespace ECommander
|
||||
@ -651,7 +695,7 @@ public:
|
||||
EObj num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(Obj, Obj::EObj)
|
||||
ID_LIKE_OPERATORS(Obj, Obj::EObj)
|
||||
|
||||
namespace SecSkillLevel
|
||||
{
|
||||
@ -741,10 +785,51 @@ public:
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const ETerrainType actionType);
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const ETerrainType terrainType);
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(ETerrainType, ETerrainType::EETerrainType)
|
||||
ID_LIKE_OPERATORS(ETerrainType, ETerrainType::EETerrainType)
|
||||
|
||||
class DLL_LINKAGE EDiggingStatus
|
||||
{
|
||||
public:
|
||||
enum EEDiggingStatus
|
||||
{
|
||||
UNKNOWN = -1,
|
||||
CAN_DIG = 0,
|
||||
LACK_OF_MOVEMENT,
|
||||
WRONG_TERRAIN,
|
||||
TILE_OCCUPIED
|
||||
};
|
||||
|
||||
EDiggingStatus(EEDiggingStatus _num = UNKNOWN) : num(_num)
|
||||
{}
|
||||
|
||||
ID_LIKE_CLASS_COMMON(EDiggingStatus, EEDiggingStatus)
|
||||
|
||||
EEDiggingStatus num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS(EDiggingStatus, EDiggingStatus::EEDiggingStatus)
|
||||
|
||||
class DLL_LINKAGE EPathfindingLayer
|
||||
{
|
||||
public:
|
||||
enum EEPathfindingLayer : ui8
|
||||
{
|
||||
LAND = 0, SAIL = 1, WATER, AIR, NUM_LAYERS, WRONG, AUTO
|
||||
};
|
||||
|
||||
EPathfindingLayer(EEPathfindingLayer _num = WRONG) : num(_num)
|
||||
{}
|
||||
|
||||
ID_LIKE_CLASS_COMMON(EPathfindingLayer, EEPathfindingLayer)
|
||||
|
||||
EEPathfindingLayer num;
|
||||
};
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EPathfindingLayer pathfindingLayer);
|
||||
|
||||
ID_LIKE_OPERATORS(EPathfindingLayer, EPathfindingLayer::EEPathfindingLayer)
|
||||
|
||||
class BFieldType
|
||||
{
|
||||
@ -767,7 +852,7 @@ public:
|
||||
EBFieldType num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(BFieldType, BFieldType::EBFieldType)
|
||||
ID_LIKE_OPERATORS(BFieldType, BFieldType::EBFieldType)
|
||||
|
||||
namespace EPlayerStatus
|
||||
{
|
||||
@ -807,7 +892,7 @@ public:
|
||||
EArtifactPosition num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(ArtifactPosition, ArtifactPosition::EArtifactPosition)
|
||||
ID_LIKE_OPERATORS(ArtifactPosition, ArtifactPosition::EArtifactPosition)
|
||||
|
||||
class ArtifactID
|
||||
{
|
||||
@ -824,6 +909,7 @@ public:
|
||||
FIRST_AID_TENT = 6,
|
||||
//CENTAUR_AXE = 7,
|
||||
//BLACKSHARD_OF_THE_DEAD_KNIGHT = 8,
|
||||
ARMAGEDDONS_BLADE = 128,
|
||||
TITANS_THUNDER = 135,
|
||||
//CORNUCOPIA = 140,
|
||||
//FIXME: the following is only true if WoG is enabled. Otherwise other mod artifacts will take these slots.
|
||||
@ -851,7 +937,7 @@ public:
|
||||
EArtifactID num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(ArtifactID, ArtifactID::EArtifactID)
|
||||
ID_LIKE_OPERATORS(ArtifactID, ArtifactID::EArtifactID)
|
||||
|
||||
class CreatureID
|
||||
{
|
||||
@ -895,7 +981,7 @@ public:
|
||||
ECreatureID num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(CreatureID, CreatureID::ECreatureID)
|
||||
ID_LIKE_OPERATORS(CreatureID, CreatureID::ECreatureID)
|
||||
|
||||
class SpellID
|
||||
{
|
||||
@ -939,7 +1025,7 @@ public:
|
||||
ESpellID num;
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(SpellID, SpellID::ESpellID)
|
||||
ID_LIKE_OPERATORS(SpellID, SpellID::ESpellID)
|
||||
|
||||
enum class ESpellSchool: ui8
|
||||
{
|
||||
@ -949,8 +1035,6 @@ enum class ESpellSchool: ui8
|
||||
EARTH = 3
|
||||
};
|
||||
|
||||
ID_LIKE_OPERATORS_DECLS(SpellID, SpellID::ESpellID)
|
||||
|
||||
// Typedef declarations
|
||||
typedef ui8 TFaction;
|
||||
typedef si64 TExpType;
|
||||
@ -961,8 +1045,8 @@ typedef si32 TQuantity;
|
||||
typedef int TRmgTemplateZoneId;
|
||||
|
||||
#undef ID_LIKE_CLASS_COMMON
|
||||
#undef ID_LIKE_OPERATORS_DECLS
|
||||
#undef ID_LIKE_OPERATORS_INTERNAL_DECLS
|
||||
#undef ID_LIKE_OPERATORS
|
||||
#undef ID_LIKE_OPERATORS_INTERNAL
|
||||
#undef INSTID_LIKE_CLASS_COMMON
|
||||
#undef OP_DECL_INT
|
||||
|
||||
|
@ -763,8 +763,29 @@ void CBonusSystemNode::popBonuses(const CSelector &s)
|
||||
child->popBonuses(s);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::updateBonuses(const CSelector &s)
|
||||
{
|
||||
BonusList bl;
|
||||
exportedBonuses.getBonuses(bl, s);
|
||||
for(Bonus *b : bl)
|
||||
{
|
||||
b->turnsRemain--;
|
||||
if(b->turnsRemain <= 0)
|
||||
removeBonus(b);
|
||||
}
|
||||
|
||||
for(CBonusSystemNode *child : children)
|
||||
child->updateBonuses(s);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::addNewBonus(Bonus *b)
|
||||
{
|
||||
//turnsRemain shouldn't be zero for following durations
|
||||
if(Bonus::NTurns(b) || Bonus::NDays(b) || Bonus::OneWeek(b))
|
||||
{
|
||||
assert(b->turnsRemain);
|
||||
}
|
||||
|
||||
assert(!vstd::contains(exportedBonuses,b));
|
||||
exportedBonuses.push_back(b);
|
||||
exportBonus(b);
|
||||
@ -950,18 +971,7 @@ void CBonusSystemNode::getRedDescendants(TNodes &out)
|
||||
|
||||
void CBonusSystemNode::battleTurnPassed()
|
||||
{
|
||||
BonusList bonusesCpy = exportedBonuses; //copy, because removing bonuses invalidates iters
|
||||
for (auto & elem : bonusesCpy)
|
||||
{
|
||||
Bonus *b = elem;
|
||||
|
||||
if(b->duration & Bonus::N_TURNS)
|
||||
{
|
||||
b->turnsRemain--;
|
||||
if(b->turnsRemain <= 0)
|
||||
removeBonus(b);
|
||||
}
|
||||
}
|
||||
updateBonuses(Bonus::NTurns);
|
||||
}
|
||||
|
||||
void CBonusSystemNode::exportBonus(Bonus * b)
|
||||
@ -1183,6 +1193,7 @@ namespace Selector
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType(&Bonus::source);
|
||||
DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange(&Bonus::effectRange);
|
||||
DLL_LINKAGE CWillLastTurns turns;
|
||||
DLL_LINKAGE CWillLastDays days;
|
||||
DLL_LINKAGE CSelectFieldAny<Bonus::LimitEffect> anyRange(&Bonus::effectRange);
|
||||
|
||||
CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype)
|
||||
|
@ -294,7 +294,7 @@ struct DLL_LINKAGE Bonus
|
||||
};
|
||||
|
||||
ui16 duration; //uses BonusDuration values
|
||||
si16 turnsRemain; //used if duration is N_TURNS or N_DAYS
|
||||
si16 turnsRemain; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
|
||||
|
||||
BonusType type; //uses BonusType values - says to what is this bonus - 1 byte
|
||||
TBonusSubtype subtype; //-1 if not applicable - 4 bytes
|
||||
@ -686,6 +686,7 @@ public:
|
||||
//bool isLimitedOnUs(Bonus *b) const; //if bonus should be removed from list acquired from this node
|
||||
|
||||
void popBonuses(const CSelector &s);
|
||||
void updateBonuses(const CSelector &s);
|
||||
virtual std::string bonusToString(const Bonus *bonus, bool description) const {return "";}; //description or bonus name
|
||||
virtual std::string nodeName() const;
|
||||
|
||||
@ -810,7 +811,7 @@ public:
|
||||
bool operator()(const Bonus *bonus) const
|
||||
{
|
||||
return turnsRequested <= 0 //every present effect will last zero (or "less") turns
|
||||
|| !(bonus->duration & Bonus::N_TURNS) //so do every not expriing after N-turns effect
|
||||
|| !Bonus::NTurns(bonus) //so do every not expriing after N-turns effect
|
||||
|| bonus->turnsRemain > turnsRequested;
|
||||
}
|
||||
CWillLastTurns& operator()(const int &setVal)
|
||||
@ -820,6 +821,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CWillLastDays
|
||||
{
|
||||
public:
|
||||
int daysRequested;
|
||||
|
||||
bool operator()(const Bonus *bonus) const
|
||||
{
|
||||
if(daysRequested <= 0 || Bonus::Permanent(bonus) || Bonus::OneBattle(bonus))
|
||||
return true;
|
||||
else if(Bonus::OneDay(bonus))
|
||||
return false;
|
||||
else if(Bonus::NDays(bonus) || Bonus::OneWeek(bonus))
|
||||
{
|
||||
return bonus->turnsRemain > daysRequested;
|
||||
}
|
||||
|
||||
return false; // TODO: ONE_WEEK need support for turnsRemain, but for now we'll exclude all unhandled durations
|
||||
}
|
||||
CWillLastDays& operator()(const int &setVal)
|
||||
{
|
||||
daysRequested = setVal;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//Stores multiple limiters. If any of them fails -> bonus is dropped.
|
||||
class DLL_LINKAGE LimiterList : public ILimiter
|
||||
{
|
||||
@ -958,6 +984,7 @@ namespace Selector
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusSource> sourceType;
|
||||
extern DLL_LINKAGE CSelectFieldEqual<Bonus::LimitEffect> effectRange;
|
||||
extern DLL_LINKAGE CWillLastTurns turns;
|
||||
extern DLL_LINKAGE CWillLastDays days;
|
||||
extern DLL_LINKAGE CSelectFieldAny<Bonus::LimitEffect> anyRange;
|
||||
|
||||
CSelector DLL_LINKAGE typeSubtype(Bonus::BonusType Type, TBonusSubtype Subtype);
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "mapObjects/CObjectClassesHandler.h"
|
||||
#include "StartInfo.h"
|
||||
#include "CGameState.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "CPlayerState.h"
|
||||
|
||||
void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
|
||||
{
|
||||
@ -38,14 +40,14 @@ void CPrivilagedInfoCallback::getFreeTiles (std::vector<int3> &tiles) const
|
||||
for (int yd = 0; yd < gs->map->height; yd++)
|
||||
{
|
||||
tinfo = getTile(int3 (xd,yd,zd));
|
||||
if (tinfo->terType != ETerrainType::WATER && !tinfo->blocked) //land and free
|
||||
if (tinfo->terType != ETerrainType::WATER && tinfo->terType != ETerrainType::ROCK && !tinfo->blocked) //land and free
|
||||
tiles.push_back (int3 (xd,yd,zd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player/*=uninit*/, int mode/*=0*/ ) const
|
||||
void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player/*=uninit*/, int mode/*=0*/, bool patrolDistance/*=false*/) const
|
||||
{
|
||||
if(!!player && *player >= PlayerColor::PLAYER_LIMIT)
|
||||
{
|
||||
@ -61,7 +63,13 @@ void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt
|
||||
{
|
||||
for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
|
||||
{
|
||||
double distance = pos.dist2d(int3(xd,yd,pos.z)) - 0.5;
|
||||
int3 tilePos(xd,yd,pos.z);
|
||||
double distance;
|
||||
if(patrolDistance)
|
||||
distance = pos.mandist2d(tilePos);
|
||||
else
|
||||
distance = pos.dist2d(tilePos) - 0.5;
|
||||
|
||||
if(distance <= radious)
|
||||
{
|
||||
if(!player
|
||||
|
@ -30,7 +30,7 @@ class DLL_LINKAGE CPrivilagedInfoCallback : public CGameInfoCallback
|
||||
public:
|
||||
CGameState * gameState();
|
||||
void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
|
||||
void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode=0) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
|
||||
void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode = 0, bool patrolDistance = false) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
|
||||
void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
|
||||
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "ResourceSet.h"
|
||||
//#include "CObstacleInstance.h"
|
||||
#include "CGameStateFwd.h"
|
||||
#include "mapping/CMap.h"
|
||||
#include "mapping/CMapDefines.h"
|
||||
#include "CObstacleInstance.h"
|
||||
|
||||
#include "spells/ViewSpellInt.h"
|
||||
@ -363,6 +363,7 @@ struct GiveBonus : public CPackForClient //115
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & bonus & id & bdescr & who;
|
||||
assert( id != -1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1218,7 +1219,7 @@ struct TeleportDialog : public Query//2006
|
||||
|
||||
const CGHeroInstance *hero;
|
||||
TeleportChannelID channel;
|
||||
std::vector<ObjectInstanceID> exits;
|
||||
TTeleportExitsList exits;
|
||||
bool impassable;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "CTownHandler.h"
|
||||
#include "mapping/CMapInfo.h"
|
||||
#include "StartInfo.h"
|
||||
#include "CPlayerState.h"
|
||||
|
||||
/*
|
||||
* NetPacksLib.cpp, part of VCMI engine
|
||||
@ -263,6 +264,9 @@ DLL_LINKAGE void GiveBonus::applyGs( CGameState *gs )
|
||||
|
||||
assert(cbsn);
|
||||
|
||||
if(Bonus::OneWeek(&bonus))
|
||||
bonus.turnsRemain = 8 - gs->getDate(Date::DAY_OF_WEEK); // set correct number of days before adding bonus
|
||||
|
||||
auto b = new Bonus(bonus);
|
||||
cbsn->addNewBonus(b);
|
||||
|
||||
@ -1023,13 +1027,15 @@ DLL_LINKAGE void NewTurn::applyGs( CGameState *gs )
|
||||
creatureSet.second.applyGs(gs);
|
||||
|
||||
gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs
|
||||
if(gs->getDate(Date::DAY_OF_WEEK) == 1) //new week
|
||||
gs->globalEffects.popBonuses(Bonus::OneWeek); //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;
|
||||
|
||||
if(gs->getDate(Date::DAY_OF_WEEK) == 1)
|
||||
gs->updateRumor();
|
||||
}
|
||||
|
||||
DLL_LINKAGE void SetObjectProperty::applyGs( CGameState *gs )
|
||||
@ -1329,14 +1335,18 @@ DLL_LINKAGE void StartAction::applyGs( CGameState *gs )
|
||||
switch(ba.actionType)
|
||||
{
|
||||
case Battle::DEFEND:
|
||||
st->state -= EBattleStackState::DEFENDING_ANIM;
|
||||
st->state.insert(EBattleStackState::DEFENDING);
|
||||
st->state.insert(EBattleStackState::DEFENDING_ANIM);
|
||||
break;
|
||||
case Battle::WAIT:
|
||||
st->state -= EBattleStackState::DEFENDING_ANIM;
|
||||
st->state.insert(EBattleStackState::WAITING);
|
||||
return;
|
||||
case Battle::HERO_SPELL: //no change in current stack state
|
||||
return;
|
||||
default: //any active stack action - attack, catapult, heal, spell...
|
||||
st->state -= EBattleStackState::DEFENDING_ANIM;
|
||||
st->state.insert(EBattleStackState::MOVED);
|
||||
break;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ struct PlayerSettings
|
||||
Ebonus bonus;
|
||||
si16 castle;
|
||||
si32 hero,
|
||||
heroPortrait; //-1 if default, else ID
|
||||
heroPortrait; //-1 if default, else ID
|
||||
|
||||
std::string heroName;
|
||||
PlayerColor color; //from 0 -
|
||||
@ -70,13 +70,13 @@ struct StartInfo
|
||||
{
|
||||
enum EMode {NEW_GAME, LOAD_GAME, CAMPAIGN, DUEL, INVALID = 255};
|
||||
|
||||
EMode mode;
|
||||
ui8 difficulty; //0=easy; 4=impossible
|
||||
|
||||
typedef std::map<PlayerColor, PlayerSettings> TPlayerInfos;
|
||||
TPlayerInfos playerInfos; //color indexed
|
||||
|
||||
ui32 seedToBeUsed; //0 if not sure (client requests server to decide, will be send in reply pack)
|
||||
EMode mode;
|
||||
ui8 difficulty; //0=easy; 4=impossible
|
||||
|
||||
typedef std::map<PlayerColor, PlayerSettings> TPlayerInfos;
|
||||
TPlayerInfos playerInfos; //color indexed
|
||||
|
||||
ui32 seedToBeUsed; //0 if not sure (client requests server to decide, will be send in reply pack)
|
||||
ui32 seedPostInit; //so we know that game is correctly synced at the start; 0 if not known yet
|
||||
ui32 mapfileChecksum; //0 if not relevant
|
||||
ui8 turnTime; //in minutes, 0=unlimited
|
||||
|
@ -34,9 +34,9 @@ void IVCMIDirs::init()
|
||||
#endif
|
||||
#endif // __MINGW32__
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Shlobj.h>
|
||||
#include <Shellapi.h>
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
// Generates script file named _temp.bat in 'to' directory and runs it
|
||||
// Script will:
|
||||
|
16
lib/int3.h
16
lib/int3.h
@ -105,6 +105,11 @@ public:
|
||||
{
|
||||
return std::sqrt((double)dist2dSQ(o));
|
||||
}
|
||||
//manhattan distance used for patrol radius (z coord is not used)
|
||||
double mandist2d(const int3 & o) const
|
||||
{
|
||||
return abs(o.x - x) + abs(o.y - y);
|
||||
}
|
||||
|
||||
bool areNeighbours(const int3 & o) const
|
||||
{
|
||||
@ -131,6 +136,12 @@ public:
|
||||
{
|
||||
h & x & y & z;
|
||||
}
|
||||
|
||||
static std::array<int3, 8> getDirs()
|
||||
{
|
||||
return { { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
|
||||
int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) } };
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & str, const int3 & sth)
|
||||
@ -154,9 +165,6 @@ struct ShashInt3
|
||||
}
|
||||
};
|
||||
|
||||
static const int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
|
||||
int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) };
|
||||
|
||||
template<typename Container>
|
||||
int3 findClosestTile (Container & container, int3 dest)
|
||||
{
|
||||
@ -175,4 +183,4 @@ int3 findClosestTile (Container & container, int3 dest)
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CArmedInstance.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -15,6 +15,7 @@
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CPlayerState.h"
|
||||
|
||||
void CArmedInstance::randomizeArmy(int type)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CGHeroInstance.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -22,6 +22,8 @@
|
||||
#include "../CGameState.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../CTownHandler.h"
|
||||
#include "CGTownInstance.h"
|
||||
|
||||
///helpers
|
||||
static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const ui16 soundID)
|
||||
@ -56,7 +58,7 @@ static int lowestSpeed(const CGHeroInstance * chi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &from) const
|
||||
ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const
|
||||
{
|
||||
unsigned ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
|
||||
@ -80,30 +82,40 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &fro
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(!hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType))
|
||||
else if(ti->nativeTerrain != from.terType && !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType))
|
||||
{
|
||||
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
||||
// This is clearly bug in H3 however intended behaviour is not clear.
|
||||
// Current VCMI behaviour will ignore neutrals in calculations so army in VCMI
|
||||
// will always have best penalty without any influence from player-defined stacks order
|
||||
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
int nativeTerrain = VLC->townh->factions[stack.second->type->faction]->nativeTerrain;
|
||||
if(nativeTerrain != -1 && nativeTerrain != from.terType)
|
||||
{
|
||||
ret = VLC->heroh->terrCosts[from.terType];
|
||||
ret -= getSecSkillLevel(SecondarySkill::PATHFINDING) * 25;
|
||||
if(ret < GameConstants::BASE_MOVEMENT_COST)
|
||||
ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = VLC->heroh->terrCosts[from.terType];
|
||||
ret -= getSecSkillLevel(SecondarySkill::PATHFINDING) * 25;
|
||||
if(ret < GameConstants::BASE_MOVEMENT_COST)
|
||||
ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CGHeroInstance::getNativeTerrain() const
|
||||
{
|
||||
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
||||
// This is clearly bug in H3 however intended behaviour is not clear.
|
||||
// Current VCMI behaviour will ignore neutrals in calculations so army in VCMI
|
||||
// will always have best penalty without any influence from player-defined stacks order
|
||||
|
||||
// TODO: What should we do if all hero stacks are neutral creatures?
|
||||
int nativeTerrain = -1;
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
int stackNativeTerrain = VLC->townh->factions[stack.second->type->faction]->nativeTerrain;
|
||||
if(stackNativeTerrain == -1)
|
||||
continue;
|
||||
|
||||
if(nativeTerrain == -1)
|
||||
nativeTerrain = stackNativeTerrain;
|
||||
else if(nativeTerrain != stackNativeTerrain)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nativeTerrain;
|
||||
}
|
||||
|
||||
int3 CGHeroInstance::convertPosition(int3 src, bool toh3m) //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
|
||||
{
|
||||
if (toh3m)
|
||||
@ -129,16 +141,6 @@ int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position o
|
||||
}
|
||||
}
|
||||
|
||||
bool CGHeroInstance::canFly() const
|
||||
{
|
||||
return hasBonusOfType(Bonus::FLYING_MOVEMENT);
|
||||
}
|
||||
|
||||
bool CGHeroInstance::canWalkOnSea() const
|
||||
{
|
||||
return hasBonusOfType(Bonus::WATER_WALKING);
|
||||
}
|
||||
|
||||
ui8 CGHeroInstance::getSecSkillLevel(SecondarySkill skill) const
|
||||
{
|
||||
for(auto & elem : secSkills)
|
||||
@ -181,8 +183,11 @@ bool CGHeroInstance::canLearnSkill() const
|
||||
return secSkills.size() < GameConstants::SKILL_PER_HERO;
|
||||
}
|
||||
|
||||
int CGHeroInstance::maxMovePoints(bool onLand) const
|
||||
int CGHeroInstance::maxMovePoints(bool onLand, const TurnInfo * ti) const
|
||||
{
|
||||
if(!ti)
|
||||
ti = new TurnInfo(this);
|
||||
|
||||
int base;
|
||||
|
||||
if(onLand)
|
||||
@ -201,10 +206,10 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
|
||||
}
|
||||
|
||||
const Bonus::BonusType bt = onLand ? Bonus::LAND_MOVEMENT : Bonus::SEA_MOVEMENT;
|
||||
const int bonus = valOfBonuses(Bonus::MOVEMENT) + valOfBonuses(bt);
|
||||
const int bonus = ti->valOfBonuses(Bonus::MOVEMENT) + ti->valOfBonuses(bt);
|
||||
|
||||
const int subtype = onLand ? SecondarySkill::LOGISTICS : SecondarySkill::NAVIGATION;
|
||||
const double modifier = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, subtype) / 100.0;
|
||||
const double modifier = ti->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, subtype) / 100.0;
|
||||
|
||||
return int(base* (1+modifier)) + bonus;
|
||||
}
|
||||
@ -261,10 +266,10 @@ void CGHeroInstance::initHero()
|
||||
spells -= SpellID::PRESET;
|
||||
|
||||
if(!getArt(ArtifactPosition::MACH4) && !getArt(ArtifactPosition::SPELLBOOK) && type->haveSpellBook) //no catapult means we haven't read pre-existent set -> use default rules for spellbook
|
||||
putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0));
|
||||
putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(ArtifactID::SPELLBOOK));
|
||||
|
||||
if(!getArt(ArtifactPosition::MACH4))
|
||||
putArtifact(ArtifactPosition::MACH4, CArtifactInstance::createNewArtifactInstance(3)); //everyone has a catapult
|
||||
putArtifact(ArtifactPosition::MACH4, CArtifactInstance::createNewArtifactInstance(ArtifactID::CATAPULT)); //everyone has a catapult
|
||||
|
||||
if(portrait < 0 || portrait == 255)
|
||||
portrait = type->imageIndex;
|
||||
@ -1099,9 +1104,11 @@ int CGHeroInstance::getBoatType() const
|
||||
|
||||
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
||||
{
|
||||
// FIXME: Offsets need to be fixed once we get rid of convertPosition
|
||||
// Check issue 515 for details
|
||||
offsets =
|
||||
{
|
||||
int3(0,1,0), int3(0,-1,0), int3(-1,0,0), int3(+1,0,0), int3(1,1,0), int3(-1,1,0), int3(1,-1,0), int3(-1,-1,0)
|
||||
int3(-1,1,0), int3(-1,-1,0), int3(-2,0,0), int3(0,0,0), int3(0,1,0), int3(-2,1,0), int3(0,-1,0), int3(-2,-1,0)
|
||||
};
|
||||
}
|
||||
|
||||
@ -1171,30 +1178,25 @@ CBonusSystemNode * CGHeroInstance::whereShouldBeAttached(CGameState *gs)
|
||||
return CArmedInstance::whereShouldBeAttached(gs);
|
||||
}
|
||||
|
||||
int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark /*= false*/) const
|
||||
int CGHeroInstance::movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark /*= false*/, const TurnInfo * ti) const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::FREE_SHIP_BOARDING))
|
||||
return (MPsBefore - basicCost) * static_cast<double>(maxMovePoints(disembark)) / maxMovePoints(!disembark);
|
||||
if(!ti)
|
||||
ti = new TurnInfo(this);
|
||||
|
||||
int mp1 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL);
|
||||
int mp2 = ti->getMaxMovePoints(disembark ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND);
|
||||
if(ti->hasBonusOfType(Bonus::FREE_SHIP_BOARDING))
|
||||
return (MPsBefore - basicCost) * static_cast<double>(mp1) / mp2;
|
||||
|
||||
return 0; //take all MPs otherwise
|
||||
}
|
||||
|
||||
CGHeroInstance::ECanDig CGHeroInstance::diggingStatus() const
|
||||
EDiggingStatus CGHeroInstance::diggingStatus() const
|
||||
{
|
||||
if(movement < maxMovePoints(true))
|
||||
return LACK_OF_MOVEMENT;
|
||||
else if(cb->getTile(getPosition(false))->terType == ETerrainType::WATER)
|
||||
return WRONG_TERRAIN;
|
||||
else
|
||||
{
|
||||
const TerrainTile *t = cb->getTile(getPosition());
|
||||
//TODO look for hole
|
||||
//CGI->mh->getTerrainDescr(h->getPosition(false), hlp, false);
|
||||
if(/*hlp.length() || */t->blockingObjects.size() > 1)
|
||||
return TILE_OCCUPIED;
|
||||
else
|
||||
return CAN_DIG;
|
||||
}
|
||||
return EDiggingStatus::LACK_OF_MOVEMENT;
|
||||
|
||||
return cb->getTile(getPosition(false))->getDiggingStatus();
|
||||
}
|
||||
|
||||
ArtBearer::ArtBearer CGHeroInstance::bearerType() const
|
||||
|
@ -21,6 +21,7 @@ class CHero;
|
||||
class CGBoat;
|
||||
class CGTownInstance;
|
||||
struct TerrainTile;
|
||||
struct TurnInfo;
|
||||
|
||||
class CGHeroPlaceholder : public CGObjectInstance
|
||||
{
|
||||
@ -39,10 +40,6 @@ public:
|
||||
class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator, public CArtifactSet, public ISpellCaster
|
||||
{
|
||||
public:
|
||||
enum ECanDig
|
||||
{
|
||||
CAN_DIG, LACK_OF_MOVEMENT, WRONG_TERRAIN, TILE_OCCUPIED
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ui8 moveDir; //format: 123
|
||||
@ -75,12 +72,23 @@ public:
|
||||
|
||||
struct DLL_LINKAGE Patrol
|
||||
{
|
||||
Patrol(){patrolling=false;patrolRadious=-1;};
|
||||
Patrol(){patrolling=false;initialPos=int3();patrolRadious=-1;};
|
||||
bool patrolling;
|
||||
int3 initialPos;
|
||||
ui32 patrolRadious;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & patrolling & patrolRadious;
|
||||
h & patrolling;
|
||||
if(version >= 755)
|
||||
{
|
||||
h & initialPos;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
patrolling = false;
|
||||
initialPos = int3();
|
||||
}
|
||||
h & patrolRadious;
|
||||
}
|
||||
} patrol;
|
||||
|
||||
@ -129,12 +137,11 @@ public:
|
||||
EAlignment::EAlignment getAlignment() const;
|
||||
const std::string &getBiography() const;
|
||||
bool needsLastStack()const override;
|
||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
int getNativeTerrain() const;
|
||||
ui32 getLowestCreatureSpeed() const;
|
||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||
bool canFly() const;
|
||||
bool canWalkOnSea() const;
|
||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||
|
||||
@ -161,8 +168,8 @@ public:
|
||||
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
||||
void levelUp(std::vector<SecondarySkill> skills);
|
||||
|
||||
int maxMovePoints(bool onLand) const;
|
||||
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark = false) const;
|
||||
int maxMovePoints(bool onLand, const TurnInfo * ti = nullptr) const;
|
||||
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark = false, const TurnInfo * ti = nullptr) const;
|
||||
|
||||
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest
|
||||
double getFightingStrength() const; // takes attack / defense skill into account
|
||||
@ -174,7 +181,7 @@ public:
|
||||
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
|
||||
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
|
||||
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
|
||||
ECanDig diggingStatus() const; //0 - can dig; 1 - lack of movement; 2 -
|
||||
EDiggingStatus diggingStatus() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* CGMarket.cpp, part of VCMI engine
|
||||
*
|
||||
@ -17,6 +17,7 @@
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CGameState.h"
|
||||
#include "CGTownInstance.h"
|
||||
|
||||
///helpers
|
||||
static void openWindow(const OpenWindow::EWindow type, const int id1, const int id2 = -1)
|
||||
|
@ -51,7 +51,7 @@ void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const
|
||||
|
||||
void CGPandoraBox::giveContentsUpToExp(const CGHeroInstance *h) const
|
||||
{
|
||||
cb->removeAfterVisit(this);
|
||||
afterSuccessfulVisit();
|
||||
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
@ -331,6 +331,11 @@ void CGPandoraBox::heroLevelUpDone(const CGHeroInstance *hero) const
|
||||
giveContentsAfterExp(hero);
|
||||
}
|
||||
|
||||
void CGPandoraBox::afterSuccessfulVisit() const
|
||||
{
|
||||
cb->removeAfterVisit(this);
|
||||
}
|
||||
|
||||
void CGEvent::onHeroVisit( const CGHeroInstance * h ) const
|
||||
{
|
||||
if(!(availableFor & (1 << h->tempOwner.getNum())))
|
||||
@ -362,3 +367,13 @@ void CGEvent::activated( const CGHeroInstance * h ) const
|
||||
giveContentsUpToExp(h);
|
||||
}
|
||||
}
|
||||
|
||||
void CGEvent::afterSuccessfulVisit() const
|
||||
{
|
||||
if(removeAfterVisit)
|
||||
{
|
||||
cb->removeAfterVisit(this);
|
||||
}
|
||||
else if(hasGuardians)
|
||||
hasGuardians = false;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class DLL_LINKAGE CGPandoraBox : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
std::string message;
|
||||
bool hasGuardians; //helper - after battle even though we have no stacks, allows us to know that there was battle
|
||||
mutable bool hasGuardians; //helper - after battle even though we have no stacks, allows us to know that there was battle
|
||||
|
||||
//gained things:
|
||||
ui32 gainedExp;
|
||||
@ -54,6 +54,7 @@ protected:
|
||||
private:
|
||||
void getText( InfoWindow &iw, bool &afterBattle, int val, int negative, int positive, const CGHeroInstance * h ) const;
|
||||
void getText( InfoWindow &iw, bool &afterBattle, int text, const CGHeroInstance * h ) const;
|
||||
virtual void afterSuccessfulVisit() const;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGEvent : public CGPandoraBox //event objects
|
||||
@ -74,4 +75,5 @@ public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
private:
|
||||
void activated(const CGHeroInstance * h) const;
|
||||
void afterSuccessfulVisit() const override;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CGTownInstance.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -17,6 +17,8 @@
|
||||
#include "../CModHandler.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../mapping/CMapDefines.h"
|
||||
#include "../CPlayerState.h"
|
||||
|
||||
std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
|
||||
std::vector<int> CGTownInstance::universitySkills;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "CObjectHandler.h"
|
||||
#include "CGMarket.h" // For IMarket interface
|
||||
@ -52,11 +52,7 @@ public:
|
||||
CSpecObjInfo * info; //h3m info about dewlling
|
||||
TCreaturesSet creatures; //creatures[level] -> <vector of alternative ids (base creature and upgrades, creatures amount>
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this) & creatures;
|
||||
}
|
||||
|
||||
private:
|
||||
void initObj() override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void newTurn() const override;
|
||||
@ -64,9 +60,14 @@ public:
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
private:
|
||||
void updateGuards() const;
|
||||
void heroAcceptsCreatures(const CGHeroInstance *h) const;
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this) & creatures;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CGTownBuilding : public IObjectInterface
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CObjectHandler.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -18,8 +18,10 @@
|
||||
#include "../filesystem/ResourceID.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../mapping/CMap.h"
|
||||
|
||||
#include "CObjectClassesHandler.h"
|
||||
#include "CGTownInstance.h"
|
||||
|
||||
IGameCallback * IObjectInterface::cb = nullptr;
|
||||
|
||||
|
@ -22,6 +22,10 @@ class CGObjectInstance;
|
||||
struct MetaString;
|
||||
struct BattleResult;
|
||||
|
||||
// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
|
||||
// For now it's will be there till teleports code refactored and moved into own file
|
||||
typedef std::vector<std::pair<ObjectInstanceID, int3>> TTeleportExitsList;
|
||||
|
||||
class DLL_LINKAGE IObjectInterface
|
||||
{
|
||||
public:
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "CObjectClassesHandler.h"
|
||||
#include "MiscObjects.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CGameState.h"
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CPlayerState.h"
|
||||
|
||||
#include "CObjectClassesHandler.h"
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "../spells/CSpellHandler.h"
|
||||
#include "../IGameCallback.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../CPlayerState.h"
|
||||
|
||||
std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist;
|
||||
ui8 CGObelisk::obeliskCount; //how many obelisks are on map
|
||||
@ -164,7 +166,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
|
||||
case FIGHT:
|
||||
fight(h);
|
||||
break;
|
||||
case FLEE: //flee
|
||||
case FLEE:
|
||||
{
|
||||
flee(h);
|
||||
break;
|
||||
@ -322,13 +324,13 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
|
||||
|
||||
int charisma = powerFactor + h->getSecSkillLevel(SecondarySkill::DIPLOMACY) + sympathy;
|
||||
|
||||
if(charisma < character) //creatures will fight
|
||||
return -2;
|
||||
if(charisma < character)
|
||||
return FIGHT;
|
||||
|
||||
if (allowJoin)
|
||||
{
|
||||
if(h->getSecSkillLevel(SecondarySkill::DIPLOMACY) + sympathy + 1 >= character)
|
||||
return 0; //join for free
|
||||
return JOIN_FOR_FREE;
|
||||
|
||||
else if(h->getSecSkillLevel(SecondarySkill::DIPLOMACY) * 2 + sympathy + 1 >= character)
|
||||
return VLC->creh->creatures[subID]->cost[6] * getStackCount(SlotID(0)); //join for gold
|
||||
@ -336,10 +338,10 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
|
||||
|
||||
//we are still here - creatures have not joined hero, flee or fight
|
||||
|
||||
if (charisma > character)
|
||||
return -1; //flee
|
||||
if (charisma > character && !neverFlees)
|
||||
return FLEE;
|
||||
else
|
||||
return -2; //fight
|
||||
return FIGHT;
|
||||
}
|
||||
|
||||
void CGCreature::fleeDecision(const CGHeroInstance *h, ui32 pursue) const
|
||||
@ -361,7 +363,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
|
||||
{
|
||||
if(!accept)
|
||||
{
|
||||
if(takenAction(h,false) == -1) //they flee
|
||||
if(takenAction(h,false) == FLEE)
|
||||
{
|
||||
cb->setObjProperty(id, ObjProperty::MONSTER_REFUSED_JOIN, true);
|
||||
flee(h);
|
||||
@ -834,7 +836,7 @@ bool CGTeleport::isTeleport(const CGObjectInstance * obj)
|
||||
|
||||
bool CGTeleport::isConnected(const CGTeleport * src, const CGTeleport * dst)
|
||||
{
|
||||
return src && dst && src != dst && src->isChannelExit(dst->id);
|
||||
return src && dst && src->isChannelExit(dst->id);
|
||||
}
|
||||
|
||||
bool CGTeleport::isConnected(const CGObjectInstance * src, const CGObjectInstance * dst)
|
||||
@ -913,7 +915,13 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
|
||||
if(isEntrance())
|
||||
{
|
||||
if(cb->isTeleportChannelBidirectional(channel) && 1 < cb->getTeleportChannelExits(channel).size())
|
||||
td.exits = cb->getTeleportChannelExits(channel);
|
||||
{
|
||||
auto exits = cb->getTeleportChannelExits(channel);
|
||||
for(auto exit : exits)
|
||||
{
|
||||
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(cb->getObj(exit)->visitablePos(), true)));
|
||||
}
|
||||
}
|
||||
|
||||
if(cb->isTeleportChannelImpassable(channel))
|
||||
{
|
||||
@ -929,9 +937,9 @@ void CGMonolith::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->showTeleportDialog(&td);
|
||||
}
|
||||
|
||||
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const
|
||||
void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
|
||||
{
|
||||
ObjectInstanceID objId(answer);
|
||||
int3 dPos;
|
||||
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
|
||||
@ -939,14 +947,12 @@ void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer,
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(objId == ObjectInstanceID())
|
||||
objId = getRandomExit(hero);
|
||||
else if(vstd::isValidIndex(exits, answer))
|
||||
dPos = exits[answer].second;
|
||||
else
|
||||
assert(vstd::contains(exits, objId)); // Likely cheating attempt: not random teleporter choosen, but it's not from provided list
|
||||
dPos = CGHeroInstance::convertPosition(cb->getObj(getRandomExit(hero))->visitablePos(), true);
|
||||
|
||||
auto obj = cb->getObj(objId);
|
||||
if(obj)
|
||||
cb->moveHero(hero->id,CGHeroInstance::convertPosition(obj->pos,true) - getVisitableOffset(), true);
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
}
|
||||
|
||||
void CGMonolith::initObj()
|
||||
@ -986,7 +992,10 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
|
||||
td.impassable = true;
|
||||
}
|
||||
else
|
||||
td.exits.push_back(getRandomExit(h));
|
||||
{
|
||||
auto exit = getRandomExit(h);
|
||||
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(cb->getObj(exit)->visitablePos(), true)));
|
||||
}
|
||||
|
||||
cb->showTeleportDialog(&td);
|
||||
}
|
||||
@ -1085,31 +1094,35 @@ void CGWhirlpool::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->changeStackCount(StackLocation(h, targetstack), -countToTake);
|
||||
}
|
||||
else
|
||||
td.exits = getAllExits(true);
|
||||
{
|
||||
auto exits = getAllExits();
|
||||
for(auto exit : exits)
|
||||
{
|
||||
auto blockedPosList = cb->getObj(exit)->getBlockedPos();
|
||||
for(auto bPos : blockedPosList)
|
||||
td.exits.push_back(std::make_pair(exit, CGHeroInstance::convertPosition(bPos, true)));
|
||||
}
|
||||
}
|
||||
|
||||
cb->showTeleportDialog(&td);
|
||||
}
|
||||
|
||||
void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const
|
||||
void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const
|
||||
{
|
||||
ObjectInstanceID objId(answer);
|
||||
int3 dPos;
|
||||
auto realExits = getAllExits();
|
||||
if(!exits.size() && !realExits.size())
|
||||
return;
|
||||
else if(objId == ObjectInstanceID())
|
||||
objId = getRandomExit(hero);
|
||||
else if(vstd::isValidIndex(exits, answer))
|
||||
dPos = exits[answer].second;
|
||||
else
|
||||
assert(vstd::contains(exits, objId)); // Likely cheating attempt: not random teleporter choosen, but it's not from provided list
|
||||
|
||||
auto obj = cb->getObj(objId);
|
||||
if(obj)
|
||||
{
|
||||
auto obj = cb->getObj(getRandomExit(hero));
|
||||
std::set<int3> tiles = obj->getBlockedPos();
|
||||
auto & tile = *RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator());
|
||||
cb->moveHero(hero->id, tile + int3(1,0,0), true);
|
||||
|
||||
cb->moveHero(hero->id,CGHeroInstance::convertPosition(obj->pos,true) - getVisitableOffset(), true);
|
||||
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator()), true);
|
||||
}
|
||||
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
}
|
||||
|
||||
bool CGWhirlpool::isProtected( const CGHeroInstance * h )
|
||||
|
@ -227,7 +227,8 @@ class DLL_LINKAGE CGMine : public CArmedInstance
|
||||
public:
|
||||
Res::ERes producedResource;
|
||||
ui32 producedQuantity;
|
||||
|
||||
|
||||
private:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
@ -239,6 +240,7 @@ public:
|
||||
std::string getObjectName() const override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
@ -265,29 +267,33 @@ struct DLL_LINKAGE TeleportChannel
|
||||
|
||||
class DLL_LINKAGE CGTeleport : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
enum EType {UNKNOWN, ENTRANCE, EXIT, BOTH};
|
||||
|
||||
EType type;
|
||||
TeleportChannelID channel;
|
||||
|
||||
CGTeleport();
|
||||
bool isEntrance() const;
|
||||
bool isExit() const;
|
||||
bool isChannelEntrance(ObjectInstanceID id) const;
|
||||
bool isChannelExit(ObjectInstanceID id) const;
|
||||
std::vector<ObjectInstanceID> getAllEntrances(bool excludeCurrent = false) const;
|
||||
std::vector<ObjectInstanceID> getAllExits(bool excludeCurrent = false) const;
|
||||
ObjectInstanceID getRandomExit(const CGHeroInstance * h) const;
|
||||
|
||||
virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const = 0;
|
||||
std::vector<ObjectInstanceID> getAllEntrances(bool excludeCurrent = false) const;
|
||||
|
||||
protected:
|
||||
enum EType {UNKNOWN, ENTRANCE, EXIT, BOTH};
|
||||
EType type;
|
||||
|
||||
CGTeleport();
|
||||
ObjectInstanceID getRandomExit(const CGHeroInstance * h) const;
|
||||
std::vector<ObjectInstanceID> getAllExits(bool excludeCurrent = false) const;
|
||||
|
||||
public:
|
||||
TeleportChannelID channel;
|
||||
|
||||
bool isEntrance() const;
|
||||
bool isExit() const;
|
||||
|
||||
virtual void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const = 0;
|
||||
|
||||
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 bool isExitPassable(CGameState * gs, const CGHeroInstance * h, const CGObjectInstance * obj);
|
||||
static std::vector<ObjectInstanceID> getPassableExits(CGameState * gs, const CGHeroInstance * h, std::vector<ObjectInstanceID> exits);
|
||||
static void addToChannel(std::map<TeleportChannelID, 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);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -299,11 +305,12 @@ class DLL_LINKAGE CGMonolith : public CGTeleport
|
||||
{
|
||||
TeleportChannelID findMeChannel(std::vector<Obj> IDs, int SubID) const;
|
||||
|
||||
public:
|
||||
protected:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
|
||||
void initObj() override;
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGTeleport&>(*this);
|
||||
@ -312,9 +319,10 @@ public:
|
||||
|
||||
class DLL_LINKAGE CGSubterraneanGate : public CGMonolith
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
|
||||
public:
|
||||
static void postInit();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -325,11 +333,11 @@ public:
|
||||
|
||||
class DLL_LINKAGE CGWhirlpool : public CGMonolith
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, std::vector<ObjectInstanceID> exits) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
|
||||
static bool isProtected( const CGHeroInstance * h );
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGMonolith&>(*this);
|
||||
|
@ -292,7 +292,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory(CBinaryReader & r
|
||||
|
||||
std::vector< std::vector<ui8> > CCampaignHandler::getFile(const std::string & name, bool headerOnly)
|
||||
{
|
||||
CCompressedStream stream(std::move(CResourceHandler::get()->load(ResourceID(name, EResType::CAMPAIGN))), true);
|
||||
CCompressedStream stream(CResourceHandler::get()->load(ResourceID(name, EResType::CAMPAIGN)), true);
|
||||
|
||||
std::vector< std::vector<ui8> > ret;
|
||||
do
|
||||
@ -363,7 +363,7 @@ std::vector<CGHeroInstance *> CCampaignScenario::getLostCrossoverHeroes() const
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::move(lostCrossoverHeroes);
|
||||
return lostCrossoverHeroes;
|
||||
}
|
||||
|
||||
bool CScenarioTravel::STravelBonus::isBonusForHero() const
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "CDrawRoadsOperation.h"
|
||||
#include "CMap.h"
|
||||
|
||||
const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::patterns =
|
||||
{
|
||||
|
@ -11,9 +11,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "CMap.h"
|
||||
#include "CMapEditManager.h"
|
||||
|
||||
struct TerrainTile;
|
||||
|
||||
class CDrawRoadsOperation : public CMapOperation
|
||||
{
|
||||
|
@ -132,11 +132,13 @@ Obj TerrainTile::topVisitableId(bool excludeTop) const
|
||||
|
||||
CGObjectInstance * TerrainTile::topVisitableObj(bool excludeTop) const
|
||||
{
|
||||
auto visitableObj = visitableObjects;
|
||||
if(excludeTop && visitableObj.size())
|
||||
visitableObj.pop_back();
|
||||
if(visitableObjects.empty() || (excludeTop && visitableObjects.size() == 1))
|
||||
return nullptr;
|
||||
|
||||
return visitableObj.size() ? visitableObj.back() : nullptr;
|
||||
if(excludeTop)
|
||||
return visitableObjects[visitableObjects.size()-2];
|
||||
|
||||
return visitableObjects.back();
|
||||
}
|
||||
|
||||
bool TerrainTile::isCoastal() const
|
||||
@ -144,6 +146,18 @@ bool TerrainTile::isCoastal() const
|
||||
return extTileFlags & 64;
|
||||
}
|
||||
|
||||
EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
|
||||
{
|
||||
if(terType == ETerrainType::WATER || terType == ETerrainType::ROCK)
|
||||
return EDiggingStatus::WRONG_TERRAIN;
|
||||
|
||||
int allowedBlocked = excludeTop ? 1 : 0;
|
||||
if(blockingObjects.size() > allowedBlocked || topVisitableObj(excludeTop))
|
||||
return EDiggingStatus::TILE_OCCUPIED;
|
||||
else
|
||||
return EDiggingStatus::CAN_DIG;
|
||||
}
|
||||
|
||||
bool TerrainTile::hasFavourableWinds() const
|
||||
{
|
||||
return extTileFlags & 128;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../LogicalExpression.h"
|
||||
#include "CMapDefines.h"
|
||||
|
||||
class CArtifactInstance;
|
||||
class CGObjectInstance;
|
||||
@ -47,18 +48,6 @@ struct DLL_LINKAGE SHeroName
|
||||
}
|
||||
};
|
||||
|
||||
namespace EAiTactic
|
||||
{
|
||||
enum EAiTactic
|
||||
{
|
||||
NONE = -1,
|
||||
RANDOM,
|
||||
WARRIOR,
|
||||
BUILDER,
|
||||
EXPLORER
|
||||
};
|
||||
}
|
||||
|
||||
/// The player info constains data about which factions are allowed, AI tactical settings,
|
||||
/// the main hero name, where to generate the hero, whether the faction should be selected randomly,...
|
||||
struct DLL_LINKAGE PlayerInfo
|
||||
@ -216,93 +205,6 @@ struct DLL_LINKAGE DisposedHero
|
||||
}
|
||||
};
|
||||
|
||||
/// The map event is an event which e.g. gives or takes resources of a specific
|
||||
/// amount to/from players and can appear regularly or once a time.
|
||||
class DLL_LINKAGE CMapEvent
|
||||
{
|
||||
public:
|
||||
CMapEvent();
|
||||
|
||||
bool earlierThan(const CMapEvent & other) const;
|
||||
bool earlierThanOrEqual(const CMapEvent & other) const;
|
||||
|
||||
std::string name;
|
||||
std::string message;
|
||||
TResources resources;
|
||||
ui8 players; // affected players, bit field?
|
||||
ui8 humanAffected;
|
||||
ui8 computerAffected;
|
||||
ui32 firstOccurence;
|
||||
ui32 nextOccurence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & name & message & resources
|
||||
& players & humanAffected & computerAffected & firstOccurence & nextOccurence;
|
||||
}
|
||||
};
|
||||
|
||||
/// The castle event builds/adds buildings/creatures for a specific town.
|
||||
class DLL_LINKAGE CCastleEvent: public CMapEvent
|
||||
{
|
||||
public:
|
||||
CCastleEvent();
|
||||
|
||||
std::set<BuildingID> buildings;
|
||||
std::vector<si32> creatures;
|
||||
CGTownInstance * town;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & static_cast<CMapEvent &>(*this);
|
||||
h & buildings & creatures;
|
||||
}
|
||||
};
|
||||
|
||||
/// The terrain tile describes the terrain type and the visual representation of the terrain.
|
||||
/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it.
|
||||
struct DLL_LINKAGE TerrainTile
|
||||
{
|
||||
TerrainTile();
|
||||
|
||||
/// Gets true if the terrain is not a rock. If from is water/land, same type is also required.
|
||||
bool entrableTerrain(const TerrainTile * from = nullptr) const;
|
||||
bool entrableTerrain(bool allowLand, bool allowSea) const;
|
||||
/// Checks for blocking objects and terraint type (water / land).
|
||||
bool isClear(const TerrainTile * from = nullptr) const;
|
||||
/// Gets the ID of the top visitable object or -1 if there is none.
|
||||
Obj topVisitableId(bool excludeTop = false) const;
|
||||
CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
|
||||
bool isWater() const;
|
||||
bool isCoastal() const;
|
||||
bool hasFavourableWinds() const;
|
||||
|
||||
ETerrainType terType;
|
||||
ui8 terView;
|
||||
ERiverType::ERiverType riverType;
|
||||
ui8 riverDir;
|
||||
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
|
||||
ui8 extTileFlags;
|
||||
bool visitable;
|
||||
bool blocked;
|
||||
|
||||
std::vector<CGObjectInstance *> visitableObjects;
|
||||
std::vector<CGObjectInstance *> blockingObjects;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & terType & terView & riverType & riverDir & roadType &roadDir & extTileFlags;
|
||||
h & visitable & blocked;
|
||||
h & visitableObjects & blockingObjects;
|
||||
}
|
||||
};
|
||||
|
||||
namespace EMapFormat
|
||||
{
|
||||
enum EMapFormat
|
||||
|
99
lib/mapping/CMapDefines.h
Normal file
99
lib/mapping/CMapDefines.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* CMapDefines.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/// The map event is an event which e.g. gives or takes resources of a specific
|
||||
/// amount to/from players and can appear regularly or once a time.
|
||||
class DLL_LINKAGE CMapEvent
|
||||
{
|
||||
public:
|
||||
CMapEvent();
|
||||
|
||||
bool earlierThan(const CMapEvent & other) const;
|
||||
bool earlierThanOrEqual(const CMapEvent & other) const;
|
||||
|
||||
std::string name;
|
||||
std::string message;
|
||||
TResources resources;
|
||||
ui8 players; // affected players, bit field?
|
||||
ui8 humanAffected;
|
||||
ui8 computerAffected;
|
||||
ui32 firstOccurence;
|
||||
ui32 nextOccurence; /// specifies after how many days the event will occur the next time; 0 if event occurs only one time
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & name & message & resources
|
||||
& players & humanAffected & computerAffected & firstOccurence & nextOccurence;
|
||||
}
|
||||
};
|
||||
|
||||
/// The castle event builds/adds buildings/creatures for a specific town.
|
||||
class DLL_LINKAGE CCastleEvent: public CMapEvent
|
||||
{
|
||||
public:
|
||||
CCastleEvent();
|
||||
|
||||
std::set<BuildingID> buildings;
|
||||
std::vector<si32> creatures;
|
||||
CGTownInstance * town;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & static_cast<CMapEvent &>(*this);
|
||||
h & buildings & creatures;
|
||||
}
|
||||
};
|
||||
|
||||
/// The terrain tile describes the terrain type and the visual representation of the terrain.
|
||||
/// Furthermore the struct defines whether the tile is visitable or/and blocked and which objects reside in it.
|
||||
struct DLL_LINKAGE TerrainTile
|
||||
{
|
||||
TerrainTile();
|
||||
|
||||
/// Gets true if the terrain is not a rock. If from is water/land, same type is also required.
|
||||
bool entrableTerrain(const TerrainTile * from = nullptr) const;
|
||||
bool entrableTerrain(bool allowLand, bool allowSea) const;
|
||||
/// Checks for blocking objects and terraint type (water / land).
|
||||
bool isClear(const TerrainTile * from = nullptr) const;
|
||||
/// Gets the ID of the top visitable object or -1 if there is none.
|
||||
Obj topVisitableId(bool excludeTop = false) const;
|
||||
CGObjectInstance * topVisitableObj(bool excludeTop = false) const;
|
||||
bool isWater() const;
|
||||
bool isCoastal() const;
|
||||
EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
|
||||
bool hasFavourableWinds() const;
|
||||
|
||||
ETerrainType terType;
|
||||
ui8 terView;
|
||||
ERiverType::ERiverType riverType;
|
||||
ui8 riverDir;
|
||||
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
|
||||
ui8 extTileFlags;
|
||||
bool visitable;
|
||||
bool blocked;
|
||||
|
||||
std::vector<CGObjectInstance *> visitableObjects;
|
||||
std::vector<CGObjectInstance *> blockingObjects;
|
||||
|
||||
template <typename Handler>
|
||||
void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & terType & terView & riverType & riverDir & roadType &roadDir & extTileFlags;
|
||||
h & visitable & blocked;
|
||||
h & visitableObjects & blockingObjects;
|
||||
}
|
||||
};
|
@ -7,6 +7,7 @@
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "CDrawRoadsOperation.h"
|
||||
#include "../mapping/CMap.h"
|
||||
|
||||
MapRect::MapRect() : x(0), y(0), z(0), width(0), height(0)
|
||||
{
|
||||
|
@ -12,11 +12,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "CMap.h"
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
class CGObjectInstance;
|
||||
class CTerrainViewPatternConfig;
|
||||
struct TerrainViewPattern;
|
||||
class CMap;
|
||||
|
||||
/// Represents a map rectangle.
|
||||
struct DLL_LINKAGE MapRect
|
||||
|
@ -20,7 +20,7 @@ std::unique_ptr<CMap> CMapService::loadMap(const std::string & name)
|
||||
getMapPatcher(name)->patchMapHeader(header);
|
||||
header.release();
|
||||
|
||||
return std::move(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const std::string & name)
|
||||
@ -28,7 +28,7 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const std::string & name)
|
||||
auto stream = getStreamFromFS(name);
|
||||
std::unique_ptr<CMapHeader> header = getMapLoader(stream)->loadMapHeader();
|
||||
getMapPatcher(name)->patchMapHeader(header);
|
||||
return std::move(header);
|
||||
return header;
|
||||
}
|
||||
|
||||
std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const std::string & name)
|
||||
@ -40,7 +40,7 @@ std::unique_ptr<CMap> CMapService::loadMap(const ui8 * buffer, int size, const s
|
||||
getMapPatcher(name)->patchMapHeader(header);
|
||||
header.release();
|
||||
|
||||
return std::move(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int size, const std::string & name)
|
||||
@ -48,7 +48,7 @@ std::unique_ptr<CMapHeader> CMapService::loadMapHeader(const ui8 * buffer, int s
|
||||
auto stream = getStreamFromMem(buffer, size);
|
||||
std::unique_ptr<CMapHeader> header = getMapLoader(stream)->loadMapHeader();
|
||||
getMapPatcher(name)->patchMapHeader(header);
|
||||
return std::move(header);
|
||||
return header;
|
||||
}
|
||||
|
||||
std::unique_ptr<CInputStream> CMapService::getStreamFromFS(const std::string & name)
|
||||
|
@ -668,8 +668,7 @@ void CMapLoaderH3M::readAllowedArtifacts()
|
||||
}
|
||||
if (map->version == EMapFormat::ROE)
|
||||
{
|
||||
// Armageddon's Blade
|
||||
map->allowedArtifact[128] = false;
|
||||
map->allowedArtifact[ArtifactID::ARMAGEDDONS_BLADE] = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1061,7 +1060,7 @@ void CMapLoaderH3M::readObjects()
|
||||
case Obj::RANDOM_HERO:
|
||||
case Obj::PRISON:
|
||||
{
|
||||
nobj = readHero(idToBeGiven);
|
||||
nobj = readHero(idToBeGiven, objPos);
|
||||
break;
|
||||
}
|
||||
case Obj::MONSTER: //Monster
|
||||
@ -1550,7 +1549,7 @@ void CMapLoaderH3M::readCreatureSet(CCreatureSet * out, int number)
|
||||
out->validTypes(true);
|
||||
}
|
||||
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven)
|
||||
CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven, const int3 & initialPos)
|
||||
{
|
||||
auto nhi = new CGHeroInstance();
|
||||
|
||||
@ -1659,6 +1658,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven)
|
||||
else
|
||||
{
|
||||
nhi->patrol.patrolling = true;
|
||||
nhi->patrol.initialPos = CGHeroInstance::convertPosition(initialPos, false);
|
||||
}
|
||||
|
||||
if(map->version > EMapFormat::ROE)
|
||||
|
@ -172,7 +172,7 @@ private:
|
||||
* @param idToBeGiven the object id which should be set for the hero
|
||||
* @return a object instance
|
||||
*/
|
||||
CGObjectInstance * readHero(ObjectInstanceID idToBeGiven);
|
||||
CGObjectInstance * readHero(ObjectInstanceID idToBeGiven, const int3 & initialPos);
|
||||
|
||||
/**
|
||||
* Reads a seer hut.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../CArtHandler.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CPlayerState.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../CTownHandler.h"
|
||||
#include "../CModHandler.h" //needed?
|
||||
@ -24,8 +24,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
template<typename Serializer>
|
||||
void registerTypesMapObjects1(Serializer &s)
|
||||
{
|
||||
|
@ -78,6 +78,11 @@ void CMapGenOptions::setPlayerCount(si8 value)
|
||||
resetPlayersMap();
|
||||
}
|
||||
|
||||
si8 CMapGenOptions::getHumanOnlyPlayerCount() const
|
||||
{
|
||||
return humanPlayersCount;
|
||||
}
|
||||
|
||||
si8 CMapGenOptions::getTeamCount() const
|
||||
{
|
||||
return teamCount;
|
||||
@ -96,7 +101,7 @@ si8 CMapGenOptions::getCompOnlyPlayerCount() const
|
||||
|
||||
void CMapGenOptions::setCompOnlyPlayerCount(si8 value)
|
||||
{
|
||||
assert(value == RANDOM_SIZE || (value >= 0 && value <= getPlayerCount()));
|
||||
assert(value == RANDOM_SIZE || (getPlayerCount() == RANDOM_SIZE || (value >= 0 && value <= getPlayerCount())));
|
||||
compOnlyPlayerCount = value;
|
||||
|
||||
if (getPlayerCount() != RANDOM_SIZE && getCompOnlyPlayerCount() != RANDOM_SIZE)
|
||||
|
@ -108,6 +108,8 @@ public:
|
||||
si8 getPlayerCount() const;
|
||||
void setPlayerCount(si8 value);
|
||||
|
||||
si8 getHumanOnlyPlayerCount() const;
|
||||
|
||||
/// The count of the teams ranging from 0 to <players count - 1> or RANDOM_SIZE for random.
|
||||
si8 getTeamCount() const;
|
||||
void setTeamCount(si8 value);
|
||||
|
@ -17,7 +17,7 @@ static const int3 dirs4[] = {int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0)}
|
||||
|
||||
void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo)
|
||||
{
|
||||
for(const int3 &dir : dirs)
|
||||
for(const int3 &dir : int3::getDirs())
|
||||
{
|
||||
int3 n = pos + dir;
|
||||
if(map->isInTheMap(n))
|
||||
|
@ -735,7 +735,7 @@ bool CRmgTemplateZone::createRoad(CMapGenerator* gen, const int3& src, const int
|
||||
std::map<int3, int3> cameFrom; // The map of navigated nodes.
|
||||
std::map<int3, float> distances;
|
||||
|
||||
int3 currentNode = src;
|
||||
//int3 currentNode = src;
|
||||
gen->setRoad (src, ERoadType::NO_ROAD); //just in case zone guard already has road under it. Road under nodes will be added at very end
|
||||
|
||||
cameFrom[src] = int3(-1, -1, -1); //first node points to finish condition
|
||||
@ -824,7 +824,7 @@ bool CRmgTemplateZone::connectPath(CMapGenerator* gen, const int3& src, bool onl
|
||||
std::map<int3, int3> cameFrom; // The map of navigated nodes.
|
||||
std::map<int3, float> distances;
|
||||
|
||||
int3 currentNode = src;
|
||||
//int3 currentNode = src;
|
||||
|
||||
cameFrom[src] = int3(-1, -1, -1); //first node points to finish condition
|
||||
distances[src] = 0;
|
||||
@ -866,7 +866,7 @@ bool CRmgTemplateZone::connectPath(CMapGenerator* gen, const int3& src, bool onl
|
||||
return;
|
||||
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
||||
{
|
||||
auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||
if (vstd::contains(this->tileinfo, pos))
|
||||
{
|
||||
cameFrom[pos] = currentNode;
|
||||
@ -902,7 +902,7 @@ bool CRmgTemplateZone::connectWithCenter(CMapGenerator* gen, const int3& src, bo
|
||||
std::map<int3, int3> cameFrom; // The map of navigated nodes.
|
||||
std::map<int3, float> distances;
|
||||
|
||||
int3 currentNode = src;
|
||||
//int3 currentNode = src;
|
||||
|
||||
cameFrom[src] = int3(-1, -1, -1); //first node points to finish condition
|
||||
distances[src] = 0;
|
||||
@ -950,7 +950,7 @@ bool CRmgTemplateZone::connectWithCenter(CMapGenerator* gen, const int3& src, bo
|
||||
|
||||
if (distance < bestDistanceSoFar || !vstd::contains(closed, pos))
|
||||
{
|
||||
auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||
//auto obj = gen->map->getTile(pos).topVisitableObj();
|
||||
if (vstd::contains(this->tileinfo, pos))
|
||||
{
|
||||
cameFrom[pos] = currentNode;
|
||||
@ -2336,7 +2336,8 @@ ObjectInfo CRmgTemplateZone::getRandomObject(CMapGenerator* gen, CTreasurePileIn
|
||||
}
|
||||
assert (0); //we should never be here
|
||||
}
|
||||
//FIXME: control reaches end of non-void function. Missing return?
|
||||
|
||||
return ObjectInfo(); // unreachable
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::addAllPossibleObjects(CMapGenerator* gen)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "CZonePlacer.h"
|
||||
#include "CRmgTemplateZone.h"
|
||||
#include "../mapping/CMap.h"
|
||||
|
||||
#include "CZoneGraphGenerator.h"
|
||||
|
||||
|
@ -12,8 +12,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CMapGenerator.h"
|
||||
#include "../mapping/CMap.h"
|
||||
|
||||
#include "float3.h"
|
||||
#include "../int3.h"
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "../BattleState.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CGameInfoCallback.h"
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../CPlayerState.h"
|
||||
|
||||
///SummonBoatMechanics
|
||||
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
|
||||
///HealingSpellMechanics
|
||||
void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
|
@ -640,7 +640,7 @@ std::string CSpell::AnimationInfo::selectProjectile(const double angle) const
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
///CSpell::TargetInfo
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user