From e3231db1c9b058b8de6b4d34d5773114e8c7e38d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 11 Dec 2012 12:12:46 +0000 Subject: [PATCH] - primaryResource and warMachine now use string ID - fixed long delays on moving units in garrisons - fixed bug on loading available spells from map - removed unused bigImgs from Graphics --- client/CCastleInterface.cpp | 59 ++------ client/CKingdomInterface.cpp | 2 +- client/CPlayerInterface.cpp | 40 ++++-- client/CPlayerInterface.h | 2 + client/GUIClasses.cpp | 255 +++++++++++++++++++++-------------- client/GUIClasses.h | 31 +++-- client/Graphics.cpp | 10 +- client/Graphics.h | 1 - config/buildings.json | 32 ++--- lib/CTownHandler.cpp | 14 +- lib/Map/CMapService.cpp | 4 +- 11 files changed, 250 insertions(+), 200 deletions(-) diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index e5e4311cc..3ce62fe8f 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -109,9 +109,8 @@ void CBuildingRect::clickRight(tribool down, bool previousState) const CBuilding *bld = town->town->buildings[bid]; if (bid < EBuilding::DWELL_FIRST) { - std::vector comps(1, new CComponent(CComponent::building, bld->tid, bld->bid)); - - CRClickPopup::createAndPush(bld->Description(), comps); + CRClickPopup::createAndPush(CInfoWindow::genText(bld->Name(), bld->Description()), + new CComponent(CComponent::building, bld->tid, bld->bid)); } else { @@ -325,8 +324,8 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) CHeroGSlot *other = upg ? owner->garrisonedHero : owner->visitingHero; if(!down) { - owner->garr->splitting = false; - owner->garr->highlighted = NULL; + owner->garr->setSplittingMode(false); + owner->garr->selectSlot(nullptr); if(hero && selection) { @@ -361,7 +360,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState) else if(hero) { setHighlight(true); - owner->garr->highlighted = NULL; + owner->garr->selectSlot(nullptr); showAll(screen2); } hover(false);hover(true); //refresh statusbar @@ -1067,16 +1066,7 @@ void CCreaInfo::clickRight(tribool down, bool previousState) if (showAvailable) GH.pushInt(new CDwellingInfoBox(screen->w/2, screen->h/2, town, level)); else - { - std::string descr = genGrowthText(); - CInfoPopup *mess = new CInfoPopup();//creating popup - mess->free = true; - mess->bitmap = CMessage::drawBoxTextBitmapSub - (LOCPLINT->playerID, descr,graphics->bigImgs[creature->iconIndex],""); - mess->pos.x = screen->w/2 - mess->bitmap->w/2; - mess->pos.y = screen->h/2 - mess->bitmap->h/2; - GH.pushInt(mess); - } + CRClickPopup::createAndPush(genGrowthText(), new CComponent(CComponent::creature, creature->idNumber)); } } @@ -1118,21 +1108,11 @@ void CTownInfo::hover(bool on) } void CTownInfo::clickRight(tribool down, bool previousState) -{//FIXME: castleInt may be NULL - if(down && building && LOCPLINT->castleInt) - { - CInfoPopup *mess = new CInfoPopup(); - mess->free = true; +{ + if(down && building) + CRClickPopup::createAndPush(CInfoWindow::genText(building->Name(), building->Description()), + new CComponent(CComponent::building, building->tid, building->bid)); - mess->bitmap = CMessage::drawBoxTextBitmapSub - (LOCPLINT->playerID, - building->Description(), - LOCPLINT->castleInt->bicons->ourImages[building->bid].bitmap, - building->Name()); - mess->pos.x = screen->w/2 - mess->bitmap->w/2; - mess->pos.y = screen->h/2 - mess->bitmap->h/2; - GH.pushInt(mess); - } } void CCastleInterface::keyPressed( const SDL_KeyboardEvent & key ) @@ -1646,28 +1626,13 @@ CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell) void CMageGuildScreen::Scroll::clickLeft(tribool down, bool previousState) { if(down) - { - std::vector comps(1, - new CComponent(CComponent::spell,spell->id,0) - ); - LOCPLINT->showInfoDialog(spell->descriptions[0],comps, soundBase::sound_todo); - } + LOCPLINT->showInfoDialog(spell->descriptions[0], new CComponent(CComponent::spell,spell->id)); } void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState) { if(down) - { - CInfoPopup *vinya = new CInfoPopup(); - vinya->free = true; - vinya->bitmap = CMessage::drawBoxTextBitmapSub - (LOCPLINT->playerID, - spell->descriptions[0],graphics->spellscr->ourImages[spell->id].bitmap, - spell->name,30,30); - vinya->pos.x = screen->w/2 - vinya->bitmap->w/2; - vinya->pos.y = screen->h/2 - vinya->bitmap->h/2; - GH.pushInt(vinya); - } + CRClickPopup::createAndPush(spell->descriptions[0], new CComponent(CComponent::spell, spell->id)); } void CMageGuildScreen::Scroll::hover(bool on) diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index 401c75dfa..3b3413cda 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -813,7 +813,7 @@ CTownItem::CTownItem(const CGTownInstance* Town): void CTownItem::updateGarrisons() { - garr->highlighted = NULL; + garr->selectSlot(nullptr); garr->setArmy(town->getUpperArmy(), 0); garr->setArmy(town->visitingHero, 1); garr->recreateSlots(); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 6f0453828..23771de99 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -509,7 +509,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) if(CCastleInterface *c = castleInt) { - c->garr->highlighted = NULL; + c->garr->selectSlot(nullptr); c->garr->setArmy(town->getUpperArmy(), 0); c->garr->setArmy(town->visitingHero, 1); c->garr->recreateSlots(); @@ -535,10 +535,11 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn waitWhileDialog(); openTownWindow(town); } -void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj) +void CPlayerInterface::garrisonsChanged(std::vector objs) { boost::unique_lock un(*pim); - updateInfo(obj); + BOOST_FOREACH(auto object, objs) + updateInfo(object); for(std::list::iterator i = GH.listInt.begin(); i != GH.listInt.end(); i++) { @@ -548,7 +549,7 @@ void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj) if(CTradeWindow *cmw = dynamic_cast(*i)) { - if(obj == cmw->hero) + if(vstd::contains(objs, cmw->hero)) cmw->garrisonChanged(); } } @@ -556,6 +557,11 @@ void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj) GH.totalRedraw(); } +void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj) +{ + garrisonsChanged(std::vector(1, obj)); +} + void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished { EVENT_HANDLER_CALLED_BY_CLIENT; @@ -953,6 +959,14 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector } +void CPlayerInterface::showInfoDialog(const std::string &text, CComponent * component) +{ + std::vector intComps; + intComps.push_back(component); + + showInfoDialog(text, intComps, soundBase::sound_todo, true); +} + void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector & components, int soundID, bool delComps) { waitWhileDialog(); @@ -2327,9 +2341,13 @@ void CPlayerInterface::stacksErased(const StackLocation &location) void CPlayerInterface::stacksSwapped(const StackLocation &loc1, const StackLocation &loc2) { EVENT_HANDLER_CALLED_BY_CLIENT; - garrisonChanged(loc1.army); + + std::vector objects; + objects.push_back(loc1.army); if(loc2.army != loc1.army) - garrisonChanged(loc2.army); + objects.push_back(loc2.army); + + garrisonsChanged(objects); } void CPlayerInterface::newStackInserted(const StackLocation &location, const CStackInstance &stack) @@ -2342,11 +2360,13 @@ void CPlayerInterface::stacksRebalanced(const StackLocation &src, const StackLoc { EVENT_HANDLER_CALLED_BY_CLIENT; - garrisonChanged(src.army); - if(dst.army != src.army) - garrisonChanged(dst.army); + std::vector objects; + objects.push_back(src.army); + if(src.army != dst.army) + objects.push_back(dst.army); + + garrisonsChanged(objects); } -#undef UPDATE_IF void CPlayerInterface::artifactPut(const ArtifactLocation &al) { diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 834f1e739..59b34d841 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -210,6 +210,7 @@ public: //-------------// void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList onYes, CFunctionList onNo); + void garrisonsChanged(std::vector objs); void garrisonChanged(const CGObjectInstance * obj); void heroKilled(const CGHeroInstance* hero); void waitWhileDialog(bool unlockPim = true); @@ -223,6 +224,7 @@ public: void updateInfo(const CGObjectInstance * specific); void init(CCallback * CB); int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on + void showInfoDialog(const std::string &text, CComponent * component); void showInfoDialog(const std::string &text, const std::vector & components = std::vector(), int soundID = 0, bool delComps = false); void showYesNoDialog(const std::string &text, CFunctionList onYes, CFunctionList onNo, bool DelComps = false, const std::vector & components = std::vector()); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close void stopMovement(); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index cb2994940..8c2b63d6c 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -200,6 +200,14 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town): init(InfoAboutTown(town, true)); } +void CGarrisonSlot::setHighlight(bool on) +{ + if (on) + selectionImage->recActions |= UPDATE | SHOWALL; //show + else + selectionImage->recActions &= ~(UPDATE | SHOWALL); //hide +} + void CGarrisonSlot::hover (bool on) { ////Hoverable::hover(on); @@ -208,29 +216,29 @@ void CGarrisonSlot::hover (bool on) std::string temp; if(creature) { - if(owner->highlighted) + if(owner->getSelection()) { - if(owner->highlighted == this) + if(owner->getSelection() == this) { temp = CGI->generaltexth->tcommands[4]; //View %s boost::algorithm::replace_first(temp,"%s",creature->nameSing); } - else if (owner->highlighted->creature == creature) + else if (owner->getSelection()->creature == creature) { temp = CGI->generaltexth->tcommands[2]; //Combine %s armies boost::algorithm::replace_first(temp,"%s",creature->nameSing); } - else if (owner->highlighted->creature) + else if (owner->getSelection()->creature) { temp = CGI->generaltexth->tcommands[7]; //Exchange %s with %s - boost::algorithm::replace_first(temp,"%s",owner->highlighted->creature->nameSing); + boost::algorithm::replace_first(temp,"%s",owner->getSelection()->creature->nameSing); boost::algorithm::replace_first(temp,"%s",creature->nameSing); } else { - tlog2 << "Warning - shouldn't be - highlighted void slot "<highlighted<getSelection()<highlighted = NULL; + owner->selectSlot(nullptr); } } else @@ -252,12 +260,12 @@ void CGarrisonSlot::hover (bool on) } else { - if(owner->highlighted) + if(owner->getSelection()) { - const CArmedInstance *highl = owner->highlighted->getObj(); + const CArmedInstance *highl = owner->getSelection()->getObj(); if( highl->needsLastStack() //we are moving stack from hero's && highl->stacksCount() == 1 //it's only stack - && owner->highlighted->upg != upg //we're moving it to the other garrison + && owner->getSelection()->upg != upg //we're moving it to the other garrison ) { temp = CGI->generaltexth->tcommands[5]; //Cannot move last army to garrison @@ -265,7 +273,7 @@ void CGarrisonSlot::hover (bool on) else { temp = CGI->generaltexth->tcommands[6]; //Move %s - boost::algorithm::replace_first(temp,"%s",owner->highlighted->creature->nameSing); + boost::algorithm::replace_first(temp,"%s",owner->getSelection()->creature->nameSing); } } else @@ -281,12 +289,12 @@ void CGarrisonSlot::hover (bool on) } } -const CArmedInstance * CGarrisonSlot::getObj() +const CArmedInstance * CGarrisonSlot::getObj() const { return (!upg)?(owner->armedObjs[0]):(owner->armedObjs[1]); } -bool CGarrisonSlot::our() +bool CGarrisonSlot::our() const { return upg?(owner->owned[1]):(owner->owned[0]); } @@ -303,9 +311,9 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) if(down) { bool refr = false; - if(owner->highlighted) + if(owner->getSelection()) { - if(owner->highlighted == this) //view info + if(owner->getSelection() == this) //view info { UpgradeInfo pom; LOCPLINT->cb->getUpgradeInfo(getObj(), ID, pom); @@ -317,8 +325,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) if (canUpgrade) upgr = boost::bind(&CCallback::upgradeCreature, LOCPLINT->cb, getObj(), ID, pom.newID[0]); if (canDismiss) dism = boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID); - owner->highlighted = NULL; - owner->splitting = false; + owner->selectSlot(nullptr); + owner->setSplittingMode(false); for(size_t i = 0; isplitButtons.size(); i++) owner->splitButtons[i]->block(true); @@ -331,61 +339,61 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) else { // Only allow certain moves if troops aren't removable or not ours. - if ( ( owner->highlighted->our()//our creature is selected - || owner->highlighted->creature == creature )//or we are rebalancing army + if ( ( owner->getSelection()->our()//our creature is selected + || owner->getSelection()->creature == creature )//or we are rebalancing army && ( owner->removableUnits - || (upg == 0 && ( owner->highlighted->upg == 1 && !creature ) ) - || (upg == 1 && owner->highlighted->upg == 1 ) ) ) + || (upg == 0 && ( owner->getSelection()->upg == 1 && !creature ) ) + || (upg == 1 && owner->getSelection()->upg == 1 ) ) ) { //we want to split - if((owner->splitting || LOCPLINT->shiftPressed()) + if((owner->getSplittingMode() || LOCPLINT->shiftPressed()) && (!creature - || (creature == owner->highlighted->creature))) + || (creature == owner->getSelection()->creature))) { owner->p2 = ID; //store the second stack pos owner->pb = upg;//store the second stack owner (up or down army) - owner->splitting = false; + owner->setSplittingMode(false); int minLeft=0, minRight=0; - if(upg != owner->highlighted->upg) //not splitting within same army + if(upg != owner->getSelection()->upg) //not splitting within same army { - if(owner->highlighted->getObj()->stacksCount() == 1 //we're splitting away the last stack - && owner->highlighted->getObj()->needsLastStack() ) + if(owner->getSelection()->getObj()->stacksCount() == 1 //we're splitting away the last stack + && owner->getSelection()->getObj()->needsLastStack() ) { minLeft = 1; } if(getObj()->stacksCount() == 1 //destination army can't be emptied, unless we're rebalancing two stacks of same creature - && owner->highlighted->creature == creature + && owner->getSelection()->creature == creature && getObj()->needsLastStack() ) { minRight = 1; } } - GH.pushInt(new CSplitWindow(owner->highlighted->creature, boost::bind(&CGarrisonInt::splitStacks, owner, _1, _2), - minLeft, minRight, owner->highlighted->count, count)); + GH.pushInt(new CSplitWindow(owner->getSelection()->creature, boost::bind(&CGarrisonInt::splitStacks, owner, _1, _2), + minLeft, minRight, owner->getSelection()->myStack->count, myStack->count)); refr = true; } - else if(creature != owner->highlighted->creature) //swap + else if(creature != owner->getSelection()->creature) //swap { LOCPLINT->cb->swapCreatures( (!upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), - (!owner->highlighted->upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), - ID,owner->highlighted->ID); + (!owner->getSelection()->upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), + ID,owner->getSelection()->ID); } else //merge { LOCPLINT->cb->mergeStacks( - (!owner->highlighted->upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), + (!owner->getSelection()->upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), (!upg)?(owner->armedObjs[0]):(owner->armedObjs[1]), - owner->highlighted->ID,ID); + owner->getSelection()->ID,ID); } } else // Highlight { if(creature) - owner->highlighted = this; + owner->selectSlot(this); redraw(); refr = true; } @@ -417,7 +425,7 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) } if (!artSelected && creature) { - owner->highlighted = this; + owner->selectSlot(this); if(creature) { for(size_t i = 0; isplitButtons.size(); i++) @@ -431,6 +439,26 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState) } } +void CGarrisonSlot::update() +{ + myStack = getObj()->getStackPtr(ID); + creature = myStack ? myStack->type : NULL; + + if (creature) + { + creatureImage->recActions |= (UPDATE | SHOWALL); + creatureImage->setFrame(creature->iconIndex); + + stackCount->recActions |= (UPDATE | SHOWALL); + stackCount->setTxt(boost::lexical_cast(myStack->count)); + } + else + { + creatureImage->recActions &= ~(UPDATE | SHOWALL); + stackCount->recActions &= ~(UPDATE | SHOWALL); + } +} + CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg, const CStackInstance * Creature) { OBJ_CONSTRUCTION_CAPTURING_ALL; @@ -444,15 +472,15 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg ID = IID; myStack = Creature; creature = Creature ? Creature->type : NULL; - if (creature) - { - std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT"; - creatureImage = new CAnimImage(imgName, creature->iconIndex); - } - else - creatureImage = nullptr; - count = Creature ? Creature->count : 0; + std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT"; + + creatureImage = new CAnimImage(imgName, creature ? creature->iconIndex : 0); + if (!creature) + creatureImage->recActions &= ~(UPDATE | SHOWALL); + + selectionImage = new CAnimImage(imgName, 1); + selectionImage->recActions &= ~(UPDATE | SHOWALL); //hide it if(Owner->smallIcons) { @@ -464,29 +492,12 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg pos.w = 58; pos.h = 64; } -} -void CGarrisonSlot::showAll(SDL_Surface * to) -{ - std::map &imgs = (owner->smallIcons ? graphics->smallImgs : graphics->bigImgs); - if(creature) - { - creatureImage->showAll(to); - char buf[15]; - SDL_itoa(count,buf,10); - printTo(buf, pos.x+pos.w, pos.y+pos.h+1, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, Colors::WHITE, to); - - if((owner->highlighted==this) - || (owner->splitting && owner->highlighted->creature == creature)) - { - blitAt(imgs[-1],pos,to); - } - } - else//empty slot - { - if(owner->splitting && owner->highlighted->our()) - blitAt(imgs[-1],pos,to); - } + stackCount = new CLabel(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE); + if (!creature) + stackCount->recActions &= ~(UPDATE | SHOWALL); + else + stackCount->setTxt(boost::lexical_cast(myStack->count)); } void CGarrisonInt::addSplitBtn(CAdventureMapButton * button) @@ -530,46 +541,45 @@ void CGarrisonInt::createSlots() createSet (slotsDown, armedObjs[1], garOffset.x, garOffset.y, width+interx, 1); } -void CGarrisonInt::deleteSlots() -{ - for (int i=0; iblock(true); - deleteSlots(); - createSlots(); + + BOOST_FOREACH(CGarrisonSlot * slot, slotsUp) + slot->update(); + + BOOST_FOREACH(CGarrisonSlot * slot, slotsDown) + slot->update(); } void CGarrisonInt::splitClick() { - if(!highlighted) + if(!getSelection()) return; - splitting = !splitting; + setSplittingMode(!getSplittingMode()); redraw(); } void CGarrisonInt::splitStacks(int, int amountRight) { - LOCPLINT->cb->splitStack(armedObjs[highlighted->upg], armedObjs[pb], highlighted->ID, p2, amountRight); + LOCPLINT->cb->splitStack(armedObjs[getSelection()->upg], armedObjs[pb], getSelection()->ID, p2, amountRight); } CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, - SDL_Surface *pomsur, const Point& SurOffset, - const CArmedInstance *s1, const CArmedInstance *s2, - bool _removableUnits, bool smallImgs, bool _twoRows ) - : interx(inx), garOffset(garsOffset), highlighted(NULL), splitting(false), - smallIcons(smallImgs), removableUnits (_removableUnits), twoRows(_twoRows) + SDL_Surface *pomsur, const Point& SurOffset, + const CArmedInstance *s1, const CArmedInstance *s2, + bool _removableUnits, bool smallImgs, bool _twoRows ) : + highlighted(nullptr), + inSplittingMode(false), + interx(inx), + garOffset(garsOffset), + smallIcons(smallImgs), + removableUnits(_removableUnits), + twoRows(_twoRows) { setArmy(s1, false); setArmy(s2, true); @@ -581,12 +591,50 @@ CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, void CGarrisonInt::activate() { for(size_t i = 0; iisBlocked()) != !highlighted) - splitButtons[i]->block(!highlighted); + splitButtons[i]->block(getSelection() != nullptr); CIntObject::activate(); } +const CGarrisonSlot * CGarrisonInt::getSelection() +{ + return highlighted; +} + +void CGarrisonInt::selectSlot(CGarrisonSlot *slot) +{ + if (slot != highlighted) + { + if (highlighted) + highlighted->setHighlight(false); + + highlighted = slot; + + if (highlighted) + highlighted->setHighlight(true); + } +} + +void CGarrisonInt::setSplittingMode(bool on) +{ + assert(on == false || highlighted != nullptr); //can't be in splitting mode without selection + + if (inSplittingMode || on) + { + BOOST_FOREACH(CGarrisonSlot * slot, slotsUp) + slot->setHighlight(slot->creature == nullptr || slot->creature == getSelection()->creature); + + BOOST_FOREACH(CGarrisonSlot * slot, slotsDown) + slot->setHighlight(slot->creature == nullptr || slot->creature == getSelection()->creature); + inSplittingMode = on; + } +} + +bool CGarrisonInt::getSplittingMode() +{ + return inSplittingMode; +} + void CGarrisonInt::setArmy(const CArmedInstance *army, bool bottomGarrison) { owned[bottomGarrison] = army ? (army->tempOwner == LOCPLINT->playerID || army->tempOwner == 254) : false; //254 - neutral objects (pandora, banks) @@ -689,6 +737,11 @@ CInfoWindow * CInfoWindow::create(const std::string &text, int playerID /*= 1*/, return ret; } +std::string CInfoWindow::genText(std::string title, std::string description) +{ + return std::string("{") + title + "}" + "\n\n" + description; +} + void CInfoWindow::setDelComps(bool DelComps) { delComps = DelComps; @@ -5193,16 +5246,8 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState) { if(down) { - CInfoPopup *message = new CInfoPopup(); - message->free = true; - message->bitmap = CMessage::drawBoxTextBitmapSub - (LOCPLINT->playerID, - CGI->generaltexth->skillInfoTexts[ID][0], - graphics->abils82->ourImages[ID*3+3].bitmap, - CGI->generaltexth->skillName[ID]); - message->pos.x = screen->w/2 - message->bitmap->w/2; - message->pos.y = screen->h/2 - message->bitmap->h/2; - GH.pushInt(message); + CRClickPopup::createAndPush(CGI->generaltexth->skillInfoTexts[ID][0], + new CComponent(CComponent::secskill, ID, 0)); } } @@ -5813,6 +5858,14 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom GH.pushInt(rcpi); } +void CRClickPopup::createAndPush(const std::string &txt, CComponent * component) +{ + CInfoWindow::TCompsInfo intComps; + intComps.push_back(component); + + createAndPush(txt, intComps); +} + Point CInfoBoxPopup::toScreen(Point p) { vstd::abetween(p.x, adventureInt->terrain.pos.x + 100, adventureInt->terrain.pos.x + adventureInt->terrain.pos.w - 100); diff --git a/client/GUIClasses.h b/client/GUIClasses.h index abb28d7b8..16a502bad 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -105,6 +105,9 @@ public: static void showYesNoDialog( const std::string & text, const std::vector *components, const CFunctionList &onYes, const CFunctionList &onNo, bool DelComps = true, int player = 1); //use only before the game starts! (showYesNoDialog in LOCPLINT must be used then) static CInfoWindow *create(const std::string &text, int playerID = 1, const std::vector *components = NULL, bool DelComps = false); + + /// create text from title and description: {title}\n\n description + static std::string genText(std::string title, std::string description); }; /// component selection window @@ -130,6 +133,7 @@ public: static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific); static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo()); + static void createAndPush(const std::string &txt, CComponent * component); static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT); }; @@ -210,7 +214,7 @@ public: std::string getDescription(); std::string getSubtitle(); - CComponent(Etype Type, int Subtype, int Val, ESize imageSize=large);//c-tor + CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large);//c-tor CComponent(const Component &c); //c-tor void clickRight(tribool down, bool previousState); //call-in @@ -311,18 +315,20 @@ class CGarrisonSlot : public CIntObject CGarrisonInt *owner; const CStackInstance *myStack; //NULL if slot is empty const CCreature *creature; - int count; //number of creatures int upg; //0 - up garrison, 1 - down garrison - bool highlight; CAnimImage * creatureImage; + CAnimImage * selectionImage; // image for selection, not always visible + CLabel * stackCount; + + void setHighlight(bool on); public: virtual void hover (bool on); //call-in - const CArmedInstance * getObj(); - bool our(); + const CArmedInstance * getObj() const; + bool our() const; void clickRight(tribool down, bool previousState); void clickLeft(tribool down, bool previousState); - void showAll(SDL_Surface * to); + void update(); CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg=0, const CStackInstance * Creature=NULL); friend class CGarrisonInt; @@ -331,15 +337,23 @@ public: /// Class which manages slots of upper and lower garrison, splitting of units class CGarrisonInt :public CIntObject { + CGarrisonSlot *highlighted; //chosen slot. Should be changed only via selectSlot + bool inSplittingMode; + public: + void selectSlot(CGarrisonSlot * slot); //null = deselect + const CGarrisonSlot * getSelection(); + + void setSplittingMode(bool on); + bool getSplittingMode(); + int interx; //space between slots Point garOffset; //offset between garrisons (not used if only one hero) - CGarrisonSlot *highlighted; //chosen slot std::vector splitButtons; //may be empty if no buttons int p2, //TODO: comment me shiftPos;//1st slot of the second row, set shiftPoint for effect - bool splitting, pb, + bool pb, smallIcons, //true - 32x32 imgs, false - 58x64 removableUnits,//player can remove units from up twoRows,//slots will be placed in 2 rows @@ -358,7 +372,6 @@ public: void activate(); void createSlots(); - void deleteSlots(); void recreateSlots(); void splitClick(); //handles click on split button diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 6f6e42040..3d6c80296 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -129,7 +129,7 @@ void Graphics::initializeBattleGraphics() } Graphics::Graphics() { - CDefHandler *smi, *smi2; + CDefHandler *smi2; std::vector tasks; //preparing list of graphics to load tasks += boost::bind(&Graphics::loadFonts,this); @@ -140,7 +140,6 @@ Graphics::Graphics() tasks += boost::bind(&Graphics::loadErmuToPicture,this); tasks += GET_DEF_ESS(artDefs,"ARTIFACT.DEF"); tasks += GET_DEF_ESS(resources32,"RESOURCE.DEF"); - tasks += GET_DEF(smi,"CPRSMALL.DEF"); tasks += GET_DEF(smi2,"TWCRPORT.DEF"); tasks += GET_DEF_ESS(flags,"CREST58.DEF"); tasks += GET_DEF_ESS(abils82,"SECSK82.DEF"); @@ -155,13 +154,6 @@ Graphics::Graphics() CSDL_Ext::alphaTransform(heroMoveArrows->ourImages[y].bitmap); } - //handling 32x32px imgs - smi->notFreeImgs = true; - for (size_t i=0; iourImages.size(); ++i) - { - smallImgs[i-2] = smi->ourImages[i].bitmap; - } - delete smi; smi2->notFreeImgs = true; for (size_t i=0; iourImages.size(); ++i) { diff --git a/client/Graphics.h b/client/Graphics.h index 5f00acadd..10daea6e4 100644 --- a/client/Graphics.h +++ b/client/Graphics.h @@ -58,7 +58,6 @@ public: CDefEssential * getDef(const CGObjectInstance * obj); CDefEssential * getDef(const CGDefInfo * info); //creatures - std::map smallImgs; //creature ID -> small 32x32 img of creature; //ID=-2 is for blank (black) img; -1 for the border std::map bigImgs; //creature ID -> big 58x64 img of creature; //ID=-2 is for blank (black) img; -1 for the border //towns std::map ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type diff --git a/config/buildings.json b/config/buildings.json index 67e2d4e6d..4d9cdf1da 100644 --- a/config/buildings.json +++ b/config/buildings.json @@ -145,9 +145,8 @@ ["Angel", "Archangel"] ], "horde" : [ 2, -1 ], - "primaryResource" : 127, "mageGuild" : 4, - "warMachine" : 4, + "warMachine" : "Ballista", "buildings" : [ @@ -396,8 +395,8 @@ ], "horde" : [ 1, 4 ], "mageGuild" : 5, - "primaryResource" : 4, - "warMachine" : 6, + "primaryResource" : "crystal", + "warMachine" : "FirstAidTent", "buildings" : [ @@ -641,9 +640,9 @@ ["LesserTitan", "GreaterTitan"] ], "horde" : [ 1, -1 ], - "primaryResource" : 5, + "primaryResource" : "gems", "mageGuild" : 5, - "warMachine" : 5, + "warMachine" : "AmmoCart", "buildings" : [ @@ -886,8 +885,8 @@ ], "horde" : [ 0, 2 ], "mageGuild" : 5, - "primaryResource" : 1, - "warMachine" : 5, + "primaryResource" : "mercury", + "warMachine" : "Ballista", "buildings" : [ @@ -1136,8 +1135,7 @@ ], "horde" : [ 0, -1 ], "mageGuild" : 5, - "primaryResource" : 127, - "warMachine" : 6, + "warMachine" : "FirstAidTent", "buildings" : [ @@ -1380,8 +1378,8 @@ ], "horde" : [ 0, -1 ], "mageGuild" : 5, - "primaryResource" : 3, - "warMachine" : 4, + "primaryResource" : "sulfur", + "warMachine" : "Ballista", "buildings" : [ @@ -1622,8 +1620,7 @@ ], "horde" : [ 0, -1 ], "mageGuild" : 3, - "primaryResource" : 127, - "warMachine" : 5, + "warMachine" : "AmmoCart", "buildings" : [ @@ -1866,8 +1863,7 @@ ], "horde" : [ 0, -1 ], "mageGuild" : 3, - "primaryResource" : 127, - "warMachine" : 6, + "warMachine" : "FirstAidTent", "buildings" : [ @@ -2115,8 +2111,8 @@ ], "horde" : [ 0, -1 ], "mageGuild" : 5, - "primaryResource" : 1, - "warMachine" : 4, + "primaryResource" : "mercury", + "warMachine" : "Ballista", "buildings" : [ diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 3b8bf8ba9..d0808648a 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -396,9 +396,19 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source) void CTownHandler::loadTown(CTown &town, const JsonNode & source) { + auto resIter = boost::find(GameConstants::RESOURCE_NAMES, source["primaryResource"].String()); + if (resIter == boost::end(GameConstants::RESOURCE_NAMES)) + town.primaryRes = 127; //Wood + Ore + else + town.primaryRes = resIter - boost::begin(GameConstants::RESOURCE_NAMES); + + VLC->modh->identifiers.requestIdentifier(std::string("creature." + source["warMachine"].String()), + [&town](si32 creature) + { + town.warMachine = CArtHandler::convertMachineID(creature, true); + }); + town.mageLevel = source["mageGuild"].Float(); - town.primaryRes = source["primaryResource"].Float(); - town.warMachine = source["warMachine"].Float(); town.names = source["names"].convertTo >(); // Horde building creature level diff --git a/lib/Map/CMapService.cpp b/lib/Map/CMapService.cpp index 91f3d1af7..38159dbcd 100644 --- a/lib/Map/CMapService.cpp +++ b/lib/Map/CMapService.cpp @@ -2293,7 +2293,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID) { if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY) { - if(c == (c | static_cast(std::pow(2., yy)))) + if(c != (c | static_cast(std::pow(2., yy)))) { nt->obligatorySpells.push_back((pos - ist) * 8 + yy); } @@ -2310,7 +2310,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID) { if((pos - ist) * 8 + yy < GameConstants::SPELLS_QUANTITY) { - if(c == (c | static_cast(std::pow(2., yy)))) + if(c != (c | static_cast(std::pow(2., yy)))) { nt->possibleSpells.push_back((pos - ist) * 8 + yy); }