diff --git a/AdventureMapButton.cpp b/AdventureMapButton.cpp index 3d9721db8..c08fcdb43 100644 --- a/AdventureMapButton.cpp +++ b/AdventureMapButton.cpp @@ -40,6 +40,13 @@ AdventureMapButton::AdventureMapButton( const std::string &Name, const std::stri pom[0] = Name; init(Callback, pom, HelpBox, info->playerColoured, info->defName, &info->additionalDefs, info->x, info->y, key); } + +AdventureMapButton::AdventureMapButton( const std::pair help, const CFunctionList &Callback, int x, int y, const std::string &defName, int key/*=0*/, std::vector * add /*= NULL*/, bool playerColoredButton /*= false */ ) +{ + std::map pom; + pom[0] = help.first; + init(Callback, pom, help.second, playerColoredButton, defName, add, x, y, key); +} void AdventureMapButton::clickLeft (tribool down) { if(blocked) @@ -79,7 +86,7 @@ void AdventureMapButton::hover (bool on) std::string *name = (vstd::contains(hoverTexts,state)) ? (&hoverTexts[state]) : (vstd::contains(hoverTexts,0) ? (&hoverTexts[0]) : NULL); - if(name) //if there is no name, there is nohing to display also + if(name && !blocked) //if there is no name, there is nohing to display also { if (LOCPLINT->curint == static_cast(LOCPLINT->battleInt)) //for battle buttons { diff --git a/AdventureMapButton.h b/AdventureMapButton.h index fb7961f5c..13be09b3a 100644 --- a/AdventureMapButton.h +++ b/AdventureMapButton.h @@ -29,6 +29,7 @@ public: AdventureMapButton(); //c-tor AdventureMapButton( const std::map &, const std::string &HelpBox, const CFunctionList &Callback, int x, int y, const std::string &defName, int key=0, std::vector * add = NULL, bool playerColoredButton = false );//c-tor AdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, int x, int y, const std::string &defName, int key=0, std::vector * add = NULL, bool playerColoredButton = false );//c-tor + AdventureMapButton( const std::pair help, const CFunctionList &Callback, int x, int y, const std::string &defName, int key=0, std::vector * add = NULL, bool playerColoredButton = false );//c-tor AdventureMapButton( const std::string &Name, const std::string &HelpBox, const CFunctionList &Callback, config::ButtonInfo *info, int key=0);//c-tor //AdventureMapButton( std::string Name, std::string HelpBox, boost::function Callback, int x, int y, std::string defName, bool activ=false, std::vector * add = NULL, bool playerColoredButton = false );//c-tor diff --git a/CGameState.cpp b/CGameState.cpp index 381e03a56..5b6e3aa9b 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -434,7 +434,6 @@ CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, con } } - void CGameState::applyNL(IPack * pack) { switch(pack->getType()) @@ -455,6 +454,11 @@ void CGameState::applyNL(IPack * pack) if(n->resetBuilded) //reset amount of structures set in this turn in towns BOOST_FOREACH(CGTownInstance* t, map->towns) t->builded = 0; + BOOST_FOREACH(CGHeroInstance *h, map->heroes) + h->bonuses.remove_if(HeroBonus::OneDay); + if(getDate(1) == 7) //new week + BOOST_FOREACH(CGHeroInstance *h, map->heroes) + h->bonuses.remove_if(HeroBonus::OneDay); break; } case 102: //set resource amount diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index dfeeab517..97e49e3e1 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -2372,6 +2372,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town ) void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroBonus &bonus, bool gain ) { + if(bonus.type == HeroBonus::NONE) return; boost::unique_lock un(*pim); redrawHeroWin(hero); } @@ -2989,6 +2990,7 @@ void CRecrutationWindow::Cancel() } void CRecrutationWindow::sliderMoved(int to) { + buy->block(!to); } void CRecrutationWindow::clickLeft(tribool down) { @@ -3045,6 +3047,7 @@ void CRecrutationWindow::activate() max->activate(); cancel->activate(); slider->activate(); + LOCPLINT->statusbar = bar; } void CRecrutationWindow::deactivate() { @@ -3089,6 +3092,7 @@ void CRecrutationWindow::show(SDL_Surface * to) curx += 120; } c++; + bar->show(); } CRecrutationWindow::CRecrutationWindow(const std::vector > &Creatures, const boost::function &Recruit) //creatures - pairs :recruit(Recruit) @@ -3115,6 +3119,10 @@ CRecrutationWindow::CRecrutationWindow(const std::vector > &C pos.y = screen->h/2 - bitmap->h/2; pos.w = bitmap->w; pos.h = bitmap->h; + bar = new CStatusBar(pos.x+8, pos.y+370, "APHLFTRT.bmp", 471); + max = new AdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecrutationWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m); + buy = new AdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecrutationWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN); + cancel = new AdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecrutationWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE); slider = new CSlider(pos.x+176,pos.y+279,135,boost::bind(&CRecrutationWindow::sliderMoved,this, _1),1,std::min(amounts[0],creatures[0].amount),0,true); std::string pom; printAtMiddle(CGI->generaltexth->allTexts[346],113,231,GEOR13,zwykly,bitmap); //cost per troop t @@ -3144,14 +3152,12 @@ CRecrutationWindow::CRecrutationWindow(const std::vector > &C curx += 120; } - max = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Max,this),pos.x+134,pos.y+313,"IRCBTNS.DEF",SDLK_m); - buy = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Buy,this),pos.x+212,pos.y+313,"IBY6432.DEF",SDLK_RETURN); - cancel = new AdventureMapButton("","",boost::bind(&CRecrutationWindow::Cancel,this),pos.x+290,pos.y+313,"ICN6432.DEF",SDLK_ESCAPE); - if(!creatures[0].amount) + if(!creatures[0].amount || !amounts[0]) { max->block(true); - buy->block(true); + slider->block(true); } + //buy->block(true); //not needed, will be blocked by initing slider on 0 } CRecrutationWindow::~CRecrutationWindow() { @@ -3164,6 +3170,7 @@ CRecrutationWindow::~CRecrutationWindow() delete cancel; SDL_FreeSurface(bitmap); delete slider; + delete bar; } CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner) diff --git a/CPlayerInterface.h b/CPlayerInterface.h index 1305dbbb7..20ce2ee78 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -527,6 +527,7 @@ public: CSlider *slider; AdventureMapButton *max, *buy, *cancel; SDL_Surface *bitmap; + CStatusBar *bar; int which; //which creature is active void close(); diff --git a/CPreGame.cpp b/CPreGame.cpp index 2e432cd56..84be54cba 100644 --- a/CPreGame.cpp +++ b/CPreGame.cpp @@ -38,6 +38,48 @@ CPreGame * CPG; namespace fs = boost::filesystem; namespace s = CSDL_Ext; +int getNextCastle(int current, PlayerInfo * ourInf, bool next=true) //next=flase => previous castle +{ + int dir = next ? 1 : -1; + if (current==-2) //no castle - no change + return current; + else if (current==-1) //random => first/last available + { + int pom = (next) ? (0) : (F_NUMBER-1); // last or first + for (;pom>=0 && pomallowedFactions) + { + current=pom; + break; + } + else continue; + } + } + else // next/previous available + { + for (;;) + { + current+=dir; + if (((int)pow((double)2,(int)current))&ourInf->allowedFactions) + { + break; + } + if (current>=F_NUMBER || current<0) + { + double p1 = log((double)ourInf->allowedFactions)/log(2.0f)+0.000001f; + double check = p1-((int)p1); + if (check < 0.001) + current=(int)p1; + else + current=-1; + break; + } + } + } + return current; +} + HighButton::HighButton( SDL_Rect Pos, CDefHandler* Imgs, bool Sel, int id) { type=0; @@ -441,6 +483,7 @@ int Options::nextAllowedHero(int min, int max, int incl, int dir) //incl 0 - wla } return -1; } + void Options::OptionSwitch::press(bool down) { HighButton::press(down); @@ -452,50 +495,21 @@ void Options::OptionSwitch::press(bool down) { case -1: //castle change { - int oCas = ourOpt->castle; - if (ourOpt->castle==-2) //no castle - no change - return; - else if (ourOpt->castle==-1) //random => first/last available - { - int pom = (left) ? (F_NUMBER-1) : (0); // last or first - for (;pom>=0 && pomallowedFactions) - { - ourOpt->castle=pom; - break; - } - else continue; - } - } - else // next/previous available - { - for (;;) - { - ourOpt->castle+=dir; - if (((int)pow((double)2,(int)ourOpt->castle))&ourInf->allowedFactions) - { - break; - } - if (ourOpt->castle>=F_NUMBER || ourOpt->castle<0) - { - double p1 = log((double)ourInf->allowedFactions)/log(2.0f)+0.000001f; - double check = p1-((int)p1); - if (check < 0.001) - ourOpt->castle=(int)p1; - else - ourOpt->castle=-1; - break; - } - } - } + int nCas = getNextCastle(ourOpt->castle,ourInf,!left); - if (oCas!=ourOpt->castle) //changed castle + if (nCas!=ourOpt->castle) //changed castle { - ourOpt->hero=-1; - ourOpt->bonus = brandom; - CPG->ourOptions->showIcon(0,serialID,false); - CPG->ourOptions->showIcon(1,serialID,false); + ourOpt->castle = nCas; + if(ourOpt->hero != -2) + { + ourOpt->hero=-1; + CPG->ourOptions->showIcon(0,serialID,false); + } + if(ourOpt->bonus==bresource) + { + ourOpt->bonus = brandom; + CPG->ourOptions->showIcon(1,serialID,false); + } } break; } @@ -754,18 +768,29 @@ void Options::show() poptions.push_back(new PlayerOptions(playersSoFar,i)); poptions[poptions.size()-1]->nr=playersSoFar; poptions[poptions.size()-1]->color=(Ecolor)i; - poptions[poptions.size()-1]->Cleft.show(); - poptions[poptions.size()-1]->Cright.show(); - poptions[poptions.size()-1]->Hleft.show(); - poptions[poptions.size()-1]->Hright.show(); + + if(CPG->ret.playerInfos[playersSoFar].hero != -2) + { + poptions[poptions.size()-1]->Hleft.show(); + poptions[poptions.size()-1]->Hright.show(); + CPG->btns.push_back(&poptions[poptions.size()-1]->Hleft); + CPG->btns.push_back(&poptions[poptions.size()-1]->Hright); + } + + if(getNextCastle(CPG->ret.playerInfos[playersSoFar].castle,&ms.ourMaps[ms.selected].players[i]) != CPG->ret.playerInfos[playersSoFar].castle) + { + poptions[poptions.size()-1]->Cleft.show(); + poptions[poptions.size()-1]->Cright.show(); + CPG->btns.push_back(&poptions[poptions.size()-1]->Cleft); + CPG->btns.push_back(&poptions[poptions.size()-1]->Cright); + } + poptions[poptions.size()-1]->Bleft.show(); poptions[poptions.size()-1]->Bright.show(); - CPG->btns.push_back(&poptions[poptions.size()-1]->Cleft); - CPG->btns.push_back(&poptions[poptions.size()-1]->Cright); - CPG->btns.push_back(&poptions[poptions.size()-1]->Hleft); - CPG->btns.push_back(&poptions[poptions.size()-1]->Hright); CPG->btns.push_back(&poptions[poptions.size()-1]->Bleft); CPG->btns.push_back(&poptions[poptions.size()-1]->Bright); + + CSDL_Ext::printAtMiddle(CPG->ret.playerInfos[playersSoFar].name,111,137+playersSoFar*50,GEOR13,zwykly); if (ms.ourMaps[ms.selected].players[i].canHumanPlay) { @@ -1289,7 +1314,7 @@ void MapSel::select(int which, bool updateMapsList, bool forceSettingsUpdate) } pset.heroPortrait=-1; if (! - ((curVector()[which].players[i].generateHeroAtMainTown + (((curVector()[which].players[i].generateHeroAtMainTown || curVector()[which].version==RoE) && curVector()[which].players[i].hasMainTown) || curVector()[which].players[i].p8) ) diff --git a/ChangeLog b/ChangeLog index ccc4e6ccf..b17d89cf4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ TOWN INTERFACE: OBJECTS: New objects supported: + * Magic Well * Faerie Ring * Swan Pond * Idol of Fortune diff --git a/client/Client.h b/client/Client.h index b562b2577..67b7f18bd 100644 --- a/client/Client.h +++ b/client/Client.h @@ -87,6 +87,7 @@ public: void moveHero(int hid, int3 pos, bool instant){}; void giveHeroBonus(GiveBonus * bonus){}; void setMovePoints(SetMovePoints * smp){}; + void setManaPoints(int hid, int val){}; ////////////////////////////////////////////////////////////////////////// friend class CCallback; //handling players actions friend void processCommand(const std::string &message, CClient *&client); //handling console diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 7d5bc0ade..5b303cb42 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1719,6 +1719,49 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const } const std::string & CGBonusingObject::getHoverText() const +{ + const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); + hoverName = VLC->generaltexth->names[ID]; + if(h) + { + if(!h->getBonus(HeroBonus::OBJECT,ID)) + hoverName += " " + VLC->generaltexth->allTexts[353]; //not visited + else + hoverName += " " + VLC->generaltexth->allTexts[352]; //visited + } + return hoverName; +} + +void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const +{ + int message; + InfoWindow iw; + iw.player = h->tempOwner; + if(h->getBonus(HeroBonus::OBJECT,ID)) //has already visited Well today + { + message = 78; + } + else if(h->mana < h->manaLimit()) + { + GiveBonus gbonus; + gbonus.bonus.type = HeroBonus::NONE; + gbonus.hid = h->id; + gbonus.bonus.duration = HeroBonus::ONE_DAY; + gbonus.bonus.source = HeroBonus::OBJECT; + gbonus.bonus.id = ID; + cb->giveHeroBonus(&gbonus); + cb->setManaPoints(h->id,h->manaLimit()); + message = 77; + } + else + { + message = 79; + } + iw.text << std::pair(11,message); //"A second drink at the well in one day will not help you." + cb->showInfoDialog(&iw); +} + +const std::string & CGMagicWell::getHoverText() const { const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer()); hoverName = VLC->generaltexth->names[ID]; diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index d7f0ee554..2ca5365e7 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -623,6 +623,19 @@ public: } }; +class DLL_EXPORT CGMagicWell : public CGObjectInstance //objects giving bonuses to luck/morale/movement +{ +public: + void onHeroVisit(const CGHeroInstance * h) const; + const std::string & getHoverText() const; + + template void serialize(Handler &h, const int version) + { + h & static_cast(*this); + } +}; + + class DLL_EXPORT CObjectHandler diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 6a7760899..710551609 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -23,4 +23,17 @@ struct DLL_EXPORT HeroBonus { h & duration & type & source & val & id & description; } -}; \ No newline at end of file + + static bool OneDay(const HeroBonus &hb) + { + return hb.duration==HeroBonus::ONE_DAY; + } + static bool OneWeek(const HeroBonus &hb) + { + return hb.duration==HeroBonus::ONE_WEEK; + } + static bool OneBattle(const HeroBonus &hb) + { + return hb.duration==HeroBonus::ONE_BATTLE; + } +}; diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 8e4e7b513..d58c4973a 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -59,5 +59,6 @@ public: virtual void moveHero(int hid, int3 pos, bool instant)=0; virtual void giveHeroBonus(GiveBonus * bonus)=0; virtual void setMovePoints(SetMovePoints * smp)=0; + virtual void setManaPoints(int hid, int val)=0; }; #endif // __IGAMECALLBACK_H__ \ No newline at end of file diff --git a/map.cpp b/map.cpp index 3d14e87d2..25c46813a 100644 --- a/map.cpp +++ b/map.cpp @@ -1790,6 +1790,11 @@ void Mapa::readObjects( unsigned char * bufor, int &i) nobj = new CGBonusingObject(); break; } + case 49: //Magic Well + { + nobj = new CGMagicWell(); + break; + } case 214: //hero placeholder { i+=3; //TODO: handle it more properly @@ -1830,13 +1835,11 @@ void Mapa::readEvents( unsigned char * bufor, int &i ) { ne.message +=bufor[i]; ++i; } - ne.wood = readNormalNr(bufor,i); i+=4; - ne.mercury = readNormalNr(bufor,i); i+=4; - ne.ore = readNormalNr(bufor,i); i+=4; - ne.sulfur = readNormalNr(bufor,i); i+=4; - ne.crystal = readNormalNr(bufor,i); i+=4; - ne.gems = readNormalNr(bufor,i); i+=4; - ne.gold = readNormalNr(bufor,i); i+=4; + ne.resources.resize(RESOURCE_QUANTITY); + for(int k=0; k < 7; k++) + { + ne.resources[k] = readNormalNr(bufor,i); i+=4; + } ne.players = bufor[i]; ++i; if(version>AB) { diff --git a/map.h b/map.h index 893617fe2..10095715d 100644 --- a/map.h +++ b/map.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "global.h" #ifndef _MSC_VER #include "hch/CObjectHandler.h" @@ -185,15 +186,15 @@ class DLL_EXPORT CMapEvent { public: std::string name, message; - si32 wood, mercury, ore, sulfur, crystal, gems, gold; //gained / taken resources + std::vector resources; //gained / taken resources ui8 players; //affected players ui8 humanAffected; ui8 computerAffected; ui32 firstOccurence; - ui32 nextOccurence; //after nextOccurance day event will occure; if it it 0, event occures only one time; + ui32 nextOccurence; //after nextOccurance day event will occur; if it it 0, event occures only one time; template void serialize(Handler &h, const int version) { - h & name & message & wood & mercury & ore & sulfur & crystal & gems & gold + h & name & message & resources & players & humanAffected & computerAffected & firstOccurence & nextOccurence; } }; @@ -296,7 +297,7 @@ struct DLL_EXPORT Mapa : public CMapHeader std::vector allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed std::vector allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed std::vector allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed - std::vector events; + std::list events; int3 grailPos; int grailRadious; @@ -506,6 +507,9 @@ struct DLL_EXPORT Mapa : public CMapHeader case 31: //Fountain of Youth SERIALIZE(CGBonusingObject); break; + case 49: //Magic Well + SERIALIZE(CGMagicWell); + break; default: SERIALIZE(CGObjectInstance); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index c6ff6f0da..fd461595b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2459,4 +2459,12 @@ void CGameHandler::giveHeroBonus( GiveBonus * bonus ) void CGameHandler::setMovePoints( SetMovePoints * smp ) { sendAndApply(smp); +} + +void CGameHandler::setManaPoints( int hid, int val ) +{ + SetMana sm; + sm.hid = hid; + sm.val = val; + sendAndApply(&sm); } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 4254e982f..d2e4cd97d 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -105,6 +105,7 @@ public: void moveHero(int hid, int3 pos, bool instant); void giveHeroBonus(GiveBonus * bonus); void setMovePoints(SetMovePoints * smp); + void setManaPoints(int hid, int val); ////////////////////////////////////////////////////////////////////////// void init(StartInfo *si, int Seed);