From 0693312a8ecfc1588e1b771cecf32c7ffc030c40 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 18 Jul 2011 15:21:16 +0000 Subject: [PATCH] - fixed several crashes with joining creatures - support for loading *.tga images - minor fixes --- client/CAnimation.cpp | 17 +-- client/CBitmapHandler.cpp | 51 +++++--- client/CBitmapHandler.h | 3 + client/CCastleInterface.cpp | 225 ++++++++++++++++++++++-------------- client/CCastleInterface.h | 5 +- client/GUIBase.h | 11 ++ client/GUIClasses.cpp | 22 ++-- client/GUIClasses.h | 1 + lib/CLodHandler.cpp | 61 +++++----- lib/CLodHandler.h | 10 +- lib/IGameCallback.cpp | 9 +- lib/IGameCallback.h | 2 +- server/CGameHandler.cpp | 2 +- 13 files changed, 255 insertions(+), 164 deletions(-) diff --git a/client/CAnimation.cpp b/client/CAnimation.cpp index c37aef5be..79d450ac4 100644 --- a/client/CAnimation.cpp +++ b/client/CAnimation.cpp @@ -577,22 +577,7 @@ SDLImage::SDLImage(SDL_Surface * from, bool extraRef): SDLImage::SDLImage(std::string filename, bool compressed): margins(0,0) { - if (spriteh->haveFile(filename, FILE_GRAPHICS)) - { - int size; - unsigned char * pic=NULL; - pic = spriteh->giveFile(filename, FILE_GRAPHICS, &size); - surf = IMG_Load_RW( SDL_RWFromMem((void*)pic, size), 1); - delete [] pic; - } - else if(bitmaph->haveFile(filename, FILE_GRAPHICS)) - { - surf = BitmapHandler::loadBitmap(filename); - } - else - { - surf = NULL; - } + surf = BitmapHandler::loadBitmap(filename); if (surf == NULL) { diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp index e4e342c43..0a7047237 100644 --- a/client/CBitmapHandler.cpp +++ b/client/CBitmapHandler.cpp @@ -17,10 +17,9 @@ * */ -boost::mutex bitmap_handler_mx; - extern DLL_EXPORT CLodHandler *bitmaph; extern DLL_EXPORT CLodHandler *bitmaph_ab; +extern DLL_EXPORT CLodHandler *spriteh; void CPCXConv::openPCX(char * PCX, int len) { @@ -53,7 +52,7 @@ SDL_Surface * CPCXConv::getSurface() const int width = -1, height = -1; Epcxformat format; - int fSize,y;//,i; //TODO use me 'i' + int fSize,y; bool check1, check2; unsigned char add; int it=0; @@ -149,26 +148,23 @@ bool isPCX(const unsigned char *header)//check whether file can be PCX according return fSize == width*height || fSize == width*height*3; } -SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey) +SDL_Surface * BitmapHandler::loadBitmapFromLod(CLodHandler *lod, std::string fname, bool setKey) { if(!fname.size()) { tlog2 << "Call to loadBitmap with void fname!\n"; return NULL; } - SDL_Surface * ret=NULL; - int size; - unsigned char * file = 0; - if (bitmaph->haveFile(fname, FILE_GRAPHICS)) - file = bitmaph->giveFile(fname, FILE_GRAPHICS, &size); - else if (bitmaph_ab->haveFile(fname, FILE_GRAPHICS)) - file = bitmaph_ab->giveFile(fname, FILE_GRAPHICS, &size); - - if (!file) + if (!lod->haveFile(fname, FILE_GRAPHICS)) { tlog2<<"Entry for file "<giveFile(fname, FILE_GRAPHICS, &size); if (isPCX(file)) {//H3-style PCX @@ -185,10 +181,37 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey) } else { //loading via SDL_Image - ret = IMG_Load_RW( SDL_RWFromMem((void*)file, size), 1); + std::string filename = lod->getFileName(fname, FILE_GRAPHICS); + std::string ext; + lod->convertName(filename, &ext); + + if (ext == ".TGA")//Special case - targa can't be loaded by IMG_Load_RW (no magic constants in header) + { + SDL_RWops *rw = SDL_RWFromMem((void*)file, size); + ret = IMG_LoadTGA_RW( rw ); + SDL_FreeRW(rw); + } + else + ret = IMG_Load_RW( SDL_RWFromMem((void*)file, size), 1); + if (!ret) tlog1<<"Failed to open "<haveFile(fname, FILE_GRAPHICS)) + return loadBitmapFromLod(bitmaph, fname, setKey); + + if (bitmaph_ab->haveFile(fname, FILE_GRAPHICS)) + return loadBitmapFromLod(bitmaph_ab, fname, setKey); + + if (spriteh->haveFile(fname, FILE_GRAPHICS)) + return loadBitmapFromLod(spriteh, fname, setKey); + + tlog1<<"Failed to find file "<creatures.size() <= level || town->creatures[level].second.empty()) { level = -1; + label = NULL; + picture = NULL; return;//No creature } used = LCLICK | RCLICK | HOVER; @@ -1058,8 +1058,42 @@ CCreaInfo::CCreaInfo(int posX, int posY, const CGTownInstance *Town, int Level): unsigned int creatureID = town->creatures[level].second.back(); creature = CGI->creh->creatures[creatureID]; - label = new CLabel(24, 40, FONT_SMALL, CENTER, zwykly, boost::lexical_cast(town->creatureGrowth(level))); picture = new CAnimImage("CPRSMALL", creatureID+2, 0, 8, 0); + + std::string value; + if (showAvailable) + value = boost::lexical_cast(town->creatures[level].first); + else + value = boost::lexical_cast(town->creatureGrowth(level)); + + if (compact) + { + label = new CLabel(40, 32, FONT_TINY, BOTTOMRIGHT, zwykly, value); + pos.x += 8; + pos.w = 32; + pos.h = 32; + } + else + { + label = new CLabel(24, 40, FONT_SMALL, CENTER, zwykly, value); + pos.w = 48; + pos.h = 48; + } +} + +void CCreaInfo::update() +{ + if (label) + { + std::string value; + if (showAvailable) + value = boost::lexical_cast(town->creatures[level].first); + else + value = boost::lexical_cast(town->creatureGrowth(level)); + + if (value != label->text) + label->setTxt(value); + } } void CCreaInfo::hover(bool on) @@ -1076,9 +1110,14 @@ void CCreaInfo::hover(bool on) } void CCreaInfo::clickLeft(tribool down, bool previousState) -{//FIXME: castleInt should be present - may be NULL if no castle window opened - if(previousState && (!down) && LOCPLINT->castleInt) - LOCPLINT->castleInt->builds->enterDwelling(level); +{ + if(previousState && (!down)) + { + int offset = LOCPLINT->castleInt? (-87) : 0; + + GH.pushInt(new CRecruitmentWindow(town, level, town, + boost::bind(&CCallback::recruitCreatures, LOCPLINT->cb, town, _1, _2, level), offset)); + } } int CCreaInfo::AddToString(std::string from, std::string & to, int numb) @@ -1090,88 +1129,98 @@ int CCreaInfo::AddToString(std::string from, std::string & to, int numb) return numb; } +std::string CCreaInfo::genGrowthText() +{ + int summ=0; + std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number + boost::algorithm::replace_first(descr,"%s", creature->nameSing); + boost::algorithm::replace_first(descr,"%d", boost::lexical_cast(town->creatureGrowth(level))); + + descr +="\n"+CGI->generaltexth->allTexts[590]; + summ = creature->growth; + boost::algorithm::replace_first(descr,"%d", boost::lexical_cast(summ)); + + if ( level>=0 && levelbuiltBuildings, Buildings::CASTLE)) + summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::CASTLE]->Name()+" %+d",descr,summ); + else if ( vstd::contains(town->builtBuildings, Buildings::CITADEL)) + summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::CITADEL]->Name()+" %+d",descr,summ/2); + + summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, //double growth or plague + summ * creature->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100); + + summ+=AddToString(CGI->generaltexth->artifNames[133] + " %+d",descr, + summ * town->valOfGlobalBonuses + (Selector::type(Bonus::CREATURE_GROWTH_PERCENT) && Selector::sourceType(Bonus::ARTIFACT))/100); //Statue of Legion + + if(town->town->hordeLvl[0]==level)//horde, x to summ + if( vstd::contains(town->builtBuildings, Buildings::HORDE_1) || vstd::contains(town->builtBuildings, Buildings::HORDE_1_UPGR)) + summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::HORDE_1]->Name()+" %+d",descr, + creature->hordeGrowth); + + if(town->town->hordeLvl[1]==level)//horde, x to summ + if( vstd::contains(town->builtBuildings, Buildings::HORDE_2) || vstd::contains(town->builtBuildings, Buildings::HORDE_2_UPGR)) + summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::HORDE_2]->Name()+" %+d",descr, + creature->hordeGrowth); + + int cnt = 0; + + std::vector< const CGDwelling * > myDwellings = LOCPLINT->cb->getMyDwellings(); + for (std::vector::const_iterator it = myDwellings.begin(); it != myDwellings.end(); ++it) + if (CGI->creh->creatures[town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0]) + cnt++;//external dwellings count to summ + summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt); + + boost::shared_ptr bl; + const CGHeroInstance *hero = town->garrisonHero; + if (hero) + { + bl = hero->getAllBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level) + && Selector::sourceType(Bonus::ARTIFACT), 0, hero); + } + hero = town->visitingHero; + if (hero) + { + boost::shared_ptr blAppend = hero->getAllBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level) + && Selector::sourceType(Bonus::ARTIFACT), 0, hero); + if (town->garrisonHero) + bl->insert(bl->size(), blAppend->begin(), blAppend->end()); + else + bl = blAppend; + } + + if (bl->size()) + summ+=AddToString (CGI->arth->artifacts[bl->front()->sid]->Name()+" %+d", descr, bl->totalValue()); + + //TODO: player bonuses + + if(vstd::contains(town->builtBuildings, Buildings::GRAIL)) //grail - +50% to ALL growth + summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::GRAIL]->Name()+" %+d",descr,summ/2); + + summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, creature->valOfBonuses(Bonus::CREATURE_GROWTH)); + } + return descr; +} + void CCreaInfo::clickRight(tribool down, bool previousState) { if(down) { - int summ=0; - std::string descr=CGI->generaltexth->allTexts[589];//Growth of creature is number - boost::algorithm::replace_first(descr,"%s", creature->nameSing); - boost::algorithm::replace_first(descr,"%d", boost::lexical_cast(town->creatureGrowth(level))); - - descr +="\n"+CGI->generaltexth->allTexts[590]; - summ = creature->growth; - boost::algorithm::replace_first(descr,"%d", boost::lexical_cast(summ)); - - if ( level>=0 && levelw/2, screen->h/2, town, level)); + else { - - if ( vstd::contains(town->builtBuildings, Buildings::CASTLE)) - summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::CASTLE]->Name()+" %+d",descr,summ); - else if ( vstd::contains(town->builtBuildings, Buildings::CITADEL)) - summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::CITADEL]->Name()+" %+d",descr,summ/2); - - summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, //double growth or plague - summ * creature->valOfBonuses(Bonus::CREATURE_GROWTH_PERCENT)/100); - - summ+=AddToString(CGI->generaltexth->artifNames[133] + " %+d",descr, - summ * town->valOfGlobalBonuses - (Selector::type(Bonus::CREATURE_GROWTH_PERCENT) && Selector::sourceType(Bonus::ARTIFACT))/100); //Statue of Legion - - if(town->town->hordeLvl[0]==level)//horde, x to summ - if( vstd::contains(town->builtBuildings, Buildings::HORDE_1) || vstd::contains(town->builtBuildings, Buildings::HORDE_1_UPGR)) - summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::HORDE_1]->Name()+" %+d",descr, - creature->hordeGrowth); - - if(town->town->hordeLvl[1]==level)//horde, x to summ - if( vstd::contains(town->builtBuildings, Buildings::HORDE_2) || vstd::contains(town->builtBuildings, Buildings::HORDE_2_UPGR)) - summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::HORDE_2]->Name()+" %+d",descr, - creature->hordeGrowth); - - int cnt = 0; - - std::vector< const CGDwelling * > myDwellings = LOCPLINT->cb->getMyDwellings(); - for (std::vector::const_iterator it = myDwellings.begin(); it != myDwellings.end(); ++it) - if (CGI->creh->creatures[town->town->basicCreatures[level]]->idNumber == (*it)->creatures[0].second[0]) - cnt++;//external dwellings count to summ - summ+=AddToString(CGI->generaltexth->allTexts[591],descr,cnt); - - boost::shared_ptr bl; - const CGHeroInstance *hero = town->garrisonHero; - if (hero) - { - bl = hero->getAllBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level) - && Selector::sourceType(Bonus::ARTIFACT), 0, hero); - } - hero = town->visitingHero; - if (hero) - { - boost::shared_ptr blAppend = hero->getAllBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level) - && Selector::sourceType(Bonus::ARTIFACT), 0, hero); - if (town->garrisonHero) - bl->insert(bl->size(), blAppend->begin(), blAppend->end()); - else - bl = blAppend; - } - - if (bl->size()) - summ+=AddToString (CGI->arth->artifacts[bl->front()->sid]->Name()+" %+d", descr, bl->totalValue()); - - //TODO: player bonuses - - if(vstd::contains(town->builtBuildings, Buildings::GRAIL)) //grail - +50% to ALL growth - summ+=AddToString(CGI->buildh->buildings[town->subID][Buildings::GRAIL]->Name()+" %+d",descr,summ/2); - - summ+=AddToString(CGI->generaltexth->allTexts[63] + " %+d",descr, creature->valOfBonuses(Bonus::CREATURE_GROWTH)); + std::string descr = genGrowthText(); + CInfoPopup *mess = new CInfoPopup();//creating popup + mess->free = true; + mess->bitmap = CMessage::drawBoxTextBitmapSub + (LOCPLINT->playerID, descr,graphics->bigImgs[creature->idNumber],""); + mess->pos.x = screen->w/2 - mess->bitmap->w/2; + mess->pos.y = screen->h/2 - mess->bitmap->h/2; + GH.pushInt(mess); } - - CInfoPopup *mess = new CInfoPopup();//creating popup - mess->free = true; - mess->bitmap = CMessage::drawBoxTextBitmapSub - (LOCPLINT->playerID, descr,graphics->bigImgs[creature->idNumber],""); - mess->pos.x = screen->w/2 - mess->bitmap->w/2; - mess->pos.y = screen->h/2 - mess->bitmap->h/2; - GH.pushInt(mess); } } diff --git a/client/CCastleInterface.h b/client/CCastleInterface.h index 9a1eb91ca..f46670e5f 100644 --- a/client/CCastleInterface.h +++ b/client/CCastleInterface.h @@ -161,15 +161,18 @@ class CCreaInfo : public CIntObject const CGTownInstance * town; const CCreature *creature; int level; + bool showAvailable; CAnimImage *picture; CLabel * label; int AddToString(std::string from, std::string & to, int numb); + std::string genGrowthText(); public: - CCreaInfo(int posX, int posY, const CGTownInstance *Town, int Level); + CCreaInfo(Point position, const CGTownInstance *Town, int Level, bool compact=false, bool showAvailable=false); + void update(); void hover(bool on); void clickLeft(tribool down, bool previousState); void clickRight(tribool down, bool previousState); diff --git a/client/GUIBase.h b/client/GUIBase.h index fa415eaa1..662d6d5f9 100644 --- a/client/GUIBase.h +++ b/client/GUIBase.h @@ -283,6 +283,17 @@ struct Rect : public SDL_Rect return Rect(); } } + Rect operator|(const Rect &p) const //union of two rects + { + Rect ret; + ret.x = std::min(p.x, this->x); + ret.y = std::min(p.y, this->y); + int x2 = std::max(p.x+p.w, this->x+this->w); + int y2 = std::max(p.y+p.h, this->y+this->h); + ret.w = x2 -ret.x; + ret.h = y2 -ret.y; + return ret; + } }; /// Defines a show method diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index cbae78927..cf251363d 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -4513,6 +4513,16 @@ CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance garr->addSplitBtn(split); } quit = new AdventureMapButton(CGI->generaltexth->tcommands[8],"",boost::bind(&CGarrisonWindow::close,this),399,314,"IOK6432.DEF",SDLK_RETURN); + + std::string titleText; + if (garr->armedObjs[1]->tempOwner == garr->armedObjs[0]->tempOwner) + titleText = CGI->generaltexth->allTexts[709]; + else + { + titleText = CGI->generaltexth->allTexts[35]; + boost::algorithm::replace_first(titleText, "%s", garr->armedObjs[0]->Slots().begin()->second->type->namePl); + } + title = new CLabel(275, 30, FONT_BIG, CENTER, tytulowy, titleText); } CGarrisonWindow::~CGarrisonWindow() @@ -4523,18 +4533,8 @@ void CGarrisonWindow::showAll(SDL_Surface * to) { CIntObject::showAll(to); - std::string title; - if (garr->armedObjs[1]->tempOwner == garr->armedObjs[0]->tempOwner) - title = CGI->generaltexth->allTexts[709]; - else - { - title = CGI->generaltexth->allTexts[35]; - boost::algorithm::replace_first(title, "%s", garr->armedObjs[0]->Slots().begin()->second->type->namePl); - } - blitAtLoc(graphics->flags->ourImages[garr->armedObjs[1]->getOwner()].bitmap,28,124,to); blitAtLoc(graphics->portraitLarge[static_cast(garr->armedObjs[1])->portrait],29,222,to); - printAtMiddleLoc(title,275,30,FONT_BIG,tytulowy,to); } IShowActivable::IShowActivable() @@ -5143,7 +5143,7 @@ void CArtifactsOfHero::setHero(const CGHeroInstance * hero) void CArtifactsOfHero::dispose() { //delNull(curHero); - unmarkSlots(false); + //unmarkSlots(false); CCS->curh->dragAndDropCursor(NULL); } diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 4754c0b41..ffa97421b 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -1072,6 +1072,7 @@ class CGarrisonWindow : public CWindowWithGarrison { public: CPicture *bg; //background surface + CLabel *title; AdventureMapButton *quit; void close(); diff --git a/lib/CLodHandler.cpp b/lib/CLodHandler.cpp index 30b3e8334..8ee5b04f5 100644 --- a/lib/CLodHandler.cpp +++ b/lib/CLodHandler.cpp @@ -60,14 +60,23 @@ std::string readString(const unsigned char * bufor, int &i) return ret; } -unsigned char * CLodHandler::giveFile(const std::string defName, LodFileType type, int * length) +void CLodHandler::convertName(std::string &filename, std::string *extension) { - std::string fname = defName; - std::transform(fname.begin(), fname.end(), fname.begin(), (int(*)(int))toupper); - int dotPos = fname.find_last_of('.'); - if ( dotPos != -1 ) - fname.erase(dotPos); + std::transform(filename.begin(), filename.end(), filename.begin(), toupper); + size_t dotPos = filename.find_last_of("/."); + + if ( dotPos != std::string::npos && filename[dotPos] == '.') + { + if (extension) + *extension = filename.substr(dotPos); + filename.erase(dotPos); + } +} + +unsigned char * CLodHandler::giveFile(std::string fname, LodFileType type, int * length) +{ + convertName(fname); boost::unordered_set::const_iterator en_it = entries.find(Entry(fname, type)); if(en_it == entries.end()) //nothing's been found @@ -127,15 +136,20 @@ unsigned char * CLodHandler::giveFile(const std::string defName, LodFileType typ return NULL; } -bool CLodHandler::haveFile(const std::string name, LodFileType type) +std::string CLodHandler::getFileName(std::string lodFile, LodFileType type) { - std::string fname = name; - std::transform(fname.begin(), fname.end(), fname.begin(), (int(*)(int))toupper); - int dotPos = fname.find_last_of('.'); - if ( dotPos != -1 ) - fname.erase(dotPos); - - return vstd::contains(entries, Entry(fname, type)); + convertName(lodFile); + boost::unordered_set::const_iterator it = entries.find(Entry(lodFile, type)); + + if (it != entries.end()) + return it->realName; + return ""; +} + +bool CLodHandler::haveFile(std::string name, LodFileType type) +{ + convertName(name); + return vstd::contains(entries, Entry(name, type)); } DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, unsigned char *& out, int wBits) @@ -219,20 +233,12 @@ void CLodHandler::extractFile(const std::string FName, const std::string name) } } -void CLodHandler::initEntry(Entry &e, const std::string name) +void CLodHandler::initEntry(Entry &e, std::string name) { - e.name = name; - //file names stored in upper case without extension - std::transform(e.name.begin(), e.name.end(), e.name.begin(), toupper); std::string ext; - - size_t dotPos = e.name.find_last_of('.'); - if ( dotPos < e.name.size() ) - { - ext = e.name.substr(dotPos); - e.name.erase(dotPos); - } - + convertName(name, &ext); + e.name = name; + std::map::iterator it = extMap.find(ext); if (it == extMap.end()) e.type = FILE_OTHER; @@ -254,6 +260,7 @@ void CLodHandler::init(const std::string lodFile, const std::string dirName) EXT(".JPG", FILE_GRAPHICS); EXT(".PCX", FILE_GRAPHICS); EXT(".PNG", FILE_GRAPHICS); + EXT(".TGA", FILE_GRAPHICS); #undef EXT myDir = dirName; @@ -328,7 +335,7 @@ void CLodHandler::init(const std::string lodFile, const std::string dirName) tlog1<<"Warning: No "+dirName+"/ folder!"< it will be copied here (including dot) + void convertName(std::string &filename, std::string *extension=NULL); boost::unordered_set entries; CLodHandler(); ~CLodHandler(); void init(const std::string lodFile, const std::string dirName); - - unsigned char * giveFile(const std::string defName, LodFileType type=FILE_ANY, int * length=NULL); //returns pointer to the decompressed data - it must be deleted when no longer needed! - bool haveFile(const std::string name, LodFileType type=FILE_ANY);//check if file is present in lod - std::string getTextFile(const std::string name, LodFileType type=FILE_TEXT); //extracts one file + std::string getFileName(std::string lodFile, LodFileType type=FILE_ANY); + unsigned char * giveFile(std::string defName, LodFileType type=FILE_ANY, int * length=NULL); //returns pointer to the decompressed data - it must be deleted when no longer needed! + bool haveFile(std::string name, LodFileType type=FILE_ANY);//check if file is present in lod + std::string getTextFile(std::string name, LodFileType type=FILE_TEXT); //extracts one file void extractFile(const std::string FName, const std::string name); //extracts a specific file static unsigned char * getUnpackedFile(const std::string & path, int * sizeOut); //loads given file, decompresses and returns diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index b2fa63ce6..e7d6e7be4 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -1101,10 +1101,17 @@ int CPlayerSpecificInfoCallback::howManyHeroes(bool includeGarrisoned) const return getHeroCount(player,includeGarrisoned); } -const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId) const +const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId, bool includeGarrisoned) const { const PlayerState *p = getPlayer(player); ERROR_RET_VAL_IF(!p, "No player info", NULL); + + if (!includeGarrisoned) + { + for(unsigned int i = 0; i < p->heroes.size() && i<=serialId; i++) + if(p->heroes[i]->inTownGarrison) + serialId++; + } ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", NULL); return p->heroes[serialId]; } diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 51f7fe8c9..33f205c73 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -213,7 +213,7 @@ public: std::vector getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible int getHeroSerial(const CGHeroInstance * hero)const; const CGTownInstance* getTownBySerial(int serialId) const; // serial id is [0, number of towns) - const CGHeroInstance* getHeroBySerial(int serialId) const; // serial id is [0, number of heroes) + const CGHeroInstance* getHeroBySerial(int serialId, bool includeGarrisoned=true) const; // serial id is [0, number of heroes) std::vector getHeroesInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible std::vector getMyDwellings() const; //returns all dwellings that belong to player std::vector getMyObjects() const; //returns all objects flagged by belonging player diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 7155b8732..ca432fb5d 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4825,7 +4825,7 @@ bool CGameHandler::addToSlot(const StackLocation &sl, const CCreature *c, TQuant void CGameHandler::tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) { - if(!dst->canBeMergedWith(*src, allowMerging)) + if(!src->canBeMergedWith(*dst, allowMerging)) { if (allowMerging) //do that, add all matching creatures. {