From fc6d6e02a3a0ffb282c3d127cb5e9d6bc2e82fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sat, 11 Dec 2010 23:11:26 +0000 Subject: [PATCH] More fixes for stacks, some basic macro-based logging for bonus graph operations. --- client/CCastleInterface.cpp | 2 + client/Client.h | 4 +- client/GUIClasses.cpp | 10 +++-- hch/CObjectHandler.cpp | 16 +++++--- hch/CObjectHandler.h | 2 + lib/CCreatureSet.cpp | 15 ++++++++ lib/CCreatureSet.h | 1 + lib/CGameState.cpp | 20 ++++++++++ lib/CGameState.h | 2 + lib/HeroBonus.cpp | 9 +++++ lib/HeroBonus.h | 5 ++- lib/IGameCallback.h | 4 +- lib/NetPacks.h | 2 +- lib/map.cpp | 26 ++++++------- lib/map.h | 2 +- server/CGameHandler.cpp | 76 +++++++++++++++++++++---------------- server/CGameHandler.h | 16 ++++++-- 17 files changed, 143 insertions(+), 69 deletions(-) diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index 41b955596..15a90c248 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -26,6 +26,8 @@ #include #include #include +#include "../hch/CCreatureHandler.h" +#include "../hch/CMusicHandler.h" using namespace boost::assign; using namespace CSDL_Ext; diff --git a/client/Client.h b/client/Client.h index 92eb300a8..dea748714 100644 --- a/client/Client.h +++ b/client/Client.h @@ -110,13 +110,13 @@ public: void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function &cb){}; void showThievesGuildWindow(int requestingObjId){}; void giveResource(int player, int which, int val){}; - void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove) {}; + void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) {}; void takeCreatures (int objid, TSlots creatures){}; void takeCreatures (int objid, std::vector creatures){}; bool changeStackType(const StackLocation &sl, CCreature *c){return false;}; bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false){return false;}; bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count){return false;}; - bool eraseStack(const StackLocation &sl){return false;}; + bool eraseStack(const StackLocation &sl, bool forceRemoval = false){return false;}; bool swapStacks(const StackLocation &sl1, const StackLocation &sl2){return false;} bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count){return false;} void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished){} diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 409878c2f..b9264677c 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -47,6 +47,8 @@ #include "../StartInfo.h" #include "CPreGame.h" #include "../lib/HeroBonus.h" +#include "../hch/CCreatureHandler.h" +#include "../hch/CMusicHandler.h" /* * GUIClasses.cpp, part of VCMI engine @@ -4873,8 +4875,8 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero) { if(curHero != hero) { - delete curHero; - hero = curHero = new CGHeroInstance(*hero); + //delete curHero; + //hero = curHero = new CGHeroInstance(*hero); } // Compensate backpack pos if an artifact was insertad before it. @@ -4923,8 +4925,8 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero) if(hero != curHero) { - delete curHero; - curHero = new CGHeroInstance(*hero); +// delete curHero; +// curHero = new CGHeroInstance(*hero); } if (curHero->artifacts.size() > 0) diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 74d8004ac..ce32c6144 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1575,6 +1575,11 @@ void CGHeroInstance::initExp() level = 1; } +std::string CGHeroInstance::nodeName() const +{ + return "Hero " + name; +} + void CGDwelling::initObj() { switch(ID) @@ -5008,24 +5013,23 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con if (creatures.Slots().size()) { //this part is taken straight from creature bank MetaString loot; - CCreatureSet ourArmy = creatures; - for(TSlots::const_iterator i = ourArmy.Slots().begin(); i != ourArmy.Slots().end(); i++) + for(TSlots::const_iterator i = creatures.Slots().begin(); i != creatures.Slots().end(); i++) { //build list of joined creatures iw.components.push_back(Component(*i->second)); loot << "%s"; loot.addReplacement(*i->second); } - if (ourArmy.Slots().size() == 1 && ourArmy.Slots().begin()->second->count == 1) - iw.text.addTxt (MetaString::ADVOB_TXT, 185); + if (creatures.Slots().size() == 1 && creatures.Slots().begin()->second->count == 1) + iw.text.addTxt(MetaString::ADVOB_TXT, 185); else - iw.text.addTxt (MetaString::ADVOB_TXT, 186); + iw.text.addTxt(MetaString::ADVOB_TXT, 186); iw.text.addReplacement(loot.buildList()); iw.text.addReplacement(h->name); cb->showInfoDialog(&iw); - cb->giveCreatures (id, h, ourArmy, true); + cb->giveCreatures (id, h, creatures, true); //boost::bind(&CGPandoraBox::endBattle, this, h, _1) } if(!afterBattle && message.size()) diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index d20b39486..ab3fd11f1 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -369,6 +369,8 @@ public: ////////////////////////////////////////////////////////////////////////// + + virtual std::string nodeName() const OVERRIDE; void setPropertyDer(ui8 what, ui32 val);//synchr void initObj(); void onHeroVisit(const CGHeroInstance * h) const; diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 58cf63029..5dd14720d 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -7,6 +7,7 @@ #include "IGameCallback.h" #include "CGameState.h" #include "../hch/CGeneralTextHandler.h" +#include const CStackInstance &CCreatureSet::operator[](TSlot slot) const { @@ -465,6 +466,20 @@ CStackInstance::~CStackInstance() } +std::string CStackInstance::nodeName() const +{ + std::ostringstream oss; + oss << "Stack of " << count << " creatures of "; + if(type) + oss << type->namePl; + else if(idRand) + oss << "[no type, idRand=" << idRand << "]"; + else + oss << "[UNDEFINED TYPE]"; + + return oss.str(); +} + CStackBasicDescriptor::CStackBasicDescriptor() { type = NULL; diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 1abae9530..98d3ed8af 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -64,6 +64,7 @@ public: void setType(const CCreature *c); void setArmyObj(const CArmedInstance *ArmyObj); bool valid(bool allowUnrandomized) const; + virtual std::string nodeName() const OVERRIDE; }; DLL_EXPORT std::ostream & operator<<(std::ostream & str, const CStackInstance & sth); diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index e25044cc1..d41a58d56 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1038,6 +1038,21 @@ const CGHeroInstance * CStack::getMyHero() const return NULL; } +std::string CStack::nodeName() const +{ + std::ostringstream oss; + oss << "Battle stack of " << count << " creatures of "; + if(type) + oss << type->namePl; + else + oss << "[UNDEFINED TYPE]"; + + oss << " from slot " << (int)slot; + if(base && base->armyObj) + oss << " of armyobj=" << base->armyObj->id; + return oss.str(); +} + CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, std::map &available, const CHeroClass *bannedClass /*= NULL*/) const { CGHeroInstance *ret = NULL; @@ -4556,6 +4571,11 @@ PlayerState::PlayerState() } +std::string PlayerState::nodeName() const +{ + return "Player " + (color < VLC->generaltexth->capColors.size() ? VLC->generaltexth->capColors[color] : boost::lexical_cast(color)); +} + // void PlayerState::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const // { // return; //no loops possible diff --git a/lib/CGameState.h b/lib/CGameState.h index 6056396cf..379ac748c 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -143,6 +143,7 @@ public: ui8 daysWithoutCastle; PlayerState(); + std::string nodeName() const OVERRIDE; //override //void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const; @@ -281,6 +282,7 @@ public: CStack(const CStackBasicDescriptor *stack, int O, int I, bool AO, int S = 255); //c-tor CStack(); //c-tor ~CStack(); + std::string nodeName() const OVERRIDE; void init(); //set initial (invalid) values void postInit(); //used to finish initialization when inheriting creature parameters is working diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 9a94186e7..39875844e 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -18,6 +18,8 @@ DLL_EXPORT const std::map bonusNameMap = boost::assign::map_list_of BONUS_LIST; #undef BONUS_NAME +#define BONUS_LOG_LINE(x) tlog0 << x << std::endl + int DLL_EXPORT BonusList::totalValue() const { int base = 0; @@ -406,12 +408,14 @@ void CBonusSystemNode::newChildAttached(CBonusSystemNode *child) { assert(!vstd::contains(children, child)); children.push_back(child); + BONUS_LOG_LINE(child->nodeName() << " #attached to# " << nodeName()); } void CBonusSystemNode::childDetached(CBonusSystemNode *child) { assert(vstd::contains(children, child)); children -= child; + BONUS_LOG_LINE(child->nodeName() << " #detached from# " << nodeName()); } void CBonusSystemNode::detachFromAll() @@ -425,6 +429,11 @@ bool CBonusSystemNode::isIndependentNode() const return parents.empty() && children.empty(); } +std::string CBonusSystemNode::nodeName() const +{ + return std::string("Bonus system node of type ") + typeid(*this).name(); +} + int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/) { if(obj) diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 386d25fb5..3e8fb7c49 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -394,8 +394,8 @@ public: bool hasBonusFrom(ui8 source, ui32 sourceID) const; void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs int getBonusesCount(int from, int id) const; - virtual ui32 getMinDamage() const; //used for stacks and creatures only - virtual ui32 getMaxDamage() const; + ui32 getMinDamage() const; //used for stacks and creatures only + ui32 getMaxDamage() const; int MoraleVal() const; //range [-3, +3] int LuckVal() const; //range [-3, +3] @@ -426,6 +426,7 @@ public: CBonusSystemNode *whereToPropagate(Bonus *b); void popBonuses(const CSelector &s); + virtual std::string nodeName() const; template void serialize(Handler &h, const int version) { diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 40e8ebe32..f953924de 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -87,13 +87,13 @@ public: virtual void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function &cb) =0; //cb will be called when player closes garrison window virtual void showThievesGuildWindow(int requestingObjId) =0; virtual void giveResource(int player, int which, int val)=0; - virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove) =0; + virtual void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) =0; //virtual void takeCreatures (int objid, TSlots creatures) =0; virtual void takeCreatures (int objid, std::vector creatures) =0; virtual bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) =0; virtual bool changeStackType(const StackLocation &sl, CCreature *c) =0; virtual bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count = -1) =0; //count -1 => moves whole stack - virtual bool eraseStack(const StackLocation &sl) =0; + virtual bool eraseStack(const StackLocation &sl, bool forceRemoval = false) =0; virtual bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) =0; virtual bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) =0; //makes new stack or increases count of already existing virtual void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished) =0; //merges army from src do dst or opens a garrison window diff --git a/lib/NetPacks.h b/lib/NetPacks.h index b4d700da3..03a56da7f 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -752,7 +752,7 @@ struct ChangeStackCount : CGarrisonOperationPack //521 template void serialize(Handler &h, const int version) { - h & sl & count; + h & sl & count & absoluteValue; } }; diff --git a/lib/map.cpp b/lib/map.cpp index 6950f3f2b..a333e02e7 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -777,10 +777,9 @@ void Mapa::loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int nt->garrisonHero = NULL; } -void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int &i ) +CGObjectInstance * Mapa::loadHero(const unsigned char * bufor, int &i) { - CGHeroInstance * nhi = new CGHeroInstance; - nobj=nhi; + CGHeroInstance * nhi = new CGHeroInstance(); int identifier = 0; if(version>RoE) @@ -789,20 +788,20 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int } ui8 owner = bufor[i++]; - nobj->subID = readNormalNr(bufor,i, 1); ++i; + nhi->subID = readNormalNr(bufor,i, 1); ++i; for(unsigned int j=0; jsubID == nobj->subID) + if(predefinedHeroes[j]->subID == nhi->subID) { - *nhi = *predefinedHeroes[j]; + tlog0 << "Hero " << nhi->subID << " will be taken from the predefined heroes list.\n"; + delete nhi; + nhi = predefinedHeroes[j]; break; } } - nobj->setOwner(owner); + nhi->setOwner(owner); - //(*(static_cast(nhi))) = *nobj; - //delete nobj; nhi->portrait = nhi->subID; for(unsigned int j=0; jmoveDir = 4; - nhi->isStanding = true; - nhi->level = -1; - nhi->mana = -1; - nhi->movement = -1; + + return nhi; } void Mapa::readRumors( const unsigned char * bufor, int &i) @@ -1385,7 +1381,7 @@ void Mapa::readObjects( const unsigned char * bufor, int &i) } case 34: case 70: case 62: //34 - hero; 70 - random hero; 62 - prison { - loadHero(nobj, bufor, i); + nobj = loadHero(bufor, i); break; } case 4: //Arena diff --git a/lib/map.h b/lib/map.h index 6b8effcd6..f73f43e8e 100644 --- a/lib/map.h +++ b/lib/map.h @@ -293,7 +293,7 @@ struct DLL_EXPORT Mapa : public CMapHeader void readPredefinedHeroes( const unsigned char * bufor, int &i); void readHeader( const unsigned char * bufor, int &i); void readRumors( const unsigned char * bufor, int &i); - void loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int &i); + CGObjectInstance *loadHero(const unsigned char * bufor, int &i); void loadTown( CGObjectInstance * &nobj, const unsigned char * bufor, int &i, int subid); int loadSeerHut( const unsigned char * bufor, int i, CGObjectInstance *& nobj); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 6e51aca74..d46c2c083 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -310,28 +310,6 @@ void CGameHandler::changeSecSkill( int ID, int which, int val, bool abs/*=false* } } -void CGameHandler::takeCasualties(const CArmedInstance *army, BattleInfo *bat) -{ - int color = army->tempOwner; - if(color == 254) - color = NEUTRAL_PLAYER; - - BOOST_FOREACH(CStack *st, bat->stacks) - { - if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks - continue; - - if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) - { - StackLocation sl(army, st->slot); - if(st->alive()) - changeStackCount(sl, st->count, true); - else - eraseStack(sl); - } - } -} - void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town) { battleEndCallback = new boost::function(cb); @@ -567,7 +545,6 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) { - BattleResultsApplied resultsApplied; resultsApplied.player1 = bEndArmy1->tempOwner; resultsApplied.player2 = bEndArmy2->tempOwner; @@ -584,18 +561,16 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer battleResult.data->exp[0] *= (100+hero1->getSecSkillLevel(21)*5)/100.0f;//sholar skill if (hero2) battleResult.data->exp[1] *= (100+hero2->getSecSkillLevel(21)*5)/100.0f; - sendAndApply(battleResult.data); - - //casualties among heroes armies - takeCasualties(bEndArmy1, gs->curB); - takeCasualties(bEndArmy2, gs->curB); ui8 sides[2]; sides[0] = gs->curB->side1; sides[1] = gs->curB->side2; - ui8 loser = sides[!battleResult.data->winner]; - + + CasualtiesAfterBattle cab1(bEndArmy1, gs->curB), cab2(bEndArmy2, gs->curB); //calculate casualties before deleting battle + sendAndApply(battleResult.data); + cab1.takeFromArmy(this); cab2.takeFromArmy(this); //take casualties after battle is deleted + //if one hero has lost we will erase him if(battleResult.data->winner!=0 && hero1) { @@ -2087,7 +2062,7 @@ void CGameHandler::giveResource(int player, int which, int val) sr.val = gs->players.find(player)->second.resources[which]+val; sendAndApply(&sr); } -void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove) +void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove) { assert(0); // if (creatures.stacksCount() <= 0) @@ -3082,6 +3057,7 @@ bool CGameHandler::garrisonSwap( si32 tid ) intown.garrison = -1; intown.visiting = town->garrisonHero->id; sendAndApply(&intown); + return true; } else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero { @@ -5246,13 +5222,14 @@ bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, T return true; } -bool CGameHandler::eraseStack(const StackLocation &sl) +bool CGameHandler::eraseStack(const StackLocation &sl, bool forceRemoval/* = false*/) { if(!sl.army->hasStackAtSlot(sl.slot)) COMPLAIN_RET("Cannot find a stack to erase"); if(sl.army->Slots().size() == 1 //from the last stack - && sl.army->needsLastStack()) //that must be left + && sl.army->needsLastStack() //that must be left + && !forceRemoval) //ignore above conditions if we are forcing removal { COMPLAIN_RET("Cannot erase the last stack!"); } @@ -5379,4 +5356,37 @@ bool CGameHandler::swapStacks(const StackLocation &sl1, const StackLocation &sl2 sendAndApply(&ss); return true; } +} + +CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat) +{ + int color = army->tempOwner; + if(color == 254) + color = NEUTRAL_PLAYER; + + BOOST_FOREACH(CStack *st, bat->stacks) + { + if(vstd::contains(st->state, SUMMONED)) //don't take into account sumoned stacks + continue; + + if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) + { + StackLocation sl(army, st->slot); + if(st->alive()) + newStackCounts.push_back(std::pair(sl, st->count)); + else + newStackCounts.push_back(std::pair(sl, 0)); + } + } +} + +void CasualtiesAfterBattle::takeFromArmy(CGameHandler *gh) +{ + BOOST_FOREACH(TStackAndItsNewCount &ncount, newStackCounts) + { + if(ncount.second > 0) + gh->changeStackCount(ncount.first, ncount.second, true); + else + gh->eraseStack(ncount.first, true); + } } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 89fd34381..f1701bd31 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -23,6 +23,7 @@ * */ +class CGameHandler; class CVCMIServer; class CGameState; struct StartInfo; @@ -74,6 +75,16 @@ public: } }; +struct CasualtiesAfterBattle +{ + typedef std::pair TStackAndItsNewCount; + enum {ERASE = -1}; + std::vector newStackCounts; + + CasualtiesAfterBattle(const CArmedInstance *army, BattleInfo *bat); + void takeFromArmy(CGameHandler *gh); +}; + class CGameHandler : public IGameCallback { private: @@ -94,7 +105,6 @@ public: bool isAllowedExchange(int id1, int id2); void giveSpells(const CGTownInstance *t, const CGHeroInstance *h); int moveStack(int stack, int dest); //returned value - travelled distance - void takeCasualties(const CArmedInstance *army, BattleInfo *bat); void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero void checkLossVictory(ui8 player); void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all @@ -138,12 +148,12 @@ public: void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function &cb); void showThievesGuildWindow(int requestingObjId); //TODO: make something more general? void giveResource(int player, int which, int val); - void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet &creatures, bool remove); + void giveCreatures (int objid, const CGHeroInstance * h, const CCreatureSet &creatures, bool remove); void takeCreatures (int objid, std::vector creatures); bool changeStackType(const StackLocation &sl, CCreature *c); bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false); bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count); - bool eraseStack(const StackLocation &sl); + bool eraseStack(const StackLocation &sl, bool forceRemoval = false); bool swapStacks(const StackLocation &sl1, const StackLocation &sl2); bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count); void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished);