diff --git a/client/AdventureMapButton.cpp b/client/AdventureMapButton.cpp index 9d64cb93d..1c6a528d3 100644 --- a/client/AdventureMapButton.cpp +++ b/client/AdventureMapButton.cpp @@ -199,27 +199,28 @@ void AdventureMapButton::hover (bool on) } } -void AdventureMapButton::activate() -{ -// if (active) return; -// active=true; - activateLClick(); - activateRClick(); - activateHover(); - activateKeys(); -} -void AdventureMapButton::deactivate() -{ -// if (!active) return; -// active=false; - deactivateLClick(); - deactivateRClick(); - deactivateHover(); - deactivateKeys(); -} +//void AdventureMapButton::activate() +//{ +//// if (active) return; +//// active=true; +// activateLClick(); +// activateRClick(); +// activateHover(); +// activateKeys(); +//} +//void AdventureMapButton::deactivate() +//{ +//// if (!active) return; +//// active=false; +// deactivateLClick(); +// deactivateRClick(); +// deactivateHover(); +// deactivateKeys(); +//} void AdventureMapButton::init(const CFunctionList &Callback, const std::map &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector * add, int x, int y, int key) { + used = LCLICK | RCLICK | HOVER | KEYBOARD; callback = Callback; blocked = actOnDown = false; type=2; diff --git a/client/AdventureMapButton.h b/client/AdventureMapButton.h index 792a439a0..51cd5fdaf 100644 --- a/client/AdventureMapButton.h +++ b/client/AdventureMapButton.h @@ -42,8 +42,8 @@ public: int curimg; //curently displayed image from imgs virtual void show(SDL_Surface * to); virtual void showAll(SDL_Surface * to); - virtual void activate()=0; - virtual void deactivate()=0; + //virtual void activate()=0; + //virtual void deactivate()=0; CButtonBase(); //c-tor virtual ~CButtonBase(); //d-tor }; @@ -63,8 +63,8 @@ public: virtual void clickLeft(tribool down, bool previousState); void hover (bool on); void block(ui8 on); //if button is blocked then it'll change it's graphic to inactive (offset==2) and won't react on l-clicks - void activate(); // makes button active - void deactivate(); // makes button inactive (but doesn't delete) + //void activate(); // makes button active + //void deactivate(); // makes button inactive (but doesn't delete) 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 diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index f0bc509c0..cac9f2a18 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -571,7 +571,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState) if(!objs.size()) return; - const CGObjectInstance * obj = objs.front(); + const CGObjectInstance * obj = objs.back(); switch(obj->ID) { case HEROI_TYPE: @@ -1728,6 +1728,8 @@ void CAdvMapInt::centerOn(int3 on) LOCPLINT->adventureInt->position = on; LOCPLINT->adventureInt->updateScreen=true; updateMinimap=true; + underground.curimg = on.z; //change underground switch button image + underground.redraw(); } void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) { diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index e9a7c1a48..c6b76ca70 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -270,7 +270,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) else if(other->hero && other->highlight) { bool allow = true; - if(upg) //moving hero out of town - check if it is allowed + if(!upg) //moving hero out of town - check if it is allowed { if(!hero && LOCPLINT->cb->howManyHeroes(false) >= 8) { @@ -505,7 +505,7 @@ CCastleInterface::~CCastleInterface() SDL_FreeSurface(townInt); SDL_FreeSurface(cityBg); delete exit; - delete split; + //delete split; delete hall; delete fort; delete garr; @@ -749,7 +749,7 @@ void CCastleInterface::showAll( SDL_Surface * to/*=NULL*/) if(screen->w != 800 || screen->h !=600) CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15); exit->show(to); - split->show(to); + //split->show(to); } void CCastleInterface::townChange() @@ -796,7 +796,7 @@ void CCastleInterface::activate() garr->activate(); LOCPLINT->statusbar = statusbar; exit->activate(); - split->activate(); + //split->activate(); for(size_t i=0;iactivate(); @@ -812,7 +812,7 @@ void CCastleInterface::deactivate() townlist->deactivate(); garr->deactivate(); exit->deactivate(); - split->deactivate(); + //split->deactivate(); for(size_t i=0;ideactivate(); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 2635c0dee..1f75ebcc4 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -386,6 +386,9 @@ CGarrisonInt::~CGarrisonInt() } delete sdown; } + + for(size_t i = 0; iactivate(); } void CGarrisonInt::createSlots() { @@ -3424,6 +3424,12 @@ void CArtPlace::clickLeft(tribool down, bool previousState) { if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported) { + if(ourArt->id == 3) //catapult cannot be highlighted + { + std::vector catapult(1, new SComponent(SComponent::artifact, 3, 0)); + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped. + return; + } clicked = true; ourOwner->commonInfo->activeArtPlace = this; } @@ -3432,8 +3438,24 @@ void CArtPlace::clickLeft(tribool down, bool previousState) { if(slotID >= 19) //we are an backpack slot - remove active artifact and put it to the last free pos in backpack { //TODO: putting artifacts in the middle of backpack (pushing following arts) - - LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19); + const CArtifact *cur = ourOwner->commonInfo->activeArtPlace->ourArt; + assert(cur); //there is highlighted slot, it must contain an art + switch(cur->id) + { + case 3: + //should not happen, catapult cannot be selected + break; + case 4: case 5: case 6: + { + std::string text = CGI->generaltexth->allTexts[153]; + boost::algorithm::replace_first(text, "%s", cur->Name()); + LOCPLINT->showInfoDialog(text); + } + break; + default: + LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19); + break; + } } //check if swap is possible else if(this->fitsHere(ourOwner->commonInfo->activeArtPlace->ourArt) && ourOwner->commonInfo->activeArtPlace->fitsHere(this->ourArt)) @@ -3495,8 +3517,12 @@ bool CArtPlace::fitsHere(const CArtifact * art) { if(!art) return true; //you can have no artifact somewhere - if(slotID > 18 || vstd::contains(art->possibleSlots,slotID)) //backpack or right slot + if(slotID > 18 && art->id >= 3 && art->id <= 6 //everything can bee placed in backpack exept of War Machines + || vstd::contains(art->possibleSlots,slotID)) + { return true; + } + return false; } CArtPlace::~CArtPlace() @@ -4075,7 +4101,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) ourBar = new CStatusBar(pos.x + 3, pos.y + 577, "TSTATBAR.bmp", 726); //garrison interface - garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true); + garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true, true); garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+10,pos.y+132,"TSBTNS.DEF")); garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+740,pos.y+132,"TSBTNS.DEF")); diff --git a/int3.h b/int3.h index 480513b42..e1dc5d393 100644 --- a/int3.h +++ b/int3.h @@ -15,20 +15,28 @@ */ class CCreature; + +//a few typedefs for CCreatureSet +typedef si32 TSlot, TQuantity; +typedef ui32 TCreature; +typedef std::pair TStack; +typedef std::map TSlots; + class CCreatureSet //seven combined creatures { public: - std::map > slots; //slots[slot_id]=> pair(creature_id,creature_quantity) - bool formation; //false - wide, true - tight - bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 0 to 6 + TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity) + ui8 formation; //false - wide, true - tight + + bool setCreature (TSlot slot, TCreature type, TQuantity quantity) //slots 0 to 6 { - slots[slot] = std::pair(type, quantity); //brutal force + slots[slot] = TStack(type, quantity); //brutal force if (slots.size() > 7) return false; else return true; } - si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) const //returns -1 if no slot available + TSlot getSlotFor(TCreature creature, ui32 slotsAmount=7) const //returns -1 if no slot available { - for(std::map >::const_iterator i=slots.begin(); i!=slots.end(); ++i) + for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) { if(i->second.first == creature) { @@ -44,6 +52,37 @@ public: } return -1; //no slot available } + bool mergableStacks(std::pair &out, TSlot preferable = -1) //looks for two same stacks, returns slot positions + { + //try to match creature to our preferred stack + if(preferable >= 0 && slots.find(preferable) != slots.end()) + { + TCreature id = slots[preferable].first; + for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) + { + if(id == j->second.first) + { + out.first = preferable; + out.second = j->first; + return true; + } + } + } + + for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i) + { + for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j) + { + if(i->second.first == j->second.first) + { + out.first = i->first; + out.second = j->first; + return true; + } + } + } + return false; + } template void serialize(Handler &h, const int version) { h & slots & formation; @@ -54,7 +93,7 @@ public: } void sweep() { - for(std::map >::iterator i=slots.begin(); i!=slots.end(); ++i) + for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i) { if(!i->second.second) { diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 9be32aac0..dc5246284 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -2097,6 +2097,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int || dp.turns > turn || (dp.turns >= turn && dp.moveRemains < remains)) //this route is faster { + assert(&dp != cp->theNodeBefore); //two tiles can't point to each other dp.moveRemains = remains; dp.turns = turn; dp.theNodeBefore = cp; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index cace55de1..51836ff3b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2162,10 +2162,21 @@ bool CGameHandler::garrisonSwap( si32 tid ) int pos = csn.getSlotFor(cso.slots.begin()->second.first); if(pos<0) { - complain("Cannot make garrison swap, not enough free slots!"); - return false; + //try to merge two other stacks to make place + std::pair toMerge; + if(csn.mergableStacks(toMerge, cso.slots.begin()->first)) + { + //merge + csn.slots[toMerge.second].second += csn.slots[toMerge.first].second; + csn.slots[toMerge.first] = cso.slots.begin()->second; + } + else + { + complain("Cannot make garrison swap, not enough free slots!"); + return false; + } } - if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack + else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack { csn.slots[pos].second += cso.slots.begin()->second.second; }