From 9206a1339097d55bfbe3ac2368ab7e4153f08eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Mon, 20 Jul 2009 23:34:06 +0000 Subject: [PATCH] Fixed fighting guardians of Dwellings (and other objs as well). Most of creature generators should work fine. --- client/CPlayerInterface.cpp | 23 +++++++-------- client/CPlayerInterface.h | 1 + client/Client.h | 5 ++-- hch/CObjectHandler.cpp | 31 ++++++++----------- lib/IGameCallback.h | 7 +++-- lib/NetPacksLib.cpp | 2 +- server/CGameHandler.cpp | 59 ++++++++++++++++++++++++------------- server/CGameHandler.h | 10 ++++--- 8 files changed, 79 insertions(+), 59 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index f15d23f51..791a1fe99 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1025,12 +1025,7 @@ void CPlayerInterface::receivedResource(int type, int val) void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector& skills, boost::function &callback) { - { - boost::unique_lock un(showingDialog->mx); - while(showingDialog->data) - showingDialog->cond.wait(un); - } - + waitWhileDialog(); CGI->soundh->playSound(soundBase::heroNewLevel); boost::unique_lock un(*pim); @@ -1378,12 +1373,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector & components, int soundID) { - { - boost::unique_lock un(showingDialog->mx); - while(showingDialog->data) - showingDialog->cond.wait(un); - } - + waitWhileDialog(); boost::unique_lock un(*pim); if(stillMoveHero.get() == DURING_MOVE)//if we are in the middle of hero movement @@ -1424,6 +1414,7 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, const std::vecto void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector &components, ui32 askID, int soundID, bool selection, bool cancel ) { + waitWhileDialog(); boost::unique_lock un(*pim); CGI->soundh->playSound(static_cast(soundID)); @@ -1734,6 +1725,7 @@ const CGHeroInstance * CPlayerInterface::getWHero( int pos ) void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int level) { + waitWhileDialog(); std::vector > cres; for(int i = 0; i < dwelling->creatures.size(); i++) { @@ -1745,6 +1737,13 @@ void CPlayerInterface::showRecruitmentDialog(const CGDwelling *dwelling, int lev pushInt(cr); } +void CPlayerInterface::waitWhileDialog() +{ + boost::unique_lock un(showingDialog->mx); + while(showingDialog->data) + showingDialog->cond.wait(un); +} + void SystemOptions::setMusicVolume( int newVolume ) { musicVolume = newVolume; diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 03b6cdd4a..64477a3c4 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -192,6 +192,7 @@ public: //-------------// + void waitWhileDialog(); bool shiftPressed() const; //determines if shift key is pressed (left or right or both) void redrawHeroWin(const CGHeroInstance * hero); void updateWater(); diff --git a/client/Client.h b/client/Client.h index a984d3baa..388005a3f 100644 --- a/client/Client.h +++ b/client/Client.h @@ -96,8 +96,9 @@ public: void heroVisitCastle(int obj, int heroID){}; void stopHeroVisitCastle(int obj, int heroID){}; void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack - void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb){}; //use hero=NULL for no hero - void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb){}; //for hero<=>neutral army + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb = 0){}; //use hero=NULL for no hero + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb = 0){}; //if any of armies is hero, hero will be used + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle void setAmount(int objid, ui32 val){}; bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255){return false;}; void giveHeroBonus(GiveBonus * bonus){}; diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index cfbf700e2..f3bb7d3c8 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -652,13 +652,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const else { //battle - cb->startBattleI( - &h->army, - &army, - h->pos, - h, - this, - 0); + cb->startBattleI(h, this); } } else if(ID == 62) //prison @@ -1113,7 +1107,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const { if(answer) - cb->startBattleI(h->id,army,pos,boost::bind(&CGDwelling::fightOver, this, h, _1)); + cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1)); } void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const @@ -1667,12 +1661,12 @@ void CGCreature::endBattle( BattleResult *result ) const } else { - int killedAmount=0; - for(std::set >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++) - if(i->first == subID) - killedAmount += i->second; - cb->setAmount(id, army.slots.find(0)->second.second - killedAmount); - + //int killedAmount=0; + //for(std::set >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++) + // if(i->first == subID) + // killedAmount += i->second; + //cb->setAmount(id, army.slots.find(0)->second.second - killedAmount); + MetaString ms; int pom = CCreature::getQuantityID(army.slots.find(0)->second.second); pom = 174 + 3*pom + 1; @@ -1861,7 +1855,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co void CGCreature::fight( const CGHeroInstance *h ) const { - cb->startBattleI(h->id,army,pos,boost::bind(&CGCreature::endBattle,this,_1)); + cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1)); } void CGCreature::flee( const CGHeroInstance * h ) const @@ -1997,7 +1991,7 @@ void CGResource::collectRes( int player ) const void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const { if(agreed) - cb->startBattleI(h->id,army,pos,boost::bind(&CGResource::endBattle,this,_1,h)); + cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h)); } void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const @@ -2164,6 +2158,7 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const if(ID == 5) { InfoWindow iw; + iw.soundID = soundBase::treasure; iw.player = h->tempOwner; iw.components.push_back(Component(4,subID,0,0)); if(message.length()) @@ -2206,7 +2201,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const { if(agreed) - cb->startBattleI(h->id,army,pos,boost::bind(&CGArtifact::endBattle,this,_1,h)); + cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h)); } void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const @@ -2695,7 +2690,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const else iw.text.addTxt(MetaString::ADVOB_TXT, 16); cb->showInfoDialog(&iw); - cb->startBattleI(h->id,army,pos,boost::bind(&CGEvent::endBattle,this,h,_1)); + cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1)); } else { diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index a4072a948..96d1babbe 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -31,6 +31,7 @@ struct PlayerSettings; struct CPackForClient; class CArtHandler; class CArtifact; +class CArmedInstance; class DLL_EXPORT IGameCallback { @@ -73,8 +74,10 @@ public: virtual void heroVisitCastle(int obj, int heroID)=0; virtual void stopHeroVisitCastle(int obj, int heroID)=0; virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack - virtual void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb)=0; //use hero=NULL for no hero - virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb)=0; //for hero<=>neutral army + virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb = 0)=0; //use hero=NULL for no hero + virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb = 0)=0; //if any of armies is hero, hero will be used + virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle + //virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb)=0; //for hero<=>neutral army virtual void setAmount(int objid, ui32 val)=0; virtual bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255)=0; virtual void giveHeroBonus(GiveBonus * bonus)=0; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 86653fcbb..dc4f59e51 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -288,7 +288,7 @@ void TryMoveHero::applyGs( CGameState *gs ) CGHeroInstance *h = gs->getHero(id); h->movement = movePoints; - if(result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) + if((result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) && start != end) h->moveDir = getDir(start,end); if(result == EMBARK) //hero enters boat at dest tile diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1a83661c6..e5ca2b65f 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -294,6 +294,8 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs) static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat) { + if(color == 254) + color = 255; CCreatureSet ret(set); for(int i=0; istacks.size();i++) { @@ -309,10 +311,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf return ret; } -void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function cb) +void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb) { BattleInfo *curB = new BattleInfo; - setupBattle(curB, tile, army1, army2, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces + setupBattle(curB, tile, army1->army, army2->army, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces NEW_ROUND; //TODO: pre-tactic stuff, call scripts etc. @@ -401,10 +403,8 @@ askInterfaceForMove: //casualties among heroes armies SetGarrisons sg; - if(hero1) - sg.garrs[hero1->id] = takeCasualties(hero1->tempOwner,hero1->army,gs->curB); - if(hero2) - sg.garrs[hero2->id] = takeCasualties(hero2->tempOwner,hero2->army,gs->curB); + sg.garrs[army1->id] = takeCasualties(army1->tempOwner,army1->army,gs->curB); + sg.garrs[army2->id] = takeCasualties(army2->tempOwner,army2->army,gs->curB); sendAndApply(&sg); //end battle, remove all info, free memory @@ -822,7 +822,7 @@ namespace CGH } } -void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 ) +void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 ) { battleResult.set(NULL); std::vector & stacks = (curB->stacks); @@ -837,7 +837,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army curB->side2=(hero2)?(hero2->tempOwner):(-1); curB->round = -2; curB->activeStack = -1; - for(std::map >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++) + for(std::map >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++) { stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first)); if(hero1) @@ -890,7 +890,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army { stacks[b]->position = attackerLoose[army1.slots.size()-1][b]; } - for(std::map >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++) + for(std::map >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++) { stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first)); //base luck/morale calculations @@ -1170,7 +1170,8 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* && complain("Cannot move hero, destination tile is on water!") || (h->boat && t.tertype != TerrainTile::water && t.blocked) && complain("Cannot disembark hero, tile is blocked!") - || !h->movement && complain("Hero don't have any movement points left!")) + || (!h->movement && dst != h->pos) + && complain("Hero don't have any movement points left!")) { //send info about movement failure sendAndApply(&tmh); @@ -1266,11 +1267,15 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* { if(obj->ID==HEROI_TYPE) { - if(obj->tempOwner==h->tempOwner) - return true;//TODO: exchange - //TODO: check for ally CGHeroInstance *dh = static_cast(obj); - startBattleI(&h->army,&dh->army,dst,h,dh,0); + + if(obj->tempOwner==h->tempOwner) + { + heroExchange(h->id, dh->id); + return true; + } + //TODO: check for ally + startBattleI(h, dh); return true; } } @@ -1397,17 +1402,31 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 sendAndApply(&sha); } -void CGameHandler::startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb) //use hero=NULL for no hero +void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb) //use hero=NULL for no hero { - boost::thread(boost::bind(&CGameHandler::startBattle,this,*const_cast(army1),*const_cast(army2),tile,const_cast(hero1), const_cast(hero2),cb)); + boost::thread(boost::bind(&CGameHandler::startBattle,this,army1,army2,tile,hero1,hero2,cb)); } -void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb) //for hero<=>neutral army + +void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb ) { - CGHeroInstance* h = const_cast(getHero(heroID)); - startBattleI(&h->army,&army,tile,h,NULL,cb); - //battle(&h->army,army,tile,h,NULL); + startBattleI(army1, army2, tile, + army1->ID == 34 ? static_cast(army1) : NULL, + army2->ID == 34 ? static_cast(army2) : NULL, + cb); } +void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb) +{ + startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb); +} + +//void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb) //for hero<=>neutral army +//{ +// CGHeroInstance* h = const_cast(getHero(heroID)); +// startBattleI(&h->army,&army,tile,h,NULL,cb); +// //battle(&h->army,army,tile,h,NULL); +//} + void CGameHandler::changeSpells( int hid, bool give, const std::set &spells ) { ChangeSpells cs; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 7ce05e84d..d5a1e74f2 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -84,11 +84,11 @@ public: bool isAllowedExchange(int id1, int id2); void giveSpells(const CGTownInstance *t, const CGHeroInstance *h); void moveStack(int stack, int dest); - void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero + void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack void prepareAttacked(BattleStackAttacked &bsa, CStack *def); void checkForBattleEnd( std::vector &stacks ); - void setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army1, CCreatureSet &army2, CGHeroInstance * hero1, CGHeroInstance * hero2 ); + void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 ); CGameHandler(void); @@ -121,8 +121,10 @@ public: void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack void moveArtifact(int hid, int oldPosition, int destPos); void removeArtifact(int hid, int pos); - void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero - void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb); //use hero=NULL for no hero + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb); + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb = 0); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle + //void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army void setAmount(int objid, ui32 val); bool moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker = 255); void giveHeroBonus(GiveBonus * bonus);