mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-05 13:04:54 +02:00
Merged fixes from the branch.
This commit is contained in:
commit
0abbe71b25
@ -68,40 +68,38 @@
|
|||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\..\VCMI_global_debug.props" />
|
||||||
<Import Project="..\..\VCMI_global.props" />
|
<Import Project="..\..\VCMI_global.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\..\VCMI_global_debug.props" />
|
||||||
<Import Project="..\..\VCMI_global.props" />
|
<Import Project="..\..\VCMI_global.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="PropertySheets">
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="PropertySheets">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\..\VCMI_global_release.props" />
|
||||||
<Import Project="..\..\VCMI_global.props" />
|
<Import Project="..\..\VCMI_global.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="PropertySheets">
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="PropertySheets">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
<Import Project="..\..\VCMI_global_release.props" />
|
||||||
<Import Project="..\..\VCMI_global.props" />
|
<Import Project="..\..\VCMI_global.props" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<OutDir>..\..\..\AI</OutDir>
|
<OutDir>$(VCMI_Out)\AI\</OutDir>
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
<IncludePath>$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)\AI\</OutDir>
|
<OutDir>$(VCMI_Out)\AI\</OutDir>
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
|
||||||
<OutDir>$(SolutionDir)$(Configuration)\bin\AI\</OutDir>
|
<OutDir>$(VCMI_Out)\AI\</OutDir>
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
|
||||||
<OutDir>$(SolutionDir)$(Configuration)\bin\AI\</OutDir>
|
<OutDir>$(VCMI_Out)\AI\</OutDir>
|
||||||
<IncludePath>$(IncludePath)</IncludePath>
|
|
||||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
@ -116,7 +114,6 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>../..;../../../libs;../../..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -132,7 +129,6 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -146,13 +142,13 @@
|
|||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalOptions>/Zm130 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>G:\Programowanie\VCMI\RD;../../../libs;../../;E:\vcmi\rep - assembla\trunk;E:\C++\lua bin;E:\C++\boost_1_43_0\lib;E:\C++\SDL_mixer-1.2.7\lib;E:\C++\SDL_ttf-2.0.8\lib;E:\C++\zlib 1.2.3 binaries\lib;E:\C++\SDL-1.2.11\devlibs - visual\SDL-1.2.11\lib;F:\C++\SDL_Image 1.2.5\SDL_image-1.2.5\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
@ -166,13 +162,13 @@
|
|||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalOptions>/Zm130 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>VCMI_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
<OutputFile>$(OutDir)EmptyAI.dll</OutputFile>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
@ -493,12 +493,15 @@ void VCAI::showThievesGuildWindow (const CGObjectInstance * obj)
|
|||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::playerBlocked(int reason)
|
void VCAI::playerBlocked(int reason, bool start)
|
||||||
{
|
{
|
||||||
LOG_TRACE_PARAMS(logAi, "reason '%i'", reason);
|
LOG_TRACE_PARAMS(logAi, "reason '%i', start '%i'", reason % start);
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
if (reason == PlayerBlocked::UPCOMING_BATTLE)
|
if (start && reason == PlayerBlocked::UPCOMING_BATTLE)
|
||||||
status.setBattle(UPCOMING_BATTLE);
|
status.setBattle(UPCOMING_BATTLE);
|
||||||
|
|
||||||
|
if(reason == PlayerBlocked::ONGOING_MOVEMENT)
|
||||||
|
status.setMove(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::showPuzzleMap()
|
void VCAI::showPuzzleMap()
|
||||||
@ -571,15 +574,17 @@ void VCAI::artifactDisassembled(const ArtifactLocation &al)
|
|||||||
|
|
||||||
void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start)
|
void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start)
|
||||||
{
|
{
|
||||||
LOG_TRACE_PARAMS(logAi, "start '%i'", start);
|
LOG_TRACE_PARAMS(logAi, "start '%i'; obj '%s'", start % (visitedObj ? visitedObj->hoverName : std::string("n/a")));
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
if (start)
|
if(start)
|
||||||
{
|
{
|
||||||
markObjectVisited (visitedObj);
|
markObjectVisited (visitedObj);
|
||||||
erase_if_present(reservedObjs, visitedObj); //unreserve objects
|
erase_if_present(reservedObjs, visitedObj); //unreserve objects
|
||||||
erase_if_present(reservedHeroesMap[visitor], visitedObj);
|
erase_if_present(reservedHeroesMap[visitor], visitedObj);
|
||||||
completeGoal (CGoal(GET_OBJ).sethero(visitor)); //we don't need to visit in anymore
|
completeGoal (CGoal(GET_OBJ).sethero(visitor)); //we don't need to visit in anymore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status.heroVisit(visitedObj, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= nullptr*/)
|
void VCAI::availableArtifactsChanged(const CGBlackMarket *bm /*= nullptr*/)
|
||||||
@ -2629,6 +2634,7 @@ AIStatus::AIStatus()
|
|||||||
{
|
{
|
||||||
battle = NO_BATTLE;
|
battle = NO_BATTLE;
|
||||||
havingTurn = false;
|
havingTurn = false;
|
||||||
|
ongoingHeroMovement = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AIStatus::~AIStatus()
|
AIStatus::~AIStatus()
|
||||||
@ -2701,8 +2707,8 @@ void AIStatus::madeTurn()
|
|||||||
void AIStatus::waitTillFree()
|
void AIStatus::waitTillFree()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mx);
|
boost::unique_lock<boost::mutex> lock(mx);
|
||||||
while(battle != NO_BATTLE || remainingQueries.size())
|
while(battle != NO_BATTLE || remainingQueries.size() || objectsBeingVisited.size() || ongoingHeroMovement)
|
||||||
cv.wait(lock);
|
cv.timed_wait(lock, boost::posix_time::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AIStatus::haveTurn()
|
bool AIStatus::haveTurn()
|
||||||
@ -2738,6 +2744,26 @@ void AIStatus::receivedAnswerConfirmation(int answerRequestID, int result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AIStatus::heroVisit(const CGObjectInstance *obj, bool started)
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mx);
|
||||||
|
if(started)
|
||||||
|
objectsBeingVisited.push_back(obj);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(objectsBeingVisited.size() == 1);
|
||||||
|
objectsBeingVisited.clear();
|
||||||
|
}
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AIStatus::setMove(bool ongoing)
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mx);
|
||||||
|
ongoingHeroMovement = ongoing;
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
int3 whereToExplore(HeroPtr h)
|
int3 whereToExplore(HeroPtr h)
|
||||||
{
|
{
|
||||||
//TODO it's stupid and ineffective, write sth better
|
//TODO it's stupid and ineffective, write sth better
|
||||||
|
@ -75,6 +75,8 @@ class AIStatus
|
|||||||
BattleState battle;
|
BattleState battle;
|
||||||
std::map<QueryID, std::string> remainingQueries;
|
std::map<QueryID, std::string> remainingQueries;
|
||||||
std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query)
|
std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query)
|
||||||
|
std::vector<const CGObjectInstance*> objectsBeingVisited;
|
||||||
|
bool ongoingHeroMovement;
|
||||||
|
|
||||||
bool havingTurn;
|
bool havingTurn;
|
||||||
|
|
||||||
@ -82,6 +84,7 @@ public:
|
|||||||
AIStatus();
|
AIStatus();
|
||||||
~AIStatus();
|
~AIStatus();
|
||||||
void setBattle(BattleState BS);
|
void setBattle(BattleState BS);
|
||||||
|
void setMove(bool ongoing);
|
||||||
BattleState getBattle();
|
BattleState getBattle();
|
||||||
void addQuery(QueryID ID, std::string description);
|
void addQuery(QueryID ID, std::string description);
|
||||||
void removeQuery(QueryID ID);
|
void removeQuery(QueryID ID);
|
||||||
@ -92,6 +95,7 @@ public:
|
|||||||
bool haveTurn();
|
bool haveTurn();
|
||||||
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
|
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
|
||||||
void receivedAnswerConfirmation(int answerRequestID, int result);
|
void receivedAnswerConfirmation(int answerRequestID, int result);
|
||||||
|
void heroVisit(const CGObjectInstance *obj, bool started);
|
||||||
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@ -327,7 +331,7 @@ public:
|
|||||||
virtual void artifactAssembled(const ArtifactLocation &al) override;
|
virtual void artifactAssembled(const ArtifactLocation &al) override;
|
||||||
virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override;
|
virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override;
|
||||||
virtual void showThievesGuildWindow (const CGObjectInstance * obj) override;
|
virtual void showThievesGuildWindow (const CGObjectInstance * obj) override;
|
||||||
virtual void playerBlocked(int reason) override;
|
virtual void playerBlocked(int reason, bool start) override;
|
||||||
virtual void showPuzzleMap() override;
|
virtual void showPuzzleMap() override;
|
||||||
virtual void showShipyardDialog(const IShipyard *obj) override;
|
virtual void showShipyardDialog(const IShipyard *obj) override;
|
||||||
virtual void gameOver(PlayerColor player, bool victory) override;
|
virtual void gameOver(PlayerColor player, bool victory) override;
|
||||||
|
@ -601,6 +601,13 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID build
|
|||||||
castleInt->townlist->update(town);
|
castleInt->townlist->update(town);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlayerInterface::battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2)
|
||||||
|
{
|
||||||
|
//Don't wait for dialogs when we are non-active hot-seat player
|
||||||
|
if(LOCPLINT == this)
|
||||||
|
waitForAllDialogs();
|
||||||
|
}
|
||||||
|
|
||||||
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
|
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
@ -990,6 +997,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, CComponent * comp
|
|||||||
|
|
||||||
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<CComponent*> & components, int soundID, bool delComps)
|
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<CComponent*> & components, int soundID, bool delComps)
|
||||||
{
|
{
|
||||||
|
LOG_TRACE_PARAMS(logGlobal, "player=%s, text=%s, is LOCPLINT=%d", playerID % text % (this==LOCPLINT));
|
||||||
waitWhileDialog();
|
waitWhileDialog();
|
||||||
|
|
||||||
if (settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed())
|
if (settings["session"]["autoSkip"].Bool() && !LOCPLINT->shiftPressed())
|
||||||
|
@ -203,6 +203,7 @@ public:
|
|||||||
void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks
|
void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks
|
||||||
void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect
|
void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect
|
||||||
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override;
|
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override;
|
||||||
|
void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
|
||||||
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||||
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom) override; //called when stacks are healed / resurrected
|
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom) override; //called when stacks are healed / resurrected
|
||||||
void battleNewStackAppeared(const CStack * stack) override; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
void battleNewStackAppeared(const CStack * stack) override; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||||
|
@ -246,7 +246,7 @@ void DisassembledArtifact::applyCl( CClient *cl )
|
|||||||
void HeroVisit::applyCl( CClient *cl )
|
void HeroVisit::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
assert(hero);
|
assert(hero);
|
||||||
INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting);
|
INTERFACE_CALL_IF_PRESENT(player, heroVisit, hero, obj, starting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewTurn::applyCl( CClient *cl )
|
void NewTurn::applyCl( CClient *cl )
|
||||||
@ -600,6 +600,17 @@ void ExchangeDialog::applyCl(CClient *cl)
|
|||||||
INTERFACE_CALL_IF_PRESENT(heroes[0]->tempOwner, heroExchangeStarted, heroes[0]->id, heroes[1]->id, queryID);
|
INTERFACE_CALL_IF_PRESENT(heroes[0]->tempOwner, heroExchangeStarted, heroes[0]->id, heroes[1]->id, queryID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleStart::applyFirstCl( CClient *cl )
|
||||||
|
{
|
||||||
|
//Cannot use the usual macro because curB is not set yet
|
||||||
|
CALL_ONLY_THAT_BATTLE_INTERFACE(info->sides[0].color, battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject,
|
||||||
|
info->tile, info->sides[0].hero, info->sides[1].hero);
|
||||||
|
CALL_ONLY_THAT_BATTLE_INTERFACE(info->sides[1].color, battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject,
|
||||||
|
info->tile, info->sides[0].hero, info->sides[1].hero);
|
||||||
|
BATTLE_INTERFACE_CALL_RECEIVERS(battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject,
|
||||||
|
info->tile, info->sides[0].hero, info->sides[1].hero);
|
||||||
|
}
|
||||||
|
|
||||||
void BattleStart::applyCl( CClient *cl )
|
void BattleStart::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
cl->battleStarted(info);
|
cl->battleStarted(info);
|
||||||
@ -780,7 +791,7 @@ void SystemMessage::applyCl( CClient *cl )
|
|||||||
|
|
||||||
void PlayerBlocked::applyCl( CClient *cl )
|
void PlayerBlocked::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
INTERFACE_CALL_IF_PRESENT(player,playerBlocked,reason);
|
INTERFACE_CALL_IF_PRESENT(player,playerBlocked,reason, startOrEnd==BLOCKADE_STARTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void YourTurn::applyCl( CClient *cl )
|
void YourTurn::applyCl( CClient *cl )
|
||||||
|
@ -85,7 +85,9 @@ CBattleStackAnimation::CBattleStackAnimation(CBattleInterface * owner, const CSt
|
|||||||
: CBattleAnimation(owner),
|
: CBattleAnimation(owner),
|
||||||
myAnim(owner->creAnims[stack->ID]),
|
myAnim(owner->creAnims[stack->ID]),
|
||||||
stack(stack)
|
stack(stack)
|
||||||
{}
|
{
|
||||||
|
assert(myAnim);
|
||||||
|
}
|
||||||
|
|
||||||
void CAttackAnimation::nextFrame()
|
void CAttackAnimation::nextFrame()
|
||||||
{
|
{
|
||||||
|
@ -153,7 +153,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
//initializing armies
|
//initializing armies
|
||||||
this->army1 = army1;
|
this->army1 = army1;
|
||||||
this->army2 = army2;
|
this->army2 = army2;
|
||||||
std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks();
|
std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks(true);
|
||||||
for(const CStack *s : stacks)
|
for(const CStack *s : stacks)
|
||||||
{
|
{
|
||||||
newStack(s);
|
newStack(s);
|
||||||
@ -3652,7 +3652,7 @@ void CBattleInterface::showPiecesOfWall(SDL_Surface * to, std::vector<int> piece
|
|||||||
|
|
||||||
const CStack *turret = nullptr;
|
const CStack *turret = nullptr;
|
||||||
|
|
||||||
for(auto & stack : curInt->cb->battleGetAllStacks())
|
for(auto & stack : curInt->cb->battleGetAllStacks(true))
|
||||||
{
|
{
|
||||||
if(stack->position == stackPos)
|
if(stack->position == stackPos)
|
||||||
{
|
{
|
||||||
|
@ -177,11 +177,14 @@ bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TStacks CBattleInfoEssentials::battleGetAllStacks() const /*returns all stacks, alive or dead or undead or mechanical :) */
|
TStacks CBattleInfoEssentials::battleGetAllStacks(bool includeTurrets /*= false*/) const /*returns all stacks, alive or dead or undead or mechanical :) */
|
||||||
{
|
{
|
||||||
TStacks ret;
|
TStacks ret;
|
||||||
RETURN_IF_NOT_BATTLE(ret);
|
RETURN_IF_NOT_BATTLE(ret);
|
||||||
boost::copy(getBattle()->stacks, std::back_inserter(ret));
|
boost::copy(getBattle()->stacks, std::back_inserter(ret));
|
||||||
|
if(!includeTurrets)
|
||||||
|
vstd::erase_if(ret, [](const CStack *stack) { return stack->type->idNumber == CreatureID::ARROW_TOWERS; });
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +248,7 @@ const CStack* CBattleInfoEssentials::battleGetStackByID(int ID, bool onlyAlive)
|
|||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE(nullptr);
|
RETURN_IF_NOT_BATTLE(nullptr);
|
||||||
|
|
||||||
for(auto s : battleGetAllStacks())
|
for(auto s : battleGetAllStacks(true))
|
||||||
if(s->ID == ID && (!onlyAlive || s->alive()))
|
if(s->ID == ID && (!onlyAlive || s->alive()))
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
@ -512,7 +515,7 @@ SpellID CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERa
|
|||||||
const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyAlive) const
|
const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyAlive) const
|
||||||
{
|
{
|
||||||
RETURN_IF_NOT_BATTLE(nullptr);
|
RETURN_IF_NOT_BATTLE(nullptr);
|
||||||
for(auto s : battleGetAllStacks())
|
for(auto s : battleGetAllStacks(true))
|
||||||
if(vstd::contains(s->getHexes(), pos) && (!onlyAlive || s->alive()))
|
if(vstd::contains(s->getHexes(), pos) && (!onlyAlive || s->alive()))
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
@ -594,7 +597,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto allStacks = battleGetAllStacks();
|
auto allStacks = battleGetAllStacks(true);
|
||||||
if(!vstd::contains_if(allStacks, [](const CStack *stack) { return stack->willMove(100000); })) //little evil, but 100000 should be enough for all effects to disappear
|
if(!vstd::contains_if(allStacks, [](const CStack *stack) { return stack->willMove(100000); })) //little evil, but 100000 should be enough for all effects to disappear
|
||||||
{
|
{
|
||||||
//No stack will be able to move, battle is over.
|
//No stack will be able to move, battle is over.
|
||||||
@ -602,7 +605,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto s : battleGetAllStacks())
|
for(auto s : battleGetAllStacks(true))
|
||||||
{
|
{
|
||||||
if((turn <= 0 && !s->willMove()) //we are considering current round and stack won't move
|
if((turn <= 0 && !s->willMove()) //we are considering current round and stack won't move
|
||||||
|| (turn > 0 && !s->canMove(turn)) //stack won't be able to move in later rounds
|
|| (turn > 0 && !s->canMove(turn)) //stack won't be able to move in later rounds
|
||||||
|
@ -168,7 +168,7 @@ public:
|
|||||||
ETerrainType battleTerrainType() const;
|
ETerrainType battleTerrainType() const;
|
||||||
BFieldType battleGetBattlefieldType() const;
|
BFieldType battleGetBattlefieldType() const;
|
||||||
std::vector<shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
|
std::vector<shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
|
||||||
TStacks battleGetAllStacks() const; //returns all stacks, alive or dead or undead or mechanical :)
|
TStacks battleGetAllStacks(bool includeTurrets = false) const; //returns all stacks, alive or dead or undead or mechanical :)
|
||||||
bool battleHasNativeStack(ui8 side) const;
|
bool battleHasNativeStack(ui8 side) const;
|
||||||
si8 battleGetWallState(int partOfWall) const; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
si8 battleGetWallState(int partOfWall) const; //for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall, [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
|
||||||
int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
|
int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
|
||||||
|
@ -1369,6 +1369,10 @@ void CGameState::init(StartInfo * si)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Early check for #1444-like problems
|
||||||
|
for(auto building : vti->builtBuildings)
|
||||||
|
assert(vti->town->buildings[building]);
|
||||||
|
|
||||||
//town events
|
//town events
|
||||||
for(CCastleEvent &ev : vti->events)
|
for(CCastleEvent &ev : vti->events)
|
||||||
{
|
{
|
||||||
|
@ -2749,7 +2749,6 @@ void CGTownInstance::battleFinished(const CGHeroInstance *hero, const BattleResu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
|
bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
return vstd::contains(visitors, h->id);
|
return vstd::contains(visitors, h->id);
|
||||||
|
@ -634,6 +634,17 @@ public:
|
|||||||
|
|
||||||
h & town & townAndVis;
|
h & town & townAndVis;
|
||||||
BONUS_TREE_DESERIALIZATION_FIX
|
BONUS_TREE_DESERIALIZATION_FIX
|
||||||
|
|
||||||
|
vstd::erase_if(builtBuildings, [this](BuildingID building) -> bool
|
||||||
|
{
|
||||||
|
if(!town->buildings.count(building) || !town->buildings.at(building))
|
||||||
|
{
|
||||||
|
logGlobal->errorStream() << boost::format("#1444-like issue in CGTownInstance::serialize. From town %s at %s removing the bogus builtBuildings item %s")
|
||||||
|
% name % pos % building;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ public:
|
|||||||
//Fix #1444 corrupted save
|
//Fix #1444 corrupted save
|
||||||
while(auto badElem = vstd::tryFindIf(buildings, findNull))
|
while(auto badElem = vstd::tryFindIf(buildings, findNull))
|
||||||
{
|
{
|
||||||
std::cout << "#1444-like bug encountered, fixing buildings list by removing bogus entry " << badElem->first << " from " << faction->name << std::endl;
|
logGlobal->errorStream() << "#1444-like bug encountered in CTown::serialize, fixing buildings list by removing bogus entry " << badElem->first << " from " << faction->name;
|
||||||
buildings.erase(badElem->first);
|
buildings.erase(badElem->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
virtual void battleSpellCast(const BattleSpellCast *sc){};
|
virtual void battleSpellCast(const BattleSpellCast *sc){};
|
||||||
virtual void battleStacksEffectsSet(const SetStackEffect & sse){};//called when a specific effect is set to stacks
|
virtual void battleStacksEffectsSet(const SetStackEffect & sse){};//called when a specific effect is set to stacks
|
||||||
virtual void battleTriggerEffect(const BattleTriggerEffect & bte){}; //called for various one-shot effects
|
virtual void battleTriggerEffect(const BattleTriggerEffect & bte){}; //called for various one-shot effects
|
||||||
|
virtual void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) {}; //called just before battle start
|
||||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
|
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||||
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
|
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
|
||||||
virtual void battleNewStackAppeared(const CStack * stack){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
virtual void battleNewStackAppeared(const CStack * stack){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
|
||||||
@ -126,7 +127,7 @@ public:
|
|||||||
virtual void requestRealized(PackageApplied *pa){};
|
virtual void requestRealized(PackageApplied *pa){};
|
||||||
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
|
virtual void objectPropertyChanged(const SetObjectProperty * sop){}; //eg. mine has been flagged
|
||||||
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
|
virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
|
||||||
virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
|
virtual void playerBlocked(int reason, bool start){}; //reason: 0 - upcoming battle
|
||||||
virtual void gameOver(PlayerColor player, bool victory){}; //player lost or won the game
|
virtual void gameOver(PlayerColor player, bool victory){}; //player lost or won the game
|
||||||
virtual void playerStartsTurn(PlayerColor player){};
|
virtual void playerStartsTurn(PlayerColor player){};
|
||||||
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
|
virtual void showComp(const Component &comp, std::string message) {}; //display component in the advmapint infobox
|
||||||
|
@ -230,14 +230,16 @@ struct PlayerBlocked : public CPackForClient //96
|
|||||||
PlayerBlocked(){type = 96;};
|
PlayerBlocked(){type = 96;};
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
|
|
||||||
enum EReason { UPCOMING_BATTLE };
|
enum EReason { UPCOMING_BATTLE, ONGOING_MOVEMENT };
|
||||||
|
enum EMode { BLOCKADE_STARTED, BLOCKADE_ENDED };
|
||||||
|
|
||||||
EReason reason;
|
EReason reason;
|
||||||
|
EMode startOrEnd;
|
||||||
PlayerColor player;
|
PlayerColor player;
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & reason & player;
|
h & reason & startOrEnd & player;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1090,6 +1092,7 @@ struct HeroVisit : CPackForClient //531
|
|||||||
{
|
{
|
||||||
const CGHeroInstance *hero;
|
const CGHeroInstance *hero;
|
||||||
const CGObjectInstance *obj;
|
const CGObjectInstance *obj;
|
||||||
|
PlayerColor player; //if hero was killed during the visit, its color is already reset
|
||||||
bool starting; //false -> ending
|
bool starting; //false -> ending
|
||||||
|
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
@ -1097,7 +1100,7 @@ struct HeroVisit : CPackForClient //531
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & hero & obj & starting;
|
h & hero & obj & player & starting;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1360,6 +1363,8 @@ struct BattleInfo;
|
|||||||
struct BattleStart : public CPackForClient//3000
|
struct BattleStart : public CPackForClient//3000
|
||||||
{
|
{
|
||||||
BattleStart(){type = 3000;};
|
BattleStart(){type = 3000;};
|
||||||
|
|
||||||
|
void applyFirstCl(CClient *cl);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "CCreatureHandler.h"
|
#include "CCreatureHandler.h"
|
||||||
#include "CGameState.h"
|
#include "CGameState.h"
|
||||||
#include "BattleState.h"
|
#include "BattleState.h"
|
||||||
|
#include "CTownHandler.h"
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
@ -448,6 +449,7 @@ DLL_LINKAGE void NewStructures::applyGs( CGameState *gs )
|
|||||||
CGTownInstance *t = gs->getTown(tid);
|
CGTownInstance *t = gs->getTown(tid);
|
||||||
for(const auto & id : bid)
|
for(const auto & id : bid)
|
||||||
{
|
{
|
||||||
|
assert(t->town->buildings[id]);
|
||||||
t->builtBuildings.insert(id);
|
t->builtBuildings.insert(id);
|
||||||
}
|
}
|
||||||
t->builded = builded;
|
t->builded = builded;
|
||||||
|
@ -3253,13 +3253,18 @@ static EndAction end_action;
|
|||||||
|
|
||||||
bool CGameHandler::makeBattleAction( BattleAction &ba )
|
bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||||
{
|
{
|
||||||
logGlobal->errorStream() << "\tMaking action of type " << ba.actionType;
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
|
|
||||||
const CStack *stack = battleGetStackByID(ba.stackNumber); //may be nullptr if action is not about stack
|
const CStack *stack = battleGetStackByID(ba.stackNumber); //may be nullptr if action is not about stack
|
||||||
|
const CStack *destinationStack = ba.actionType == Battle::WALK_AND_ATTACK ? gs->curB->battleGetStackByPos(ba.additionalInfo)
|
||||||
|
: ba.actionType == Battle::SHOOT ? gs->curB->battleGetStackByPos(ba.destinationTile)
|
||||||
|
: nullptr;
|
||||||
const bool isAboutActiveStack = stack && (stack == battleActiveStack());
|
const bool isAboutActiveStack = stack && (stack == battleActiveStack());
|
||||||
|
|
||||||
|
logGlobal->traceStream() << boost::format(
|
||||||
|
"Making action: type=%d; side=%d; stack=%s; dst=%s; additionalInfo=%d; stackAtDst=%s")
|
||||||
|
% ba.actionType % (int)ba.side % (stack ? stack->getName() : std::string("none"))
|
||||||
|
% ba.destinationTile % ba.additionalInfo % (destinationStack ? destinationStack->getName() : std::string("none"));
|
||||||
|
|
||||||
switch(ba.actionType)
|
switch(ba.actionType)
|
||||||
{
|
{
|
||||||
@ -3370,8 +3375,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
StartAction start_action(ba);
|
StartAction start_action(ba);
|
||||||
sendAndApply(&start_action); //start movement and attack
|
sendAndApply(&start_action); //start movement and attack
|
||||||
|
|
||||||
const CStack *stackAtEnd = gs->curB->battleGetStackByPos(ba.additionalInfo);
|
if(!stack || !destinationStack)
|
||||||
if(!stack || !stackAtEnd)
|
|
||||||
{
|
{
|
||||||
sendAndApply(&end_action);
|
sendAndApply(&end_action);
|
||||||
break;
|
break;
|
||||||
@ -3380,7 +3384,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
BattleHex startingPos = stack->position;
|
BattleHex startingPos = stack->position;
|
||||||
int distance = moveStack(ba.stackNumber, ba.destinationTile);
|
int distance = moveStack(ba.stackNumber, ba.destinationTile);
|
||||||
|
|
||||||
logGlobal->traceStream() << stack->nodeName() << " will attack " << stackAtEnd->nodeName();
|
logGlobal->traceStream() << stack->nodeName() << " will attack " << destinationStack->nodeName();
|
||||||
|
|
||||||
if(stack->position != ba.destinationTile //we wasn't able to reach destination tile
|
if(stack->position != ba.destinationTile //we wasn't able to reach destination tile
|
||||||
&& !(stack->doubleWide()
|
&& !(stack->doubleWide()
|
||||||
@ -3396,12 +3400,12 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stackAtEnd && stack->ID == stackAtEnd->ID) //we should just move, it will be handled by following check
|
if(destinationStack && stack->ID == destinationStack->ID) //we should just move, it will be handled by following check
|
||||||
{
|
{
|
||||||
stackAtEnd = nullptr;
|
destinationStack = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!stackAtEnd)
|
if(!destinationStack)
|
||||||
{
|
{
|
||||||
complain(boost::str(boost::format("walk and attack error: no stack at additionalInfo tile (%d)!\n") % ba.additionalInfo));
|
complain(boost::str(boost::format("walk and attack error: no stack at additionalInfo tile (%d)!\n") % ba.additionalInfo));
|
||||||
ok = false;
|
ok = false;
|
||||||
@ -3409,7 +3413,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !CStack::isMeleeAttackPossible(stack, stackAtEnd) )
|
if( !CStack::isMeleeAttackPossible(stack, destinationStack) )
|
||||||
{
|
{
|
||||||
complain("Attack cannot be performed!");
|
complain("Attack cannot be performed!");
|
||||||
sendAndApply(&end_action);
|
sendAndApply(&end_action);
|
||||||
@ -3426,10 +3430,10 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
if (stack &&
|
if (stack &&
|
||||||
stack->alive() && //move can cause death, eg. by walking into the moat
|
stack->alive() && //move can cause death, eg. by walking into the moat
|
||||||
stackAtEnd->alive())
|
destinationStack->alive())
|
||||||
{
|
{
|
||||||
BattleAttack bat;
|
BattleAttack bat;
|
||||||
prepareAttack(bat, stack, stackAtEnd, (i ? 0 : distance), ba.additionalInfo); //no distance travelled on second attack
|
prepareAttack(bat, stack, destinationStack, (i ? 0 : distance), ba.additionalInfo); //no distance travelled on second attack
|
||||||
//prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo);
|
//prepareAttack(bat, stack, stackAtEnd, 0, ba.additionalInfo);
|
||||||
handleAttackBeforeCasting(bat); //only before first attack
|
handleAttackBeforeCasting(bat); //only before first attack
|
||||||
sendAndApply(&bat);
|
sendAndApply(&bat);
|
||||||
@ -3437,13 +3441,13 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//counterattack
|
//counterattack
|
||||||
if (stackAtEnd
|
if (destinationStack
|
||||||
&& !stack->hasBonusOfType(Bonus::BLOCKS_RETALIATION)
|
&& !stack->hasBonusOfType(Bonus::BLOCKS_RETALIATION)
|
||||||
&& stackAtEnd->ableToRetaliate()
|
&& destinationStack->ableToRetaliate()
|
||||||
&& stack->alive()) //attacker may have died (fire shield)
|
&& stack->alive()) //attacker may have died (fire shield)
|
||||||
{
|
{
|
||||||
BattleAttack bat;
|
BattleAttack bat;
|
||||||
prepareAttack(bat, stackAtEnd, stack, 0, stack->position);
|
prepareAttack(bat, destinationStack, stack, 0, stack->position);
|
||||||
bat.flags |= BattleAttack::COUNTER;
|
bat.flags |= BattleAttack::COUNTER;
|
||||||
sendAndApply(&bat);
|
sendAndApply(&bat);
|
||||||
handleAfterAttackCasting(bat);
|
handleAfterAttackCasting(bat);
|
||||||
@ -3462,7 +3466,6 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
}
|
}
|
||||||
case Battle::SHOOT:
|
case Battle::SHOOT:
|
||||||
{
|
{
|
||||||
const CStack *destStack= gs->curB->battleGetStackByPos(ba.destinationTile);
|
|
||||||
if( !gs->curB->battleCanShoot(stack, ba.destinationTile) )
|
if( !gs->curB->battleCanShoot(stack, ba.destinationTile) )
|
||||||
{
|
{
|
||||||
complain("Cannot shoot!");
|
complain("Cannot shoot!");
|
||||||
@ -3475,7 +3478,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
BattleAttack bat;
|
BattleAttack bat;
|
||||||
bat.flags |= BattleAttack::SHOT;
|
bat.flags |= BattleAttack::SHOT;
|
||||||
prepareAttack(bat, stack, destStack, 0, ba.destinationTile);
|
prepareAttack(bat, stack, destinationStack, 0, ba.destinationTile);
|
||||||
handleAttackBeforeCasting(bat);
|
handleAttackBeforeCasting(bat);
|
||||||
sendAndApply(&bat);
|
sendAndApply(&bat);
|
||||||
handleAfterAttackCasting(bat);
|
handleAfterAttackCasting(bat);
|
||||||
@ -3485,14 +3488,14 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
|
|
||||||
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
const CGHeroInstance * attackingHero = gs->curB->battleGetFightingHero(ba.side);
|
||||||
|
|
||||||
if( destStack->alive()
|
if( destinationStack->alive()
|
||||||
&& (stack->getCreature()->idNumber == CreatureID::BALLISTA)
|
&& (stack->getCreature()->idNumber == CreatureID::BALLISTA)
|
||||||
&& (attackingHero->getSecSkillLevel(SecondarySkill::ARTILLERY) >= SecSkillLevel::ADVANCED)
|
&& (attackingHero->getSecSkillLevel(SecondarySkill::ARTILLERY) >= SecSkillLevel::ADVANCED)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BattleAttack bat2;
|
BattleAttack bat2;
|
||||||
bat2.flags |= BattleAttack::SHOT;
|
bat2.flags |= BattleAttack::SHOT;
|
||||||
prepareAttack(bat2, stack, destStack, 0, ba.destinationTile);
|
prepareAttack(bat2, stack, destinationStack, 0, ba.destinationTile);
|
||||||
sendAndApply(&bat2);
|
sendAndApply(&bat2);
|
||||||
}
|
}
|
||||||
//allow more than one additional attack
|
//allow more than one additional attack
|
||||||
@ -3503,13 +3506,13 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
if(
|
if(
|
||||||
stack->alive()
|
stack->alive()
|
||||||
&& destStack->alive()
|
&& destinationStack->alive()
|
||||||
&& stack->shots
|
&& stack->shots
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BattleAttack bat;
|
BattleAttack bat;
|
||||||
bat.flags |= BattleAttack::SHOT;
|
bat.flags |= BattleAttack::SHOT;
|
||||||
prepareAttack(bat, stack, destStack, 0, ba.destinationTile);
|
prepareAttack(bat, stack, destinationStack, 0, ba.destinationTile);
|
||||||
sendAndApply(&bat);
|
sendAndApply(&bat);
|
||||||
handleAfterAttackCasting(bat);
|
handleAfterAttackCasting(bat);
|
||||||
}
|
}
|
||||||
@ -4983,6 +4986,7 @@ void CGameHandler::objectVisited( const CGObjectInstance * obj, const CGHeroInst
|
|||||||
HeroVisit hv;
|
HeroVisit hv;
|
||||||
hv.obj = obj;
|
hv.obj = obj;
|
||||||
hv.hero = h;
|
hv.hero = h;
|
||||||
|
hv.player = h->tempOwner;
|
||||||
hv.starting = true;
|
hv.starting = true;
|
||||||
sendAndApply(&hv);
|
sendAndApply(&hv);
|
||||||
|
|
||||||
@ -4996,6 +5000,7 @@ void CGameHandler::objectVisitEnded(const CObjectVisitQuery &query)
|
|||||||
logGlobal->traceStream() << query.visitingHero->nodeName() << " visit ends.\n";
|
logGlobal->traceStream() << query.visitingHero->nodeName() << " visit ends.\n";
|
||||||
|
|
||||||
HeroVisit hv;
|
HeroVisit hv;
|
||||||
|
hv.player = query.players.front();
|
||||||
hv.obj = nullptr; //not necessary, moreover may have been deleted in the meantime
|
hv.obj = nullptr; //not necessary, moreover may have been deleted in the meantime
|
||||||
hv.hero = query.visitingHero;
|
hv.hero = query.visitingHero;
|
||||||
assert(hv.hero);
|
assert(hv.hero);
|
||||||
@ -5059,6 +5064,7 @@ void CGameHandler::engageIntoBattle( PlayerColor player )
|
|||||||
PlayerBlocked pb;
|
PlayerBlocked pb;
|
||||||
pb.player = player;
|
pb.player = player;
|
||||||
pb.reason = PlayerBlocked::UPCOMING_BATTLE;
|
pb.reason = PlayerBlocked::UPCOMING_BATTLE;
|
||||||
|
pb.startOrEnd = PlayerBlocked::BLOCKADE_STARTED;
|
||||||
sendAndApply(&pb);
|
sendAndApply(&pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,11 @@ void CQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
|||||||
gh->queries.popQuery(*this);
|
gh->queries.popQuery(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CQuery::onAdding(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile)
|
CObjectVisitQuery::CObjectVisitQuery(const CGObjectInstance *Obj, const CGHeroInstance *Hero, int3 Tile)
|
||||||
: visitedObject(Obj), visitingHero(Hero), tile(Tile), removeObjectAfterVisit(false)
|
: visitedObject(Obj), visitingHero(Hero), tile(Tile), removeObjectAfterVisit(false)
|
||||||
{
|
{
|
||||||
@ -169,6 +174,7 @@ void Queries::addQuery(QueryPtr query)
|
|||||||
void Queries::addQuery(PlayerColor player, QueryPtr query)
|
void Queries::addQuery(PlayerColor player, QueryPtr query)
|
||||||
{
|
{
|
||||||
LOG_TRACE_PARAMS(logGlobal, "player='%s', query='%s'", player % query);
|
LOG_TRACE_PARAMS(logGlobal, "player='%s', query='%s'", player % query);
|
||||||
|
query->onAdding(gh, player);
|
||||||
queries[player].push_back(query);
|
queries[player].push_back(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,3 +378,21 @@ void CHeroMovementQuery::onExposure(CGameHandler *gh, QueryPtr topQuery)
|
|||||||
|
|
||||||
gh->queries.popIfTop(*this);
|
gh->queries.popIfTop(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHeroMovementQuery::onRemoval(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
PlayerBlocked pb;
|
||||||
|
pb.player = color;
|
||||||
|
pb.reason = PlayerBlocked::ONGOING_MOVEMENT;
|
||||||
|
pb.startOrEnd = PlayerBlocked::BLOCKADE_ENDED;
|
||||||
|
gh->sendAndApply(&pb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHeroMovementQuery::onAdding(CGameHandler *gh, PlayerColor color)
|
||||||
|
{
|
||||||
|
PlayerBlocked pb;
|
||||||
|
pb.player = color;
|
||||||
|
pb.reason = PlayerBlocked::ONGOING_MOVEMENT;
|
||||||
|
pb.startOrEnd = PlayerBlocked::BLOCKADE_STARTED;
|
||||||
|
gh->sendAndApply(&pb);
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@ public:
|
|||||||
virtual bool blocksPack(const CPack *pack) const; //query can block attempting actions by player. Eg. he can't move hero during the battle.
|
virtual bool blocksPack(const CPack *pack) const; //query can block attempting actions by player. Eg. he can't move hero during the battle.
|
||||||
|
|
||||||
virtual bool endsByPlayerAnswer() const; //query is removed after player gives answer (like dialogs)
|
virtual bool endsByPlayerAnswer() const; //query is removed after player gives answer (like dialogs)
|
||||||
|
virtual void onAdding(CGameHandler *gh, PlayerColor color); //called just before query is pushed on stack
|
||||||
virtual void onRemoval(CGameHandler *gh, PlayerColor color); //called after query is removed from stack
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color); //called after query is removed from stack
|
||||||
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);//called when query immediately above is removed and this is exposed (becomes top)
|
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);//called when query immediately above is removed and this is exposed (becomes top)
|
||||||
virtual std::string toString() const;
|
virtual std::string toString() const;
|
||||||
@ -98,6 +99,8 @@ public:
|
|||||||
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);
|
virtual void onExposure(CGameHandler *gh, QueryPtr topQuery);
|
||||||
|
|
||||||
CHeroMovementQuery(const TryMoveHero &Tmh, const CGHeroInstance *Hero, bool VisitDestAfterVictory = false);
|
CHeroMovementQuery(const TryMoveHero &Tmh, const CGHeroInstance *Hero, bool VisitDestAfterVictory = false);
|
||||||
|
virtual void onAdding(CGameHandler *gh, PlayerColor color) override;
|
||||||
|
virtual void onRemoval(CGameHandler *gh, PlayerColor color) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDialogQuery : public CQuery
|
class CDialogQuery : public CQuery
|
||||||
|
Loading…
x
Reference in New Issue
Block a user