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"
|
||||
|
||||
using boost::optional;
|
||||
CBattleCallback * cbc;
|
||||
shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
#define LOGL(text) print(text)
|
||||
#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");
|
||||
cbc = cb = CB;
|
||||
|
@ -109,7 +109,7 @@ struct PotentialTargets
|
||||
class CBattleAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
CBattleCallback *cb;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
|
||||
//Previous setting of cb
|
||||
bool wasWaitingForRealize, wasUnlockingGs;
|
||||
@ -119,7 +119,7 @@ public:
|
||||
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 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
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "CEmptyAI.h"
|
||||
|
||||
void CEmptyAI::init(CCallback * CB)
|
||||
void CEmptyAI::init(shared_ptr<CCallback> CB)
|
||||
{
|
||||
cb = CB;
|
||||
human=false;
|
||||
|
@ -7,10 +7,10 @@ struct HeroMoveDetails;
|
||||
|
||||
class CEmptyAI : public CGlobalAI
|
||||
{
|
||||
CCallback *cb;
|
||||
shared_ptr<CCallback> cb;
|
||||
|
||||
public:
|
||||
void init(CCallback * CB) override;
|
||||
void init(shared_ptr<CCallback> CB) override;
|
||||
void yourTurn() override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override;
|
||||
|
@ -41,23 +41,27 @@
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v110_xp</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@ -106,7 +110,8 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>VCMI_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalOptions>/Zm130 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -122,7 +127,7 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -140,7 +145,7 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -160,7 +165,7 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>StdInc.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>VCMI_DLL;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../../CCallback.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
|
||||
CPlayerBattleCallback * cbc;
|
||||
shared_ptr<CBattleCallback> cbc;
|
||||
|
||||
CStupidAI::CStupidAI(void)
|
||||
: side(-1), cb(NULL)
|
||||
@ -19,7 +19,7 @@ CStupidAI::~CStupidAI(void)
|
||||
print("destroyed");
|
||||
}
|
||||
|
||||
void CStupidAI::init( CBattleCallback * CB )
|
||||
void CStupidAI::init(shared_ptr<CBattleCallback> CB)
|
||||
{
|
||||
print("init called, saving ptr to IBattleCallback");
|
||||
cbc = cb = CB;
|
||||
|
@ -5,14 +5,14 @@
|
||||
class CStupidAI : public CBattleGameInterface
|
||||
{
|
||||
int side;
|
||||
CBattleCallback *cb;
|
||||
shared_ptr<CBattleCallback> cb;
|
||||
|
||||
void print(const std::string &text) const;
|
||||
public:
|
||||
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 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
|
||||
|
@ -34,7 +34,7 @@ struct SetGlobalState
|
||||
assert(!cb.get());
|
||||
|
||||
ai.reset(AI);
|
||||
cb.reset(AI->myCb);
|
||||
cb.reset(AI->myCb.get());
|
||||
}
|
||||
~SetGlobalState()
|
||||
{
|
||||
@ -823,7 +823,7 @@ void VCAI::showMarketWindow(const IMarket *market, const CGHeroInstance *visitor
|
||||
NET_EVENT_HANDLER;
|
||||
}
|
||||
|
||||
void VCAI::init(CCallback * CB)
|
||||
void VCAI::init(shared_ptr<CCallback> CB)
|
||||
{
|
||||
LOG_TRACE(logAi);
|
||||
myCb = CB;
|
||||
|
@ -291,7 +291,7 @@ public:
|
||||
AIStatus status;
|
||||
std::string battlename;
|
||||
|
||||
CCallback *myCb;
|
||||
shared_ptr<CCallback> myCb;
|
||||
|
||||
unique_ptr<boost::thread> makingTurn;
|
||||
|
||||
@ -306,7 +306,7 @@ public:
|
||||
|
||||
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 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}
|
||||
EndProjectSection
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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.Build.0 = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -135,9 +135,9 @@ CPlayerInterface::~CPlayerInterface()
|
||||
|
||||
LOCPLINT = NULL;
|
||||
}
|
||||
void CPlayerInterface::init(CCallback * CB)
|
||||
void CPlayerInterface::init(shared_ptr<CCallback> CB)
|
||||
{
|
||||
cb = dynamic_cast<CCallback*>(CB);
|
||||
cb = CB;
|
||||
if(observerInDuelMode)
|
||||
return;
|
||||
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
static CBattleInterface * battleInt; //NULL if no battle
|
||||
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)
|
||||
|
||||
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 openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||
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
|
||||
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);
|
||||
|
@ -91,7 +91,6 @@ void CClient::init()
|
||||
IObjectInterface::cb = this;
|
||||
serv = nullptr;
|
||||
gs = nullptr;
|
||||
cb = nullptr;
|
||||
erm = nullptr;
|
||||
terminate = false;
|
||||
}
|
||||
@ -216,6 +215,7 @@ void CClient::endGame( bool closeConnection /*= true*/ )
|
||||
}
|
||||
|
||||
callbacks.clear();
|
||||
battleCallbacks.clear();
|
||||
logNetwork->infoStream() << "Deleted playerInts.";
|
||||
|
||||
logNetwork->infoStream() << "Client stopped.";
|
||||
@ -372,7 +372,6 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
}
|
||||
|
||||
int humanPlayers = 0;
|
||||
int sensibleAILimit = settings["session"]["oneGoodAI"].Bool() ? 1 : PlayerColor::PLAYER_LIMIT_I;
|
||||
for(auto it = gs->scenarioOps->playerInfos.begin();
|
||||
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;
|
||||
if(si->mode != StartInfo::DUEL)
|
||||
{
|
||||
auto cb = make_shared<CCallback>(gs,color,this);
|
||||
if(it->second.playerID == PlayerSettings::PLAYER_AI)
|
||||
{
|
||||
std::string AItoGive = settings["server"]["playerAI"].String();
|
||||
if(!sensibleAILimit)
|
||||
AItoGive = "EmptyAI";
|
||||
else
|
||||
sensibleAILimit--;
|
||||
playerint[color] = static_cast<CGameInterface*>(CDynLibHandler::getNewAI(AItoGive));
|
||||
logNetwork->infoStream() << "Player " << static_cast<int>(color.getNum()) << " will be lead by " << AItoGive;
|
||||
auto AiToGive = aiNameForPlayer(it->second, false);
|
||||
logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % color % AiToGive;
|
||||
installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color);
|
||||
}
|
||||
else
|
||||
{
|
||||
playerint[color] = new CPlayerInterface(color);
|
||||
installNewPlayerInterface(new CPlayerInterface(color), color);
|
||||
humanPlayers++;
|
||||
}
|
||||
battleints[color] = playerint[color];
|
||||
|
||||
logNetwork->traceStream() << "\tInitializing the interface";
|
||||
playerint[color]->init(cb.get());
|
||||
battleCallbacks[color] = callbacks[color] = cb;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cbc = make_shared<CBattleCallback>(gs, color, this);
|
||||
battleCallbacks[color] = cbc;
|
||||
|
||||
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());
|
||||
std::string AItoGive = aiNameForPlayer(it->second, true);
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(AItoGive), color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,12 +409,8 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
||||
boost::unique_lock<boost::recursive_mutex> un(*LOCPLINT->pim);
|
||||
CPlayerInterface *p = new CPlayerInterface(PlayerColor::NEUTRAL);
|
||||
p->observerInDuelMode = true;
|
||||
battleints[PlayerColor::UNFLAGGABLE] = playerint[PlayerColor::UNFLAGGABLE] = p;
|
||||
privilagedBattleEventReceivers.push_back(p);
|
||||
installNewPlayerInterface(p, boost::none);
|
||||
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);
|
||||
}
|
||||
@ -502,10 +474,7 @@ void CClient::serialize( Handler &h, const int version )
|
||||
{
|
||||
if(pid == PlayerColor::NEUTRAL)
|
||||
{
|
||||
//CBattleCallback * cbc = new CBattleCallback(gs, pid, this);//FIXME: unused?
|
||||
CBattleGameInterface *cbgi = CDynLibHandler::getNewBattleAI(dllname);
|
||||
battleints[pid] = cbgi;
|
||||
cbgi->init(cb);
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
|
||||
//TODO? consider serialization
|
||||
continue;
|
||||
}
|
||||
@ -525,9 +494,7 @@ void CClient::serialize( Handler &h, const int version )
|
||||
nInt->human = isHuman;
|
||||
nInt->playerID = pid;
|
||||
|
||||
battleCallbacks[pid] = callbacks[pid] = make_shared<CCallback>(gs,pid,this);
|
||||
battleints[pid] = playerint[pid] = nInt;
|
||||
nInt->init(callbacks[pid].get());
|
||||
installNewPlayerInterface(nInt, pid);
|
||||
nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above
|
||||
}
|
||||
|
||||
@ -658,10 +625,7 @@ void CClient::battleFinished()
|
||||
|
||||
void CClient::loadNeutralBattleAI()
|
||||
{
|
||||
battleints[PlayerColor::NEUTRAL] = CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String());
|
||||
auto cbc = make_shared<CBattleCallback>(gs, PlayerColor::NEUTRAL, this);
|
||||
battleCallbacks[PlayerColor::NEUTRAL] = cbc;
|
||||
battleints[PlayerColor::NEUTRAL]->init(cbc.get());
|
||||
installNewBattleInterface(CDynLibHandler::getNewBattleAI(settings["server"]["neutralAI"].String()), PlayerColor::NEUTRAL);
|
||||
}
|
||||
|
||||
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( COSer<CSaveFile> &h, const int version );
|
||||
|
||||
|
@ -112,7 +112,6 @@ public:
|
||||
class CClient : public IGameCallback
|
||||
{
|
||||
public:
|
||||
CCallback *cb;
|
||||
std::map<PlayerColor,shared_ptr<CCallback> > callbacks; //callbacks given to player interfaces
|
||||
std::map<PlayerColor,shared_ptr<CBattleCallback> > battleCallbacks; //callbacks given to player interfaces
|
||||
std::vector<IGameEventsReceiver*> privilagedGameEventReceivers; //scripting modules, spectator interfaces
|
||||
@ -141,6 +140,10 @@ public:
|
||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||
|
||||
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 stopConnection();
|
||||
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),
|
||||
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),
|
||||
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;
|
||||
|
||||
@ -172,8 +172,16 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector< std::string > & backref = graphics->battleBacks[ curInt->cb->battleGetBattlefieldType() ];
|
||||
background = BitmapHandler::loadBitmap(backref[ rand() % backref.size()], false );
|
||||
auto bfieldType = (int)curInt->cb->battleGetBattlefieldType();
|
||||
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
|
||||
@ -446,6 +454,8 @@ CBattleInterface::~CBattleInterface()
|
||||
|
||||
delete siegeH;
|
||||
|
||||
delete autofightingAI;
|
||||
|
||||
//TODO: play AI tracks if battle was during AI turn
|
||||
//if (!curInt->makingTurn)
|
||||
//CCS->musich->playMusicFromSet(CCS->musich->aiMusics, -1);
|
||||
@ -1254,6 +1264,39 @@ void CBattleInterface::bAutofightf()
|
||||
{
|
||||
if(spellDestSelectMode) //we are casting a spell
|
||||
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()
|
||||
|
@ -48,6 +48,7 @@ class CClickableHex;
|
||||
struct BattleHex;
|
||||
struct InfoAboutHero;
|
||||
struct BattleAction;
|
||||
class CBattleGameInterface;
|
||||
|
||||
/// Class which manages the locked hex fields that are blocked e.g. by obstacles
|
||||
class CBattleObstacle
|
||||
@ -155,6 +156,8 @@ private:
|
||||
PossibleActions selectedAction; //last action chosen (and saved) by player
|
||||
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 endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled)
|
||||
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
std::string dllName;
|
||||
|
||||
virtual ~CBattleGameInterface() {};
|
||||
virtual void init(CBattleCallback * CB){};
|
||||
virtual void init(shared_ptr<CBattleCallback> CB){};
|
||||
|
||||
//battle call-ins
|
||||
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
|
||||
{
|
||||
public:
|
||||
virtual void init(CCallback * CB){};
|
||||
virtual void init(shared_ptr<CCallback> CB){};
|
||||
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
|
||||
|
||||
//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
|
||||
@ -115,7 +115,7 @@ public:
|
||||
CAdventureAI() : battleAI(NULL), cbc(NULL) {};
|
||||
|
||||
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
|
||||
|
||||
|
@ -4384,6 +4384,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||
{
|
||||
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 *secondHero = gs->curB->heroes[!ba.side];
|
||||
if(!h)
|
||||
|
Loading…
Reference in New Issue
Block a user