mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
Some very early work towards autofight feature.
Added EmptyAI to the solution. Passing callbacks by shared_ptr.
This commit is contained in:
parent
06dbdd234f
commit
254f194220
@ -8,7 +8,7 @@
|
|||||||
#include "../../lib/VCMI_Lib.h"
|
#include "../../lib/VCMI_Lib.h"
|
||||||
|
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
CBattleCallback * cbc;
|
shared_ptr<CBattleCallback> cbc;
|
||||||
|
|
||||||
#define LOGL(text) print(text)
|
#define LOGL(text) print(text)
|
||||||
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl))
|
#define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl))
|
||||||
@ -85,7 +85,7 @@ CBattleAI::~CBattleAI(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleAI::init( CBattleCallback * CB )
|
void CBattleAI::init(shared_ptr<CBattleCallback> CB)
|
||||||
{
|
{
|
||||||
print("init called, saving ptr to IBattleCallback");
|
print("init called, saving ptr to IBattleCallback");
|
||||||
cbc = cb = CB;
|
cbc = cb = CB;
|
||||||
|
@ -109,7 +109,7 @@ struct PotentialTargets
|
|||||||
class CBattleAI : public CBattleGameInterface
|
class CBattleAI : public CBattleGameInterface
|
||||||
{
|
{
|
||||||
int side;
|
int side;
|
||||||
CBattleCallback *cb;
|
shared_ptr<CBattleCallback> cb;
|
||||||
|
|
||||||
//Previous setting of cb
|
//Previous setting of cb
|
||||||
bool wasWaitingForRealize, wasUnlockingGs;
|
bool wasWaitingForRealize, wasUnlockingGs;
|
||||||
@ -119,7 +119,7 @@ public:
|
|||||||
CBattleAI(void);
|
CBattleAI(void);
|
||||||
~CBattleAI(void);
|
~CBattleAI(void);
|
||||||
|
|
||||||
void init(CBattleCallback * CB) OVERRIDE;
|
void init(shared_ptr<CBattleCallback> CB) OVERRIDE;
|
||||||
void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
|
void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
|
||||||
void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
|
void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
|
||||||
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
|
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CEmptyAI.h"
|
#include "CEmptyAI.h"
|
||||||
|
|
||||||
void CEmptyAI::init(CCallback * CB)
|
void CEmptyAI::init(shared_ptr<CCallback> CB)
|
||||||
{
|
{
|
||||||
cb = CB;
|
cb = CB;
|
||||||
human=false;
|
human=false;
|
||||||
|
@ -7,10 +7,10 @@ struct HeroMoveDetails;
|
|||||||
|
|
||||||
class CEmptyAI : public CGlobalAI
|
class CEmptyAI : public CGlobalAI
|
||||||
{
|
{
|
||||||
CCallback *cb;
|
shared_ptr<CCallback> cb;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(CCallback * CB) override;
|
void init(shared_ptr<CCallback> CB) override;
|
||||||
void yourTurn() override;
|
void yourTurn() override;
|
||||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||||
|
@ -41,23 +41,27 @@
|
|||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v110</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v110</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v110_xp</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<PlatformToolset>v110_xp</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
@ -106,7 +110,8 @@
|
|||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalOptions>/Zm130 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
@ -122,7 +127,7 @@
|
|||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
@ -140,7 +145,7 @@
|
|||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
@ -160,7 +165,7 @@
|
|||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/CCreatureHandler.h"
|
#include "../../lib/CCreatureHandler.h"
|
||||||
|
|
||||||
CPlayerBattleCallback * cbc;
|
shared_ptr<CBattleCallback> cbc;
|
||||||
|
|
||||||
CStupidAI::CStupidAI(void)
|
CStupidAI::CStupidAI(void)
|
||||||
: side(-1), cb(NULL)
|
: side(-1), cb(NULL)
|
||||||
@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void)
|
|||||||
print("destroyed");
|
print("destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStupidAI::init( CBattleCallback * CB )
|
void CStupidAI::init(shared_ptr<CBattleCallback> CB)
|
||||||
{
|
{
|
||||||
print("init called, saving ptr to IBattleCallback");
|
print("init called, saving ptr to IBattleCallback");
|
||||||
cbc = cb = CB;
|
cbc = cb = CB;
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
class CStupidAI : public CBattleGameInterface
|
class CStupidAI : public CBattleGameInterface
|
||||||
{
|
{
|
||||||
int side;
|
int side;
|
||||||
CBattleCallback *cb;
|
shared_ptr<CBattleCallback> cb;
|
||||||
|
|
||||||
void print(const std::string &text) const;
|
void print(const std::string &text) const;
|
||||||
public:
|
public:
|
||||||
CStupidAI(void);
|
CStupidAI(void);
|
||||||
~CStupidAI(void);
|
~CStupidAI(void);
|
||||||
|
|
||||||
void init(CBattleCallback * CB) OVERRIDE;
|
void init(shared_ptr<CBattleCallback> CB) OVERRIDE;
|
||||||
void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
|
void actionFinished(const BattleAction &action) OVERRIDE;//occurs AFTER every action taken by any stack or by the hero
|
||||||
void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
|
void actionStarted(const BattleAction &action) OVERRIDE;//occurs BEFORE every action taken by any stack or by the hero
|
||||||
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
|
BattleAction activeStack(const CStack * stack) OVERRIDE; //called when it's turn of that stack
|
||||||
|
@ -34,7 +34,7 @@ struct SetGlobalState
|
|||||||
assert(!cb.get());
|
assert(!cb.get());
|
||||||
|
|
||||||
ai.reset(AI);
|
ai.reset(AI);
|
||||||
cb.reset(AI->myCb);
|
cb.reset(AI->myCb.get());
|
||||||
}
|
}
|
||||||
~SetGlobalState()
|
~SetGlobalState()
|
||||||
{
|
{
|
||||||
@ -823,7 +823,7 @@ void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor
|
|||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::init(CCallback * CB)
|
void VCAI::init(shared_ptr<CCallback> CB)
|
||||||
{
|
{
|
||||||
LOG_TRACE(logAi);
|
LOG_TRACE(logAi);
|
||||||
myCb = CB;
|
myCb = CB;
|
||||||
|
@ -291,7 +291,7 @@ public:
|
|||||||
AIStatus status;
|
AIStatus status;
|
||||||
std::string battlename;
|
std::string battlename;
|
||||||
|
|
||||||
CCallback *myCb;
|
shared_ptr<CCallback> myCb;
|
||||||
|
|
||||||
unique_ptr<boost::thread> makingTurn;
|
unique_ptr<boost::thread> makingTurn;
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ public:
|
|||||||
|
|
||||||
virtual std::string getBattleAIName() const OVERRIDE;
|
virtual std::string getBattleAIName() const OVERRIDE;
|
||||||
|
|
||||||
virtual void init(CCallback * CB) OVERRIDE;
|
virtual void init(shared_ptr<CCallback> CB) OVERRIDE;
|
||||||
virtual void yourTurn() OVERRIDE;
|
virtual void yourTurn() OVERRIDE;
|
||||||
|
|
||||||
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) OVERRIDE; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) OVERRIDE; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||||
|
@ -35,6 +35,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Editor", "editor\Editor.vcx
|
|||||||
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
|
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmptyAI", "AI\EmptyAI\EmptyAI.vcxproj", "{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
@ -146,6 +151,18 @@ Global
|
|||||||
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.ActiveCfg = Release|Win32
|
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32
|
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|Win32.Build.0 = Release|Win32
|
||||||
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|Win32
|
{B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|Win32.ActiveCfg = RD|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|Win32.Build.0 = RD|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|x64.ActiveCfg = RD|x64
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.RD|x64.Build.0 = RD|x64
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|Win32.ActiveCfg = RD|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|Win32.Build.0 = RD|Win32
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|x64.ActiveCfg = RD|x64
|
||||||
|
{C41C4EB6-6F74-4F37-9FB0-9FA6BF377837}.Release|x64.Build.0 = RD|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -135,9 +135,9 @@ CPlayerInterface::~CPlayerInterface()
|
|||||||
|
|
||||||
LOCPLINT = NULL;
|
LOCPLINT = NULL;
|
||||||
}
|
}
|
||||||
void CPlayerInterface::init(CCallback * CB)
|
void CPlayerInterface::init(shared_ptr<CCallback> CB)
|
||||||
{
|
{
|
||||||
cb = dynamic_cast<CCallback*>(CB);
|
cb = CB;
|
||||||
if(observerInDuelMode)
|
if(observerInDuelMode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
static CBattleInterface * battleInt; //NULL if no battle
|
static CBattleInterface * battleInt; //NULL if no battle
|
||||||
CInGameConsole * cingconsole;
|
CInGameConsole * cingconsole;
|
||||||
|
|
||||||
CCallback * cb; //to communicate with engine
|
shared_ptr<CCallback> cb; //to communicate with engine
|
||||||
const BattleAction *curAction; //during the battle - action currently performed by active stack (or NULL)
|
const BattleAction *curAction; //during the battle - action currently performed by active stack (or NULL)
|
||||||
|
|
||||||
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
std::list<CInfoWindow *> dialogs; //queue of dialogs awaiting to be shown (not currently shown!)
|
||||||
@ -221,7 +221,7 @@ public:
|
|||||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||||
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||||
void updateInfo(const CGObjectInstance * specific);
|
void updateInfo(const CGObjectInstance * specific);
|
||||||
void init(CCallback * CB);
|
void init(shared_ptr<CCallback> CB);
|
||||||
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
||||||
void showInfoDialog(const std::string &text, CComponent * component);
|
void showInfoDialog(const std::string &text, CComponent * component);
|
||||||
void showInfoDialog(const std::string &text, const std::vector<CComponent*> & components = std::vector<CComponent*>(), int soundID = 0, bool delComps = false);
|
void showInfoDialog(const std::string &text, const std::vector<CComponent*> & components = std::vector<CComponent*>(), int soundID = 0, bool delComps = false);
|
||||||
|
@ -91,7 +91,6 @@ void CClient::init()
|
|||||||
IObjectInterface::cb = this;
|
IObjectInterface::cb = this;
|
||||||
serv = nullptr;
|
serv = nullptr;
|
||||||
gs = nullptr;
|
gs = nullptr;
|
||||||
cb = nullptr;
|
|
||||||
erm = nullptr;
|
erm = nullptr;
|
||||||
terminate = false;
|
terminate = false;
|
||||||
}
|
}
|
||||||
@ -216,6 +215,7 @@ void CClient::endGame( bool closeConnection /*= true*/ )
|
|||||||
}
|
}
|
||||||
|
|
||||||
callbacks.clear();
|
callbacks.clear();
|
||||||
|
battleCallbacks.clear();
|
||||||
logNetwork->infoStream() << "Deleted playerInts.";
|
logNetwork->infoStream() << "Deleted playerInts.";
|
||||||
|
|
||||||
logNetwork->infoStream() << "Client stopped.";
|
logNetwork->infoStream() << "Client stopped.";
|
||||||
@ -372,7 +372,6 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
}
|
}
|
||||||
|
|
||||||
int humanPlayers = 0;
|
int humanPlayers = 0;
|
||||||
int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I;
|
|
||||||
for(auto it = gs->scenarioOps->playerInfos.begin();
|
for(auto it = gs->scenarioOps->playerInfos.begin();
|
||||||
it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players
|
it != gs->scenarioOps->playerInfos.end(); ++it)//initializing interfaces for players
|
||||||
{
|
{
|
||||||
@ -384,45 +383,22 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
logNetwork->traceStream() << "Preparing interface for player " << color;
|
logNetwork->traceStream() << "Preparing interface for player " << color;
|
||||||
if(si->mode != StartInfo::DUEL)
|
if(si->mode != StartInfo::DUEL)
|
||||||
{
|
{
|
||||||
auto cb = make_shared<CCallback>(gs,color,this);
|
|
||||||
if(it->second.playerID == PlayerSettings::PLAYER_AI)
|
if(it->second.playerID == PlayerSettings::PLAYER_AI)
|
||||||
{
|
{
|
||||||
std::string AItoGive = settings["server"]["playerAI"].String();
|
auto AiToGive = aiNameForPlayer(it->second, false);
|
||||||
if(!sensibleAILimit)
|
logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive;
|
||||||
AItoGive = "EmptyAI";
|
installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
|
||||||
else
|
|
||||||
sensibleAILimit--;
|
|
||||||
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive));
|
|
||||||
logNetwork->infoStream() << "Player " << static_cast<int>(color.getNum()) << " will be lead by " << AItoGive;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
playerint[color] = new CPlayerInterface(color);
|
installNewPlayerInterface(new CPlayerInterface(color), color);
|
||||||
humanPlayers++;
|
humanPlayers++;
|
||||||
}
|
}
|
||||||
battleints[color] = playerint[color];
|
|
||||||
|
|
||||||
logNetwork->traceStream() << "\tInitializing the interface";
|
|
||||||
playerint[color]->init(cb.get());
|
|
||||||
battleCallbacks[color] = callbacks[color] = cb;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto cbc = make_shared<CBattleCallback>(gs, color, this);
|
std::string AItoGive = aiNameForPlayer(it->second, true);
|
||||||
battleCallbacks[color] = cbc;
|
installNewBattleInterface(CDynLibHandler::getNewBattleAI(AItoGive), color);
|
||||||
|
|
||||||
std::string AItoGive = it->second.name;
|
|
||||||
if(AItoGive.empty())
|
|
||||||
{
|
|
||||||
if(color == PlayerColor(0))
|
|
||||||
battleints[color] = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
|
||||||
else
|
|
||||||
battleints[color] = CDynLibHandler::getNewBattleAI("StupidAI");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
battleints[color] = CDynLibHandler::getNewBattleAI(AItoGive);
|
|
||||||
battleints[color]->init(cbc.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,12 +409,8 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL);
|
CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL);
|
||||||
p->observerInDuelMode = true;
|
p->observerInDuelMode = true;
|
||||||
battleints[PlayerColor::UNFLAGGABLE] = playerint[PlayerColor::UNFLAGGABLE] = p;
|
installNewPlayerInterface(p, boost::none);
|
||||||
privilagedBattleEventReceivers.push_back(p);
|
|
||||||
GH.curInt = p;
|
GH.curInt = p;
|
||||||
auto cb = make_shared<CCallback>(gs, boost::optional<PlayerColor>(), this);
|
|
||||||
battleCallbacks[PlayerColor::NEUTRAL] = callbacks[PlayerColor::NEUTRAL] = cb;
|
|
||||||
p->init(cb.get());
|
|
||||||
}
|
}
|
||||||
battleStarted(gs->curB);
|
battleStarted(gs->curB);
|
||||||
}
|
}
|
||||||
@ -502,10 +474,7 @@ void CClient::serialize( Handler &h, const int version )
|
|||||||
{
|
{
|
||||||
if(pid == PlayerColor::NEUTRAL)
|
if(pid == PlayerColor::NEUTRAL)
|
||||||
{
|
{
|
||||||
//CBattleCallback * cbc = new CBattleCallback(gs, pid, this);//FIXME: unused?
|
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
|
||||||
CBattleGameInterface *cbgi = CDynLibHandler::getNewBattleAI(dllname);
|
|
||||||
battleints[pid] = cbgi;
|
|
||||||
cbgi->init(cb);
|
|
||||||
//TODO? consider serialization
|
//TODO? consider serialization
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -525,9 +494,7 @@ void CClient::serialize( Handler &h, const int version )
|
|||||||
nInt->human = isHuman;
|
nInt->human = isHuman;
|
||||||
nInt->playerID = pid;
|
nInt->playerID = pid;
|
||||||
|
|
||||||
battleCallbacks[pid] = callbacks[pid] = make_shared<CCallback>(gs,pid,this);
|
installNewPlayerInterface(nInt, pid);
|
||||||
battleints[pid] = playerint[pid] = nInt;
|
|
||||||
nInt->init(callbacks[pid].get());
|
|
||||||
nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above
|
nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,10 +625,7 @@ void CClient::battleFinished()
|
|||||||
|
|
||||||
void CClient::loadNeutralBattleAI()
|
void CClient::loadNeutralBattleAI()
|
||||||
{
|
{
|
||||||
battleints[PlayerColor::NEUTRAL] = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
installNewBattleInterface(CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()), PlayerColor::NEUTRAL);
|
||||||
auto cbc = make_shared<CBattleCallback>(gs, PlayerColor::NEUTRAL, this);
|
|
||||||
battleCallbacks[PlayerColor::NEUTRAL] = cbc;
|
|
||||||
battleints[PlayerColor::NEUTRAL]->init(cbc.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::commitPackage( CPackForClient *pack )
|
void CClient::commitPackage( CPackForClient *pack )
|
||||||
@ -746,6 +710,65 @@ void CClient::campaignMapFinished( shared_ptr<CCampaignState> camp )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color)
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
|
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||||
|
|
||||||
|
if(!color)
|
||||||
|
privilagedGameEventReceivers.push_back(gameInterface);
|
||||||
|
|
||||||
|
playerint[colorUsed] = gameInterface;
|
||||||
|
|
||||||
|
logGlobal->traceStream() << boost::format("\tInitializing the interface for player %s") % colorUsed;
|
||||||
|
auto cb = make_shared<CCallback>(gs, color, this);
|
||||||
|
callbacks[colorUsed] = cb;
|
||||||
|
battleCallbacks[colorUsed] = cb;
|
||||||
|
gameInterface->init(cb);
|
||||||
|
|
||||||
|
installNewBattleInterface(gameInterface, color, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback /*= true*/)
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||||
|
PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE);
|
||||||
|
|
||||||
|
if(!color)
|
||||||
|
privilagedBattleEventReceivers.push_back(battleInterface);
|
||||||
|
|
||||||
|
battleints[colorUsed] = battleInterface;
|
||||||
|
|
||||||
|
if(needCallback)
|
||||||
|
{
|
||||||
|
logGlobal->traceStream() << boost::format("\tInitializing the battle interface for player %s") % *color;
|
||||||
|
auto cbc = make_shared<CBattleCallback>(gs, color, this);
|
||||||
|
battleCallbacks[colorUsed] = cbc;
|
||||||
|
battleInterface->init(cbc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CClient::aiNameForPlayer(const PlayerSettings &ps, bool battleAI)
|
||||||
|
{
|
||||||
|
if(ps.name.size())
|
||||||
|
{
|
||||||
|
std::string filename = VCMIDirs::get().libraryPath() + "/AI/" + VCMIDirs::get().libraryName(ps.name);
|
||||||
|
if(boost::filesystem::exists(filename))
|
||||||
|
return ps.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I;
|
||||||
|
std::string goodAI = battleAI ? settings["server"]["neutralAI"].String() : settings["server"]["playerAI"].String();
|
||||||
|
std::string badAI = battleAI ? "StupidAI" : "EmptyAI";
|
||||||
|
|
||||||
|
|
||||||
|
//TODO what about human players
|
||||||
|
if(battleints.size() >= sensibleAILimit)
|
||||||
|
return badAI;
|
||||||
|
|
||||||
|
return goodAI;
|
||||||
|
}
|
||||||
|
|
||||||
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
||||||
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
||||||
|
|
||||||
|
@ -112,7 +112,6 @@ public:
|
|||||||
class CClient : public IGameCallback
|
class CClient : public IGameCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CCallback *cb;
|
|
||||||
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||||
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||||
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||||
@ -141,6 +140,10 @@ public:
|
|||||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||||
|
|
||||||
void loadNeutralBattleAI();
|
void loadNeutralBattleAI();
|
||||||
|
void installNewPlayerInterface(CGameInterface *gameInterface, boost::optional<PlayerColor> color);
|
||||||
|
void installNewBattleInterface(CBattleGameInterface* battleInterface, boost::optional<PlayerColor> color, bool needCallback = true);
|
||||||
|
std::string aiNameForPlayer(const PlayerSettings &ps, bool battleAI); //empty means no AI -> human
|
||||||
|
|
||||||
void endGame(bool closeConnection = true);
|
void endGame(bool closeConnection = true);
|
||||||
void stopConnection();
|
void stopConnection();
|
||||||
void save(const std::string & fname);
|
void save(const std::string & fname);
|
||||||
|
@ -93,8 +93,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
activeStack(NULL), stackToActivate(NULL), selectedStack(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1),
|
activeStack(NULL), stackToActivate(NULL), selectedStack(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1),
|
||||||
currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL),
|
currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL), stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL),
|
||||||
siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0),
|
siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0),
|
||||||
givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL)
|
givenCommand(NULL), myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL),
|
||||||
|
autofightingAI(nullptr), background(nullptr)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION;
|
OBJ_CONSTRUCTION;
|
||||||
|
|
||||||
@ -172,8 +172,16 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector< std::string > & backref = graphics->battleBacks[ curInt->cb->battleGetBattlefieldType() ];
|
auto bfieldType = (int)curInt->cb->battleGetBattlefieldType();
|
||||||
background = BitmapHandler::loadBitmap(backref[ rand() % backref.size()], false );
|
if(graphics->battleBacks.size() <= bfieldType || bfieldType < 0)
|
||||||
|
logGlobal->errorStream() << bfieldType << " is not valid battlefield type index!";
|
||||||
|
else if(graphics->battleBacks[bfieldType].empty())
|
||||||
|
logGlobal->errorStream() << bfieldType << " battlefield type does not have any backgrounds!";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::string bgName = vstd::pickRandomElementOf(graphics->battleBacks[bfieldType], rand);
|
||||||
|
background = BitmapHandler::loadBitmap(bgName, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//preparing menu background
|
//preparing menu background
|
||||||
@ -446,6 +454,8 @@ CBattleInterface::~CBattleInterface()
|
|||||||
|
|
||||||
delete siegeH;
|
delete siegeH;
|
||||||
|
|
||||||
|
delete autofightingAI;
|
||||||
|
|
||||||
//TODO: play AI tracks if battle was during AI turn
|
//TODO: play AI tracks if battle was during AI turn
|
||||||
//if (!curInt->makingTurn)
|
//if (!curInt->makingTurn)
|
||||||
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
|
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
|
||||||
@ -1254,6 +1264,39 @@ void CBattleInterface::bAutofightf()
|
|||||||
{
|
{
|
||||||
if(spellDestSelectMode) //we are casting a spell
|
if(spellDestSelectMode) //we are casting a spell
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
static bool isAutoFightOn = false;
|
||||||
|
static unique_ptr<boost::thread> aiThread = nullptr;
|
||||||
|
|
||||||
|
if(isAutoFightOn)
|
||||||
|
{
|
||||||
|
assert(autofightingAI);
|
||||||
|
isAutoFightOn = false;
|
||||||
|
aiThread->join();
|
||||||
|
|
||||||
|
vstd::clear_pointer(autofightingAI);
|
||||||
|
aiThread = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isAutoFightOn = true;
|
||||||
|
autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
||||||
|
autofightingAI->init(curInt->cb);
|
||||||
|
autofightingAI->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide());
|
||||||
|
|
||||||
|
//Deactivate everything
|
||||||
|
deactivate();
|
||||||
|
bAutofight->activate(); //only autofight button is to remain active
|
||||||
|
aiThread = make_unique<boost::thread>([&]
|
||||||
|
{
|
||||||
|
auto ba = new BattleAction(autofightingAI->activeStack(activeStack));
|
||||||
|
|
||||||
|
if(isAutoFightOn)
|
||||||
|
{
|
||||||
|
givenCommand->setn(ba);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::bSpellf()
|
void CBattleInterface::bSpellf()
|
||||||
|
@ -48,6 +48,7 @@ class CClickableHex;
|
|||||||
struct BattleHex;
|
struct BattleHex;
|
||||||
struct InfoAboutHero;
|
struct InfoAboutHero;
|
||||||
struct BattleAction;
|
struct BattleAction;
|
||||||
|
class CBattleGameInterface;
|
||||||
|
|
||||||
/// Class which manages the locked hex fields that are blocked e.g. by obstacles
|
/// Class which manages the locked hex fields that are blocked e.g. by obstacles
|
||||||
class CBattleObstacle
|
class CBattleObstacle
|
||||||
@ -155,6 +156,8 @@ private:
|
|||||||
PossibleActions selectedAction; //last action chosen (and saved) by player
|
PossibleActions selectedAction; //last action chosen (and saved) by player
|
||||||
PossibleActions illegalAction; //most likely action that can't be performed here
|
PossibleActions illegalAction; //most likely action that can't be performed here
|
||||||
|
|
||||||
|
CBattleGameInterface *autofightingAI;
|
||||||
|
|
||||||
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
void getPossibleActionsForStack (const CStack * stack); //called when stack gets its turn
|
||||||
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
std::string dllName;
|
std::string dllName;
|
||||||
|
|
||||||
virtual ~CBattleGameInterface() {};
|
virtual ~CBattleGameInterface() {};
|
||||||
virtual void init(CBattleCallback * CB){};
|
virtual void init(shared_ptr<CBattleCallback> CB){};
|
||||||
|
|
||||||
//battle call-ins
|
//battle call-ins
|
||||||
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
|
virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
|
class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void init(CCallback * CB){};
|
virtual void init(shared_ptr<CCallback> CB){};
|
||||||
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
|
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
|
||||||
|
|
||||||
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||||
@ -115,7 +115,7 @@ public:
|
|||||||
CAdventureAI() : battleAI(NULL), cbc(NULL) {};
|
CAdventureAI() : battleAI(NULL), cbc(NULL) {};
|
||||||
|
|
||||||
CBattleGameInterface *battleAI;
|
CBattleGameInterface *battleAI;
|
||||||
CBattleCallback *cbc;
|
shared_ptr<CBattleCallback> cbc;
|
||||||
|
|
||||||
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
||||||
|
|
||||||
|
@ -4384,6 +4384,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
{
|
{
|
||||||
case Battle::HERO_SPELL:
|
case Battle::HERO_SPELL:
|
||||||
{
|
{
|
||||||
|
COMPLAIN_RET_FALSE_IF(ba.side > 1, "Side must be 0 or 1!");
|
||||||
|
|
||||||
|
|
||||||
const CGHeroInstance *h = gs->curB->heroes[ba.side];
|
const CGHeroInstance *h = gs->curB->heroes[ba.side];
|
||||||
const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side];
|
const CGHeroInstance *secondHero = gs->curB->heroes[!ba.side];
|
||||||
if(!h)
|
if(!h)
|
||||||
|
Loading…
Reference in New Issue
Block a user