diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 8d26fd6ec..f471a1f64 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -374,15 +374,20 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac } else { - std::set cres; + CCreatureSet cres; //get types of creatures that need their own slot for(TSlots::const_iterator i = cs.stacks.begin(); i != cs.stacks.end(); i++) - cres.insert(i->second->type); + cres.addToSlot(i->first, i->second->type->idNumber, 1, true); + TSlot j; for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); i++) - cres.insert(i->second->type); - - return cres.size() <= ARMY_SIZE; + { + if ((j = cres.getSlotFor(i->second->type)) >= 0) + cres.addToSlot(j, i->second->type->idNumber, 1, true); //merge if possible + else + return false; //no place found + } + return true; //all stacks found their slots } } diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index e118cf2f9..4480289d9 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -4873,6 +4873,7 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con { InfoWindow iw; iw.player = h->getOwner(); + std::string msg = message; //in case box is removed in the meantime bool changesPrimSkill = false; for (int i = 0; i < primskills.size(); i++) @@ -5044,11 +5045,10 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con cb->showInfoDialog(&iw); cb->giveCreatures(this, h, creatures, true); - //boost::bind(&CGPandoraBox::endBattle, this, h, _1) } - if(!afterBattle && message.size()) + if(!afterBattle && msg.size()) { - iw.text << message; + iw.text << msg; cb->showInfoDialog(&iw); } if (!creatures.Slots().size()) diff --git a/lib/CObjectHandler.h b/lib/CObjectHandler.h index 391de10c4..c11a6e1eb 100644 --- a/lib/CObjectHandler.h +++ b/lib/CObjectHandler.h @@ -654,7 +654,6 @@ class DLL_EXPORT CGPandoraBox : public CArmedInstance { public: std::string message; - ui8 removeAfterVisit; //true if event is removed after occurring //gained things: ui32 gainedExp; @@ -688,17 +687,15 @@ public: class DLL_EXPORT CGEvent : public CGPandoraBox //event objects { public: - + ui8 removeAfterVisit; //true if event is removed after occurring ui8 availableFor; //players whom this event is available for ui8 computerActivate; //true if computre player can activate this event ui8 humanActivate; //true if human player can activate this event template void serialize(Handler &h, const int version) { - h & static_cast(*this); - h & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills - & abilities & abilityLevels & artifacts & spells & creatures & availableFor - & computerActivate & humanActivate; + h & static_cast(*this); + h & removeAfterVisit & availableFor & computerActivate & humanActivate; } void onHeroVisit(const CGHeroInstance * h) const; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d0c94e77f..dfb6490e3 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1586,13 +1586,12 @@ void CGameHandler::giveCreatures(const CArmedInstance *obj, const CGHeroInstance COMPLAIN_RET_IF(creatures.stacksCount() > ARMY_SIZE, "Too many stacks to give!"); //first we move creatures to give to make them army of object-source - for(int i = 0; i != creatures.stacksCount(); i++) + for (TSlots::const_iterator stack = creatures.Slots().begin(); stack != creatures.Slots().end(); stack++) { - TSlots::const_iterator stack = creatures.Slots().begin(); - addToSlot(StackLocation(obj, i), stack->second->type, stack->second->count); - } + addToSlot(StackLocation(obj, obj->getSlotFor(stack->second->type)), stack->second->type, stack->second->count); + } - tryJoiningArmy(obj, h, remove, false); + tryJoiningArmy(obj, h, remove, true); } void CGameHandler::takeCreatures(int objid, std::vector creatures) @@ -4522,6 +4521,24 @@ void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstanc { if(!dst->canBeMergedWith(*src, allowMerging)) { + if (allowMerging) //do that, add all matching creatures. + { + bool cont = true; + while (cont) + { + for(TSlots::const_iterator i = src->stacks.begin(); i != src->stacks.end(); i++)//while there are unmoved creatures + { + TSlot pos = dst->getSlotFor(i->second->type); + if(pos > -1) + { + moveStack(StackLocation(src, i->first), StackLocation(dst, pos)); + cont = true; + break; //or iterator crashes + } + cont = false; + } + } + } boost::function removeOrNot = 0; if(removeObjWhenFinished) removeOrNot = boost::bind(&IGameCallback::removeObject,this,src->id);