diff --git a/client/CMT.cpp b/client/CMT.cpp index c0efb119d..c47222eaa 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -76,7 +76,7 @@ void processCommand(const std::string &message); static void setScreenRes(int w, int h, int bpp, bool fullscreen); void dispose(); void playIntro(); -void listenForEvents(); +void listenForEvents(); void startGame(StartInfo * options); void init() @@ -414,95 +414,95 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen) SDL_ShowCursor(SDL_DISABLE); } -void listenForEvents() -{ - SDL_Event *ev = NULL; - while(1) //main SDL events loop - { - ev = new SDL_Event(); - - int ret = SDL_WaitEvent(ev); - if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT))) - { - LOCPLINT->pim->lock(); - client->close(); - console->end(); - SDL_Delay(750); - tlog0 << "Ending...\n"; - exit(EXIT_SUCCESS); - } - else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4) - { - boost::unique_lock lock(*LOCPLINT->pim); - bool full = !(screen->flags&SDL_FULLSCREEN); - setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full); - GH.totalRedraw(); - } - eventsM.lock(); - events.push(ev); - eventsM.unlock(); - } -} - -void startGame(StartInfo * options) -{ - if(gOnlyAI) - { - for (size_t i =0; i < options->playerInfos.size(); i++) - { - options->playerInfos[i].human = false; - } - } - - if(screen->w != conf.cc.resx || screen->h != conf.cc.resy) - { - setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen); - } - - CClient cl; - if(options->mode == 0) //new game - { - timeHandler pomtime; - char portc[10]; - SDL_itoa(conf.cc.port,portc,10); - CClient::runServer(portc); - tlog0<<"Preparing shared memory and starting server: "<musich->stopMusic(); - client->run(); - //boost::thread t(boost::bind(&CClient::run,&cl)); - } - else //load game - { - std::string fname = options->mapname; - boost::algorithm::erase_last(fname,".vlgm1"); - cl.load(fname); - client = &cl; - CGI->musich->stopMusic(); - client->run(); - //boost::thread t(boost::bind(&CClient::run,&cl)); - } +void listenForEvents() +{ + SDL_Event *ev = NULL; + while(1) //main SDL events loop + { + ev = new SDL_Event(); + + int ret = SDL_WaitEvent(ev); + if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT))) + { + LOCPLINT->pim->lock(); + client->close(); + console->end(); + SDL_Delay(750); + tlog0 << "Ending...\n"; + exit(EXIT_SUCCESS); + } + else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4) + { + boost::unique_lock lock(*LOCPLINT->pim); + bool full = !(screen->flags&SDL_FULLSCREEN); + setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full); + GH.totalRedraw(); + } + eventsM.lock(); + events.push(ev); + eventsM.unlock(); + } +} + +void startGame(StartInfo * options) +{ + if(gOnlyAI) + { + for (size_t i =0; i < options->playerInfos.size(); i++) + { + options->playerInfos[i].human = false; + } + } + + if(screen->w != conf.cc.resx || screen->h != conf.cc.resy) + { + setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen); + } + + CClient cl; + if(options->mode == 0) //new game + { + timeHandler pomtime; + char portc[10]; + SDL_itoa(conf.cc.port,portc,10); + CClient::runServer(portc); + tlog0<<"Preparing shared memory and starting server: "<musich->stopMusic(); + client->run(); + //boost::thread t(boost::bind(&CClient::run,&cl)); + } + else //load game + { + std::string fname = options->mapname; + boost::algorithm::erase_last(fname,".vlgm1"); + cl.load(fname); + client = &cl; + CGI->musich->stopMusic(); + client->run(); + //boost::thread t(boost::bind(&CClient::run,&cl)); + } } \ No newline at end of file diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 9d5f1a555..62b9ddab1 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -32,7 +32,7 @@ * Full text of license available in license.txt file, in main folder * */ -namespace fs = boost::filesystem; +namespace fs = boost::filesystem; void startGame(StartInfo * options); CGPreGame * CGP; diff --git a/client/Client.h b/client/Client.h index c47b97e43..ec19221a7 100644 --- a/client/Client.h +++ b/client/Client.h @@ -101,9 +101,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 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 startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0){}; //use hero=NULL for no hero + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb = 0){}; //if any of armies is hero, hero will be used + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, 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/config/battleStartpos.txt b/config/battleStartpos.txt index 0d101a090..5e5d210d1 100644 --- a/config/battleStartpos.txt +++ b/config/battleStartpos.txt @@ -31,4 +31,21 @@ 66 83 117 134 66 83 100 117 134 49 66 83 117 134 151 -49 66 83 100 117 134 151 \ No newline at end of file +49 66 83 100 117 134 151 +//creature_bank +//attacker +57 +57 61 +57 61 90 +57 61 90 93 +57 61 90 93 96 +57 61 90 93 96 125 +57 61 90 93 96 125 129 +//defender +2 +2 15 +2 15 100 +2 15 100 185 +2 15 100 185 172 +2 15 100 185 172 87 +2 15 100 185 172 87 8 \ No newline at end of file diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index ce881351d..b933f197c 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -677,7 +677,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const else { //battle - cb->startBattleI(h, this); + cb->startBattleI(h, this, false); } } else if(ID == 62) //prison @@ -1160,7 +1160,7 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co void CGDwelling::wantsFight( const CGHeroInstance *h, ui32 answer ) const { if(answer) - cb->startBattleI(h, this, boost::bind(&CGDwelling::fightOver, this, h, _1)); + cb->startBattleI(h, this, false, boost::bind(&CGDwelling::fightOver, this, h, _1)); } void CGDwelling::fightOver(const CGHeroInstance *h, BattleResult *result) const @@ -1942,7 +1942,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co void CGCreature::fight( const CGHeroInstance *h ) const { - cb->startBattleI(h, this, boost::bind(&CGCreature::endBattle,this,_1)); + cb->startBattleI(h, this, false, boost::bind(&CGCreature::endBattle,this,_1)); } void CGCreature::flee( const CGHeroInstance * h ) const @@ -2078,7 +2078,7 @@ void CGResource::collectRes( int player ) const void CGResource::fightForRes(ui32 agreed, const CGHeroInstance *h) const { if(agreed) - cb->startBattleI(h, this, boost::bind(&CGResource::endBattle,this,_1,h)); + cb->startBattleI(h, this, false, boost::bind(&CGResource::endBattle,this,_1,h)); } void CGResource::endBattle( BattleResult *result, const CGHeroInstance *h ) const @@ -2288,7 +2288,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const void CGArtifact::fightForArt( ui32 agreed, const CGHeroInstance *h ) const { if(agreed) - cb->startBattleI(h, this, boost::bind(&CGArtifact::endBattle,this,_1,h)); + cb->startBattleI(h, this, false, boost::bind(&CGArtifact::endBattle,this,_1,h)); } void CGArtifact::endBattle( BattleResult *result, const CGHeroInstance *h ) const @@ -2800,7 +2800,7 @@ void CGEvent::activated( const CGHeroInstance * h ) const else iw.text.addTxt(MetaString::ADVOB_TXT, 16); cb->showInfoDialog(&iw); - cb->startBattleI(h, this, boost::bind(&CGEvent::endBattle,this,h,_1)); + cb->startBattleI(h, this, false, boost::bind(&CGEvent::endBattle,this,h,_1)); } else { @@ -2812,6 +2812,7 @@ void CGPandoraBox::initObj() { blockVisit = true; } + void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const { BlockingDialog bd (true, false); @@ -2820,23 +2821,24 @@ void CGPandoraBox::onHeroVisit(const CGHeroInstance * h) const bd.text.addTxt (MetaString::ADVOB_TXT, 14); cb->showBlockingDialog (&bd, boost::bind (&CGPandoraBox::open, this, h, _1)); } + void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const { if (accept) { - if (army) + if (army) //if pandora's box is protested by army { InfoWindow iw; iw.player = h->tempOwner; iw.text.addTxt(MetaString::ADVOB_TXT, 16); cb->showInfoDialog(&iw); - cb->startBattleI(h, this, boost::bind(&CGPandoraBox::endBattle, this, h,_1)); + cb->startBattleI(h, this, false, boost::bind(&CGPandoraBox::endBattle, this, h, _1)); //grants things after battle } - else if (message.size() == resources.size() == - primskills.size() == abilities.size() == - abilityLevels.size() == artifacts.size() == - spells.size() == creatures == - gainedExp == manaDiff == moraleDiff == luckDiff == 0) //yeaha! + else if (message.size() == 0 && resources.size() == 0 + && primskills.size() == 0 && abilities.size() == 0 + && abilityLevels.size() == 0 && artifacts.size() == 0 + && spells.size() == 0 && creatures == 0 + && gainedExp == 0 && manaDiff == 0 && moraleDiff == 0 && luckDiff == 0) //if it gives nothing without battle { InfoWindow iw; iw.player = h->tempOwner; @@ -2844,12 +2846,13 @@ void CGPandoraBox::open( const CGHeroInstance * h, ui32 accept ) const cb->showInfoDialog(&iw); } - else + else //if it gives something without battle { giveContents (h, false); } } } + void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) const { InfoWindow iw; diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index d27a55a2a..3c541f2d4 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -77,9 +77,9 @@ 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 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(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0)=0; //use hero=NULL for no hero + virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb = 0)=0; //if any of armies is hero, hero will be used + virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, 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; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 4bc4c27e6..3b3c06b53 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -322,10 +322,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf return ret; } -void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function cb) +void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb) { BattleInfo *curB = new BattleInfo; - setupBattle(curB, tile, army1->army, army2->army, hero1, hero2); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces + setupBattle(curB, tile, army1->army, army2->army, hero1, hero2, creatureBank); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces NEW_ROUND; //TODO: pre-tactic stuff, call scripts etc. @@ -842,7 +842,7 @@ void CGameHandler::run(bool resume) namespace CGH { using namespace std; - static void readItTo(ifstream & input, vector< vector > & dest) + static void readItTo(ifstream & input, vector< vector > & dest) //reads 7 lines, i-th one containing i integers, and puts it to dest { for(int j=0; j<7; ++j) { @@ -857,7 +857,7 @@ namespace CGH } } -void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 ) +void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank ) { battleResult.set(NULL); std::vector & stacks = (curB->stacks); @@ -882,7 +882,7 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet } std::string dump; positions>>dump; positions>>dump; - std::vector< std::vector > attackerLoose, defenderLoose, attackerTight, defenderTight; + std::vector< std::vector > attackerLoose, defenderLoose, attackerTight, defenderTight, attackerCreBank, defenderCreBank; CGH::readItTo(positions, attackerLoose); positions>>dump; CGH::readItTo(positions, defenderLoose); @@ -891,6 +891,11 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet CGH::readItTo(positions, attackerTight); positions>>dump; CGH::readItTo(positions, defenderTight); + positions>>dump; + positions>>dump; + CGH::readItTo(positions, attackerCreBank); + positions>>dump; + CGH::readItTo(positions, defenderCreBank); positions.close(); //battleStartpos read @@ -898,7 +903,9 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet for(std::map >::const_iterator i = army1.slots.begin(); i!=army1.slots.end(); i++, k++) { int pos; - if(army1.formation) + if(creatureBank) + pos = attackerCreBank[army1.slots.size()-1][k]; + else if(army1.formation) pos = attackerTight[army1.slots.size()-1][k]; else pos = attackerLoose[army1.slots.size()-1][k]; @@ -911,7 +918,9 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet for(std::map >::const_iterator i = army2.slots.begin(); i!=army2.slots.end(); i++, k++) { int pos; - if(army2.formation) + if(creatureBank) + pos = defenderCreBank[army1.slots.size()-1][k]; + else if(army2.formation) pos = defenderTight[army2.slots.size()-1][k]; else pos = defenderLoose[army2.slots.size()-1][k]; @@ -1374,7 +1383,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255* return true; } //TODO: check for ally - startBattleI(h, dh); + startBattleI(h, dh, false); return true; } } @@ -1530,7 +1539,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 sendAndApply(&sha); } -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 +void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb) //use hero=NULL for no hero { engageIntoBattle(army1->tempOwner); engageIntoBattle(army2->tempOwner); @@ -1538,20 +1547,20 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc if(army2->tempOwner < PLAYER_LIMIT) states.setFlag(army2->tempOwner,&PlayerStatus::engagedIntoBattle,true); - boost::thread(boost::bind(&CGameHandler::startBattle,this,army1,army2,tile,hero1,hero2,cb)); + boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb)); } -void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, boost::function cb ) +void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb ) { startBattleI(army1, army2, tile, - army1->ID == 34 ? static_cast(army1) : NULL, - army2->ID == 34 ? static_cast(army2) : NULL, - cb); + army1->ID == HEROI_TYPE ? static_cast(army1) : NULL, + army2->ID == HEROI_TYPE ? static_cast(army2) : NULL, + creatureBank, cb); } -void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function cb) +void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function cb) { - startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb); + startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), creatureBank, cb); } //void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb) //for hero<=>neutral army diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 5ff935a38..aae6302e7 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(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const 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, bool creatureBank, 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, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2 ); + void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank ); CGameHandler(void); @@ -122,9 +122,9 @@ 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 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(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb); //use hero=NULL for no hero + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb); + void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, 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);