From 215dc95acb1a6560283c603f780704b84c662c0e Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 22 Jul 2010 00:32:45 +0000 Subject: [PATCH] - implemented Hill Fort (minor issue - you can do ANY upgrades, including archers to sharpshooters without Gelu and so on) - fixed some g++ errors in macroses - minor tweaks --- CGameInterface.h | 1 + client/AdventureMapButton.cpp | 9 +- client/AdventureMapButton.h | 2 +- client/CKingdomInterface.cpp | 82 ++++-------- client/CKingdomInterface.h | 16 +-- client/CPlayerInterface.cpp | 17 ++- client/CPlayerInterface.h | 1 + client/GUIBase.cpp | 2 +- client/GUIBase.h | 11 +- client/GUIClasses.cpp | 242 ++++++++++++++++++++++++++++++++-- client/GUIClasses.h | 40 +++++- client/NetPacksClient.cpp | 8 ++ hch/CObjectHandler.cpp | 11 +- lib/NetPacks.h | 4 +- server/CGameHandler.cpp | 3 + 15 files changed, 360 insertions(+), 89 deletions(-) diff --git a/CGameInterface.h b/CGameInterface.h index 8b37213bb..d8b4e90fd 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -86,6 +86,7 @@ public: virtual void showPuzzleMap(){}; virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor){}; virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor){}; + virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor){}; virtual void showTavernWindow(const CGObjectInstance *townOrTavern){}; virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID){}; //called when a hero casts a spell virtual void tileHidden(const std::set &pos){}; diff --git a/client/AdventureMapButton.cpp b/client/AdventureMapButton.cpp index 6948d16cc..6db365cc3 100644 --- a/client/AdventureMapButton.cpp +++ b/client/AdventureMapButton.cpp @@ -252,8 +252,15 @@ void AdventureMapButton::block( ui8 on ) show(screenBuf); } -void AdventureMapButton::setDef(const std::string & defName, bool playerColoredButton) +void AdventureMapButton::setDef(const std::string & defName, bool playerColoredButton, bool reset/*=false*/) { + if (reset) + { + for (size_t i=0;inotFreeImgs = true; for (size_t i=0;iourImages.size();i++) diff --git a/client/AdventureMapButton.h b/client/AdventureMapButton.h index 02a90b975..4fb4bcbb5 100644 --- a/client/AdventureMapButton.h +++ b/client/AdventureMapButton.h @@ -77,7 +77,7 @@ public: //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 void 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 ); - void setDef(const std::string & defName, bool playerColoredButton); + void setDef(const std::string & defName, bool playerColoredButton, bool reset=false); void setPlayerColor(int player); }; diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index e1384e81b..98ee86329 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -42,9 +42,6 @@ using namespace CSDL_Ext; */ #define ADVOPT (conf.go()->ac) -CDefEssential* CKingdomInterface::slots; -CDefEssential* CKingdomInterface::fort; -CDefEssential* CKingdomInterface::hall; CKingdomInterface::CKingdomInterface() { @@ -225,7 +222,7 @@ void CKingdomInterface::close() GH.popIntTotally(this); } -void CKingdomInterface::updateAllGarrisons() +void CKingdomInterface::updateGarrisons() { for (int i = 0; ipos = genRect(64, 58, pos.x+244, pos.y + 6); - - visitHero = new LRClickableAreaOpenHero(); - visitHero->pos = genRect(64, 58, pos.x+476, pos.y + 6); + garrHero = new CHeroArea(pos.x+244, pos.y + 6, NULL); + visitHero = new CHeroArea(pos.x+476, pos.y + 6, NULL); for (int i=0; iourImages[owner->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, 4,Point(-126,37)); + garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),parent->slots->ourImages[parent->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, 4,Point(-126,37)); garr->update = true; - char buf[400]; - if (town->garrisonHero) - { - garrHero->hero = town->garrisonHero; - sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->garrisonHero->name.c_str(), town->garrisonHero->type->heroClass->name.c_str()); - garrHero->hoverText = buf; - } - if (town->visitingHero) - { - visitHero->hero = town->visitingHero; - sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->visitingHero->name.c_str(), town->visitingHero->type->heroClass->name.c_str()); - visitHero->hoverText = buf; - } + garrHero->hero = town->garrisonHero; + visitHero->hero = town->visitingHero; for (int i=0; iactivate(); townImage->activate(); - if (town->garrisonHero) - garrHero->activate(); - if (town->visitingHero) - visitHero->activate(); + garrHero->activate(); + visitHero->activate(); for (int i=0; ibuiltBuildings,30+i)) @@ -610,10 +591,8 @@ void CKingdomInterface::CTownItem::deactivate() incomeArea->deactivate(); townImage->deactivate(); - if (town->garrisonHero) - garrHero->deactivate(); - if (town->visitingHero) - visitHero->deactivate(); + garrHero->deactivate(); + visitHero->deactivate(); for (int i=0; iactive) @@ -628,10 +607,10 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to) { if (!town) {//if NULL - print background & exit - blitAt(slots->ourImages[numb % owner->PicCount].bitmap,pos.x,pos.y,to); + blitAt(parent->slots->ourImages[numb % parent->PicCount].bitmap,pos.x,pos.y,to); return; }//background - blitAt(slots->ourImages[owner->PicCount+2].bitmap,pos.x,pos.y,to); garr->show(to); + blitAt(parent->slots->ourImages[parent->PicCount+2].bitmap,pos.x,pos.y,to); garr->show(to); //town pic/name int townPic = town->subID*2; if (!town->hasFort()) @@ -643,10 +622,10 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to) //fort pic townPic = town->fortLevel()-1; if (townPic==-1) townPic = 3; - blitAt(fort->ourImages[townPic].bitmap,pos.x+111,pos.y+31,to); + blitAt(parent->fort->ourImages[townPic].bitmap,pos.x+111,pos.y+31,to); //hall pic townPic = town->hallLevel(); - blitAt(hall->ourImages[townPic].bitmap,pos.x+69,pos.y+31,to); + blitAt(parent->hall->ourImages[townPic].bitmap,pos.x+69,pos.y+31,to); //income pic std::ostringstream oss; oss << town->dailyIncome(); @@ -689,13 +668,9 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to) ostrs << town->creatures[i].first; CSDL_Ext::printTo(ostrs.str(),pos.x+440+i*37,pos.y+110,FONT_TINY,zwykly,to); } - - - if (town->garrisonHero) - blitAt(graphics->portraitLarge[town->garrisonHero->portrait],pos.x+244,pos.y+6,to); - - if (town->visitingHero) - blitAt(graphics->portraitLarge[town->visitingHero->portrait],pos.x+476,pos.y+6,to); + + garrHero->showAll(to); + visitHero->showAll(to); } CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner) @@ -703,7 +678,7 @@ CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner) OBJ_CONSTRUCTION_CAPTURING_ALL; recActions = DISPOSE | SHARE_POS; defActions = SHARE_POS; - owner = Owner; + parent = Owner; numb = num; pos.x += 23; pos.y += 25+num*116; @@ -730,8 +705,7 @@ CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner) artRight = new AdventureMapButton("", "", boost::bind (&CKingdomInterface::CHeroItem::scrollArts,this,+1), 675, 66, "hsbtns5.def", SDLK_RIGHT); - portrait = new LRClickableAreaOpenHero(); - portrait->pos = genRect(64, 58, pos.x+5, pos.y + 5); + portrait = new CHeroArea(5,5,NULL); char bufor[400]; for(int i=0; iblock(hero->artifacts.size() <= 8); artRight->block(hero->artifacts.size() <= 8); - garr = new CGarrisonInt(pos.x+6, pos.y+78, 4, Point(), slots->ourImages[owner->PicCount].bitmap, + garr = new CGarrisonInt(pos.x+6, pos.y+78, 4, Point(), parent->slots->ourImages[parent->PicCount].bitmap, Point(6,78), hero, NULL, true, true); for (int i=0; igeneraltexth->allTexts[15].c_str(), hero->name.c_str(), hero->type->heroClass->name.c_str()); - portrait->hoverText = std::string(bufor); + //sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), hero->name.c_str(), hero->type->heroClass->name.c_str()); + //portrait->hoverText = std::string(bufor); portrait->hero = hero; speciality->text = CGI->generaltexth->hTxts[hero->subID].longBonus; @@ -891,13 +865,13 @@ void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to) { if (!hero) {//if we have no hero for this slot - print background & exit - blitAt(slots->ourImages[numb % owner->PicCount].bitmap,pos.x,pos.y,to); + blitAt(parent->slots->ourImages[numb % parent->PicCount].bitmap,pos.x,pos.y,to); return; }//print background, different for arts view/backpack mode - blitAt(slots->ourImages[(artGroup!=2)?owner->PicCount:(owner->PicCount+1)].bitmap,pos.x,pos.y,to); + blitAt(parent->slots->ourImages[(artGroup!=2)?parent->PicCount:(parent->PicCount+1)].bitmap,pos.x,pos.y,to); //text "Artifacts" CSDL_Ext::printAtMiddle(CGI->generaltexth->overview[2],pos.x+320,pos.y+55,FONT_SMALL,zwykly,to); - blitAt(graphics->portraitLarge[hero->portrait],pos.x+5,pos.y+6,to); + portrait->showAll(to); garr->show(to); //hero name @@ -1034,7 +1008,7 @@ void CKingdomInterface::CHeroItem::deactivate() CKingdomInterface::CHeroItem::CArtPlace::CArtPlace(CHeroItem * owner) { - hero = owner; + parent = owner; used = LCLICK | RCLICK | HOVER; } @@ -1049,7 +1023,7 @@ void CKingdomInterface::CHeroItem::CArtPlace::clickLeft(tribool down, bool previ {tlog1<w - 620)/2, (screen->h - 595)/2), hero->hero, LOCPLINT, false); + CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), parent->hero, LOCPLINT, false); GH.pushInt(spellWindow); } else diff --git a/client/CKingdomInterface.h b/client/CKingdomInterface.h index 18bbc79f2..675ff4610 100644 --- a/client/CKingdomInterface.h +++ b/client/CKingdomInterface.h @@ -25,7 +25,7 @@ class MoraleLuckBox; * */ -class CKingdomInterface : public CIntObject +class CKingdomInterface : public CGarrisonHolder { class CTownItem : public CWindowWithGarrison { @@ -41,10 +41,10 @@ class CKingdomInterface : public CIntObject }; public: const CGTownInstance * town; - CKingdomInterface * owner; + CKingdomInterface * parent; int numb;//position on screen (1..size) HoverableArea *incomeArea;//hoverable text for town hall, fort, income - LRClickableAreaOpenHero * garrHero, *visitHero;//portraits of heroes + CHeroArea * garrHero, *visitHero;//portraits of heroes LRClickableAreaOpenTown *hallArea, *fortArea, * townImage;//town image std::vector < HoverableArea * > creaGrowth; std::vector < CCreaPlace * > creaCount; @@ -60,7 +60,7 @@ class CKingdomInterface : public CIntObject class CArtPlace: public LRClickableAreaWTextComp { public: - CHeroItem * hero; + CHeroItem * parent; CArtPlace(CHeroItem * owner); //c-tor void clickLeft(tribool down, bool previousState); void clickRight(tribool down, bool previousState); @@ -70,11 +70,11 @@ class CKingdomInterface : public CIntObject public: const CGHeroInstance * hero; - CKingdomInterface * owner; + CKingdomInterface * parent; int artGroup,numb;//current art group (0 = equiped, 1 = misc, 2 = backpack) int backpackPos;//first visible artifact in backpack AdventureMapButton * artLeft, * artRight;//buttons for backpack - LRClickableAreaOpenHero * portrait; + CHeroArea * portrait; LRClickableAreaWText * experience; MoraleLuckBox * morale, * luck; LRClickableAreaWText * spellPoints; @@ -113,7 +113,7 @@ public: int heroPos,townPos;//position of lists std::vector heroes;//heroes list std::vector towns;//towns list - static CDefEssential * slots, *fort, *hall; + CDefEssential * slots, *fort, *hall; //objects list int objSize, objPos; @@ -129,7 +129,7 @@ public: CKingdomInterface(); //c-tor ~CKingdomInterface(); //d-tor - void updateAllGarrisons();//garrison updater + void updateGarrisons();//garrison updater void moveObjectList(int newPos); void recreateHeroList(int pos);//recreating heroes list (on slider move) void recreateTownList(int pos);//same for town list diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 91d6a564a..1572fe4ac 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -486,19 +486,12 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) boost::unique_lock un(*pim); updateInfo(obj); - bool wasGarrison = false; for(std::list::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++) { if((*i)->type & IShowActivable::WITH_GARRISON) { - CWindowWithGarrison *wwg = static_cast(*i); - wwg->garr->recreateSlots(); - wasGarrison = true; - } - else if(CKingdomInterface *cki = dynamic_cast(*i)) - {//a cheat for Kingdom Overview window (it has CWindowWithGarrison-childrens which are not present in ListInt) - //need to create "Garrison Holder" class thingy - cki->updateAllGarrisons(); + CGarrisonHolder *cgh = static_cast(*i); + cgh->updateGarrisons(); } else if(CTradeWindow *cmw = dynamic_cast(*i)) { @@ -2037,6 +2030,12 @@ void CPlayerInterface::showUniversityWindow(const IMarket *market, const CGHeroI GH.pushInt(cuw); } +void CPlayerInterface::showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) +{ + CHillFortWindow *chfw = new CHillFortWindow(visitor, object); + GH.pushInt(chfw); +} + void CPlayerInterface::availableArtifactsChanged(const CGBlackMarket *bm /*= NULL*/) { if(CMarketplaceWindow *cmw = dynamic_cast(GH.topInt())) diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 021c6e2de..66f019bc8 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -177,6 +177,7 @@ public: void showPuzzleMap(); void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor); void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor); + void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor); void showTavernWindow(const CGObjectInstance *townOrTavern); void advmapSpellCast(const CGHeroInstance * caster, int spellID); //called when a hero casts a spell void tileHidden(const std::set &pos); //called when given tiles become hidden under fog of war diff --git a/client/GUIBase.cpp b/client/GUIBase.cpp index b793bcede..0531cc2a5 100644 --- a/client/GUIBase.cpp +++ b/client/GUIBase.cpp @@ -939,7 +939,7 @@ SDLKey numToDigit( SDLKey key ) if(key >= SDLK_KP0 && key <= SDLK_KP9) return SDLKey(key - SDLK_KP0 + SDLK_0); -#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName ## : return SDLK_ ## keyName; +#define REMOVE_KP(keyName) case SDLK_KP_ ## keyName : return SDLK_ ## keyName; switch(key) { REMOVE_KP(PERIOD) diff --git a/client/GUIBase.h b/client/GUIBase.h index 40c9caa3d..b6b603054 100644 --- a/client/GUIBase.h +++ b/client/GUIBase.h @@ -424,11 +424,18 @@ public: virtual void keyPressed(const SDL_KeyboardEvent & key); //call-in }; -class CWindowWithGarrison : public CIntObject +class CGarrisonHolder : public CIntObject// to unify updating garrisons via PlayerInterface +{ +public: + CGarrisonHolder(); + virtual void updateGarrisons(){}; +}; + +class CWindowWithGarrison : public CGarrisonHolder { public: CGarrisonInt *garr; - CWindowWithGarrison(); + virtual void updateGarrisons(); }; class CSimpleWindow : public CIntObject diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index e1bf0c3fa..c312ed043 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -4311,11 +4311,15 @@ IShowActivable::IShowActivable() type = 0; } -CWindowWithGarrison::CWindowWithGarrison() +CGarrisonHolder::CGarrisonHolder() { type |= WITH_GARRISON; } +void CWindowWithGarrison::updateGarrisons() +{ + garr->recreateSlots(); +} void CRClickPopupInt::show(SDL_Surface * to) { @@ -4643,18 +4647,38 @@ void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState) } } -void LRClickableAreaOpenHero::clickLeft(tribool down, bool previousState) +CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero):hero(_hero) +{ + used = LCLICK | RCLICK | HOVER; + pos.x += x; pos.w = 58; + pos.y += y; pos.h = 64; +} + +void CHeroArea::clickLeft(tribool down, bool previousState) { if((!down) && previousState && hero) LOCPLINT->openHeroWindow(hero); } -void LRClickableAreaOpenHero::clickRight(tribool down, bool previousState) +void CHeroArea::clickRight(tribool down, bool previousState) { if((!down) && previousState && hero) LOCPLINT->openHeroWindow(hero); } +void CHeroArea::hover(bool on) +{ + if (on && hero) + GH.statusbar->print(hero->hoverName); + else + GH.statusbar->clear(); +} + +void CHeroArea::showAll(SDL_Surface * to) +{ + blitAtLoc(graphics->portraitLarge[hero->portrait],0,0,to); +} + void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState) { if((!down) && previousState && town) @@ -5192,11 +5216,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) secSkillAreas[b][g]->hoverText = std::string(bufor); } - portrait[b] = new LRClickableAreaOpenHero(); - portrait[b]->pos = genRect(64, 58, pos.x + 257 + 228*b, pos.y + 13); - portrait[b]->hero = heroInst[b]; - sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), heroInst[b]->name.c_str(), heroInst[b]->type->heroClass->name.c_str()); - portrait[b]->hoverText = std::string(bufor); + portrait[b] = new CHeroArea(pos.x + 257 + 228*b, pos.y + 13, heroInst[b]); speciality[b] = new LRClickableAreaWText(); speciality[b]->pos = genRect(32, 32, pos.x + 69 + 490*b, pos.y + 45); @@ -5621,6 +5641,8 @@ int CUniversityWindow::CItem::state() return 1; if (parent->hero->secSkills.size() >= SKILL_PER_HERO)//can't learn more skills return 0; + if (parent->hero->type->heroClass->proSec[ID]==0)//can't learn this skill (like necromancy for most of non-necros) + return 0; /* if (LOCPLINT->cb->getResourceAmount(6) < 2000 )//no gold - allowed in H3, confirm button is blocked instead return 0;*/ return 2; @@ -5743,6 +5765,210 @@ void CUnivConfirmWindow::makeDeal(int skill) GH.popIntTotally(this); } +CHillFortWindow::CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object): + hero(visitor), fort(object) +{ + { + OBJ_CONSTRUCTION_CAPTURING_ALL; + + slotsCount=7; + resources = CDefHandler::giveDefEss("SMALRES.DEF"); + bg = new CPicture("APHLFTBK.PCX"); + bg->colorizeAndConvert(LOCPLINT->playerID); + + printAtMiddleLoc (fort->hoverName, 325, 32, FONT_BIG, tytulowy, bg->bg);//Hill Fort + pos = center(bg->pos); + + heroPic = new CHeroArea(30, 60, hero); + + currState.resize(slotsCount+1); + costs.resize(slotsCount); + totalSumm.resize(RESOURCE_QUANTITY); + for (int i=0; iblock(currState[i] == -1); + } + currState[slotsCount] = getState(slotsCount); + upgradeAll = new AdventureMapButton(CGI->generaltexth->allTexts[432],"",boost::bind(&CHillFortWindow::makeDeal, this, slotsCount), 30, 231, getDefForSlot(slotsCount)); + quit = new AdventureMapButton("","",boost::bind(&CGuiHandler::popIntTotally, &GH, this), 294, 275, "IOKAY.DEF", SDLK_RETURN); + bar = new CGStatusBar(327, 332); + + } + BLOCK_CAPTURING; + garr = new CGarrisonInt(pos.x+107, pos.x+84, 18, Point(),bg->bg,Point(107,60),hero,NULL); + updateGarrisons(); +} + +CHillFortWindow::~CHillFortWindow() +{ + delete garr; +} + +void CHillFortWindow::activate() +{ + CIntObject::activate(); + garr->activate(); + GH.statusbar = bar; +} + +void CHillFortWindow::deactivate() +{ + CIntObject::deactivate(); + garr->deactivate(); +} + +void CHillFortWindow::updateGarrisons() +{ + + for (int i=0; icb->getUpgradeInfo(hero, i); + if (info.newID.size())//we have upgrades here - update costs + for(std::set >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) + { + costs[i].insert(*it); + totalSumm[it->first] += it->second; + } + } + + if (currState[i] != newState )//we need to update buttons + { + currState[i] = newState; + upgrade[i]->setDef(getDefForSlot(i), false, true); + upgrade[i]->block(currState[i] == -1); + } + } + + int newState = getState(slotsCount); + if (currState[slotsCount] != newState ) + { + currState[slotsCount] = newState; + upgradeAll->setDef(getDefForSlot(slotsCount), false, true); + } + garr->recreateSlots(); +} + +void CHillFortWindow::makeDeal(int slot) +{ + int offset = (slot == slotsCount)?2:0; + switch (currState[slot]) + { + case 0: + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314 + offset], + std::vector(), soundBase::sound_todo); + break; + case 1: + LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[315 + offset], + std::vector(), soundBase::sound_todo); + break; + case 2: + for (int i=0; icb->getUpgradeInfo(hero, i); + LOCPLINT->cb->upgradeCreature(hero, i, info.newID[0]); + } + break; + + } +} + +void CHillFortWindow::showAll (SDL_Surface *to) +{ + CIntObject::showAll(to); + garr->show(to); + + for ( int i=0; i::reverse_iterator rit=costs[i].rbegin(); rit!=costs[i].rend(); rit++) + { + blitAtLoc(resources->ourImages[rit->first].bitmap, 104+76*i, curY, to); + printToLoc(boost::lexical_cast(rit->second), 168+76*i, curY+16, FONT_SMALL, zwykly, to); + curY += 20; + } + } + else//free upgrade - print gold image and "Free" text + { + blitAtLoc(resources->ourImages[6].bitmap, 104+76*i, 128, to); + printToLoc(CGI->generaltexth->allTexts[344], 168+76*i, 144, FONT_SMALL, zwykly, to); + } + } + } + for (int i=0; iourImages[i].bitmap, 104+76*i, 237, to); + printToLoc(boost::lexical_cast(totalSumm[i]), 166+76*i, 253, FONT_SMALL, zwykly, to); + } + } +} + +std::string CHillFortWindow::getDefForSlot(int slot) +{ + if ( slot == slotsCount) + switch (currState[slot]) + { + case -1: + case 0: return "APHLF4R.DEF"; + case 1: return "APHLF4Y.DEF"; + case 2: return "APHLF4G.DEF"; + } + else + switch (currState[slot]) + { + case -1: + case 0: return "APHLF1R.DEF"; + case 1: return "APHLF1Y.DEF"; + case 2: return "APHLF1G.DEF"; + } +} + +int CHillFortWindow::getState(int slot) +{ + if ( slot == slotsCount )//"Upgrade all" slot + { + bool allUpgraded = true;//All creatures are upgraded? + for (int i=0; icb->getResourceAmount(i) < totalSumm[i]) + return 0; + + return 2; + } + + if (hero->slotEmpty(slot))//no creature here + return -1; + + UpgradeInfo info = LOCPLINT->cb->getUpgradeInfo(hero, slot); + if (!info.newID.size())//already upgraded + return 1; + + for(std::set >::iterator it=info.cost[0].begin(); it!=info.cost[0].end(); it++) + if(LOCPLINT->cb->getResourceAmount(it->first) < it->second * hero->getAmount(slot)) + return 0; + return 2;//can upgrade +} + void CThievesGuildWindow::activate() { CIntObject::activate(); diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 31dd0c4f9..029526e32 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -831,12 +831,17 @@ public: ~MoraleLuckBox(); }; -class LRClickableAreaOpenHero: public LRClickableAreaWTextComp +class CHeroArea: public CIntObject { public: const CGHeroInstance * hero; + + CHeroArea(int x, int y, const CGHeroInstance * _hero); + void clickLeft(tribool down, bool previousState); void clickRight(tribool down, bool previousState); + void hover(bool on); + void showAll(SDL_Surface * to); }; @@ -976,7 +981,7 @@ class CExchangeWindow : public CWindowWithGarrison LRClickableAreaWText *speciality[2]; LRClickableAreaWText *experience[2]; LRClickableAreaWText *spellPoints[2]; - LRClickableAreaOpenHero *portrait[2]; + CHeroArea *portrait[2]; public: @@ -1111,6 +1116,37 @@ public: void makeDeal(int skill); }; +class CHillFortWindow : public CWindowWithGarrison +{ +public: + + int slotsCount;//=7; + CGStatusBar * bar; + CDefEssential *resources; + CPicture *bg; //background surface + CHeroArea *heroPic;//clickable hero image + AdventureMapButton *quit,//closes window + *upgradeAll,//upgrade all creatures + *upgrade[7];//upgrade single creature + + const CGObjectInstance * fort; + const CGHeroInstance * hero; + std::vector currState;//current state of slot - to avoid calls to getState or updating buttons + std::vector > costs;// costs [slot ID] [resource ID] = resource count for upgrade + std::vector totalSumm; // totalSum[resource ID] = value + + CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object); //c-tor + ~CHillFortWindow(); //d-tor + + void activate(); + void deactivate(); + void showAll (SDL_Surface *to); + std::string getDefForSlot(int slot); + void makeDeal(int slot);//-1 for upgrading all creatures + int getState(int slot); //-1 = no creature 0=can't upgrade, 1=upgraded, 2=can upgrade + void updateGarrisons();//update buttons after garrison changes +}; + class CThievesGuildWindow : public CIntObject { const CGObjectInstance * owner; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 175cab7c1..6b2976b10 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -745,6 +745,14 @@ void OpenWindow::applyCl(CClient *cl) INTERFACE_CALL_IF_PRESENT(cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, showMarketWindow, market, hero); } break; + case HILL_FORT_WINDOW: + { + //displays Hill fort window + const CGObjectInstance *obj = cl->getObj(id1); + const CGHeroInstance *hero = cl->getHero(id2); + INTERFACE_CALL_IF_PRESENT(cl->getTile(obj->visitablePos())->visitableObjects.back()->tempOwner, showHillFortWindow, obj, hero); + } + break; case PUZZLE_MAP: { INTERFACE_CALL_IF_PRESENT(id1, showPuzzleMap); diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 752389795..5344bdf9e 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -483,6 +483,15 @@ void CGObjectInstance::onHeroVisit( const CGHeroInstance * h ) const { switch(ID) { + case 35: //Hill fort + { + OpenWindow ow; + ow.window = OpenWindow::HILL_FORT_WINDOW; + ow.id1 = id; + ow.id2 = h->id; + cb->sendAndApply(&ow); + } + break; case 80: //Sanctuary { InfoWindow iw; @@ -1225,7 +1234,7 @@ ui8 CGHeroInstance::getSpellSchoolLevel(const CSpell * spell, int *outSelectedSc si16 skill = -1; //skill level #define TRY_SCHOOL(schoolName, schoolMechanicsId, schoolOutId) \ - if(spell-> ## schoolName) \ + if(spell-> schoolName) \ { \ int thisSchool = std::max(getSecSkillLevel(14 + (schoolMechanicsId)), valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 1 << (schoolMechanicsId))); \ if(thisSchool > skill) \ diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 5a5c9a755..5265950d7 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -629,8 +629,8 @@ struct OpenWindow : public CPackForClient //517 OpenWindow(){type = 517;}; void applyCl(CClient *cl); - enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, - THIEVES_GUILD, UNIVERSITY_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW}; + enum EWindow {EXCHANGE_WINDOW, RECRUITMENT_FIRST, RECRUITMENT_ALL, SHIPYARD_WINDOW, THIEVES_GUILD, + UNIVERSITY_WINDOW, HILL_FORT_WINDOW, MARKET_WINDOW, PUZZLE_MAP, TAVERN_WINDOW}; ui8 window; ui32 id1, id2; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 71fff8f4b..271db5728 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3213,6 +3213,9 @@ bool CGameHandler::buySecSkill( const IMarket *m, const CGHeroInstance *h, int s if (h->secSkills.size() >= SKILL_PER_HERO)//can't learn more skills COMPLAIN_RET("Hero can't learn any more skills"); + + if (h->type->heroClass->proSec[skill]==0)//can't learn this skill (like necromancy for most of non-necros) + COMPLAIN_RET("The hero can't learn this skill!"); if(!vstd::contains(m->availableItemsIds(RESOURCE_SKILL), skill)) COMPLAIN_RET("That skill is unavailable!");