diff --git a/client/BattleInterface/CBattleInterfaceClasses.cpp b/client/BattleInterface/CBattleInterfaceClasses.cpp index f685cf1c6..6731c1adf 100644 --- a/client/BattleInterface/CBattleInterfaceClasses.cpp +++ b/client/BattleInterface/CBattleInterfaceClasses.cpp @@ -316,38 +316,35 @@ void CBattleOptionsWindow::bExitf() CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CBattleInterface * _owner) : owner(_owner) { + OBJ_CONSTRUCTION_CAPTURING_ALL; this->pos = pos; - background = BitmapHandler::loadBitmap("CPRESULT.BMP", true); - graphics->blueToPlayersAdv(background, owner->curInt->playerID); - SDL_Surface * pom = SDL_ConvertSurface(background, screen->format, screen->flags); - SDL_FreeSurface(background); - background = pom; - exit = new CAdventureMapButton (std::string(), std::string(), boost::bind(&CBattleResultWindow::bExitf,this), 384 + pos.x, 505 + pos.y, "iok6432.def", SDLK_RETURN); + CPicture * bg = new CPicture("CPRESULT"); + bg->colorize(owner->curInt->playerID); + + exit = new CAdventureMapButton ("", "", boost::bind(&CBattleResultWindow::bExitf,this), 384, 505, "iok6432.def", SDLK_RETURN); exit->borderColor = Colors::MetallicGold; exit->borderEnabled = true; if(br.winner==0) //attacker won { - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 59, 124, FONT_SMALL, Colors::Cornsilk, background); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 408, 124, FONT_SMALL, Colors::Cornsilk, background); + new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[410]); + new CLabel(408, 124, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[411]); } else //if(br.winner==1) { - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[411], 59, 124, FONT_SMALL, Colors::Cornsilk, background); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[410], 412, 124, FONT_SMALL, Colors::Cornsilk, background); + new CLabel( 59, 124, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[411]); + new CLabel(412, 124, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[410]); } - - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[407], 232, 302, FONT_BIG, Colors::Jasmine, background); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[408], 232, 332, FONT_BIG, Colors::Cornsilk, background); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[409], 237, 428, FONT_BIG, Colors::Cornsilk, background); + new CLabel(232, 302, FONT_BIG, CENTER, Colors::Jasmine, CGI->generaltexth->allTexts[407]); + new CLabel(232, 332, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[408]); + new CLabel(232, 428, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[409]); std::string attackerName, defenderName; if(owner->attackingHeroInstance) //a hero attacked { - SDL_Rect temp_rect = genRect(64, 58, 21, 38); - SDL_BlitSurface(graphics->portraitLarge[owner->attackingHeroInstance->portrait], NULL, background, &temp_rect); + new CAnimImage("PortraitsLarge", owner->attackingHeroInstance->portrait, 0, 21, 38); //setting attackerName attackerName = owner->attackingHeroInstance->name; } @@ -363,15 +360,13 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect bestMonsterID = it->second->type->idNumber; } } - SDL_Rect temp_rect = genRect(64, 58, 21, 38); - SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &temp_rect); + new CAnimImage("TWCRPORT", bestMonsterID, 0, 21, 38); //setting attackerName attackerName = CGI->creh->creatures[bestMonsterID]->namePl; } if(owner->defendingHeroInstance) //a hero defended { - SDL_Rect temp_rect = genRect(64, 58, 392, 38); - SDL_BlitSurface(graphics->portraitLarge[owner->defendingHeroInstance->portrait], NULL, background, &temp_rect); + new CAnimImage("PortraitsLarge", owner->defendingHeroInstance->portrait, 0, 392, 38); //setting defenderName defenderName = owner->defendingHeroInstance->name; } @@ -387,21 +382,22 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect bestMonsterID = it->second->type->idNumber; } } - SDL_Rect temp_rect = genRect(64, 58, 392, 38); - SDL_BlitSurface(graphics->bigImgs[bestMonsterID], NULL, background, &temp_rect); + new CAnimImage("TWCRPORT", bestMonsterID, 0, 392, 38); //setting defenderName defenderName = CGI->creh->creatures[bestMonsterID]->namePl; } //printing attacker and defender's names - CSDL_Ext::printAt(attackerName, 89, 37, FONT_SMALL, Colors::Cornsilk, background); - CSDL_Ext::printTo(defenderName, 381, 53, FONT_SMALL, Colors::Cornsilk, background); + new CLabel( 89, 37, FONT_SMALL, TOPLEFT, Colors::Cornsilk, attackerName); + + new CLabel( 381, 53, FONT_SMALL, BOTTOMRIGHT, Colors::Cornsilk, defenderName); + //printing casualities for(int step = 0; step < 2; ++step) { if(br.casualties[step].size()==0) { - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[523], 235, 360 + 97*step, FONT_SMALL, Colors::Cornsilk, background); + new CLabel( 235, 360 + 97*step, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[523]); } else { @@ -409,10 +405,10 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect int yPos = 344 + step*97; for(std::map::const_iterator it=br.casualties[step].begin(); it!=br.casualties[step].end(); ++it) { - blitAt(graphics->smallImgs[it->first], xPos, yPos, background); + new CAnimImage("CPRSMALL", it->first+2, 0, xPos, yPos); std::ostringstream amount; amount<second; - CSDL_Ext::printAtMiddle(amount.str(), xPos+16, yPos + 42, FONT_SMALL, Colors::Cornsilk, background); + new CLabel( xPos+16, yPos + 42, FONT_SMALL, CENTER, Colors::Cornsilk, amount.str()); xPos += 42; } } @@ -440,7 +436,8 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect boost::algorithm::replace_first(str,"%s",ourHero->name); boost::algorithm::replace_first(str,"%d",boost::lexical_cast(br.exp[weAreAttacker?0:1])); } - CSDL_Ext::printAtMiddleWB(str, 235, 235, FONT_SMALL, 55, Colors::Cornsilk, background); + + new CTextBox(str, Rect(69, 203, 330, 68), 0, FONT_SMALL, CENTER, Colors::Cornsilk); } else // we lose { @@ -450,21 +447,21 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect { CCS->musich->playMusic(musicBase::loseCombat); CCS->videoh->open(VIDEO_LOSE_BATTLE_START); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[311], 235, 235, FONT_SMALL, Colors::Cornsilk, background); + new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[311]); break; } case 1: //flee { CCS->musich->playMusic(musicBase::retreatBattle); CCS->videoh->open(VIDEO_RETREAT_START); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[310], 235, 235, FONT_SMALL, Colors::Cornsilk, background); + new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[310]); break; } case 2: //surrender { CCS->musich->playMusic(musicBase::surrenderBattle); CCS->videoh->open(VIDEO_SURRENDER); - CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[309], 235, 220, FONT_SMALL, Colors::Cornsilk, background); + new CLabel(235, 235, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[309]); break; } } @@ -473,7 +470,6 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect CBattleResultWindow::~CBattleResultWindow() { - SDL_FreeSurface(background); } void CBattleResultWindow::activate() @@ -489,13 +485,13 @@ void CBattleResultWindow::deactivate() void CBattleResultWindow::show(SDL_Surface * to) { + CIntObject::show(to); //evaluating to if(!to) to = screen; - CCS->videoh->update(107, 70, background, false, true); + CCS->videoh->update(pos.x + 107, pos.y + 70, screen, false, true); - SDL_BlitSurface(background, NULL, to, &pos); exit->showAll(to); } @@ -759,4 +755,4 @@ CStackQueue::StackBox::~StackBox() void CStackQueue::StackBox::hover( bool on ) { -} \ No newline at end of file +} diff --git a/client/BattleInterface/CBattleInterfaceClasses.h b/client/BattleInterface/CBattleInterfaceClasses.h index 8aa4646c2..537a77831 100644 --- a/client/BattleInterface/CBattleInterfaceClasses.h +++ b/client/BattleInterface/CBattleInterfaceClasses.h @@ -88,7 +88,6 @@ public: class CBattleResultWindow : public CIntObject { private: - SDL_Surface *background; CAdventureMapButton *exit; CBattleInterface *owner; public: diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index eb1747b46..4de23887e 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -837,7 +837,9 @@ void CInfoBar::showAll(SDL_Surface * to) { CPicture bg("ADSTATOT.bmp"); bg.convertToScreenBPP(); - blitAt(graphics->flags->ourImages[enemyTurnInfo.color].bitmap, 20, 51, bg); + CAnimImage ai("CREST58", enemyTurnInfo.color, 0, 20, 51); + ai.showAll(&*bg); + int hourglassFrame = enemyTurnInfo.progress * hourglass->ourImages.size(); static int sandFrame = 0; vstd::amin(hourglassFrame, hourglass->ourImages.size()-1); @@ -933,7 +935,10 @@ void CInfoBar::showComp(const CComponent * comp, int time/*=5000*/) SDL_Surface * b = BitmapHandler::loadBitmap("ADSTATOT.bmp"); blitAt(b,pos.x+8,pos.y+11); - blitAt(comp->getImg(),pos.x+52,pos.y+54); + + CComponent* tempComp = (CComponent*)comp; //evil. TODO: remove need to move component + tempComp->moveTo(Point(pos.x+52, pos.y+54)); + tempComp->showAll(screen); printAtMiddle(comp->subtitle,pos.x+91,pos.y+158,FONT_SMALL,Colors::Cornsilk); printAtMiddleWB(comp->description,pos.x+94,pos.y+31,FONT_SMALL,26,Colors::Cornsilk); SDL_FreeSurface(b); diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index 2827b6d82..e5e1dbd4e 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -123,9 +123,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState) const CBuilding *bld = CGI->buildh->buildings[str->townID].find(bid)->second; if (bid < EBuilding::DWELL_FIRST) { - std::vector comps(1, - new CComponent(CComponent::building, bld->tid, bld->bid, - LOCPLINT->castleInt->bicons->ourImages[bld->bid].bitmap, false)); + std::vector comps(1, new CComponent(CComponent::building, bld->tid, bld->bid)); CRClickPopup::createAndPush(bld->Description(), comps); } @@ -271,7 +269,7 @@ CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstanc { if(creature->cost[i]) { - resPicture.push_back(new CPicture(graphics->resources32->ourImages[i].bitmap, 0, 0, false)); + resPicture.push_back(new CAnimImage("RESOURCE", i, 0, 0, 0)); resAmount.push_back(new CLabel(0,0, FONT_SMALL, CENTER, Colors::Cornsilk, boost::lexical_cast(creature->cost[i]))); } } @@ -303,12 +301,12 @@ void CHeroGSlot::hover (bool on) std::string temp; if(hero) { - if(highlight)//view NNN + if(selection)//view NNN { temp = CGI->generaltexth->tcommands[4]; boost::algorithm::replace_first(temp,"%s",hero->name); } - else if(other->hero && other->highlight)//exchange + else if(other->hero && other->selection)//exchange { temp = CGI->generaltexth->tcommands[7]; boost::algorithm::replace_first(temp,"%s",hero->name); @@ -330,7 +328,7 @@ void CHeroGSlot::hover (bool on) } else //we are empty slot { - if(other->highlight && other->hero) //move NNNN + if(other->selection && other->hero) //move NNNN { temp = CGI->generaltexth->tcommands[6]; boost::algorithm::replace_first(temp,"%s",other->hero->name); @@ -352,12 +350,12 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) owner->garr->splitting = false; owner->garr->highlighted = NULL; - if(hero && highlight) + if(hero && selection) { setHighlight(false); LOCPLINT->openHeroWindow(hero); } - else if(other->hero && other->highlight) + else if(other->hero && other->selection) { bool allow = true; if(upg) //moving hero out of town - check if it is allowed @@ -394,20 +392,10 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) void CHeroGSlot::deactivate() { - highlight = false; + delChildNUll(selection, true); CIntObject::deactivate(); } -void CHeroGSlot::showAll(SDL_Surface * to) -{ - if(hero) //there is hero - blitAt(graphics->portraitLarge[hero->portrait],pos,to); - else if(!upg && owner->showEmpty) //up garrison - blitAt(graphics->flags->ourImages[LOCPLINT->castleInt->town->getOwner()].bitmap,pos,to); - if(highlight) - blitAt(graphics->bigImgs[-1],pos,to); -} - CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner) { used = LCLICK | HOVER; @@ -416,9 +404,10 @@ CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSl pos.y += y; pos.w = 58; pos.h = 64; - hero = h; upg = updown; - highlight = false; + selection = nullptr; + image = nullptr; + set(h); } CHeroGSlot::~CHeroGSlot() @@ -427,7 +416,17 @@ CHeroGSlot::~CHeroGSlot() void CHeroGSlot::setHighlight( bool on ) { - highlight = on; + if (active && selection) + selection->deactivate(); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + delChildNUll(selection, true); + if (on) + selection = new CAnimImage("TWCRPORT", 1, 0); + + if (active && selection) + selection->activate(); + if(owner->garrisonedHero->hero && owner->visitingHero->hero) //two heroes in town { for(size_t i = 0; igarr->splitButtons.size(); i++) //splitting enabled when slot higlighted @@ -435,6 +434,26 @@ void CHeroGSlot::setHighlight( bool on ) } } +void CHeroGSlot::set(const CGHeroInstance *newHero) +{ + if (active && image) + image->deactivate(); + + OBJ_CONSTRUCTION_CAPTURING_ALL; + if (image) + delChild(image); + hero = newHero; + if (newHero) + image = new CAnimImage("PortraitsLarge", newHero->portrait, 0, 0, 0); + else if(!upg && owner->showEmpty) //up garrison + image = new CAnimImage("CREST58", LOCPLINT->castleInt->town->getOwner(), 0, 0, 0); + else + image = NULL; + + if (active && image) + image->activate(); +} + template class SORTHELP { @@ -797,9 +816,7 @@ void CCastleBuildings::enterBlacksmith(int ArtifactID) void CCastleBuildings::enterBuilding(int building) { - std::vector comps(1, - new CComponent(CComponent::building, town->subID,building, - LOCPLINT->castleInt->bicons->ourImages[building].bitmap, false)); + std::vector comps(1, new CComponent(CComponent::building, town->subID, building)); LOCPLINT->showInfoDialog( CGI->buildh->buildings[town->subID].find(building)->second->Description(),comps); @@ -836,9 +853,7 @@ void CCastleBuildings::enterDwelling(int level) void CCastleBuildings::enterFountain(int building) { - std::vector comps(1, - new CComponent(CComponent::building,town->subID,building, - LOCPLINT->castleInt->bicons->ourImages[building].bitmap,false)); + std::vector comps(1, new CComponent(CComponent::building,town->subID,building)); std::string descr = CGI->buildh->buildings[town->subID].find(building)->second->Description(); if ( building == 21)//we need description for mystic pond as well @@ -918,6 +933,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos): town(Town) { OBJ_CONSTRUCTION_CAPTURING_ALL; + LOCPLINT->castleInt = this; used |= KEYBOARD; builds = new CCastleBuildings(town); @@ -953,7 +969,6 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, int listPos): vstd::amax(townlist->from, 0); vstd::amin(townlist->from, LOCPLINT->towns.size() - townlist->SIZE); - LOCPLINT->castleInt = this; recreateIcons(); CCS->musich->playMusic(CCS->musich->townMusics[town->subID], -1); @@ -1277,13 +1292,13 @@ HeroSlots::HeroSlots(const CGTownInstance * Town, Point garrPos, Point visitPos, void HeroSlots::update() { - garrisonedHero->hero = town->garrisonHero; - visitingHero->hero = town->visitingHero; + garrisonedHero->set(town->garrisonHero); + visitingHero->set(town->visitingHero); } void HeroSlots::splitClicked() { - if(!!town->visitingHero && town->garrisonHero && (visitingHero->highlight || garrisonedHero->highlight)) + if(!!town->visitingHero && town->garrisonHero && (visitingHero->selection || garrisonedHero->selection)) { LOCPLINT->heroExchangeStarted(town->visitingHero->id, town->garrisonHero->id); } @@ -1468,7 +1483,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin { if(building->resources[i]) { - resPicture.push_back(new CPicture(graphics->resources32->ourImages[i].bitmap, 0, 0, false)); + resPicture.push_back(new CAnimImage("RESOURCE", i)); resAmount.push_back(new CLabel(0,0, FONT_SMALL, CENTER, Colors::Cornsilk, boost::lexical_cast(building->resources[i]))); } @@ -1836,7 +1851,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i else buy->block(true); - gold = new CPicture(graphics->resources32->ourImages[6].bitmap,148,244, false); + new CAnimImage("RESOURCE", 6, 0, 148, 244); } void CBlacksmithDialog::close() diff --git a/client/CCastleInterface.h b/client/CCastleInterface.h index c593c1856..c0c4326f4 100644 --- a/client/CCastleInterface.h +++ b/client/CCastleInterface.h @@ -66,7 +66,7 @@ class CDwellingInfoBox : public CIntObject CLabel *available; CLabel *costPerTroop; - std::vector resPicture; + std::vector resPicture; std::vector resAmount; public: CDwellingInfoBox(int centerX, int centerY, const CGTownInstance *Town, int level); @@ -81,14 +81,16 @@ public: HeroSlots *owner; const CGHeroInstance *hero; int upg; //0 - up garrison, 1 - down garrison - bool highlight; //indicates id the slot is highlighted + CAnimImage *image; + CAnimImage *selection; //selection border. NULL if not selected + void setHighlight(bool on); + void set(const CGHeroInstance *newHero); void hover (bool on); void clickLeft(tribool down, bool previousState); void deactivate(); - void showAll(SDL_Surface * to); CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner); //c-tor ~CHeroGSlot(); //d-tor }; @@ -282,7 +284,7 @@ class CBuildWindow: public CIntObject CTextBox * buildingState; CGStatusBar *statusBar; - std::vector resPicture; + std::vector resPicture; std::vector resAmount; std::string getTextForState(int state); @@ -384,7 +386,6 @@ class CBlacksmithDialog : public CIntObject CPicture *background; CPicture *animBG; CCreatureAnim * anim; - CPicture * gold; CLabel * title; CLabel * costText; CLabel * costValue; diff --git a/client/CCreatureWindow.cpp b/client/CCreatureWindow.cpp index bb5ed3b46..2dacc5e32 100644 --- a/client/CCreatureWindow.cpp +++ b/client/CCreatureWindow.cpp @@ -123,6 +123,7 @@ CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::func void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *StackNode, const CGHeroInstance *HeroOwner) { creatureArtifact = NULL; //may be set later + artifactImage = NULL; stack = Stack; c = stack->type; if(!StackNode) @@ -207,7 +208,7 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode * luck = new MoraleLuckBox(false, genRect(42, 42, 387, 100)); luck->set(stack); - new CPicture(graphics->pskillsm->ourImages[4].bitmap, 387, 51, false); //exp icon - Print it always? + new CAnimImage("PSKIL42", 4, 0, 387, 51); //exp icon - Print it always? if (type) //not in fort window { if (GameConstants::STACK_EXP) @@ -259,7 +260,7 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode * if (GameConstants::STACK_ARTIFACT) { - creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); + setArt(stack->getArt(ArtifactPosition::CREATURE_SLOT)); if (type > BATTLE) //artifact buttons inactive in battle { //TODO: disable buttons if no artifact is equipped @@ -390,12 +391,6 @@ void CCreatureWindow::showAll(SDL_Surface * to) BOOST_FOREACH(CBonusItem* b, bonusItems) b->showAll (to); - - if (GameConstants::STACK_ARTIFACT) - { - if (creatureArtifact) - blitAt(graphics->artDefs->ourImages[creatureArtifact->artType->id].bitmap, 466 + pos.x, 100 + pos.y, to); - } } void CCreatureWindow::show(SDL_Surface * to) @@ -411,10 +406,24 @@ void CCreatureWindow::sliderMoved(int newpos) redraw(); } +void CCreatureWindow::setArt(const CArtifactInstance *creatureArtifact) +{ + creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); + if (creatureArtifact) + { + if (artifactImage == NULL) + addChild(artifactImage = new CAnimImage("ARTIFACT", creatureArtifact->artType->id, 0, 466, 100), true); + else + artifactImage->setFrame(creatureArtifact->artType->id); + } + else + delChildNUll(artifactImage); +} + void CCreatureWindow::scrollArt(int dir) { //TODO: get next artifact - creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); + setArt(stack->getArt(ArtifactPosition::CREATURE_SLOT)); } void CCreatureWindow::passArtifactToHero() @@ -432,13 +441,11 @@ void CCreatureWindow::passArtifactToHero() void CCreatureWindow::artifactRemoved (const ArtifactLocation &artLoc) { - creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); //TODO: select next from the list (for Commanders) - redraw(); + setArt(stack->getArt(ArtifactPosition::CREATURE_SLOT)); //TODO: select next from the list (for Commanders) } void CCreatureWindow::artifactMoved (const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) { - creatureArtifact = stack->getArt(ArtifactPosition::CREATURE_SLOT); //TODO: select next from the list (for Commanders) - redraw(); + setArt(stack->getArt(ArtifactPosition::CREATURE_SLOT)); //TODO: select next from the list (for Commanders) } void CCreatureWindow::clickRight(tribool down, bool previousState) diff --git a/client/CCreatureWindow.h b/client/CCreatureWindow.h index 8767dc9e4..ddaf28bb1 100644 --- a/client/CCreatureWindow.h +++ b/client/CCreatureWindow.h @@ -62,6 +62,9 @@ public: CAdventureMapButton *dismiss, *upgrade, *ok; CAdventureMapButton * leftArtRoll, * rightArtRoll; //artifact selection CAdventureMapButton * passArtToHero; + CAnimImage *artifactImage; + + void setArt(const CArtifactInstance *creatureArtifact); void artifactRemoved (const ArtifactLocation &artLoc); void artifactMoved (const ArtifactLocation &artLoc, const ArtifactLocation &destLoc); diff --git a/client/CHeroWindow.cpp b/client/CHeroWindow.cpp index beba4a29d..cfbddd47f 100644 --- a/client/CHeroWindow.cpp +++ b/client/CHeroWindow.cpp @@ -1,5 +1,6 @@ #include "StdInc.h" +#include "CAnimation.h" #include "CAdvmapInterface.h" #include "../CCallback.h" #include "CGameInfo.h" @@ -69,38 +70,37 @@ void CHeroSwitcher::clickLeft(tribool down, bool previousState) { if(!down) { - const CGHeroInstance * buf = LOCPLINT->getWHero(id); - if(!buf) - return; - GH.popIntTotally(getOwner()); + const CGHeroInstance * buf = hero; + GH.popIntTotally(parent); GH.pushInt(new CHeroWindow(buf)); } } -CHeroWindow * CHeroSwitcher::getOwner() +CHeroSwitcher::CHeroSwitcher(Point _pos, const CGHeroInstance * _hero): + hero(_hero) { - return dynamic_cast(parent); -} - -CHeroSwitcher::CHeroSwitcher(int serial) -{ - pos = Rect(612, 87 + serial * 54, 48, 32) + pos; - id = serial; + OBJ_CONSTRUCTION_CAPTURING_ALL; + pos += _pos; used = LCLICK; + + image = new CAnimImage("PortraitsSmall", hero->portrait); + pos.w = image->pos.w; + pos.h = image->pos.h; } CHeroWindow::CHeroWindow(const CGHeroInstance *hero) : heroWArt(this, hero) { OBJ_CONSTRUCTION_CAPTURING_ALL; - garr = NULL; + garr = nullptr; curHero = hero; - player = LOCPLINT->playerID;//hero->tempOwner; + listSelection = nullptr; background = new CPicture("HeroScr4.BMP"); - background->colorizeAndConvert(player); + background->colorize(LOCPLINT->playerID); pos = background->center(); + new CAnimImage("CREST58", LOCPLINT->playerID, 0, 606, 8); //artifs = new CArtifactsOfHero(pos.topLeft(), true); ourBar = new CGStatusBar(7, 559, "ADROLLVR.bmp", 660); // new CStatusBar(pos.x+72, pos.y+567, "ADROLLVR.bmp", 660); @@ -116,15 +116,13 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero) tacticsButton = new CHighlightableButton(0, 0, map_list_of(0,CGI->generaltexth->heroscrn[26])(3,CGI->generaltexth->heroscrn[25]), CGI->generaltexth->heroscrn[31], false, "hsbtns8.def", NULL, 539, 483, SDLK_b); - //right list of heroes - for(int g=0; g<8; ++g) - heroListMi.push_back(new CHeroSwitcher(g)); - - flags = CDefHandler::giveDefEss("CREST58.DEF"); + for(int i=0; i < std::min(LOCPLINT->cb->howManyHeroes(false), 8); i++) + heroList.push_back(new CHeroSwitcher(Point(612, 87 + i * 54), LOCPLINT->cb->getHeroBySerial(i, false))); //areas portraitArea = new LRClickableAreaWText(Rect(18, 18, 58, 64)); + portraitImage = new CAnimImage("PortraitsLarge", 0, 0, 19, 19); for(int v=0; vgeneraltexth->heroscrn[27]); expArea = new LRClickableAreaWText(Rect(18, 228, 136, 42), CGI->generaltexth->heroscrn[9]); morale = new MoraleLuckBox(true, Rect(175,179,53,45)); @@ -145,33 +145,22 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero) { Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42); secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill)); + secSkillImages.push_back(new CAnimImage("SECSKILL", 0, 0, r.x, r.y)); } //////////////////////////////////////////////////////////////////////////??????????????? -// pos.x += 65; -// pos.y += 8; -// + //primary skills & exp and mana - new CPicture(graphics->pskillsm->ourImages[0].bitmap, 32, 111, false); - new CPicture(graphics->pskillsm->ourImages[1].bitmap, 102, 111, false); - new CPicture(graphics->pskillsm->ourImages[2].bitmap, 172, 111, false); - new CPicture(graphics->pskillsm->ourImages[5].bitmap, 242, 111, false); - new CPicture(graphics->pskillsm->ourImages[4].bitmap, 20, 230, false); - new CPicture(graphics->pskillsm->ourImages[3].bitmap, 162, 230, false); + new CAnimImage("PSKIL42", 0, 0, 32, 111, false); + new CAnimImage("PSKIL42", 1, 0, 102, 111, false); + new CAnimImage("PSKIL42", 2, 0, 172, 111, false); + new CAnimImage("PSKIL42", 3, 0, 162, 230, false); + new CAnimImage("PSKIL42", 4, 0, 20, 230, false); + new CAnimImage("PSKIL42", 5, 0, 242, 111, false); update(hero); } -CHeroWindow::~CHeroWindow() -{ - delete flags; - //SDL_FreeSurface(curBack); - //curBack = NULL; - curHero = NULL; - - //artifs->dispose(); -} - void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= false*/) { if(!hero) //something strange... no hero? it shouldn't happen @@ -181,9 +170,9 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals } assert(hero == curHero); - //assert(hero->tempOwner == LOCPLINT->playerID || hero->tempOwner == NEUTRAL_PLAYER); //for now we won't show hero windows for non-our heroes - + specArea->text = CGI->generaltexth->hTxts[curHero->subID].longBonus; + specImage->setFrame(curHero->subID); tacticsButton->callback.clear(); tacticsButton->callback2.clear(); @@ -191,6 +180,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals dismissButton->hoverTexts[0] = boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name); portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name); portraitArea->text = curHero->getBiography(); + portraitImage->setFrame(curHero->portrait); { CAdventureMapButton * split = NULL; @@ -210,8 +200,12 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals arts->setHero(curHero); artSets.push_back(arts); } - } + int serial = LOCPLINT->cb->getHeroSerial(curHero, false); + delChildNUll(listSelection); + if (serial >= 0) + listSelection = new CPicture("HPSYYY", 612, 33 + serial * 54); + } //primary skills support for(size_t g=0; gbonusValue = level; secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1]; secSkillAreas[g]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->generaltexth->skillName[skill]); + secSkillImages[g]->setFrame(skill*3 + level + 2); } //printing experience - original format does not support ui64 @@ -296,8 +291,6 @@ void CHeroWindow::questlog() void CHeroWindow::showAll(SDL_Surface * to) { CIntObject::showAll(to); - //blitting portrait - blitAtLoc(graphics->portraitLarge[curHero->portrait], 19, 19, to); //printing hero's name printAtMiddleLoc(curHero->name, 190, 38, FONT_BIG, Colors::Jasmine, to); @@ -345,42 +338,14 @@ void CHeroWindow::showAll(SDL_Surface * to) printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, Colors::Cornsilk, to); } - blitAtLoc(flags->ourImages[player].bitmap, 606, 8, to); - - //hero list blitting - - for(int slotPos=0, g=0; gwanderingHeroes.size(); ++g) - { - const CGHeroInstance * cur = LOCPLINT->wanderingHeroes[g]; - if (cur->inTownGarrison) - // Only display heroes that are not in garrison - continue; - - blitAtLoc(graphics->portraitSmall[cur->portrait], 611, 87+slotPos*54, to); - //printing yellow border - if(cur->name == curHero->name) - { - for(int f=0; fportraitSmall[cur->portrait]->w; ++f) - { - for(int h=0; hportraitSmall[cur->portrait]->h; ++h) - if(f==0 || h==0 || f==graphics->portraitSmall[cur->portrait]->w-1 || h==graphics->portraitSmall[cur->portrait]->h-1) - CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + 611+f, pos.y + 87+slotPos*54+h, 240, 220, 120); - } - } - - slotPos ++; - } - //secondary skills for(size_t v=0; vsecSkills.size()); ++v) { - blitAtLoc(graphics->abils44->ourImages[curHero->secSkills[v].first*3+3+curHero->secSkills[v].second-1].bitmap, v%2 ? 161 : 18, 276 + 48 * (v/2), to); printAtLoc(CGI->generaltexth->levels[curHero->secSkills[v].second-1], v%2 ? 212 : 68, 280 + 48 * (v/2), FONT_SMALL, Colors::Cornsilk, to); printAtLoc(CGI->generaltexth->skillName[curHero->secSkills[v].first], v%2 ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, Colors::Cornsilk, to); } //printing special ability - blitAtLoc(graphics->un44->ourImages[curHero->subID].bitmap, 18, 180, to); printAtLoc(CGI->generaltexth->jktexts[5].substr(1, CGI->generaltexth->jktexts[5].size()-2), 69, 183, FONT_SMALL, Colors::Jasmine, to); printAtLoc(CGI->generaltexth->hTxts[curHero->subID].bonusName, 69, 205, FONT_SMALL, Colors::Cornsilk, to); diff --git a/client/CHeroWindow.h b/client/CHeroWindow.h index a99f356fd..a30416e98 100644 --- a/client/CHeroWindow.h +++ b/client/CHeroWindow.h @@ -29,13 +29,12 @@ class CArtifactsOfHero; /// Button which switches hero selection class CHeroSwitcher : public CIntObject { + const CGHeroInstance * hero; + CAnimImage *image; public: - int id; - - CHeroWindow * getOwner(); virtual void clickLeft(tribool down, bool previousState); - CHeroSwitcher(int serial); + CHeroSwitcher(Point pos, const CGHeroInstance * hero); }; //helper class for calculating values of hero bonuses without bonuses from picked up artifact @@ -51,45 +50,45 @@ public: class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts { - enum ELabel {}; - std::map labels; CPicture *background; CGStatusBar * ourBar; //heroWindow's statusBar - //general graphics - CDefEssential *flags; - //buttons //CAdventureMapButton * gar4button; //splitting - std::vector heroListMi; //new better list of heroes + std::vector heroList; //list of heroes + CPicture * listSelection; //selection border //clickable areas LRClickableAreaWText * portraitArea; + CAnimImage * portraitImage; + std::vector primSkillAreas; LRClickableAreaWText * expArea; LRClickableAreaWText * spellPointsArea; LRClickableAreaWText * specArea;//speciality + CAnimImage *specImage; MoraleLuckBox * morale, * luck; std::vector secSkillAreas; + std::vector secSkillImages; CHeroWithMaybePickedArtifact heroWArt; -public: - const CGHeroInstance * curHero; CAdventureMapButton * quitButton, * dismissButton, * questlogButton; //general CHighlightableButton *tacticsButton; //garrison / formation handling; CHighlightableButtonsGroup *formations; - int player; + +public: + const CGHeroInstance * curHero; + CHeroWindow(const CGHeroInstance *hero); //c-tor - ~CHeroWindow(); //d-tor void update(const CGHeroInstance * hero, bool redrawNeeded = false); //sets main displayed hero - void showAll(SDL_Surface * to); //shows and activates adv. map interface -// void redrawCurBack(); //redraws curBAck from scratch - void quit(); //stops displaying hero window and disposes + void showAll(SDL_Surface * to); + + void quit(); //stops displaying hero window and disposes void dismissCurrent(); //dissmissed currently displayed hero (curHero) void questlog(); //show quest log in hero window - void switchHero(); //changes displayed hero + void switchHero(); //changes displayed hero //friends friend void CArtPlace::clickLeft(tribool down, bool previousState); diff --git a/client/CMessage.cpp b/client/CMessage.cpp index 35508bee2..8f1535964 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -24,11 +24,9 @@ * */ -extern SDL_Surface * screen; +//extern SDL_Surface * screen; -using namespace NMessage; - -const int COMPONENT_TO_SUBTITLE = 5; +const int COMPONENT_TO_SUBTITLE = 17; const int BETWEEN_COMPS_ROWS = 10; const int BEFORE_COMPONENTS = 30; const int SIDE_MARGIN = 30; @@ -41,14 +39,38 @@ template std::pair max(const std::pair &x, co return ret; } -namespace NMessage +//One image component + subtitles below it +class ComponentResolved : public CIntObject +{ + std::vector > * txt; +public: + CComponent *comp; + + //blit component with image centered at this position + void showAll(SDL_Surface * to); + + //ComponentResolved(); //c-tor + ComponentResolved(CComponent *Comp); //c-tor + ~ComponentResolved(); //d-tor +}; +// Full set of components for blitting on dialog box +struct ComponentsToBlit +{ + std::vector< std::vector > comps; + int w, h; + + void blitCompsOnSur(SDL_Surface * _or, int inter, int &curh, SDL_Surface *ret); + ComponentsToBlit(std::vector & SComps, int maxw, SDL_Surface* _or); //c-tor + ~ComponentsToBlit(); //d-tor +}; + +namespace { CDefHandler * ok, *cancel; std::vector > piecesOfBox; //in colors of all players SDL_Surface * background = NULL; } - void CMessage::init() { { @@ -72,14 +94,13 @@ void CMessage::init() } delete bluePieces; } - NMessage::background = BitmapHandler::loadBitmap("DIBOXBCK.BMP"); + background = BitmapHandler::loadBitmap("DIBOXBCK.BMP"); SDL_SetColorKey(background,SDL_SRCCOLORKEY,SDL_MapRGB(background->format,0,255,255)); } ok = CDefHandler::giveDef("IOKAY.DEF"); cancel = CDefHandler::giveDef("ICANCEL.DEF"); } - void CMessage::dispose() { for (int i=0;iformat->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask); @@ -319,37 +341,7 @@ std::vector > * CMessage::drawText(std::vectorsize();i++) return txtg; } -//CSimpleWindow * CMessage::genWindow(std::string text, int player, bool centerOnMouse, int Lmar, int Rmar, int Tmar, int Bmar) -//{ -// CSimpleWindow * ret = new CSimpleWindow(); -// int fontHeight; -// std::vector brtext = breakText(text,32); -// std::vector > * txtg = drawText(&brtext, fontHeight); -// std::pair txts = getMaxSizes(txtg, fontHeight); -// ret->bitmap = drawBox1(txts.first+Lmar+Rmar,txts.second+Tmar+Bmar,player); -// ret->pos.h = ret->bitmap->h; -// ret->pos.w = ret->bitmap->w; -// if (centerOnMouse) -// { -// ret->pos.x = GH.current->motion.x - ret->pos.w/2; -// ret->pos.y = GH.current->motion.y - ret->pos.h/2; -// // Put the window back on screen if necessary -// vstd::amax(ret->pos.x, 0); -// vstd::amax(ret->pos.y, 0); -// vstd::amin(ret->pos.x, conf.cc.resx - ret->pos.w); -// vstd::amin(ret->pos.y, conf.cc.resy - ret->pos.h); -// } -// else -// { -// // Center on screen -// ret->pos.x = screen->w/2 - (ret->pos.w/2); -// ret->pos.y = screen->h/2 - (ret->pos.h/2); -// } -// int curh = ret->bitmap->h/2 - (fontHeight*txtg->size())/2; -// blitTextOnSur(txtg,fontHeight,curh,ret->bitmap); -// delete txtg; -// return ret; -//} + SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_Surface* bitmap, std::string sub, int charperline/*=30*/, int imgToBmp/*=55*/ ) { int curh; @@ -367,7 +359,7 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_ + 5 // to sibtitle + (*txtg)[0][0]->h + 30; - SDL_Surface *ret = drawBox1(boxs.first,boxs.second,player); + SDL_Surface *ret = drawDialogBox(boxs.first,boxs.second,player); blitTextOnSur(txtg,fontHeight,curh,ret); curh += imgToBmp; blitAt(bitmap,(ret->w/2)-(bitmap->w/2),curh,ret); @@ -380,8 +372,6 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player) { SDL_Surface * _or = NULL; - //const Font &f = *graphics->fonts[FONT_MEDIUM]; - //int fontHeight = f.height; if(dynamic_cast(ret)) //it's selection window, so we'll blit "or" between components _or = FNT_RenderText(FONT_MEDIUM,CGI->generaltexth->allTexts[4],Colors::Cornsilk); @@ -405,7 +395,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player) ComponentsToBlit comps(ret->components,500,_or); if (ret->components.size()) - winSize.second += 30 + comps.h; //space to first component + winSize.second += 10 + comps.h; //space to first component int bw = 0; if (ret->buttons.size()) @@ -426,12 +416,11 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player) vstd::amin(winSize.first, screen->w - 150); - ret->bitmap = drawBox1 (winSize.first + 2*SIDE_MARGIN, winSize.second + 2*SIDE_MARGIN, player); + ret->bitmap = drawDialogBox (winSize.first + 2*SIDE_MARGIN, winSize.second + 2*SIDE_MARGIN, player); ret->pos.h=ret->bitmap->h; ret->pos.w=ret->bitmap->w; ret->center(); - int curh = SIDE_MARGIN; int xOffset = (ret->pos.w - ret->text->pos.w)/2; @@ -463,10 +452,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player) } } for(size_t i=0; icomponents.size(); i++) - { - ret->components[i]->pos.x += ret->pos.x; - ret->components[i]->pos.y += ret->pos.y; - } + ret->components[i]->moveBy(Point(ret->pos.x, ret->pos.y)); if(_or) SDL_FreeSurface(_or); @@ -534,29 +520,43 @@ void CMessage::drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int CSDL_Ext::blitSurface(box[3], NULL, ret, &dstR); } -ComponentResolved::ComponentResolved() +ComponentResolved::ComponentResolved( CComponent *Comp ): + comp(Comp) { - comp = NULL; - img = NULL; - txt = NULL; - txtFontHeight = 0; -} + //Temporary assign ownership on comp + if (parent) + parent->removeChild(this); + if (comp->parent) + { + comp->parent->addChild(this); + comp->parent->removeChild(comp); + } -ComponentResolved::ComponentResolved( CComponent *Comp ) -{ - comp = Comp; - img = comp->getImg(); - std::vector brtext = CMessage::breakText(comp->subtitle,14); //text - txt = CMessage::drawText(&brtext,txtFontHeight,FONT_SMALL); + addChild(comp); + defActions = 255 - DISPOSE; + pos.x = pos.y = 0; + + int textHeight = 0; + std::vector textLines = CMessage::breakText(comp->subtitle, 14); //text + txt = CMessage::drawText(&textLines, textHeight, FONT_SMALL); //calculate dimensions - std::pair textSize = CMessage::getMaxSizes(txt, txtFontHeight); - comp->pos.w = std::max(textSize.first, img->w); //bigger of: subtitle width and image width - comp->pos.h = img->h + COMPONENT_TO_SUBTITLE + textSize.second; + std::pair textSize = CMessage::getMaxSizes(txt, textHeight); + pos.w = std::max(textSize.first, comp->pos.w); //bigger of: subtitle width and image width + + pos.h = comp->pos.h + COMPONENT_TO_SUBTITLE + textSize.second; + + comp->moveTo(Point((pos.w - comp->pos.w)/2, 0)); } ComponentResolved::~ComponentResolved() { + if (parent) + { + removeChild(comp); + parent->addChild(comp); + } + for(size_t i = 0; i < txt->size(); i++) for(size_t j = 0; j < (*txt)[i].size(); j++) if((*txt)[i][j]) @@ -564,6 +564,22 @@ ComponentResolved::~ComponentResolved() delete txt; } +void ComponentResolved::showAll(SDL_Surface *to) +{ + tlog0 << "Blitting at "<< pos.x << " " << pos.y << "\n"; + int fontHeight; + if (graphics->fontsTrueType[FONT_SMALL]) + fontHeight = TTF_FontHeight(graphics->fontsTrueType[FONT_SMALL]); + else + fontHeight = graphics->fonts[FONT_SMALL]->height; + + CIntObject::showAll(to); + comp->showAll(to); + + int textY = pos.y + comp->pos.h + COMPONENT_TO_SUBTITLE; + CMessage::blitTextOnSur(txt, fontHeight, textY, to, pos.x + pos.w/2 ); +} + ComponentsToBlit::~ComponentsToBlit() { for(size_t i=0; i & SComps, int maxw, { ComponentResolved *cur = new ComponentResolved(SComps[i]); - int toadd = (cur->comp->pos.w + 12 + (_or ? _or->w : 0)); + int toadd = (cur->pos.w + 12 + (_or ? _or->w : 0)); if (curw + toadd > maxw) { curr++; vstd::amax(w,curw); - curw = cur->comp->pos.w; + curw = cur->pos.w; comps.resize(curr+1); } else @@ -605,10 +621,11 @@ ComponentsToBlit::ComponentsToBlit(std::vector & SComps, int maxw, for(size_t i=0;icomp->pos.h); - h += maxh + BETWEEN_COMPS_ROWS; + vstd::amax(maxHeight, comps[i][j]->pos.h); + + h += maxHeight + BETWEEN_COMPS_ROWS; } } @@ -616,44 +633,33 @@ void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh, { for (size_t i=0;icomp->pos.w; - vstd::amax(maxh,cur->comp->getImg()->h);//subtitles height will added later - } - if(_or) - { - totalw += (inter*2+_or->w) * ((comps)[i].size() - 1); - } - else//add space between comps in this row - { - totalw += (inter) * ((comps)[i].size() - 1); + totalw += cur->pos.w; + vstd::amax(maxHeight, cur->pos.h); } - int startHeight = curh; - int middleh = curh + maxh/2;//axis for image aligment - int curw = (ret->w/2)-(totalw/2); + //add space between comps in this row + if(_or) + totalw += (inter*2+_or->w) * ((comps)[i].size() - 1); + else + totalw += (inter) * ((comps)[i].size() - 1); + + int middleh = curh + maxHeight/2;//axis for image aligment + int curw = ret->w/2 - totalw/2; for(size_t j=0;j<(comps)[i].size();j++) { ComponentResolved *cur = (comps)[i][j]; + cur->moveTo(Point(curw, curh)); - //blit img - int imgX = curw + ( cur->comp->pos.w - cur->comp->getImg()->w ) / 2; - int imgY = startHeight; - blitAt(cur->img, imgX, imgY, ret); - cur->comp->pos.x = imgX; - cur->comp->pos.y = imgY; - - //blit subtitle - int textX = imgX + cur->comp->getImg()->w/2; - int textY = startHeight + cur->comp->getImg()->h + COMPONENT_TO_SUBTITLE; - CMessage::blitTextOnSur(cur->txt, cur->txtFontHeight, textY, ret, textX ); + //blit component + cur->showAll(ret); + curw += cur->pos.w; //if there is subsequent component blit "or" - curw += cur->comp->pos.w; if(j<((comps)[i].size()-1)) { if(_or) @@ -664,8 +670,7 @@ void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh, } curw+=inter; } - vstd::amax(curh, textY); } - curh += BETWEEN_COMPS_ROWS; + curh += maxHeight + BETWEEN_COMPS_ROWS; } } diff --git a/client/CMessage.h b/client/CMessage.h index 32324ee6f..680b6b69b 100644 --- a/client/CMessage.h +++ b/client/CMessage.h @@ -1,6 +1,7 @@ #pragma once #include "FontBase.h" +#include "UIFramework/Geometries.h" /* @@ -15,59 +16,39 @@ struct SDL_Surface; enum EWindowType {infoOnly, infoOK, yesOrNO}; -class CPreGame; -class MapSel; -class CSimpleWindow; class CInfoWindow; class CDefHandler; class CComponent; class CSelWindow; -class CSelectableComponent; -namespace NMessage -{ - extern CDefHandler * ok, *cancel; - extern std::vector > piecesOfBox; //in colors of all players - extern SDL_Surface * background ; -} - -struct ComponentResolved -{ - CComponent *comp; - - SDL_Surface *img; - std::vector > * txt; - int txtFontHeight; - - ComponentResolved(); //c-tor - ComponentResolved(CComponent *Comp); //c-tor - ~ComponentResolved(); //d-tor -}; - -struct ComponentsToBlit -{ - std::vector< std::vector > comps; - int w, h; - - void blitCompsOnSur(SDL_Surface * _or, int inter, int &curh, SDL_Surface *ret); - ComponentsToBlit(std::vector & SComps, int maxw, SDL_Surface* _or); //c-tor - ~ComponentsToBlit(); //d-tor -}; +class ComponentResolved; /// Class which draws formatted text messages and generates chat windows class CMessage { public: - + //Function usd only in CMessage.cpp static std::pair getMaxSizes(std::vector > * txtg, int fontHeight); static std::vector > * drawText(std::vector * brtext, int &fontHeigh, EFonts font = FONT_MEDIUM); static SDL_Surface * blitTextOnSur(std::vector > * txtg, int fontHeight, int & curh, SDL_Surface * ret, int xCenterPos=-1); //xPos==-1 works as if ret->w/2 - static void drawIWindow(CInfoWindow * ret, std::string text, int player); - static CSimpleWindow * genWindow(std::string text, int player, bool centerOnMouse=false, int Lmar=35, int Rmar=35, int Tmar=35, int Bmar=35);//supports h3 text formatting; player sets color of window, Lmar/Rmar/Tmar/Bmar are Left/Right/Top/Bottom margins - static SDL_Surface * drawBox1(int w, int h, int playerColor=1); + + /// Draw border on exiting surface static void drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0); - static SDL_Surface * drawBoxTextBitmapSub(int player, std::string text, SDL_Surface* bitmap, std::string sub, int charperline=30, int imgToBmp=55); + + /// Draw simple dialog box (borders and background only) + static SDL_Surface * drawDialogBox(int w, int h, int playerColor=1); + + /// Draw simple dialog box and blit bitmap with text on it + static SDL_Surface * drawBoxTextBitmapSub(int player, std::string text, SDL_Surface* bitmap, std::string sub, int charPerline=30, int imgToBmp=55); + + + static void drawIWindow(CInfoWindow * ret, std::string text, int player); + + /// split text in lines static std::vector breakText(std::string text, size_t maxLineSize=30, const boost::function &charMetric = boost::function(), bool allowLeadingWhitespace = false); static std::vector breakText(std::string text, size_t maxLineWidth, EFonts font); + + /// constructor static void init(); + /// destructor static void dispose(); }; diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 33aa1b1f3..a33639893 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -1766,7 +1766,7 @@ void InfoCard::clickRight( tribool down, bool previousState ) void InfoCard::showTeamsPopup() { - SDL_Surface *bmp = CMessage::drawBox1(256, 90 + 50 * SEL->current->mapHeader->howManyTeams); + SDL_Surface *bmp = CMessage::drawDialogBox(256, 90 + 50 * SEL->current->mapHeader->howManyTeams); CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[657], 128, 30, FONT_MEDIUM, Colors::Jasmine, bmp); //{Team Alignments} for(int i = 0; i < SEL->current->mapHeader->howManyTeams; i++) @@ -2390,7 +2390,7 @@ void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState ) if(val == -1 || which == BONUS) //random or bonus box { - bmp = CMessage::drawBox1(256, 190); + bmp = CMessage::drawDialogBox(256, 190); std::string *description = NULL; switch(which) @@ -2462,7 +2462,7 @@ void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState ) } else if(which == TOWN) { - bmp = CMessage::drawBox1(256, 319); + bmp = CMessage::drawDialogBox(256, 319); title = &CGI->generaltexth->allTexts[80]; CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[79], 135, 137, FONT_MEDIUM, Colors::Jasmine, bmp); @@ -2491,7 +2491,7 @@ void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState ) else if(val >= 0) { const CHero *h = CGI->heroh->heroes[val]; - bmp = CMessage::drawBox1(320, 255); + bmp = CMessage::drawDialogBox(320, 255); title = &CGI->generaltexth->allTexts[77]; CSDL_Ext::printAtMiddle(*title, 167, 36, FONT_MEDIUM, Colors::Jasmine, bmp); diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 60731b404..69e5cab0b 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -629,7 +629,8 @@ static si64 lod_seek(URLContext *context, si64 pos, int whence) return -1;//video->offset; } -static URLProtocol lod_protocol = { +static URLProtocol lod_protocol = +{ protocol_name, lod_open, lod_read, @@ -653,6 +654,9 @@ CVideoPlayer::CVideoPlayer() av_register_all(); // Register our protocol 'lod' so we can directly read from mmaped memory + // TODO: URL protocol marked as deprecated in favor of avioContext + // VCMI should to it if URL protocol will be removed from ffmpeg or + // when new avioContext will be available in all distros (ETA: late 2012) #ifdef WITH_AV_REGISTER_PROTOCOL2 av_register_protocol2(&lod_protocol, sizeof(lod_protocol)); #else @@ -682,40 +686,39 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) data = vidh.extract(fname, length); - if (data) { + std::string filePath; + if (data) + { + filePath.resize(100); // Create our URL name with the 'lod' protocol as a prefix and a // back pointer to our object. Should be 32 and 64 bits compatible. - char url[100]; - sprintf(url, "%s:0x%016llx", protocol_name, (unsigned long long)(uintptr_t)this); - -#if LIBAVFORMAT_VERSION_MAJOR < 54 - int avfopen = av_open_input_file(&format, url, NULL, 0, NULL); -#else - int avfopen = avformat_open_input(&format, url, NULL, NULL); -#endif - if (avfopen != 0) { - return false; - } - } else { - // File is not in a container -#if LIBAVFORMAT_VERSION_MAJOR < 54 - int avfopen = av_open_input_file(&format, (GameConstants::DATA_DIR + "/Data/video/" + fname).c_str(), NULL, 0, NULL); -#else - int avfopen = avformat_open_input(&format, (GameConstants::DATA_DIR + "/Data/video/" + fname).c_str(), NULL, NULL); -#endif - if (avfopen != 0) { - // tlog1 << "Video file not found: " GameConstants::DATA_DIR + "/Data/video/" + fname << std::endl; - return false; - } + sprintf(&filePath[0], "%s:0x%016llx", protocol_name, (unsigned long long)(uintptr_t)this); } + else + filePath = GameConstants::DATA_DIR + "/Data/video/" + fname; +#if LIBAVFORMAT_VERSION_MAJOR < 53 + int avfopen = av_open_input_file(&format, filePath.c_str(), NULL, 0, NULL); +#else + int avfopen = avformat_open_input(&format, filePath.c_str(), NULL, NULL); +#endif + + if (avfopen != 0) + { + return false; + } // Retrieve stream information +#if LIBAVCODEC_VERSION_MAJOR < 53 if (av_find_stream_info(format) < 0) +#else + if (avformat_find_stream_info(format, NULL) < 0) +#endif return false; // Find the first video stream stream = -1; - for(ui32 i=0; inb_streams; i++) { + for(ui32 i=0; inb_streams; i++) + { #if LIBAVCODEC_VERSION_MAJOR < 53 if (format->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) #else @@ -737,13 +740,19 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) // Find the decoder for the video stream codec = avcodec_find_decoder(codecContext->codec_id); - if (codec == NULL) { + if (codec == NULL) + { // Unsupported codec return false; } // Open codec - if (avcodec_open(codecContext, codec) <0 ) { +#if LIBAVCODEC_VERSION_MAJOR < 53 + if ( avcodec_open(codecContext, codec) < 0 ) +#else + if ( avcodec_open2(codecContext, codec, NULL) < 0 ) +#endif + { // Could not open codec codec = NULL; return false; @@ -753,10 +762,13 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) frame = avcodec_alloc_frame(); // Allocate a place to put our YUV image on that screen - if (useOverlay) { + if (useOverlay) + { overlay = SDL_CreateYUVOverlay(codecContext->width, codecContext->height, SDL_YV12_OVERLAY, screen); - } else { + } + else + { dest = CSDL_Ext::newSurface(codecContext->width, codecContext->height); destRect.x = destRect.y = 0; destRect.w = codecContext->width; @@ -767,11 +779,14 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) return false; // Convert the image into YUV format that SDL uses - if (overlay) { + if (overlay) + { sws = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt, codecContext->width, codecContext->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); - } else { + } + else + { PixelFormat screenFormat = PIX_FMT_NONE; switch(screen->format->BytesPerPixel) @@ -806,22 +821,30 @@ bool CVideoPlayer::nextFrame() if (sws == NULL) return false; - while(!frameFinished) { + while(!frameFinished) + { int ret = av_read_frame(format, &packet); - if (ret < 0) { + if (ret < 0) + { // Error. It's probably an end of file. - if (doLoop && !gotError) { + if (doLoop && !gotError) + { // Rewind if (av_seek_frame(format, stream, 0, 0) < 0) break; gotError = true; - } else { + } + else + { break; } - } else { + } + else + { // Is this a packet from the video stream? - if (packet.stream_index == stream) { + if (packet.stream_index == stream) + { // Decode video frame #ifdef WITH_AVCODEC_DECODE_VIDEO2 avcodec_decode_video2(codecContext, frame, &frameFinished, &packet); @@ -831,7 +854,8 @@ bool CVideoPlayer::nextFrame() #endif // Did we get a video frame? - if (frameFinished) { + if (frameFinished) + { AVPicture pict; if (overlay) { @@ -849,7 +873,9 @@ bool CVideoPlayer::nextFrame() 0, codecContext->height, pict.data, pict.linesize); SDL_UnlockYUVOverlay(overlay); - } else { + } + else + { pict.data[0] = (ui8 *)dest->pixels; pict.linesize[0] = dest->pitch; @@ -894,7 +920,8 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo refreshCount = refreshWait; if (nextFrame()) show(x,y,dst,update); - else { + else + { open(fname); nextFrame(); @@ -904,7 +931,8 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo show(x, y--, dst, update); } } - else { + else + { redraw(x, y, dst, update); } @@ -914,35 +942,45 @@ void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, boo void CVideoPlayer::close() { fname = ""; - if (sws) { + if (sws) + { sws_freeContext(sws); sws = NULL; } - if (overlay) { + if (overlay) + { SDL_FreeYUVOverlay(overlay); overlay = NULL; } - if (dest) { + if (dest) + { SDL_FreeSurface(dest); dest = NULL; } - if (frame) { + if (frame) + { av_free(frame); frame = NULL; } - if (codec) { + if (codec) + { avcodec_close(codecContext); codec = NULL; codecContext = NULL; } - if (format) { + if (format) + { +#if LIBAVCODEC_VERSION_MAJOR < 53 av_close_input_file(format); format = NULL; +#else + avformat_close_input(&format); +#endif } } @@ -956,7 +994,8 @@ bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) pos.x = x; pos.y = y; - while(nextFrame()) { + while(nextFrame()) + { if(stopOnKey && keyDown()) return false; diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 574daacb9..38f5b2afb 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -674,106 +674,18 @@ void CInfoPopup::init(int x, int y) vstd::amin(pos.y, screen->h - bitmap->h); } -void CComponent::init(Etype Type, int Subtype, int Val) +CComponent::CComponent(Etype Type, int Subtype, int Val): + image(nullptr) { - std::ostringstream oss; - switch (Type) - { - case artifact: - description = CGI->arth->artifacts[Subtype]->Description(); - subtitle = CGI->arth->artifacts[Subtype]->Name(); - break; - case primskill: - oss << std::showpos << Val << " "; - if(Subtype < 4) - { - description = CGI->generaltexth->arraytxt[2+Subtype]; - oss << CGI->generaltexth->primarySkillNames[Subtype]; - } - else if(Subtype == 5) //spell points - { - description = CGI->generaltexth->allTexts[149]; - oss << CGI->generaltexth->allTexts[387]; - } - else - { - tlog1 << "Wrong subtype=" << Subtype << std::endl; - } - subtitle = oss.str(); - break; - case building: - description = CGI->buildh->buildings[Subtype][Val]->Description(); - subtitle = CGI->buildh->buildings[Subtype][Val]->Name(); - break; - case secskill44: case secskill: - subtitle += CGI->generaltexth->levels[Val-1] + " " + CGI->generaltexth->skillName[Subtype]; - description = CGI->generaltexth->skillInfoTexts[Subtype][Val-1]; - break; - case morale: - description = CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)]; - break; - case luck: - description = CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)]; - break; - case resource: - description = CGI->generaltexth->allTexts[242]; - oss << Val; - subtitle = oss.str(); - break; - case spell: - description = CGI->spellh->spells[Subtype]->descriptions[Val]; - subtitle = CGI->spellh->spells[Subtype]->name; - break; - case creature: - subtitle = (Val? boost::lexical_cast(Val) + " " : "") + CGI->creh->creatures[Subtype]->*(Val != 1 ? &CCreature::namePl : &CCreature::nameSing); - break; - case experience: - description = CGI->generaltexth->allTexts[241]; - oss << Val ; - if(Subtype && Val==1) - { - subtitle = CGI->generaltexth->allTexts[442]; - } - else - { - subtitle = oss.str(); - } - break; - case hero: - subtitle = description = CGI->heroh->heroes[Subtype]->name; - break; - case flag: - subtitle = CGI->generaltexth->capColors[Subtype]; - break; - } - type = Type; - subtype = Subtype; - val = Val; - if(!img) - { - free = false; - if(type == CComponent::building) - setSurface(graphics->buildingPics[subtype],val); - } - SDL_Surface * temp = this->getImg(); - if(!temp) - { - tlog1 << "Error: cannot find graphic for component with id=" << type << " subid=" << subtype << " val=" << val << std::endl; - return; - } - pos.w = temp->w; - pos.h = temp->h; -} -CComponent::CComponent(Etype Type, int Subtype, int Val, SDL_Surface *sur, bool freeSur) -{ - img = sur; - free = freeSur; + used |= RCLICK; init(Type,Subtype,Val); } -CComponent::CComponent(const Component &c) +CComponent::CComponent(const Component &c): + image(nullptr) { - img = NULL; + used |= RCLICK; + if(c.id == Component::EXPERIENCE) init(experience,c.subtype,c.val); else if(c.id == Component::SPELL) @@ -785,84 +697,143 @@ CComponent::CComponent(const Component &c) subtitle += CGI->generaltexth->allTexts[3].substr(2,CGI->generaltexth->allTexts[3].length()-2); } -CComponent::CComponent() +CComponent::CComponent(): + image(nullptr) { - img = NULL; + used |= RCLICK; } -CComponent::~CComponent() +void CComponent::init(Etype Type, int Subtype, int Val) { - if (free && img) - SDL_FreeSurface(img); -} - -SDL_Surface * CComponent::setSurface(std:: string defname, int imagepos) -{ - if (img) - tlog1<<"CComponent::setSurface: Warning - surface is already set!\n"; - CDefEssential * def = CDefHandler::giveDefEss(defname); - - free = true; - img = def->ourImages[imagepos].bitmap; - img->refcount++;//to preserve surface whed def is deleted - delete def; - return img; + type = Type; + subtype = Subtype; + val = Val; + + subtitle = getSubtitle(); + description = getDescription(); + setSurface(getFileName(), getIndex()); + + pos.w = image->pos.w; + pos.h = image->pos.h; } +//NOTE: whole method can be removed after 0.89+1 release void CComponent::show(SDL_Surface * to) { - blitAt(getImg(),pos.x,pos.y,to); + //In some places components position set manually instead of moveBy - it should be fixed + if (pos.x != image->pos.x + || pos.y != image->pos.y) + { + tlog0 << "Error: Component position may be broken. Please report\n"; + image->moveTo(pos.topLeft()); + CIntObject::showAll(to); + } + else + CIntObject::show(to); } -SDL_Surface * CComponent::getImg() const +std::string CComponent::getFileName() +{ + switch(type) + { + case primskill: return "PSKILL"; + case secskill: return "SECSK82"; + case resource: return "RESOUR82"; + case creature: return "TWCRPORT"; + case artifact: return "ARTIFACT"; + case experience: return "PSKILL"; + case secskill44: return "SECSKILL"; + case spell: return "SPELLSCR"; + case morale: return "IMRL82"; + case luck: return "ILCK82"; + case building: return graphics->buildingPics[subtype]; + case hero: return "PortraitsLarge"; + case flag: return "TWCRPORT"; + } + assert(0); + return 0; +} + +size_t CComponent::getIndex() +{ + switch(type) + { + case primskill: return subtype; + case secskill: return subtype*3 + 3 + val - 1; + case resource: return subtype; + case creature: return subtype+2; + case artifact: return subtype; + case experience: return 4; + case secskill44: return subtype*3 + 3 + val - 1; + case spell: return subtype; + case morale: return val+3; + case luck: return val+3; + case building: return val; + case hero: return subtype; + case flag: return subtype; + } + assert(0); + return 0; +} + +std::string CComponent::getDescription() { - if (img) - return img; switch (type) { - case artifact: - return graphics->artDefs->ourImages[subtype].bitmap; - case primskill: - return graphics->pskillsb->ourImages[subtype].bitmap; - case secskill44: - return graphics->abils44->ourImages[subtype*3 + 3 + val - 1].bitmap; - case secskill: - return graphics->abils82->ourImages[subtype*3 + 3 + val - 1].bitmap; - case resource: - return graphics->resources->ourImages[subtype].bitmap; - case experience: - return graphics->pskillsb->ourImages[4].bitmap; - case morale: - return graphics->morale82->ourImages[val+3].bitmap; - case luck: - return graphics->luck82->ourImages[val+3].bitmap; - case spell: - return graphics->spellscr->ourImages[subtype].bitmap; - case building: - assert(0); //img should have been set - //return setSurface(graphics->buildingPics[subtype],val); - case creature: - return graphics->bigImgs[subtype]; - case hero: - return graphics->portraitLarge[subtype]; - case flag: - return graphics->flags->ourImages[subtype].bitmap; + case primskill: return (subtype < 4)? CGI->generaltexth->arraytxt[2+subtype] //Primary skill + : CGI->generaltexth->allTexts[149]; //mana + case secskill: return CGI->generaltexth->skillInfoTexts[subtype][val-1]; + case resource: return CGI->generaltexth->allTexts[242]; + case creature: return ""; + case artifact: return CGI->arth->artifacts[subtype]->Description(); + case experience: return CGI->generaltexth->allTexts[241]; + case secskill44: return CGI->generaltexth->skillInfoTexts[subtype][val-1]; + case spell: return CGI->spellh->spells[subtype]->descriptions[val]; + case morale: return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)]; + case luck: return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)]; + case building: return CGI->buildh->buildings[subtype][val]->Description(); + case hero: return CGI->heroh->heroes[subtype]->name; + case flag: return ""; } - return NULL; + assert(0); + return 0; } + +std::string CComponent::getSubtitle() +{ + //FIXME: some of these are horrible (e.g creature) + switch(type) + { + case primskill: return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387])); + case secskill: return CGI->generaltexth->levels[val-1] + " " + CGI->generaltexth->skillName[subtype]; + case resource: return boost::lexical_cast(val); + case creature: return (val? boost::lexical_cast(val) + " " : "") + CGI->creh->creatures[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing); + case artifact: return CGI->arth->artifacts[subtype]->Name(); + case experience: return (subtype && val==1) ? CGI->generaltexth->allTexts[442] : boost::lexical_cast(val); + case secskill44: return CGI->generaltexth->levels[val-1] + " " + CGI->generaltexth->skillName[subtype]; + case spell: return CGI->spellh->spells[subtype]->name; + case morale: return ""; + case luck: return ""; + case building: return CGI->buildh->buildings[subtype][val]->Name(); + case hero: return CGI->heroh->heroes[subtype]->name; + case flag: return CGI->generaltexth->capColors[subtype]; + } + assert(0); + return ""; +} + +void CComponent::setSurface(std::string defName, int imgPos) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + delChildNUll(image); + image = new CAnimImage(defName, imgPos); +} + void CComponent::clickRight(tribool down, bool previousState) { if(description.size()) adventureInt->handleRightClick(description,down); } -void CComponent::activate() -{ - activateRClick(); -} -void CComponent::deactivate() -{ - deactivateRClick(); -} void CSelectableComponent::clickLeft(tribool down, bool previousState) { @@ -872,35 +843,30 @@ void CSelectableComponent::clickLeft(tribool down, bool previousState) onSelect(); } } + void CSelectableComponent::init() { selected = false; } -CSelectableComponent::CSelectableComponent(const Component &c, boost::function OnSelect) -:CComponent(c),onSelect(OnSelect) + +CSelectableComponent::CSelectableComponent(const Component &c, boost::function OnSelect): + CComponent(c),onSelect(OnSelect) { + used |= LCLICK | KEYBOARD; init(); } -CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function OnSelect) -:CComponent(Type,Sub,Val),onSelect(OnSelect) + +CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function OnSelect): + CComponent(Type,Sub,Val),onSelect(OnSelect) { + used |= LCLICK | KEYBOARD; init(); } + CSelectableComponent::~CSelectableComponent() { } -void CSelectableComponent::activate() -{ - activateKeys(); - CComponent::activate(); - activateLClick(); -} -void CSelectableComponent::deactivate() -{ - deactivateKeys(); - CComponent::deactivate(); - deactivateLClick(); -} + void CSelectableComponent::select(bool on) { if(on != selected) @@ -913,12 +879,13 @@ void CSelectableComponent::select(bool on) return; } } + void CSelectableComponent::show(SDL_Surface * to) { - blitAt(getImg(),pos.x,pos.y,to); + CComponent::show(to); if(selected) { - CSDL_Ext::drawBorder(to, Rect::around(Rect(pos.x, pos.y, getImg()->w, getImg()->h)), int3(239,215,123)); + CSDL_Ext::drawBorder(to, Rect::around(Rect(pos.x, pos.y, image->pos.w, image->pos.h)), int3(239,215,123)); } printAtMiddleWB(subtitle,pos.x+pos.w/2,pos.y+pos.h+25,FONT_SMALL,12,Colors::Cornsilk,to); @@ -932,9 +899,10 @@ void CSelWindow::selectionChange(unsigned to) if (!pom) continue; pom->select(i==to); - blitAt(pom->getImg(),pom->pos.x-pos.x,pom->pos.y-pos.y,bitmap); } + redraw(); } + CSelWindow::CSelWindow(const std::string &Text, int player, int charperline, const std::vector &comps, const std::vector > > &Buttons, int askID) { OBJ_CONSTRUCTION_CAPTURING_ALL; @@ -965,9 +933,6 @@ CSelWindow::CSelWindow(const std::string &Text, int player, int charperline, con comps[i]->assignedKeys.insert(SDLK_1+i); } CMessage::drawIWindow(this, Text, player); - - BOOST_FOREACH(CComponent *c, components) - c->subtitle = "";//workaround - erase subtitles since they were hard-blitted by function drawing window } void CSelWindow::madeChoice() @@ -1971,8 +1936,7 @@ CLevelWindow::CLevelWindow(const CGHeroInstance *hero, int pskill, std::vectorpos.x = curx+pos.x; - comps[i]->pos.y = 326+pos.y; + comps[i]->moveTo(Point(pos.x + curx, pos.y + 326)); if( i < (comps.size()-1) ) { curx += 44+21; //skill width + margin to "or" @@ -2021,7 +1985,10 @@ void CLevelWindow::show(SDL_Surface * to) blitAt(graphics->portraitLarge[heroPortrait],170+pos.x,66+pos.y,to); ok->showAll(to); for(int i=0;ishowAll(to); comps[i]->show(to); + } } void CMinorResDataBar::show(SDL_Surface * to) @@ -5552,17 +5519,16 @@ void CPuzzleWindow::show(SDL_Surface * to) void CTransformerWindow::CItem::showAll(SDL_Surface * to) { - SDL_Surface * backgr = graphics->bigImgs[parent->army->getCreature(id)->idNumber]; - blitAt(backgr, pos.x, pos.y, to); + CIntObject::showAll(to); printAtMiddle(boost::lexical_cast(size),pos.x+28, pos.y+76,FONT_SMALL,Colors::Cornsilk,to);//stack size } void CTransformerWindow::CItem::move() { if (left) - pos.x += 289; + moveBy(Point(289, 0)); else - pos.x -= 289; + moveBy(Point(-289, 0)); left = !left; } @@ -5578,6 +5544,7 @@ void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState) CTransformerWindow::CItem::CItem(CTransformerWindow * _parent, int _size, int _id): id(_id), size(_size), parent(_parent) { + OBJ_CONSTRUCTION_CAPTURING_ALL; used = LCLICK; left = true; pos.w = 58; @@ -5585,6 +5552,7 @@ CTransformerWindow::CItem::CItem(CTransformerWindow * _parent, int _size, int _i pos.x += 45 + (id%3)*83 + id/6*83; pos.y += 109 + (id/3)*98; + icon = new CAnimImage("TWCRPORT", parent->army->getCreature(id)->idNumber); } CTransformerWindow::CItem::~CItem() @@ -5713,11 +5681,13 @@ void CUniversityWindow::CItem::showAll(SDL_Surface * to) printAtMiddleLoc (CGI->generaltexth->skillName[ID], 22, -13, FONT_SMALL, Colors::Cornsilk,to);//Name printAtMiddleLoc (CGI->generaltexth->levels[0], 22, 57, FONT_SMALL, Colors::Cornsilk,to);//Level(always basic) - CPicture::showAll(to); + CIntObject::showAll(to); } CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y): - CPicture (graphics->abils44->ourImages[_ID*3+3].bitmap,X,Y,false),ID(_ID), parent(_parent) + CAnimImage ("SECSKILL", ID*3+3, 0, X, Y), + ID(_ID), + parent(_parent) { used = LCLICK | RCLICK | HOVER; } @@ -6194,6 +6164,7 @@ CThievesGuildWindow::~CThievesGuildWindow() void MoraleLuckBox::set(const IBonusBearer *node) { + OBJ_CONSTRUCTION_CAPTURING_ALL; const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:} const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck const int neutralDescr[] = {60, 86}; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat. @@ -6205,7 +6176,6 @@ void MoraleLuckBox::set(const IBonusBearer *node) int mrlt = -9; TModDescr mrl; - if (node) { node->getModifiersWDescr(mrl, bonusType[morale]); @@ -6233,23 +6203,21 @@ void MoraleLuckBox::set(const IBonusBearer *node) text += "\n" + mrl[it].second; } } -} - -void MoraleLuckBox::showAll(SDL_Surface * to) -{ - CDefEssential *def; + + std::string imageName; if (small) - def = morale ? graphics->morale30 : graphics->luck30; + imageName = morale ? "IMRL30": "ILCK30"; else - def = morale ? graphics->morale42 : graphics->luck42; - SDL_Surface *img = def->ourImages[bonusValue + 3].bitmap; - - blitAt(img, Rect(img).centerIn(pos), to); //put img in the center of our pos + imageName = morale ? "IMRL42" : "ILCK42"; + delChildNUll(image); + image = new CAnimImage(imageName, bonusValue + 3); + image->moveBy(Point(pos.w/2 - image->pos.w/2, pos.h/2 - image->pos.h/2));//center icon } -MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small) - :morale(Morale), - small(Small) +MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small): + image(NULL), + morale(Morale), + small(Small) { bonusValue = 0; pos = r + pos; diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 9a8877db6..0a2fa5f37 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -1,6 +1,6 @@ #pragma once - +#include "CAnimation.h" #include "FunctionList.h" #include "../lib/ResourceSet.h" #include "../lib/GameConstants.h" @@ -161,6 +161,15 @@ public: /// common popup window component class CComponent : public virtual CIntObject { + size_t getIndex(); + std::string getFileName(); + std::string getDescription(); + std::string getSubtitle(); + +protected: + CAnimImage *image; //our image + void setSurface(std::string defName, int imgPos); + public: enum Etype { @@ -172,22 +181,14 @@ public: std::string description; //r-click std::string subtitle; //TODO: comment me - SDL_Surface *img; //our image - bool free; //should surface be freed on delete - - SDL_Surface * setSurface(std::string defName, int imgPos); - - void init(Etype Type, int Subtype, int Val); - CComponent(Etype Type, int Subtype, int Val, SDL_Surface *sur=NULL, bool freeSur=false); //c-tor + virtual void init(Etype Type, int Subtype, int Val); + CComponent(Etype Type, int Subtype, int Val); //c-tor CComponent(const Component &c); //c-tor - CComponent();; //c-tor - virtual ~CComponent(); //d-tor + CComponent(); //c-tor void clickRight(tribool down, bool previousState); //call-in - SDL_Surface * getImg() const; - virtual void show(SDL_Surface * to); - virtual void activate(); - virtual void deactivate(); + + void show(SDL_Surface * to); }; class CSelectableComponent : public CComponent, public CKeyShortcut @@ -202,8 +203,6 @@ public: CSelectableComponent(const Component &c, boost::function OnSelect = 0); //c-tor ~CSelectableComponent(); //d-tor virtual void show(SDL_Surface * to); - void activate(); - void deactivate(); void select(bool on); }; @@ -777,12 +776,12 @@ public: class MoraleLuckBox : public LRClickableAreaWTextComp { + CAnimImage *image; public: bool morale; //true if morale, false if luck bool small; void set(const IBonusBearer *node); - void showAll(SDL_Surface * to); MoraleLuckBox(bool Morale, const Rect &r, bool Small=false); ~MoraleLuckBox(); @@ -1022,6 +1021,7 @@ public: bool left;//position of the item int size; //size of creature stack CTransformerWindow * parent; + CAnimImage *icon; void move(); void showAll(SDL_Surface * to); @@ -1047,7 +1047,7 @@ public: class CUniversityWindow : public CIntObject { - class CItem : public CPicture + class CItem : public CAnimImage { public: int ID;//id of selected skill diff --git a/config/creatures.json b/config/creatures.json index c622b0b60..12302a27b 100644 --- a/config/creatures.json +++ b/config/creatures.json @@ -8,7 +8,7 @@ // faction: its faction (0 to 8) // The following properties are optional: -// upgrade: number of the creature to upgrade to +// upgrades: id of the creatures to upgrade to // projectile_defname: if the creature is a shooter, graphics for the projectile // projectile_spin: if the creature is a shooter, indicate whether the projectile spins // turret_shooter: indicates whether the shooter appears in the castle turrets @@ -23,7 +23,7 @@ "level": 1, "name": [ "Pikeman" ], "faction": 0, - "upgrade": 1, + "upgrades": [1], "ability_add": [ [ "CHARGE_IMMUNITY", 0, 0, 0 ] ], //pikeman immunity to Champion charge bonus "defname": "CPKMAN.DEF" }, @@ -42,7 +42,7 @@ "level": 2, "name": [ "Archer", "LightCrossbowman" ], "faction": 0, - "upgrade": 3, + "upgrades": [3], "defname": "CLCBOW.DEF", "projectile_defname": "PLCBOWX.DEF", "projectile_spin": false, @@ -65,7 +65,7 @@ "name": [ "Griffin" ], "faction": 0, "ability_add": [ [ "ADDITIONAL_RETALIATION", 1, 0, 0 ] ], //griffins retaliate twice - "upgrade": 5, + "upgrades": [5], "defname": "CGRIFF.DEF" }, @@ -83,7 +83,7 @@ "level": 4, "name": [ "Swordsman" ], "faction": 0, - "upgrade": 7, + "upgrades": [7], "defname": "CSWORD.DEF" }, @@ -100,7 +100,7 @@ "level": 5, "name": [ "Monk" ], "faction": 0, - "upgrade": 9, + "upgrades": [9], "defname": "CMONKK.DEF", "projectile_defname": "CPRZEAX.DEF", "projectile_spin": false @@ -121,7 +121,7 @@ "level": 6, "name": [ "Cavalier" ], "faction": 0, - "upgrade": 11, + "upgrades": [11], "defname": "CCAVLR.DEF" }, @@ -140,7 +140,7 @@ "faction": 0, "ability_add": [ [ "HATE", 50, 55, 0 ], //angels hate archdevils [ "HATE", 50, 54, 0 ] ], //angels hate devils - "upgrade": 13, + "upgrades": [13], "defname": "CANGEL.DEF" }, @@ -162,7 +162,7 @@ "level": 1, "name": [ "Centaur" ], "faction": 1, - "upgrade": 15, + "upgrades": [15], "defname": "CCENTR.DEF" }, @@ -180,7 +180,7 @@ "name": [ "Dwarf" ], "faction": 1, "ability_add": [ [ "MAGIC_RESISTANCE", 20, 0, 0 ] ], //dwarf's magic resistance 20% - "upgrade": 17, + "upgrades": [17], "defname": "CDWARF.DEF" }, @@ -198,7 +198,7 @@ "level": 3, "name": [ "WoodElf" ], "faction": 1, - "upgrade": 19, + "upgrades": [19], "defname": "CELF.DEF", "projectile_defname": "PELFX.DEF", "projectile_spin": false, @@ -221,7 +221,7 @@ "name": [ "Pegasus" ], "faction": 1, "ability_add": [ [ "CHANGES_SPELL_COST_FOR_ENEMY", 2, 0, 0 ] ], //pegasus makes spell cost higher for enemy mage - "upgrade": 21, + "upgrades": [21], "defname": "CPEGAS.DEF" }, @@ -240,7 +240,7 @@ "name": [ "Treefolk" ], "faction": 1, "ability_add": [ [ "SPELL_AFTER_ATTACK", 100, 72, 0 ] ], //dendroids cast bind - "upgrade": 23, + "upgrades": [23], "defname": "CTREE.DEF" }, @@ -260,7 +260,7 @@ "faction": 1, "ability_add": [ [ "SPELL_RESISTANCE_AURA", 0, 55, 0 ], //unicorn [ "SPELL_AFTER_ATTACK", 20, 62, 0 ] ], //unicorns cast blind with 20% probability - "upgrade": 25, + "upgrades": [25], "defname": "CUNICO.DEF" }, @@ -282,7 +282,7 @@ "ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ], //green dragon is a dragon [ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //green dragon's breath [ "LEVEL_SPELL_IMMUNITY", 3, 0, 0 ] ], //green dragon's spell immunity - "upgrade": 27, + "upgrades": [27], "defname": "CGDRAG.DEF" }, @@ -302,7 +302,7 @@ "level": 1, "name": [ "ApprenticeGremlin" ], "faction": 2, - "upgrade": 29, + "upgrades": [29], "defname": "CGREMA.DEF" }, @@ -322,7 +322,7 @@ "name": [ "StoneGargoyle" ], "faction": 2, "ability_add": [ [ "NON_LIVING", 0, 0, 0 ] ], //stone gargoyles are non-living - "upgrade": 31, + "upgrades": [31], "defname": "CGARGO.DEF" }, @@ -342,7 +342,7 @@ "faction": 2, "ability_add": [ [ "SPELL_DAMAGE_REDUCTION", 50, -1, 0 ], //stone golems reduce dmg from spells [ "NON_LIVING", 0, 0, 0 ] ], //stone golems are non-living - "upgrade": 33, + "upgrades": [33], "defname": "CSGOLE.DEF" }, @@ -362,7 +362,7 @@ "name": [ "Mage" ], "faction": 2, "ability_add": [ [ "CHANGES_SPELL_COST_FOR_ALLY", 2, 0, 0 ] ], //mages reduce spell cost - "upgrade": 35, + "upgrades": [35], "defname": "CMAGE.DEF", "projectile_defname": "PMAGEX.DEF", "projectile_spin": false, @@ -374,7 +374,7 @@ "level": 4, "name": [ "ArchMage" ], "faction": 2, - "ability_add": [ [ "CHANGES_SPELL_COST_FOR_ALLY", 2, 0, 0 ]], //archmages reduce spell cost + "ability_add": [ [ "CHANGES_SPELL_COST_FOR_ALLY", 2, 0, 0 ]], //archmages reduce spell cost "defname": "CAMAGE.DEF", "projectile_defname": "PMAGEX.DEF", "projectile_spin": false @@ -387,7 +387,7 @@ "faction": 2, "ability_add": [ [ "HATE", 50, 53, 0 ], //master genies hate efreets [ "HATE", 50, 52, 0 ] ], //genies hate efreet sultans - "upgrade": 37, + "upgrades": [37], "defname": "CGENIE.DEF" }, @@ -410,7 +410,7 @@ "name": [ "NagaSentinel" ], "faction": 2, "ability_add": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //nagas block retaliation - "upgrade": 39, + "upgrades": [39], "defname": "CNAGA.DEF" }, @@ -429,7 +429,7 @@ "name": [ "LesserTitan" ], "faction": 2, "ability_add": [ ["MIND_IMMUNITY", 0, 0, 0] ], //giants are immune to mind spells - "upgrade": 41, + "upgrades": [41], "defname": "CLTITA.DEF" }, @@ -450,7 +450,7 @@ "level": 1, "name": [ "Imp" ], "faction": 3, - "upgrade": 43, + "upgrades": [43], "defname": "CIMP.DEF" }, @@ -468,7 +468,7 @@ "level": 2, "name": [ "Gog" ], "faction": 3, - "upgrade": 45, + "upgrades": [45], "defname": "CGOG.DEF", "projectile_defname": "CPRGOGX.DEF", "projectile_spin": false, @@ -491,7 +491,7 @@ "level": 3, "name": [ "HellHound" ], "faction": 3, - "upgrade": 47, + "upgrades": [47], "ability_remove": [ "FLYING" ], "defname": "CHHOUN.DEF" }, @@ -512,7 +512,7 @@ "level": 4, "name": [ "Single-HornedDemon" ], "faction": 3, - "upgrade": 49, + "upgrades": [49], "defname": "COHDEM.DEF" }, @@ -529,7 +529,7 @@ "level": 5, "name": [ "PitFiend" ], "faction": 3, - "upgrade": 51, + "upgrades": [51], "defname": "CPFIEN.DEF" }, @@ -538,7 +538,7 @@ "level": 5, "name": [ "PitFoe" ], "faction": 3, - "ability_add": [ [ "DAEMON_SUMMONING", 50, 48, 0 ], + "ability_add": [ [ "DAEMON_SUMMONING", 50, 48, 0 ], [ "CASTS", 1, 0, 0] ], //pit lord "defname": "CPFOE.DEF" }, @@ -552,7 +552,7 @@ [ "HATE", 50, 36, 0 ], [ "FLYING", 0, 0, 0 ], //efreeti hate master genies [ "FIRE_IMMUNITY", 0, 0, 0 ] ], //efreeti hate genies - "upgrade": 53, + "upgrades": [53], "defname": "CEFREE.DEF" }, @@ -578,7 +578,7 @@ [ "HATE", 50, 12, 0 ], [ "ENEMY_LUCK_DECREASING", 1, 0, 0 ], //devils //devils hate archangles [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //devils //devils hate angels - "upgrade": 55, + "upgrades": [55], "defname": "CDEVIL.DEF" }, @@ -599,7 +599,7 @@ "level": 1, "name": [ "Skeleton" ], "faction": 4, - "upgrade": 57, + "upgrades": [57], "defname": "CSKELE.DEF" }, @@ -616,7 +616,7 @@ "level": 2, "name": [ "Zombie" ], "faction": 4, - "upgrade": 59, + "upgrades": [59], "defname": "CZOMBI.DEF" }, @@ -634,7 +634,7 @@ "name": [ "Wight" ], "faction": 4, "ability_add": [ [ "FULL_HP_REGENERATION", 0, 1, 0 ] ], //wight - "upgrade": 61, + "upgrades": [61], "defname": "CWIGHT.DEF" }, @@ -654,7 +654,7 @@ "name": [ "Vampire" ], "faction": 4, "ability_add": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ] ], //vampires //vampire lords - "upgrade": 63, + "upgrades": [63], "defname": "CVAMP.DEF" }, @@ -674,7 +674,7 @@ "name": [ "Lich" ], "faction": 4, "ability_add": [ [ "SPELL_LIKE_ATTACK", 0, 76, 0 ] ], //liches - "upgrade": 65, + "upgrades": [65], "defname": "CLICH.DEF", "projectile_defname": "PLICH.DEF", "projectile_spin": false, @@ -698,7 +698,7 @@ "name": [ "BlackKnight" ], "faction": 4, "ability_add": [ [ "SPELL_AFTER_ATTACK", 20, 42, 0 ] ], //black knights - "upgrade": 67, + "upgrades": [67], "defname": "CBKNIG.DEF" }, @@ -718,7 +718,7 @@ "name": [ "BoneDragon" ], "faction": 4, "ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ] ], //bone dragon is a dragon - "upgrade": 69, + "upgrades": [69], "defname": "CNDRGN.DEF" }, @@ -738,7 +738,7 @@ "name": [ "Troglodyte" ], "faction": 5, "ability_add": [ [ "SPELL_IMMUNITY", 0, 62, 0 ] ], //troglodytes are immune to blind - "upgrade": 71, + "upgrades": [71], "defname": "CTROGL.DEF" }, @@ -757,7 +757,7 @@ "name": [ "Harpy" ], "faction": 5, "ability_add": [ [ "RETURN_AFTER_STRIKE", 0, 0, 0 ] ], //Harpies return after attack - "upgrade": 73, + "upgrades": [73], "defname": "CHARPY.DEF" }, @@ -776,7 +776,7 @@ "level": 3, "name": [ "Beholder" ], "faction": 5, - "upgrade": 75, + "upgrades": [75], "defname": "CBEHOL.DEF", "projectile_defname": "SMBALX.DEF", "projectile_spin": false @@ -785,7 +785,7 @@ { "id": 75, "level": 3, - "name": [ "EvilEye", "M75" ], + "name": [ "EvilEye", "M75" ], "faction": 5, "defname": "CEVEYE.DEF", "projectile_defname": "SMBALX.DEF", @@ -798,7 +798,7 @@ "name": [ "Medusa", "Medusae" ], "faction": 5, "ability_add": [ [ "SPELL_AFTER_ATTACK", 20, 70, 2000 ] ], //medusas //minotaurs - "upgrade": 77, + "upgrades": [77], "defname": "CMEDUS.DEF", "projectile_defname": "PMEDUSX.DEF", "projectile_spin": false, @@ -822,7 +822,7 @@ "name": [ "Minotaur" ], "faction": 5, "ability_add": [ [ "SELF_MORALE", 0, 0, 0 ] ], - "upgrade": 79, + "upgrades": [79], "defname": "CMINOT.DEF" }, @@ -840,7 +840,7 @@ "level": 6, "name": [ "Manticore" ], "faction": 5, - "upgrade": 81, + "upgrades": [81], "defname": "CMCORE.DEF" }, @@ -861,7 +861,7 @@ "ability_add": [ [ "DRAGON_NATURE", 0, 0, 0 ], //red dragon is a dragon [ "TWO_HEX_ATTACK_BREATH", 0, 0, 0 ], //Red Dragon has breath attack [ "LEVEL_SPELL_IMMUNITY", 3, 0, 0 ] ], //red dragon's spell immunity - "upgrade": 83, + "upgrades": [83], "defname": "CRDRGN.DEF" }, @@ -883,7 +883,7 @@ "level": 1, "name": [ "Goblin" ], "faction": 6, - "upgrade": 85, + "upgrades": [85], "defname": "CGOBLI.DEF" }, @@ -900,7 +900,7 @@ "level": 2, "name": [ "GoblinWolfRider" ], "faction": 6, - "upgrade": 87, + "upgrades": [87], "defname": "CBWLFR.DEF" }, @@ -918,7 +918,7 @@ "level": 3, "name": [ "Orc" ], "faction": 6, - "upgrade": 89, + "upgrades": [89], "defname": "CORC.DEF", "projectile_defname": "PORCHX.DEF", "projectile_spin": true, @@ -940,7 +940,7 @@ "level": 4, "name": [ "Ogre" ], "faction": 6, - "upgrade": 91, + "upgrades": [91], "defname": "COGRE.DEF" }, @@ -960,7 +960,7 @@ "level": 5, "name": [ "Roc" ], "faction": 6, - "upgrade": 93, + "upgrades": [93], "defname": "CROC.DEF" }, @@ -979,7 +979,7 @@ "level": 6, "name": [ "Cyclops" ], "faction": 6, - "upgrade": 95, + "upgrades": [95], "defname": "CCYCLR.DEF", "projectile_defname": "PCYCLBX.DEF", "projectile_spin": true @@ -1001,7 +1001,7 @@ "name": [ "YoungBehemoth" ], "faction": 6, "ability_add": [ [ "ENEMY_DEFENCE_REDUCTION", 40, 0, 0 ] ], //behemots - "upgrade": 97, + "upgrades": [97], "defname": "CYBEHE.DEF" }, @@ -1019,7 +1019,7 @@ "level": 1, "name": [ "Gnoll" ], "faction": 7, - "upgrade": 99, + "upgrades": [99], "defname": "CGNOLL.DEF" }, @@ -1036,7 +1036,7 @@ "level": 2, "name": [ "PrimitiveLizardman" ], "faction": 7, - "upgrade": 101, + "upgrades": [101], "defname": "CPLIZA.DEF", "projectile_defname": "PPLIZAX.DEF", "projectile_spin": false, @@ -1058,7 +1058,7 @@ "level": 5, "name": [ "CopperGorgon" ], "faction": 7, - "upgrade": 103, + "upgrades": [103], "defname": "CCGORG.DEF" }, @@ -1077,7 +1077,7 @@ "name": [ "Dragonflies", "DragonFly", "SerpentFly" ], "faction": 7, "ability_add": [ [ "SPELL_AFTER_ATTACK", 100, 78, 0 ] ], //serpent fly - "upgrade": 105, + "upgrades": [105], "defname": "CDRFLY.DEF" }, @@ -1097,7 +1097,7 @@ "name": [ "Basilisk" ], "faction": 7, "ability_add": [ [ "SPELL_AFTER_ATTACK", 20, 70, 0 ] ], //basilisks - "upgrade": 107, + "upgrades": [107], "defname": "CBASIL.DEF" }, @@ -1115,7 +1115,7 @@ "level": 6, "name": [ "Wyvern" ], "faction": 7, - "upgrade": 109, + "upgrades": [109], "defname": "CWYVER.DEF" }, @@ -1135,7 +1135,7 @@ "faction": 7, "ability_add": [ [ "BLOCKS_RETALIATION", 0, 0, 0 ], //hydras [ "ATTACKS_ALL_ADJACENT", 0, 0, 0 ] ], //hydras - "upgrade": 111, + "upgrades": [111], "defname": "CHYDRA.DEF" }, @@ -1162,7 +1162,7 @@ [ "NON_LIVING", 0, 0, 0 ], [ "MORE_DAMAGE_FROM_SPELL", 100, 19, 0 ], //air elementals are vulnerable to chain lightning [ "MORE_DAMAGE_FROM_SPELL", 100, 17, 0 ] ], //air elementals are vulnerable to lightning bolt //air elementals are non-living - "upgrade": 127, + "upgrades": [127], "defname": "CAELEM.DEF" }, @@ -1179,7 +1179,7 @@ [ "SPELL_IMMUNITY", 0, 17, 0 ], //earth elementals are immune to lightning bolt [ "NON_LIVING", 0, 0, 0 ], [ "MORE_DAMAGE_FROM_SPELL", 100, 23, 0 ] ], //earth elementals are vulnerable to meteor shower - "upgrade": 125, + "upgrades": [125], "defname": "CEELEM.DEF" }, @@ -1196,7 +1196,7 @@ [ "MORE_DAMAGE_FROM_SPELL", 100, 20, 0 ], //fire elementals are vulnerable to frost ring [ "MORE_DAMAGE_FROM_SPELL", 100, 16, 0 ], //fire elementals are vulnerable to ice bolt [ "FIRE_IMMUNITY", 0, 0, 0 ] ], //fire elementals are immune to fire spells - "upgrade": 129, + "upgrades": [129], "defname": "CFELEM.DEF" }, @@ -1217,7 +1217,7 @@ [ "MORE_DAMAGE_FROM_SPELL", 100, 21, 0 ], //water elementals are vulnerable to fireball [ "MORE_DAMAGE_FROM_SPELL", 100, 13, 0 ], //water elementals are vulnerable to fire wall [ "DOUBLE_WIDE", 0, 0, 0 ] ], - "upgrade": 123, + "upgrades": [123], "defname": "CWELEM.DEF" }, @@ -1246,7 +1246,7 @@ "level": 1, "name": [ "Pixie", "Pixies" ], "faction": 8, - "upgrade": 119, + "upgrades": [119], "defname": "CPIXIE.DEF" }, @@ -1265,7 +1265,7 @@ "faction": 8, "ability_add": [ [ "NON_LIVING", 0, 0, 0 ] ], //magic elementals shouldn't get morale "ability_remove": [ "DOUBLE_WIDE" ], - "upgrade": 121, + "upgrades": [121], "defname": "CPSYEL.DEF" }, @@ -1285,11 +1285,11 @@ "level": 3, "name": [ "IceElemental" ], "faction": 8, - "ability_add": [ [ "NON_LIVING", 0, 0, 0 ], + "ability_add": [ [ "NON_LIVING", 0, 0, 0 ], [ "DOUBLE_WIDE", 0, 0, 0 ], //ice elemental should be treated as double-wide [ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], [ "CASTS", 3, 0, 0 ], - [ "SPELLCASTER", 2, 32, 0 ]], + [ "SPELLCASTER", 2, 32, 0 ]], "defname": "CICEE.DEF", "projectile_defname": "PICEE.DEF", "projectile_spin": false @@ -1315,7 +1315,7 @@ "ability_add": [ [ "NON_LIVING", 0, 0, 0 ], //storm elementals shouldn't get morale [ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], [ "CASTS", 3, 0, 0 ], - [ "SPELLCASTER", 2, 30, 0 ]], + [ "SPELLCASTER", 2, 30, 0 ]], "defname": "CSTORM.DEF", "projectile_defname": "CPRGTIX.DEF", "projectile_spin": false, @@ -1326,11 +1326,11 @@ "id": 129, "level": 4, "name": [ "ElectricityElemental" ], - "faction": 8, + "faction": 8, "ability_add": [ [ "NON_LIVING", 0, 0, 0 ] , //energy elementals shouldn't get morale //Crystal Dragons do not fly [ "CREATURE_ENCHANT_POWER", 6, 0, 0 ], [ "CASTS", 3, 0, 0 ], - [ "SPELLCASTER", 2, 31, 0 ]], + [ "SPELLCASTER", 2, 31, 0 ]], "defname": "CNRG.DEF" }, @@ -1339,7 +1339,7 @@ "level": 7, "name": [ "Firebird" ], "faction": 8, - "upgrade": 131, + "upgrades": [131], "defname": "CFBIRD.DEF" }, @@ -1426,7 +1426,7 @@ "level": 4, "name": [ "Sharpshooter" ], "faction": -1, - "ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ], + "ability_add": [ [ "NO_WALL_PENALTY", 0, 0, 0 ], [ "NO_DISTANCE_PENALTY", 0, 0, 0 ] ], //Sharpshooter "defname": "CSHARP.DEF", "projectile_defname": "PELFX.DEF", @@ -1982,7 +1982,7 @@ } ], - // something hacking + // something hacking "unused_creatures": [ 122, 124, 126, 128, 145, 146, 147, 148, 149, 160, 161, 162, 163, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 4312d11ac..8d3640927 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -437,9 +437,10 @@ void CCreatureHandler::loadCreatures() c->faction = creature["faction"].Float(); c->animDefName = creature["defname"].String(); - value = &creature["upgrade"]; - if (!value->isNull()) - c->upgrades.insert(value->Float()); + BOOST_FOREACH(const JsonNode &value, creature["upgrades"].Vector()) + { + c->upgrades.insert(value.Float()); + } value = &creature["projectile_defname"]; if (!value->isNull()) @@ -472,7 +473,8 @@ void CCreatureHandler::loadCreatures() } } - BOOST_FOREACH(const JsonNode &creature, config["unused_creatures"].Vector()) { + BOOST_FOREACH(const JsonNode &creature, config["unused_creatures"].Vector()) + { notUsedMonsters += creature.Float(); } diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index a91951ded..028f6b56b 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -1148,13 +1148,21 @@ int CPlayerSpecificInfoCallback::getMyColor() const return player; } -int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero) const +int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const { - //boost::shared_lock lock(*gs->mx); - for (size_t i=0; iplayers[player].heroes.size();i++) + if (hero->inTownGarrison && !includeGarrisoned) + return -1; + + size_t index = 0; + auto & heroes = gs->players[player].heroes; + + for (auto curHero= heroes.begin(); curHero!=heroes.end(); curHero++) { - if (gs->players[player].heroes[i]==hero) - return i; + if (includeGarrisoned || !(*curHero)->inTownGarrison) + index++; + + if (*curHero == hero) + return index; } return -1; } diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index e3ff3723e..66a20ebff 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -226,7 +226,7 @@ public: int getMyColor() const; std::vector getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible - int getHeroSerial(const CGHeroInstance * hero)const; + int getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned=true) const; const CGTownInstance* getTownBySerial(int serialId) const; // serial id is [0, number of towns) 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