diff --git a/AI/GeniusAI/BattleLogic.cpp b/AI/GeniusAI/BattleLogic.cpp index ffbb70550..b7108c733 100644 --- a/AI/GeniusAI/BattleLogic.cpp +++ b/AI/GeniusAI/BattleLogic.cpp @@ -239,30 +239,30 @@ void CBattleLogic::MakeStatistics(int currentCreatureId) typedef SCreatureCasualties const std::pair::* CreaPairPtr; // sort max damage - std::sort(m_statMaxDamage.begin(), m_statMaxDamage.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort min damage - std::sort(m_statMinDamage.begin(), m_statMinDamage.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort max speed - std::sort(m_statMaxSpeed.begin(), m_statMaxSpeed.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort distance - std::sort(m_statDistance.begin(), m_statDistance.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort distance from shooters - std::sort(m_statDistanceFromShooters.begin(), m_statDistanceFromShooters.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort hit points - std::sort(m_statHitPoints.begin(), m_statHitPoints.end(), - bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); - // sort casualties - std::sort(m_statCasualties.begin(), m_statCasualties.end(), - bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, - bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _1)) - > - bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, - bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _2))); +// std::sort(m_statMaxDamage.begin(), m_statMaxDamage.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort min damage +// std::sort(m_statMinDamage.begin(), m_statMinDamage.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort max speed +// std::sort(m_statMaxSpeed.begin(), m_statMaxSpeed.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort distance +// std::sort(m_statDistance.begin(), m_statDistance.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort distance from shooters +// std::sort(m_statDistanceFromShooters.begin(), m_statDistanceFromShooters.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) < bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort hit points +// std::sort(m_statHitPoints.begin(), m_statHitPoints.end(), +// bind((IntPtr)&creature_stat::value_type::second, _1) > bind((IntPtr)&creature_stat::value_type::second, _2)); +// // sort casualties +// std::sort(m_statCasualties.begin(), m_statCasualties.end(), +// bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, +// bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _1)) +// > +// bind((CreaPtr)&creature_stat_casualties::value_type::second_type::damage_max, +// bind((CreaPairPtr)&creature_stat_casualties::value_type::second, _2))); } BattleAction CBattleLogic::MakeDecision(int stackID) diff --git a/CCallback.cpp b/CCallback.cpp index dbe2752ff..322f296cd 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -272,6 +272,7 @@ void CCallback::buildBoat( const IShipyard *obj ) CCallback::CCallback( CGameState * GS, int Player, CClient *C ) :CBattleCallback(GS, Player, C) { + cl = C; waitTillRealize = false; } diff --git a/CCallback.h b/CCallback.h index 47fdfd279..e6a030eba 100644 --- a/CCallback.h +++ b/CCallback.h @@ -11,6 +11,7 @@ #endif #include "lib/IGameCallback.h" +#include "lib/CBattleCallback.h" /* * CCallback.h, part of VCMI engine @@ -37,15 +38,6 @@ struct CGPath; struct CPathsInfo; struct CPack; -class IBattleCallback -{ -public: - bool waitTillRealize; //if true, request functions will return after they are realized by server - bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback! - //battle - virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack - virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions -}; class IGameActionCallback { @@ -83,29 +75,12 @@ public: virtual void buildBoat(const IShipyard *obj) = 0; }; -struct CPack; - -class CBattleCallback : public IBattleCallback, public CBattleInfoCallback -{ -protected: - void sendRequest(const CPack *request); - CClient *cl; - //virtual bool hasAccess(int playerId) const; - -public: - CBattleCallback(CGameState *GS, int Player, CClient *C); - int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack - bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions - - friend class CCallback; - friend class CClient; -}; - class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback { private: CCallback(CGameState * GS, int Player, CClient *C); public: + CClient *cl; //client-specific functionalities (pathfinding) virtual bool getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret); //DEPRACATED!!! virtual const CGPathNode *getPathInfo(int3 tile); //uses main, client pathfinder info diff --git a/Odpalarka/main.cpp b/Odpalarka/main.cpp index 12e110ac7..ac954ffe9 100644 --- a/Odpalarka/main.cpp +++ b/Odpalarka/main.cpp @@ -7,7 +7,7 @@ int main() boost::thread t(boost::bind(std::system, "VCMI_server.exe b1.json StupidAI StupidAI")); boost::thread tt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); boost::thread ttt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); - boost::thread tttt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); + //boost::thread tttt(boost::bind(std::system, "VCMI_BattleAiHost.exe")); //boost::this_thread::sleep(boost::posix_time::seconds(5)); t.join(); diff --git a/VCMI_BattleAiHost/BattleCallback.cpp b/VCMI_BattleAiHost/BattleCallback.cpp deleted file mode 100644 index 3c8d3fdb7..000000000 --- a/VCMI_BattleAiHost/BattleCallback.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "BattleCallback.h" -#include "Client.h" -#include "../lib/CGameState.h" -#include "../lib/BattleState.h" -#include "../lib/NetPacks.h" -#include "../lib/Connection.h" - - -CBattleCallback::CBattleCallback(CGameState *GS, int Player, CClient *C ) -{ - gs = GS; - player = Player; - cl = C; -} - -bool CBattleCallback::battleMakeTacticAction( BattleAction * action ) -{ - assert(cl->gs->curB->tacticDistance); - MakeAction ma; - ma.ba = *action; - sendRequest(&ma); - return true; -} -int CBattleCallback::battleMakeAction(BattleAction* action) -{ - assert(action->actionType == BattleAction::HERO_SPELL); - MakeCustomAction mca(*action); - sendRequest(&mca); - return 0; -} - -void CBattleCallback::sendRequest(const CPack* request) -{ - - //TODO should be part of CClient (client owns connection, not CB) - //but it would have to be very tricky cause template/serialization issues -// if(waitTillRealize) -// cl->waitingRequest.set(typeList.getTypeID(request)); - - cl->serv->sendPack(*request); - -// if(waitTillRealize) -// { -// if(unlockGsWhenWaiting) -// getGsMutex().unlock_shared(); -// cl->waitingRequest.waitWhileTrue(); -// if(unlockGsWhenWaiting) -// getGsMutex().lock_shared(); -// } -} \ No newline at end of file diff --git a/VCMI_BattleAiHost/BattleCallback.h b/VCMI_BattleAiHost/BattleCallback.h deleted file mode 100644 index 2326ec23e..000000000 --- a/VCMI_BattleAiHost/BattleCallback.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "../global.h" -#include "../CCallback.h" - -/*class CBattleCallback : public IBattleCallback, public CBattleInfoCallback -{ -private: - CBattleCallback(CGameState *GS, int Player, CClient *C); - - -protected: - void sendRequest(const CPack *request); - CClient *cl; - //virtual bool hasAccess(int playerId) const; - -public: - int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack - bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions - - friend class CCallback; - friend class CClient; -};*/ \ No newline at end of file diff --git a/VCMI_BattleAiHost/Client.h b/VCMI_BattleAiHost/Client.h index f359885dd..a9d68f37d 100644 --- a/VCMI_BattleAiHost/Client.h +++ b/VCMI_BattleAiHost/Client.h @@ -1,5 +1,6 @@ #pragma once #include "../global.h" +#include "../lib/CBattleCallback.h" class CGameState; class CConnection; struct CPack; @@ -7,13 +8,12 @@ class CBattleGameInterface; struct BattleAction; class CStack; -class CClient/* : public IGameCallback*/ +class CClient/* : public IGameCallback*/ : public IConnectionHandler { public: bool terminate; BattleAction *curbaction; CGameState *gs; - CConnection *serv; CBattleGameInterface *ai; CClient(); diff --git a/VCMI_BattleAiHost/NetPacksRunner.cpp b/VCMI_BattleAiHost/NetPacksRunner.cpp index 2ebc80ce2..ade923f1a 100644 --- a/VCMI_BattleAiHost/NetPacksRunner.cpp +++ b/VCMI_BattleAiHost/NetPacksRunner.cpp @@ -394,12 +394,12 @@ void EndAction::applyCl( CClient *cl ) void PackageApplied::applyCl( CClient *cl ) { -// ui8 player = GS(cl)->currentPlayer; -// INTERFACE_CALL_IF_PRESENT(player, requestRealized, this); -// if(cl->waitingRequest.get() == packType) -// cl->waitingRequest.setn(false); -// else if(cl->waitingRequest.get()) -// tlog3 << "Surprising server message!\n"; + ui8 player = GS(cl)->currentPlayer; + //INTERFACE_CALL_IF_PRESENT(player, requestRealized, this); + if(cl->waitingRequest.get() == packType) + cl->waitingRequest.setn(false); + else if(cl->waitingRequest.get()) + tlog3 << "Surprising server message!\n"; } void SystemMessage::applyCl( CClient *cl ) diff --git a/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj b/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj index 422d2be7d..d62d655cf 100644 --- a/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj +++ b/VCMI_BattleAiHost/VCMI_BattleAiHost.vcxproj @@ -132,13 +132,11 @@ - - diff --git a/VCMI_VS10.sln b/VCMI_VS10.sln index a3c015ae4..6d8dd9b1a 100644 --- a/VCMI_VS10.sln +++ b/VCMI_VS10.sln @@ -22,6 +22,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Odpalarka", "Odpalarka\Odpa {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} = {B952FFC5-3039-4DE1-9F08-90ACDA483D8F} EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C710950-7839-490C-8412-C60AC4D5238B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCMI_client", "client\VCMI_client.vcxproj", "{8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -94,6 +98,17 @@ Global {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.ActiveCfg = Release|Win32 {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|Win32.Build.0 = Release|Win32 {27B69211-D138-4142-BBC9-40F5DEA39067}.Release|x64.ActiveCfg = Release|Win32 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|Win32.Build.0 = Debug|Win32 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.ActiveCfg = Debug|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Debug|x64.Build.0 = Debug|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.ActiveCfg = RD|Win32 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|Win32.Build.0 = RD|Win32 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.ActiveCfg = RD|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.RD|x64.Build.0 = RD|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|Win32.ActiveCfg = RD|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.ActiveCfg = RD|x64 + {8355EBA8-65C2-44A4-BC2D-78053E1BF2D6}.Release|x64.Build.0 = RD|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/b1.json b/b1.json index 766f0c7ac..5d0b291e3 100644 --- a/b1.json +++ b/b1.json @@ -6,7 +6,9 @@ [ { "side" : 0, - "army" : [[10, 40]] + "army" : [[10, 40]], + "heroid" : 0, + "spells" : [1,2,3,4] } { "side" : 1, diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index c287ac928..503d13769 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -1193,6 +1193,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe ObjectConstruction h__l__p(this); if(!curInt) curInt = LOCPLINT; //may happen when we are defending during network MP game + bool duelMode = curInt->cb->getMyColor() < 0; animsAreDisplayed.setn(false); pos = myRect; @@ -1297,8 +1298,8 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe bOptions = new AdventureMapButton (CGI->generaltexth->zelp[381].first, CGI->generaltexth->zelp[381].second, boost::bind(&CBattleInterface::bOptionsf,this), 3 + pos.x, 561 + pos.y, "icm003.def", SDLK_o); bSurrender = new AdventureMapButton (CGI->generaltexth->zelp[379].first, CGI->generaltexth->zelp[379].second, boost::bind(&CBattleInterface::bSurrenderf,this), 54 + pos.x, 561 + pos.y, "icm001.def", SDLK_s); bFlee = new AdventureMapButton (CGI->generaltexth->zelp[380].first, CGI->generaltexth->zelp[380].second, boost::bind(&CBattleInterface::bFleef,this), 105 + pos.x, 561 + pos.y, "icm002.def", SDLK_r); - bFlee->block(!curInt->cb->battleCanFlee()); - bSurrender->block(curInt->cb->battleGetSurrenderCost() < 0); + bFlee->block(duelMode || !curInt->cb->battleCanFlee()); + bSurrender->block(duelMode || curInt->cb->battleGetSurrenderCost() < 0); bAutofight = new AdventureMapButton (CGI->generaltexth->zelp[382].first, CGI->generaltexth->zelp[382].second, boost::bind(&CBattleInterface::bAutofightf,this), 157 + pos.x, 561 + pos.y, "icm004.def", SDLK_a); bSpell = new AdventureMapButton (CGI->generaltexth->zelp[385].first, CGI->generaltexth->zelp[385].second, boost::bind(&CBattleInterface::bSpellf,this), 645 + pos.x, 561 + pos.y, "icm005.def", SDLK_c); bSpell->block(true); @@ -3869,6 +3870,8 @@ void CBattleInterface::endAction(const BattleAction* action) if(tacticsMode) //we have activated next stack after sending request that has been just realized -> blockmap due to movement has changed redrawBackgroundWithHexes(activeStack); + + waitForAnims(); } void CBattleInterface::hideQueue() diff --git a/client/CBattleInterface.h b/client/CBattleInterface.h index c759e46de..87c91ca7e 100644 --- a/client/CBattleInterface.h +++ b/client/CBattleInterface.h @@ -456,6 +456,9 @@ private: bool spellDestSelectMode; //if true, player is choosing destination for his spell SpellSelectionType spellSelMode; BattleAction * spellToCast; //spell for which player is choosing destination + + bool duelMode; + void endCastingSpell(); //ends casting spell (eg. when spell has been cast or canceled) void showAliveStack(const CStack *stack, SDL_Surface * to); //helper function for function show diff --git a/client/CMT.cpp b/client/CMT.cpp index d2730ec99..fb12d7c77 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -285,9 +285,6 @@ int main(int argc, char** argv) { StartInfo *si = new StartInfo(); si->mode = StartInfo::DUEL; - si->mapname = vm["battle"].as(); - si->playerInfos[0].color = 0; - si->playerInfos[1].color = 1; startGame(si); } mainGUIThread = new boost::thread(&CGuiHandler::run, boost::ref(GH)); @@ -718,9 +715,11 @@ void startGame(StartInfo * options, CConnection *serv/* = NULL*/) { case StartInfo::NEW_GAME: case StartInfo::CAMPAIGN: - case StartInfo::DUEL: client->newGame(serv, options); break; + case StartInfo::DUEL: + client->newDuel(serv, options); + break; case StartInfo::LOAD_GAME: std::string fname = options->mapname; boost::algorithm::erase_last(fname,".vlgm1"); diff --git a/client/Client.cpp b/client/Client.cpp index fdd8729c5..b6ceb55a1 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -101,13 +101,11 @@ void CClient::init() } CClient::CClient(void) -:waitingRequest(0) { init(); } CClient::CClient(CConnection *con, StartInfo *si) -:waitingRequest(0) { init(); newGame(con,si); @@ -418,6 +416,56 @@ void CClient::newGame( CConnection *con, StartInfo *si ) // } } +void CClient::newDuel(CConnection *con, StartInfo *si) +{ + serv = con; + if(!serv) + { + std::string host = "127.0.0.1"; + std::string port = "3030"; + + int i = 3; + while(!serv) + { + try + { + tlog0 << "Establishing connection...\n"; + serv = new CConnection(host, port, "DLL host"); + } + catch(...) + { + tlog1 << "\nCannot establish connection! Retrying within 2 seconds" << std::endl; + boost::this_thread::sleep(boost::posix_time::seconds(2)); + if(!--i) + exit(0); + } + } + } + + + ui8 color; + std::string battleAIName; + *serv >> *si >> battleAIName >> color; + assert(si->mode == StartInfo::DUEL); + assert(color > 1); //we are NOT participants + //tlog0 << format("Server wants us to be %s in battle %s as side %d") % battleAIName % si.mapname % (int)color; + + gs = new CGameState(); + const_cast(CGI)->state = gs; + //gs->scenarioOps = si; + gs->init(si, 0, 0); + + CPlayerInterface *p = new CPlayerInterface(-1); + privilagedBattleEventReceivers.push_back(p); + p->observerInDuelMode = true; + battleints[254] = playerint[254] = p; + GH.curInt = p; + p->init(new CCallback(gs, -1, this)); + battleStarted(gs->curB); + + serv->addStdVecItems(const_cast(CGI)->state); +} + template void CClient::serialize( Handler &h, const int version ) { diff --git a/client/Client.h b/client/Client.h index 617ef3507..e5046fa12 100644 --- a/client/Client.h +++ b/client/Client.h @@ -3,10 +3,9 @@ #include "../global.h" -#include #include "../lib/IGameCallback.h" -#include "../lib/CondSh.h" #include +#include "../lib/CBattleCallback.h" /* * Client.h, part of VCMI engine @@ -60,7 +59,7 @@ public: }; /// Class which handles client - server logic -class CClient : public IGameCallback +class CClient : public IGameCallback, public IConnectionHandler { public: CCallback *cb; @@ -70,7 +69,6 @@ public: std::map playerint; std::map battleints; bool hotSeat; - CConnection *serv; BattleAction *curbaction; CPathsInfo *pathInfo; @@ -78,7 +76,6 @@ public: CScriptingModule *erm; - CondSh waitingRequest; std::queue packs; boost::mutex packsM; @@ -91,6 +88,7 @@ public: void init(); void newGame(CConnection *con, StartInfo *si); //con - connection to server + void newDuel(CConnection *con, StartInfo *si); //con - connection to server void loadNeutralBattleAI(); void endGame(bool closeConnection = true); diff --git a/lib/CBattleCallback.cpp b/lib/CBattleCallback.cpp new file mode 100644 index 000000000..cc6e0b9ec --- /dev/null +++ b/lib/CBattleCallback.cpp @@ -0,0 +1,61 @@ +#define VCMI_DLL +#include "CBattleCallback.h" +#include "NetPacks.h" +#include "Connection.h" +#include "CGameState.h" +#include +#include "BattleState.h" + +CBattleCallback::CBattleCallback(CGameState *GS, int Player, IConnectionHandler *C ) +{ + gs = GS; + player = Player; + connHandler = C; +} + +bool CBattleCallback::battleMakeTacticAction( BattleAction * action ) +{ + assert(gs->curB->tacticDistance); + MakeAction ma; + ma.ba = *action; + sendRequest(&ma); + return true; +} +int CBattleCallback::battleMakeAction(BattleAction* action) +{ + assert(action->actionType == BattleAction::HERO_SPELL); + MakeCustomAction mca(*action); + sendRequest(&mca); + return 0; +} + +void CBattleCallback::sendRequest(const CPack* request) +{ + + //TODO should be part of CClient (client owns connection, not CB) + //but it would have to be very tricky cause template/serialization issues + if(waitTillRealize) + connHandler->waitingRequest.set(typeList.getTypeID(request)); + + connHandler->serv->sendPack(*request); + + if(waitTillRealize) + { + if(unlockGsWhenWaiting) + gs->mx->unlock_shared(); + connHandler->waitingRequest.waitWhileTrue(); + if(unlockGsWhenWaiting) + gs->mx->lock_shared(); + } +} + +IConnectionHandler::IConnectionHandler() + : waitingRequest(0) +{ + +} + +IConnectionHandler::~IConnectionHandler() +{ + +} \ No newline at end of file diff --git a/lib/CBattleCallback.h b/lib/CBattleCallback.h new file mode 100644 index 000000000..dd0b815d2 --- /dev/null +++ b/lib/CBattleCallback.h @@ -0,0 +1,42 @@ +#pragma once +#include "../global.h" +#include "IGameCallback.h" +#include "CondSh.h" + +class CConnection; + +class DLL_EXPORT IConnectionHandler +{ +public: + IConnectionHandler(); + ~IConnectionHandler(); + + CConnection *serv; + CondSh waitingRequest; +}; + +class DLL_EXPORT IBattleCallback +{ +public: + bool waitTillRealize; //if true, request functions will return after they are realized by server + bool unlockGsWhenWaiting;//if true after sending each request, gs mutex will be unlocked so the changes can be applied; NOTICE caller must have gs mx locked prior to any call to actiob callback! + //battle + virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack + virtual bool battleMakeTacticAction(BattleAction * action) =0; // performs tactic phase actions +}; + +class DLL_EXPORT CBattleCallback : public IBattleCallback, public CBattleInfoCallback +{ +protected: + void sendRequest(const CPack *request); + IConnectionHandler *connHandler; + //virtual bool hasAccess(int playerId) const; + +public: + CBattleCallback(CGameState *GS, int Player, IConnectionHandler *C); + int battleMakeAction(BattleAction* action) OVERRIDE;//for casting spells by hero - DO NOT use it for moving active stack + bool battleMakeTacticAction(BattleAction * action) OVERRIDE; // performs tactic phase actions + + friend class CCallback; + friend class CClient; +}; diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index ca1bb4d02..844c97ed0 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2720,6 +2720,12 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname) ss.stacks[i].count = stackNode.Vector()[1].Float(); i++; } + + ss.heroId = n["heroid"].Float(); + if(ss.heroId != -1) + BOOST_FOREACH(const JsonNode &spell, n["spells"].Vector()) + ss.spells.insert(spell.Float()); + } return ret; diff --git a/lib/VCMI_lib.vcxproj b/lib/VCMI_lib.vcxproj index d113c93e3..48da13721 100644 --- a/lib/VCMI_lib.vcxproj +++ b/lib/VCMI_lib.vcxproj @@ -214,6 +214,7 @@ + @@ -247,6 +248,7 @@ + diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 04b7e4797..9771bb933 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -456,7 +456,6 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer winnerHero->showNecromancyDialog(raisedStack); addToSlot(StackLocation(winnerHero, necroSlot), raisedStack.type, raisedStack.count); } - sendAndApply(&resultsApplied); if(duel) { @@ -471,10 +470,14 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer tlog0 << boost::format("\t* %d of %s\n") % i->second % c->namePl; casualtiesPoints = c->AIValue * i->second; } - tlog0 << boost::format("Total causalties points: %d\n") % casualtiesPoints; - return; + tlog0 << boost::format("Total casualties points: %d\n") % casualtiesPoints; } + sendAndApply(&resultsApplied); + + if(duel) + return; + if(visitObjectAfterVictory && winnerHero == hero1) { visitObjectOnTile(*getTile(winnerHero->getPosition()), winnerHero);