1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

- 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
This commit is contained in:
Ivan Savenko 2010-07-22 00:32:45 +00:00
parent 2f996f14ba
commit 215dc95acb
15 changed files with 360 additions and 89 deletions

View File

@ -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<int3> &pos){};

View File

@ -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;i<imgs[0].size();i++)
SDL_FreeSurface(imgs[0][i]);
imgs[0].clear();
}
CDefHandler * temp = CDefHandler::giveDef(defName);
temp->notFreeImgs = true;
for (size_t i=0;i<temp->ourImages.size();i++)

View File

@ -77,7 +77,7 @@ public:
//AdventureMapButton( std::string Name, std::string HelpBox, boost::function<void()> Callback, int x, int y, std::string defName, bool activ=false, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor
void init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * 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);
};

View File

@ -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; i<towns.size(); i++)
{
@ -464,7 +461,7 @@ void CKingdomInterface::sliderMoved(int newpos)
CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
{
recActions = DISPOSE | SHARE_POS;
owner = Owner;
parent = Owner;
numb = num;
pos.x += 23;
pos.y += 25+num*116;
@ -473,11 +470,8 @@ CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
town = NULL;
garr = NULL;
garrHero = new LRClickableAreaOpenHero();
garrHero->pos = 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; i<CREATURES_PER_TOWN;i++)
{//creatures info
@ -523,22 +517,11 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
return;
garr = NULL;
}
garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),slots->ourImages[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; i<CREATURES_PER_TOWN;i++)
{
@ -586,10 +569,8 @@ void CKingdomInterface::CTownItem::activate()
incomeArea->activate();
townImage->activate();
if (town->garrisonHero)
garrHero->activate();
if (town->visitingHero)
visitHero->activate();
garrHero->activate();
visitHero->activate();
for (int i=0; i<CREATURES_PER_TOWN;i++)
if (vstd::contains(town->builtBuildings,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; i<CREATURES_PER_TOWN;i++)
if (creaCount[i]->active)
@ -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();
@ -690,12 +669,8 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
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; i<PRIMARY_SKILLS; i++)
{
@ -807,7 +781,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
char bufor[4000];
artLeft->block(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; i<artifacts.size(); i++)
@ -834,8 +808,8 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
}
}
sprintf(bufor, CGI->generaltexth->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<<type;
if(type == 0)
{
CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->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

View File

@ -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<CHeroItem *> heroes;//heroes list
std::vector<CTownItem *> 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

View File

@ -486,19 +486,12 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
boost::unique_lock<boost::recursive_mutex> un(*pim);
updateInfo(obj);
bool wasGarrison = false;
for(std::list<IShowActivable*>::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++)
{
if((*i)->type & IShowActivable::WITH_GARRISON)
{
CWindowWithGarrison *wwg = static_cast<CWindowWithGarrison*>(*i);
wwg->garr->recreateSlots();
wasGarrison = true;
}
else if(CKingdomInterface *cki = dynamic_cast<CKingdomInterface*>(*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<CGarrisonHolder*>(*i);
cgh->updateGarrisons();
}
else if(CTradeWindow *cmw = dynamic_cast<CTradeWindow*>(*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<CMarketplaceWindow*>(GH.topInt()))

View File

@ -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<int3> &pos); //called when given tiles become hidden under fog of war

View File

@ -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)

View File

@ -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

View File

@ -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; i<slotsCount; i++)
{
currState[i] = getState(i);
upgrade[i] = new AdventureMapButton("","",boost::bind(&CHillFortWindow::makeDeal, this, i), 107+i*76, 171, getDefForSlot(i));
upgrade[i]->block(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; i<RESOURCE_QUANTITY; i++)
totalSumm[i]=0;
for (int i=0; i<slotsCount; i++)
{
costs[i].clear();
int newState = getState(i);
if (newState != -1)
{
UpgradeInfo info = LOCPLINT->cb->getUpgradeInfo(hero, i);
if (info.newID.size())//we have upgrades here - update costs
for(std::set<std::pair<int,int> >::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<SComponent*>(), soundBase::sound_todo);
break;
case 1:
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[315 + offset],
std::vector<SComponent*>(), soundBase::sound_todo);
break;
case 2:
for (int i=0; i<slotsCount; i++)
if ( slot ==i || ( slot == slotsCount && currState[i] == 2 ) )//this is activated slot or "upgrade all"
{
UpgradeInfo info = LOCPLINT->cb->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<slotsCount; i++)
{
if ( currState[i] == 0 || currState[i] == 2 )
{
if ( costs[i].size() )//we have several elements
{
int curY = 128;//reverse iterator is used to display gold as first element
for( std::map<int,int>::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<std::string>(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; i<RESOURCE_QUANTITY; i++)
{
if (totalSumm[i])//this resource is used - display it
{
blitAtLoc(resources->ourImages[i].bitmap, 104+76*i, 237, to);
printToLoc(boost::lexical_cast<std::string>(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; i<slotsCount; i++)
allUpgraded &= currState[i] == 1 || currState[i] == -1;
if (allUpgraded)
return 1;
for ( int i=0; i<RESOURCE_QUANTITY; i++)//if we need more resources
if(LOCPLINT->cb->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<std::pair<int,int> >::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();

View File

@ -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<int> currState;//current state of slot - to avoid calls to getState or updating buttons
std::vector<std::map<int,int> > costs;// costs [slot ID] [resource ID] = resource count for upgrade
std::vector<int> 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;

View File

@ -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);

View File

@ -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<int>(getSecSkillLevel(14 + (schoolMechanicsId)), valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 1 << (schoolMechanicsId))); \
if(thisSchool > skill) \

View File

@ -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;

View File

@ -3214,6 +3214,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!");