From 3152e6d5402b2c26053ccd2082be46070d92c619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Thu, 25 Aug 2011 15:24:37 +0000 Subject: [PATCH] Fixed #771, #772 and #787. Some minor changes and fixes. --- AI/GeniusAI/CGeniusAI.cpp | 7 ------- CCallback.cpp | 21 +++++++++------------ CCallback.h | 2 +- client/CBattleInterface.cpp | 10 +++++----- client/CPlayerInterface.cpp | 6 ++++++ client/CPlayerInterface.h | 1 + client/CPreGame.cpp | 6 +++--- client/CPreGame.h | 2 +- client/Client.cpp | 19 ++++++++++++++++++- client/Client.h | 1 + client/NetPacksClient.cpp | 7 +++++++ lib/CCreatureHandler.cpp | 31 ++++++++++++++++++++++++++++--- lib/CCreatureHandler.h | 1 + lib/CGameInterface.cpp | 5 +++++ lib/CGameInterface.h | 2 ++ lib/CGameState.cpp | 20 ++++++++++++++++++-- lib/CGameState.h | 3 +++ lib/Connection.cpp | 6 ++++++ lib/Connection.h | 1 + lib/NetPacks.h | 1 + 20 files changed, 117 insertions(+), 35 deletions(-) diff --git a/AI/GeniusAI/CGeniusAI.cpp b/AI/GeniusAI/CGeniusAI.cpp index 0d8a7bce0..1011759a2 100644 --- a/AI/GeniusAI/CGeniusAI.cpp +++ b/AI/GeniusAI/CGeniusAI.cpp @@ -1268,13 +1268,6 @@ void CGeniusAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2 m_battleLogic = new BattleAI::CBattleLogic(m_cb, army1, army2, tile, hero1, hero2, side); - if(m_cb->battleGetTacticDist()) - { - m_cb->waitTillRealize = false; - BattleAction endt = BattleAction::makeEndOFTacticPhase(m_cb->battleGetMySide()); - m_cb->battleMakeTacticAction(&endt); - m_cb->waitTillRealize = true; - } DbgBox("** CGeniusAI::battleStart **"); } diff --git a/CCallback.cpp b/CCallback.cpp index e6a595a25..779085f49 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -183,26 +183,23 @@ int CBattleCallback::battleMakeAction(BattleAction* action) return 0; } -template -void CBattleCallback::sendRequest(const T* request) +void CBattleCallback::sendRequest(const CPack* request) { - //TODO? should be part of CClient but it would have to be very tricky cause template/serialization issues + //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()); + cl->waitingRequest.set(typeList.getTypeID(request)); - { - boost::unique_lock lock(*cl->serv->wmx); - *cl->serv << request; - } + cl->serv->sendPack(*request); if(waitTillRealize) { if(unlockGsWhenWaiting) - gs->mx->unlock_shared(); + getGsMutex().unlock_shared(); cl->waitingRequest.waitWhileTrue(); if(unlockGsWhenWaiting) - gs->mx->lock_shared(); + getGsMutex().lock_shared(); } } @@ -246,7 +243,7 @@ void CCallback::setSelection(const CArmedInstance * obj) SetSelection ss; ss.player = player; ss.id = obj->id; - sendRequest(&ss); + sendRequest(&(CPackForClient&)ss); if(obj->ID == HEROI_TYPE) { @@ -287,7 +284,7 @@ void CCallback::save( const std::string &fname ) void CCallback::sendMessage(const std::string &mess) { PlayerMessage pm(player, mess); - sendRequest(&pm); + sendRequest(&(CPackForClient&)pm); } void CCallback::buildBoat( const IShipyard *obj ) diff --git a/CCallback.h b/CCallback.h index 0beb93b77..919d0bb7c 100644 --- a/CCallback.h +++ b/CCallback.h @@ -89,7 +89,7 @@ private: protected: - template void sendRequest(const T*request); + void sendRequest(const CPack *request); CClient *cl; //virtual bool hasAccess(int playerId) const; diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index 73d861108..78278cdc5 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -3830,11 +3830,14 @@ void CBattleInterface::startAction(const BattleAction* action) { if(action->actionType == BattleAction::END_TACTIC_PHASE) { + SDL_FreeSurface(menu); menu = BitmapHandler::loadBitmap("CBAR.bmp"); + graphics->blueToPlayersAdv(menu, curInt->playerID); + bDefence->block(false); + bWait->block(false); if(active) { - tacticsMode = false; if(btactEnd && btactNext) //if the other side had tactics, there are no buttons { btactEnd->deactivate(); @@ -3932,10 +3935,7 @@ void CBattleInterface::waitForAnims() void CBattleInterface::bEndTacticPhase() { btactEnd->block(true); - bDefence->block(false); - bWait->block(false); - BattleAction endt = BattleAction::makeEndOFTacticPhase(curInt->cb->battleGetMySide()); - curInt->cb->battleMakeTacticAction(&endt); + tacticsMode = false; } static bool immobile(const CStack *s) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index d7f4c3a4f..37889501d 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -892,6 +892,12 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba) } } +void CPlayerInterface::yourTacticPhase(int distance) +{ + while(battleInt->tacticsMode) + boost::this_thread::sleep(boost::posix_time::millisec(1)); +} + void CPlayerInterface::showComp(SComponent comp) { boost::unique_lock un(*pim); diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index b6a050f53..086178baf 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -230,6 +230,7 @@ public: void battleObstaclesRemoved(const std::set & removedObstacles) OVERRIDE; //called when a certain set of obstacles is removed from batlefield; IDs of them are given void battleCatapultAttacked(const CatapultAttack & ca) OVERRIDE; //called when catapult makes an attack void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield + void yourTacticPhase(int distance) OVERRIDE; //-------------// void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList onYes, CFunctionList onNo); diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 29e288873..ed55131ed 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -2042,7 +2042,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet for(int i = 0; i < 6; i++) btns[i] = NULL; - selectButtons(false); + selectButtons(); assert(SEL->current && SEL->current->mapHeader); const PlayerInfo &p = SEL->current->mapHeader->players[s.color]; @@ -2080,12 +2080,12 @@ void OptionsTab::PlayerOptionsEntry::showAll( SDL_Surface * to ) printAtMiddleWBLoc(CGI->generaltexth->arraytxt[206+whoCanPlay], 28, 34, FONT_TINY, 8, zwykly, to); } -void OptionsTab::PlayerOptionsEntry::selectButtons(bool onlyHero) +void OptionsTab::PlayerOptionsEntry::selectButtons() { if(!btns[0]) return; - if( (!onlyHero && pi.defaultCastle() != -1) //fixed tow + if( (pi.defaultCastle() != -1) //fixed tow || (SEL->isGuest() && s.color != playerColor)) //or not our player { btns[0]->disable(); diff --git a/client/CPreGame.h b/client/CPreGame.h index 7194251ad..9dfc20b24 100644 --- a/client/CPreGame.h +++ b/client/CPreGame.h @@ -184,7 +184,7 @@ public: enum {HUMAN_OR_CPU, HUMAN, CPU} whoCanPlay; PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S); - void selectButtons(bool onlyHero = true); //hides unavailable buttons + void selectButtons(); //hides unavailable buttons void showAll(SDL_Surface * to); }; diff --git a/client/Client.cpp b/client/Client.cpp index bd1f361f0..da3b7d665 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -523,7 +523,8 @@ void CClient::handlePack( CPack * pack ) } void CClient::updatePaths() -{ +{ + //TODO? lazy evaluation? paths now can get recalculated multiple times upon various game events const CGHeroInstance *h = getSelectedHero(); if (h)//if we have selected hero... calculatePaths(h); @@ -594,6 +595,11 @@ void CClient::battleStarted(const BattleInfo * info) battleints[info->sides[1]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); if(vstd::contains(battleints,254)) battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1); + + if(info->tacticDistance && vstd::contains(battleints,info->sides[info->tacticsSide])) + { + boost::thread hlp = boost::thread(&CClient::commenceTacticPhaseForInt, this, battleints[info->sides[info->tacticsSide]]); + } } void CClient::loadNeutralBattleAI() @@ -624,6 +630,17 @@ void CClient::calculatePaths(const CGHeroInstance *h) gs->calculatePaths(h, *pathInfo); } +void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt) +{ + setThreadName(-1, "CClient::commenceTacticPhaseForInt"); + try + { + battleInt->yourTacticPhase(gs->curB->tacticDistance); + MakeAction ma(BattleAction::makeEndOFTacticPhase(battleInt->playerID)); + serv->sendPack(ma); + } HANDLE_EXCEPTION +} + template void CClient::serialize( CISer &h, const int version ); template void CClient::serialize( COSer &h, const int version ); diff --git a/client/Client.h b/client/Client.h index 5f1a57f0d..dd982fbb4 100644 --- a/client/Client.h +++ b/client/Client.h @@ -165,6 +165,7 @@ public: void handlePack( CPack * pack ); //applies the given pack and deletes it void battleStarted(const BattleInfo * info); + void commenceTacticPhaseForInt(CBattleGameInterface *battleInt); //will be called as separate thread void commitPackage(CPackForClient *pack) OVERRIDE; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 01dfa529b..6f7dd39b6 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -241,6 +241,11 @@ void HeroVisit::applyCl( CClient *cl ) INTERFACE_CALL_IF_PRESENT(hero->tempOwner, heroVisit, hero, obj, starting); } +void NewTurn::applyCl( CClient *cl ) +{ + cl->updatePaths(); +} + void GiveBonus::applyCl( CClient *cl ) { @@ -711,6 +716,8 @@ void PackageApplied::applyCl( CClient *cl ) INTERFACE_CALL_IF_PRESENT(player, requestRealized, this); if(cl->waitingRequest.get() == packType) cl->waitingRequest.setn(false); + else if(cl->waitingRequest.get()) + tlog3 << "Suprising server message!\n"; } void SystemMessage::applyCl( CClient *cl ) diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 8b1b72992..430a3ba39 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -71,14 +71,39 @@ int CCreature::getQuantityID(const int & quantity) if (quantity<250) return 5; if (quantity<500) - return 5; - if (quantity<1000) return 6; - if (quantity<4000) + if (quantity<1000) return 7; return 8; } +int CCreature::estimateCreatureCount(int countID) +{ + switch(countID) + { + case 0: + return 3; + case 1: + return 8; + case 2: + return 15; + case 3: + return 35; + case 4: + return 75; + case 5: + return 175; + case 6: + return 375; + case 7: + return 750; + case 8: + return 2500; + default: + assert("Wrong countID!"); + } +} + bool CCreature::isDoubleWide() const { return doubleWide; diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index c6ec6d1e6..6d687e4b8 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -58,6 +58,7 @@ public: bool isEvil () const; si32 maxAmount(const std::vector &res) const; //how many creatures can be bought static int getQuantityID(const int & quantity); //0 - a few, 1 - several, 2 - pack, 3 - lots, 4 - horde, 5 - throng, 6 - swarm, 7 - zounds, 8 - legion + static int estimateCreatureCount(int countID); //reverse version of above function, returns middle of range bool isMyUpgrade(const CCreature *anotherCre) const; bool valid() const; diff --git a/lib/CGameInterface.cpp b/lib/CGameInterface.cpp index 5e3df127b..278c0f98f 100644 --- a/lib/CGameInterface.cpp +++ b/lib/CGameInterface.cpp @@ -197,4 +197,9 @@ void CAdventureAI::battleStacksHealedRes(const std::vector BattleAction CAdventureAI::activeStack(const CStack * stack) { return battleAI->activeStack(stack); +} + +void CAdventureAI::yourTacticPhase(int distance) +{ + battleAI->yourTacticPhase(distance); } \ No newline at end of file diff --git a/lib/CGameInterface.h b/lib/CGameInterface.h index bdc8610d4..300030c4e 100644 --- a/lib/CGameInterface.h +++ b/lib/CGameInterface.h @@ -67,6 +67,7 @@ public: //battle call-ins virtual BattleAction activeStack(const CStack * stack)=0; //called when it's turn of that stack + virtual void yourTacticPhase(int distance){}; //called when interface has opportunity to use Tactics skill -> use cb->battleMakeTacticAction from this function }; /// Central class for managing human player / AI interface logic @@ -116,6 +117,7 @@ public: //battle interface virtual BattleAction activeStack(const CStack * stack); + virtual void yourTacticPhase(int distance); virtual void battleNewRound(int round); virtual void battleCatapultAttacked(const CatapultAttack & ca); virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side); diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 9ed41c2b7..d7e2b3818 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2990,7 +2990,7 @@ InfoAboutHero & InfoAboutHero::operator=( const InfoAboutHero & iah ) -ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) +ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) : isDetailed(detailed) { for(TSlots::const_iterator i = army->Slots().begin(); i != army->Slots().end(); i++) { @@ -3001,11 +3001,27 @@ ArmyDescriptor::ArmyDescriptor(const CArmedInstance *army, bool detailed) } } -ArmyDescriptor::ArmyDescriptor() +ArmyDescriptor::ArmyDescriptor() : isDetailed(true) { } +int ArmyDescriptor::getStrength() const +{ + ui64 ret = 0; + if(isDetailed) + { + for(const_iterator i = begin(); i != end(); i++) + ret += i->second.type->AIValue * i->second.count; + } + else + { + for(const_iterator i = begin(); i != end(); i++) + ret += i->second.type->AIValue * CCreature::estimateCreatureCount(i->second.count); + } + return ret; +} + DuelParameters::SideSettings::StackSettings::StackSettings() : type(-1), count(0) { diff --git a/lib/CGameState.h b/lib/CGameState.h index 5a4f7d15b..176c09bae 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -76,8 +76,11 @@ namespace boost //numbers of creatures are exact numbers if detailed else they are quantity ids (0 - a few, 1 - several and so on; additionaly -1 - unknown) struct ArmyDescriptor : public std::map { + bool isDetailed; DLL_EXPORT ArmyDescriptor(const CArmedInstance *army, bool detailed); //not detailed -> quantity ids as count DLL_EXPORT ArmyDescriptor(); + + DLL_EXPORT int getStrength() const; }; struct DLL_EXPORT InfoAboutHero diff --git a/lib/Connection.cpp b/lib/Connection.cpp index 89b41c757..be39255c4 100644 --- a/lib/Connection.cpp +++ b/lib/Connection.cpp @@ -243,6 +243,12 @@ CPack * CConnection::retreivePack() return ret; } +void CConnection::sendPack(const CPack &pack) +{ + boost::unique_lock lock(*wmx); + *this << &pack; //packs has to be sent as polymorphic pointers! +} + CSaveFile::CSaveFile( const std::string &fname ) :sfile(NULL) { diff --git a/lib/Connection.h b/lib/Connection.h index 8e94ff238..c3c349b87 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -922,6 +922,7 @@ public: ~CConnection(void); CPack *retreivePack(); //gets from server next pack (allocates it with new) + void sendPack(const CPack &pack); }; DLL_EXPORT std::ostream &operator<<(std::ostream &str, const CConnection &cpc); diff --git a/lib/NetPacks.h b/lib/NetPacks.h index ae4143f18..f6d054073 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -952,6 +952,7 @@ struct NewTurn : public CPackForClient //101 { enum weekType {NORMAL, DOUBLE_GROWTH, BONUS_GROWTH, DEITYOFFIRE, PLAGUE, CUSTOM, NO_ACTION, NONE}; + void applyCl(CClient *cl); DLL_EXPORT void applyGs(CGameState *gs); struct Hero