diff --git a/client/CAdvmapInterface.cpp b/client/CAdvmapInterface.cpp index 29fa24011..16b52e89c 100644 --- a/client/CAdvmapInterface.cpp +++ b/client/CAdvmapInterface.cpp @@ -1804,17 +1804,20 @@ void CAdvMapInt::tileLClicked(const int3 &mp) if(currentHero == topBlocking) //clicked selected hero { LOCPLINT->openHeroWindow(currentHero); + return; } else if(topBlocking && (topBlocking->ID == HEROI_TYPE || topBlocking->ID == TOWNI_TYPE) //clicked our town or hero && pn->turns == 255 && topBlocking->tempOwner == LOCPLINT->playerID) //at inaccessible tile { select(static_cast(topBlocking), false); + return; } else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise { if (terrain.currentPath && terrain.currentPath->endPos() == mp)//we'll be moving { LOCPLINT->moveHero(currentHero,*terrain.currentPath); + return; } else if(mp.z == currentHero->pos.z) //remove old path and find a new one if we clicked on the map level on which hero is present { @@ -1822,6 +1825,8 @@ void CAdvMapInt::tileLClicked(const int3 &mp) terrain.currentPath = &path; if(!LOCPLINT->cb->getPath2(mp, path)) //try getting path, erase if failed LOCPLINT->eraseCurrentPathOf(currentHero); + else + return; } } } //end of hero is selected "case" @@ -1829,6 +1834,11 @@ void CAdvMapInt::tileLClicked(const int3 &mp) { throw std::string("Nothing is selected..."); } + + if(const IShipyard *shipyard = ourInaccessibleShipyard(topBlocking)) + { + LOCPLINT->showShipyardDialogOrProblemPopup(shipyard); + } } void CAdvMapInt::tileHovered(const int3 &tile) @@ -2006,6 +2016,11 @@ void CAdvMapInt::tileHovered(const int3 &tile) CGI->curh->changeGraphic(0, 0); } } + + if(const IShipyard *shipyard = ourInaccessibleShipyard(objAtTile)) + { + CGI->curh->changeGraphic(0, 6); + } } void CAdvMapInt::tileRClicked(const int3 &mp) @@ -2075,6 +2090,16 @@ const CGTownInstance * CAdvMapInt::curTown() const return NULL; } +const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *obj) const +{ + const IShipyard *ret = IShipyard::castFrom(obj); + + if(!ret || obj->tempOwner != player || CGI->curh->mode || (CGI->curh->number != 6 && CGI->curh->number != 0)) + return NULL; + + return ret; +} + CAdventureOptions::CAdventureOptions() { OBJ_CONSTRUCTION_CAPTURING_ALL; diff --git a/client/CAdvmapInterface.h b/client/CAdvmapInterface.h index 0ea1b13e6..3e69a00e3 100644 --- a/client/CAdvmapInterface.h +++ b/client/CAdvmapInterface.h @@ -14,6 +14,8 @@ class CGHeroInstance; class CGTownInstance; class CHeroWindow; class CSpell; +class IShipyard; + /*****************************/ /* @@ -218,6 +220,7 @@ public: void leaveCastingMode(bool cast = false, int3 dest = int3(-1, -1, -1)); const CGHeroInstance * curHero() const; const CGTownInstance * curTown() const; + const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or NULL else }; extern CAdvMapInt *adventureInt; diff --git a/client/CHeroWindow.cpp b/client/CHeroWindow.cpp index d8a83805d..f5b792cc9 100644 --- a/client/CHeroWindow.cpp +++ b/client/CHeroWindow.cpp @@ -40,6 +40,24 @@ extern SDL_Surface * screen; using namespace boost::assign; + +void CHeroSwitcher::clickLeft(tribool down, bool previousState) +{ + if(!down) + { + owner->deactivate(); + const CGHeroInstance * buf = LOCPLINT->getWHero(id); + owner->setHero(buf); + owner->redrawCurBack(); + owner->activate(); + } +} + +CHeroSwitcher::CHeroSwitcher() +{ + used = LCLICK; +} + CHeroWindow::CHeroWindow(int playerColor): player(playerColor) { @@ -76,7 +94,7 @@ CHeroWindow::CHeroWindow(int playerColor): for(int g=0; g<8; ++g) { //heroList.push_back(new AdventureMapButton(std::string(), std::string(), &CHeroWindow::switchHero, 677, 95+g*54, "hsbtns5.def", this)); - heroListMi.push_back(new LClickableAreaHero()); + heroListMi.push_back(new CHeroSwitcher()); heroListMi[g]->pos = genRect(32, 48, pos.x+677, pos.y + 95+g*54); heroListMi[g]->owner = this; heroListMi[g]->id = g; @@ -94,7 +112,7 @@ CHeroWindow::CHeroWindow(int playerColor): primSkillAreas[v]->pos = genRect(64, 42, pos.x+95 + 70*v, pos.y + 117); primSkillAreas[v]->text = CGI->generaltexth->arraytxt[2+v]; primSkillAreas[v]->type = v; - primSkillAreas[v]->bonus = -1; // to be initilized when hero is being set + primSkillAreas[v]->bonusValue = -1; // to be initilized when hero is being set primSkillAreas[v]->baseType = 0; sprintf(bufor, CGI->generaltexth->heroscrn[1].c_str(), CGI->generaltexth->primarySkillNames[v].c_str()); primSkillAreas[v]->hoverText = std::string(bufor); @@ -109,10 +127,10 @@ CHeroWindow::CHeroWindow(int playerColor): expArea->pos = genRect(42, 136, pos.x+83, pos.y + 236); expArea->hoverText = CGI->generaltexth->heroscrn[9]; - morale = new MoraleLuckBox(); + morale = new MoraleLuckBox(true); morale->pos = genRect(45,53,pos.x+240,pos.y+187); - luck = new MoraleLuckBox(); + luck = new MoraleLuckBox(false); luck->pos = genRect(45,53,pos.x+298,pos.y+187); spellPointsArea = new LRClickableAreaWText(); @@ -230,7 +248,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero) //primary skills support for(size_t g=0; gbonus = hero->getPrimSkillLevel(g); + primSkillAreas[g]->bonusValue = hero->getPrimSkillLevel(g); } //secondary skills support @@ -240,7 +258,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero) level = hero->secSkills[g].second; secSkillAreas[g]->type = skill; - secSkillAreas[g]->bonus = level; + secSkillAreas[g]->bonusValue = level; secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1]; sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->generaltexth->levels[level-1].c_str(), CGI->generaltexth->skillName[skill].c_str()); @@ -289,8 +307,8 @@ void CHeroWindow::setHero(const CGHeroInstance *hero) formations->select(hero->formation,true); formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb, hero, _1); - morale->set(true, hero); - luck->set(false, hero); + morale->set(hero); + luck->set(hero); //restoring pos pos.x += 65; diff --git a/client/CHeroWindow.h b/client/CHeroWindow.h index 70709a13d..f31bc88b9 100644 --- a/client/CHeroWindow.h +++ b/client/CHeroWindow.h @@ -25,7 +25,15 @@ class LRClickableAreaWText; class LRClickableAreaWTextComp; class CArtifactsOfHero; +class CHeroSwitcher : public CIntObject +{ +public: + int id; + CHeroWindow * owner; + virtual void clickLeft(tribool down, bool previousState); + CHeroSwitcher(); +}; class CHeroWindow: public CWindowWithGarrison { @@ -37,7 +45,7 @@ class CHeroWindow: public CWindowWithGarrison //buttons //AdventureMapButton * gar4button; //splitting - std::vector heroListMi; //new better list of heroes + std::vector heroListMi; //new better list of heroes CArtifactsOfHero * artifs; diff --git a/client/CKingdomInterface.cpp b/client/CKingdomInterface.cpp index 72866a894..e8e9efe46 100644 --- a/client/CKingdomInterface.cpp +++ b/client/CKingdomInterface.cpp @@ -747,10 +747,10 @@ CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner) experience->pos = genRect(33, 49, pos.x+322, pos.y+5); experience->hoverText = CGI->generaltexth->heroscrn[9]; - morale = new MoraleLuckBox(); + morale = new MoraleLuckBox(true); morale->pos = genRect(20,32,pos.x+221,pos.y+52); - luck = new MoraleLuckBox(); + luck = new MoraleLuckBox(false); luck->pos = genRect(20,32,pos.x+221,pos.y+28); spellPoints = new LRClickableAreaWText(); @@ -842,7 +842,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero) //primary skills for(size_t g=0; gbonus = hero->getPrimSkillLevel(g); + primarySkills[g]->bonusValue = hero->getPrimSkillLevel(g); //secondary skills for(size_t g=0; gsecSkills.size()); ++g) @@ -850,7 +850,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero) int skill = hero->secSkills[g].first, level = hero->secSkills[g].second; secondarySkills[g]->type = skill; - secondarySkills[g]->bonus = level; + secondarySkills[g]->bonusValue = level; secondarySkills[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1]; sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->generaltexth->levels[level-1].c_str(), CGI->generaltexth->skillName[skill].c_str()); secondarySkills[g]->hoverText = std::string(bufor); @@ -866,8 +866,8 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero) spellPoints->text = std::string(bufor); //setting morale and luck - morale->set(true,hero); - luck->set(false,hero); + morale->set(hero); + luck->set(hero); } void CKingdomInterface::CHeroItem::scrollArts(int move) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 3e2430874..496b7c9b6 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2001,4 +2001,16 @@ void CPlayerInterface::showTavernWindow(const CGObjectInstance *townOrTavern) { CTavernWindow *tv = new CTavernWindow(townOrTavern); GH.pushInt(tv); +} + +void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj) +{ + if(obj->state()) + { + MetaString txt; + obj->getProblemText(txt); + showInfoDialog(txt.toString()); + } + else + showShipyardDialog(obj); } \ No newline at end of file diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index e6eda6da9..d486840cd 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -227,6 +227,7 @@ public: CGPath *getAndVerifyPath( const CGHeroInstance * h ); void acceptTurn(); //used during hot seat after your turn message is close void tryDiggging(const CGHeroInstance *h); + void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard; CPlayerInterface(int Player, int serial);//c-tor ~CPlayerInterface();//d-tor diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index cbb030c37..6baa22a51 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -2329,6 +2329,16 @@ void CCreInfoWindow::init(const CCreature *cre, const CStackInstance *stack, int printLine(4, CGI->generaltexth->allTexts[388], cre->valOfBonuses(Bonus::STACK_HEALTH), finalNode->valOfBonuses(Bonus::STACK_HEALTH)); printLine(6, CGI->generaltexth->zelp[441].first, cre->valOfBonuses(Bonus::STACKS_SPEED), finalNode->valOfBonuses(Bonus::STACKS_SPEED)); + + //setting morale + morale = new MoraleLuckBox(true); + morale->pos = genRect(42, 42, pos.x + 24, pos.y + 189); + morale->set(stack); + //setting luck + luck = new MoraleLuckBox(false); + luck->pos = genRect(42, 42, pos.x + 77, pos.y + 189); + luck->set(stack); + //luck and morale int luck = 3, morale = 3; if(stack) @@ -4156,109 +4166,43 @@ void HoverableArea::hover (bool on) GH.statusbar->clear(); } -void HoverableArea::activate() +HoverableArea::HoverableArea() { - activateHover(); + used |= HOVER; } -void HoverableArea::deactivate() +HoverableArea::~HoverableArea() { - deactivateHover(); -} - -void LClickableArea::activate() -{ - activateLClick(); -} -void LClickableArea::deactivate() -{ - deactivateLClick(); -} -void LClickableArea::clickLeft(tribool down, bool previousState) -{ - //if(!down) - //{ - // LOCPLINT->showInfoDialog("TEST TEST AAA", std::vector()); - //} -} - -void RClickableArea::activate() -{ - activateRClick(); -} -void RClickableArea::deactivate() -{ - deactivateRClick(); -} -void RClickableArea::clickRight(tribool down, bool previousState) -{ - //if(!down) - //{ - // LOCPLINT->showInfoDialog("TEST TEST AAA", std::vector()); - //} } void LRClickableAreaWText::clickLeft(tribool down, bool previousState) { if(!down && previousState) { - LOCPLINT->showInfoDialog(text, std::vector(), soundBase::sound_todo); + LOCPLINT->showInfoDialog(text); } - //ClickableL::clickLeft(down); } void LRClickableAreaWText::clickRight(tribool down, bool previousState) { adventureInt->handleRightClick(text, down); } -void LRClickableAreaWText::activate() + +LRClickableAreaWText::LRClickableAreaWText() { - LClickableArea::activate(); - RClickableArea::activate(); - activateHover(); -} -void LRClickableAreaWText::deactivate() -{ - LClickableArea::deactivate(); - RClickableArea::deactivate(); - deactivateHover(); + used = LCLICK | RCLICK | HOVER; } -void LClickableAreaHero::clickLeft(tribool down, bool previousState) +LRClickableAreaWText::~LRClickableAreaWText() { - if(!down) - { - owner->deactivate(); - const CGHeroInstance * buf = LOCPLINT->getWHero(id); - owner->setHero(buf); - owner->redrawCurBack(); - owner->activate(); - } } void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState) { if((!down) && previousState) { - std::vector comp(1, new SComponent(SComponent::Etype(baseType), type, bonus)); - LOCPLINT->showInfoDialog(text, comp, soundBase::sound_todo); + std::vector comp(1, new SComponent(SComponent::Etype(baseType), type, bonusValue)); + LOCPLINT->showInfoDialog(text, comp); } - //ClickableL::clickLeft(down); -} -void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState) -{ - adventureInt->handleRightClick(text, down); -} -void LRClickableAreaWTextComp::activate() -{ - LClickableArea::activate(); - RClickableArea::activate(); - activateHover(); -} -void LRClickableAreaWTextComp::deactivate() -{ - LClickableArea::deactivate(); - RClickableArea::deactivate(); - deactivateHover(); } void LRClickableAreaOpenHero::clickLeft(tribool down, bool previousState) @@ -4829,7 +4773,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) primSkillAreas[g]->pos = genRect(32, 140, pos.x+329, pos.y + 19 + 36 * g); primSkillAreas[g]->text = CGI->generaltexth->arraytxt[2+g]; primSkillAreas[g]->type = g; - primSkillAreas[g]->bonus = -1; + primSkillAreas[g]->bonusValue = -1; primSkillAreas[g]->baseType = 0; sprintf(bufor, CGI->generaltexth->heroscrn[1].c_str(), CGI->generaltexth->primarySkillNames[g].c_str()); primSkillAreas[g]->hoverText = std::string(bufor); @@ -4848,7 +4792,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) secSkillAreas[b][g]->baseType = 1; secSkillAreas[b][g]->type = skill; - secSkillAreas[b][g]->bonus = level; + secSkillAreas[b][g]->bonusValue = level; secSkillAreas[b][g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1]; sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->generaltexth->levels[level - 1].c_str(), CGI->generaltexth->skillName[skill].c_str()); @@ -4881,13 +4825,13 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL) spellPoints[b]->text = std::string(bufor); //setting morale - morale[b] = new MoraleLuckBox(); + morale[b] = new MoraleLuckBox(true); morale[b]->pos = genRect(32, 32, pos.x + 177 + 490*b, pos.y + 45); - morale[b]->set(true,heroInst[b]); + morale[b]->set(heroInst[b]); //setting luck - luck[b] = new MoraleLuckBox(); + luck[b] = new MoraleLuckBox(false); luck[b]->pos = genRect(32, 32, pos.x + 213 + 490*b, pos.y + 45); - luck[b]->set(false,heroInst[b]); + luck[b]->set(heroInst[b]); } //buttons @@ -5457,50 +5401,47 @@ CThievesGuildWindow::~CThievesGuildWindow() // delete resdatabar; } - - - - - -void MoraleLuckBox::set(bool morale, const CGHeroInstance *hero) +void MoraleLuckBox::set(const CBonusSystemNode *hero) { - int mrlv = -9, mrlt = -9; - TModDescr mrl; + const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:} + const int noneTxtId[] = {77, 108}; //I don't know why we have separate "none" texts for luck and morale... + 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. + const int componentType[] = {SComponent::luck, SComponent::morale}; + const int hoverTextBase[] = {7, 4}; + const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE}; + int (CBonusSystemNode::*getValue[])() const = {&CBonusSystemNode::LuckVal, &CBonusSystemNode::MoraleVal}; - if(morale) - { - //setting morale - hero->getModifiersWDescr(mrl, Bonus::MORALE); - mrlv = hero->MoraleVal(); - mrlt = (mrlv>0)-(mrlv<0); //signum: -1 - bad morale, 0 - neutral, 1 - good - hoverText = CGI->generaltexth->heroscrn[4 - mrlt]; - baseType = SComponent::morale; - bonus = mrlv; - text = CGI->generaltexth->arraytxt[88]; - boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[86-mrlt]); - if (!mrl.size()) - text += CGI->generaltexth->arraytxt[108]; - else - for(int it=0; it < mrl.size(); it++) - text += "\n" + mrl[it].second; - } + int mrlt = -9; + TModDescr mrl; + hero->getModifiersWDescr(mrl, bonusType[morale]); + bonusValue = (hero->*getValue[morale])(); + mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good + hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt]; + baseType = componentType[morale]; + text = CGI->generaltexth->arraytxt[textId[morale]]; + boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[neutralDescr[morale]-mrlt]); + if (!mrl.size()) + text += CGI->generaltexth->arraytxt[noneTxtId[morale]]; else - { - //setting luck - hero->getModifiersWDescr(mrl, Bonus::LUCK); - mrlv = hero->LuckVal(); - mrlt = (mrlv>0)-(mrlv<0); //signum: -1 - bad luck, 0 - neutral, 1 - good - hoverText = CGI->generaltexth->heroscrn[7 - mrlt]; - baseType = SComponent::luck; - bonus = mrlv; - text = CGI->generaltexth->arraytxt[62]; - boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[60-mrlt]); - if (!mrl.size()) - text += CGI->generaltexth->arraytxt[77]; - else - for(int it=0; it < mrl.size(); it++) - text += "\n" + mrl[it].second; - } + for(int it=0; it < mrl.size(); it++) + text += "\n" + mrl[it].second; +} + +void MoraleLuckBox::showAll(SDL_Surface * to) +{ + CDefEssential *def = morale ? graphics->morale42 : graphics->luck42; + blitAt(def->ourImages[bonusValue].bitmap, pos, to); +} + +MoraleLuckBox::MoraleLuckBox(bool Morale) + :morale(Morale) +{ + bonusValue = 0; +} + +MoraleLuckBox::~MoraleLuckBox() +{ + } void CLabel::showAll(SDL_Surface * to) @@ -5571,6 +5512,8 @@ void CTextBox::showAll(SDL_Surface * to) for (int i = 0; i < howManyLinesToPrint; i++) { const std::string &line = lines[i + firstLineToPrint]; + if(!line.size()) continue; + int x = pos.x; if(alignment == CENTER) { @@ -5579,7 +5522,10 @@ void CTextBox::showAll(SDL_Surface * to) x -= slider->pos.w / 2 + 5; } - printAt(line, x, base_y + i*dy, font, color, to); + if(line.front() == '{' && line.back() == '}') + printAt(line, x, base_y + i*dy, font, tytulowy, to); + else + printAt(line, x, base_y + i*dy, font, color, to); } } diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 04f275e58..1ae94fba6 100644 --- a/client/GUIClasses.h +++ b/client/GUIClasses.h @@ -714,62 +714,43 @@ class HoverableArea: public virtual CIntObject { public: std::string hoverText; + virtual void hover (bool on); - virtual void activate(); - virtual void deactivate(); + + HoverableArea(); + virtual ~HoverableArea(); }; -class LClickableArea: public virtual CIntObject -{ -public: - virtual void clickLeft(tribool down, bool previousState); - virtual void activate(); - virtual void deactivate(); -}; - -class RClickableArea: public virtual CIntObject -{ -public: - virtual void clickRight(tribool down, bool previousState); - virtual void activate(); - virtual void deactivate(); -}; - -class LClickableAreaHero : public LClickableArea -{ -public: - int id; - CHeroWindow * owner; - virtual void clickLeft(tribool down, bool previousState); -}; - -class LRClickableAreaWText: public LClickableArea, public RClickableArea, public HoverableArea +class LRClickableAreaWText: public HoverableArea { public: std::string text; - virtual void activate(); - virtual void deactivate(); + + LRClickableAreaWText(); + virtual ~LRClickableAreaWText(); + virtual void clickLeft(tribool down, bool previousState); virtual void clickRight(tribool down, bool previousState); }; -class LRClickableAreaWTextComp: public LClickableArea, public RClickableArea, public HoverableArea +class LRClickableAreaWTextComp: public LRClickableAreaWText { public: - std::string text; int baseType; - int bonus, type; - virtual void activate(); - virtual void deactivate(); + int bonusValue, type; virtual void clickLeft(tribool down, bool previousState); - virtual void clickRight(tribool down, bool previousState); }; class MoraleLuckBox : public LRClickableAreaWTextComp { public: + bool morale; //true if morale, false if luck - void set(bool morale, const CGHeroInstance *hero); + void set(const CBonusSystemNode*hero); + void showAll(SDL_Surface * to); + + MoraleLuckBox(bool Morale); + ~MoraleLuckBox(); }; class LRClickableAreaOpenHero: public LRClickableAreaWTextComp @@ -803,7 +784,7 @@ public: const CCreature *c; //related creature std::vector upgResCost; //cost of upgrade (if not possible then empty) - //MoraleLuckBox *luck, *morale; + MoraleLuckBox *luck, *morale; AdventureMapButton *dismiss, *upgrade, *ok; CCreInfoWindow(const CStackInstance &st, int Type = 0, boost::function Upg = 0, boost::function Dsm = 0, UpgradeInfo *ui = NULL); //c-tor diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 41e47482d..defbb779c 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -5901,7 +5901,7 @@ int3 IBoatGenerator::bestLocation() const { if (tile = IObjectInterface::cb->getTile(o->pos + offsets[i])) //tile is in the map { - if (tile->tertype == TerrainTile::water) //and is water + if (tile->tertype == TerrainTile::water && (!tile->blocked || tile->blockingObjects.front()->ID == 8)) //and is water and is not blocked or is blocked by boat return o->pos + offsets[i]; } } @@ -5913,7 +5913,7 @@ int IBoatGenerator::state() const int3 tile = bestLocation(); TerrainTile *t = IObjectInterface::cb->getTile(tile); if(!t) - return 3; //no water + return 2; //no available water else if(!t->blockingObjects.size()) return 0; //OK else if(t->blockingObjects.front()->ID == 8) @@ -5934,6 +5934,28 @@ IBoatGenerator::IBoatGenerator(const CGObjectInstance *O) { } +void IBoatGenerator::getProblemText(MetaString &out, const CGHeroInstance *visitor) const +{ + switch(state()) + { + case 1: + out.addTxt(MetaString::GENERAL_TXT, 51); + break; + case 2: + if(visitor) + { + out.addTxt(MetaString::GENERAL_TXT, 134); + out.addReplacement(visitor->name); + } + else + out.addTxt(MetaString::ADVOB_TXT, 189); + break; + case 3: + tlog1 << "Shipyard without water!!! " << o->pos << "\t" << o->id << std::endl; + return; + } +} + void IShipyard::getBoatCost( std::vector &cost ) const { cost.resize(RESOURCE_QUANTITY); @@ -5948,6 +5970,9 @@ IShipyard::IShipyard(const CGObjectInstance *O) IShipyard * IShipyard::castFrom( CGObjectInstance *obj ) { + if(!obj) + return NULL; + if(obj->ID == TOWNI_TYPE) { return static_cast(obj); @@ -5958,7 +5983,7 @@ IShipyard * IShipyard::castFrom( CGObjectInstance *obj ) } else { - tlog1 << "Cannot cast to IShipyard object with ID " << obj->ID << std::endl; + //tlog1 << "Cannot cast to IShipyard object with ID " << obj->ID << std::endl; return NULL; } } @@ -5975,8 +6000,12 @@ CGShipyard::CGShipyard() void CGShipyard::getOutOffsets( std::vector &offsets ) const { - offsets += int3(1,0,0), int3(-3,0,0), int3(-3,1,0), int3(-2,1,0), int3(1,1,0), int3(1,-1,0), int3(-3,-1,0), - int3(-2,-1,0), int3(0,-1,0), int3(-1,-1,0), int3(0,1,0), int3(-1,1,0); + // H J L K I + // A x S x B + // C E G F D + offsets += int3(-3,0,0), int3(1,0,0), //AB + int3(-3,1,0), int3(1,1,0), int3(-2,1,0), int3(0,1,0), int3(-1,1,0), //CDEFG + int3(-3,-1,0), int3(1,-1,0), int3(-2,-1,0), int3(0,-1,0), int3(-1,-1,0); //HIJKL } void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const @@ -5989,19 +6018,7 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const { InfoWindow iw; iw.player = tempOwner; - switch(s) - { - case 1: - iw.text.addTxt(MetaString::GENERAL_TXT, 51); - break; - case 2: - iw.text.addTxt(MetaString::ADVOB_TXT, 189); - break; - case 3: - tlog1 << "Shipyard without water!!! " << pos << "\t" << id << std::endl; - return; - } - + getProblemText(iw.text, h); cb->showInfoDialog(&iw); } else diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index 4a9664c01..89973dffa 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -25,6 +25,7 @@ * */ +struct MetaString; class BattleInfo; class IGameCallback; struct BattleResult; @@ -129,6 +130,7 @@ public: virtual void getOutOffsets(std::vector &offsets) const =0; //offsets to obj pos when we boat can be placed int3 bestLocation() const; //returns location when the boat should be placed int state() const; //0 - can buid, 1 - there is already a boat at dest tile, 2 - dest tile is blocked, 3 - no water + void getProblemText(MetaString &out, const CGHeroInstance *visitor = NULL) const; }; class DLL_EXPORT IShipyard : public IBoatGenerator diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 12bd69fb0..a0b283a83 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -276,6 +276,13 @@ DLL_EXPORT void MetaString::toString(std::string &dst) const } } +DLL_EXPORT std::string MetaString::toString() const +{ + std::string ret; + toString(ret); + return ret; +} + DLL_EXPORT std::string MetaString::buildList () const ///used to handle loot from creature bank { diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 6c21134f8..6f4fe4ac3 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -7,6 +7,7 @@ #include "../hch/CCreatureHandler.h" #include #include "CCreatureSet.h" +#include #define FOREACH_CONST_PARENT(pname, source) TCNodes parents; getParents(parents, source); BOOST_FOREACH(const CBonusSystemNode *pname, parents) #define FOREACH_PARENT(pname, source) TNodes parents; getParents(parents, source); BOOST_FOREACH(CBonusSystemNode *pname, parents) @@ -337,12 +338,41 @@ std::string Bonus::Description() const return str.str(); } +Bonus::Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype/*=-1*/) + : duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), description(Desc) +{ + additionalInfo = -1; + turnsRemain = 0; + valType = ADDITIVE_VALUE; + effectRange = NO_LIMIT; + limiter = NULL; + boost::algorithm::trim(description); +} + +Bonus::Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype/*=-1*/, ui8 ValType /*= ADDITIVE_VALUE*/) + : duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), valType(ValType) +{ + additionalInfo = -1; + turnsRemain = 0; + effectRange = NO_LIMIT; + limiter = NULL; +} + +Bonus::Bonus() +{ + subtype = -1; + additionalInfo = -1; + turnsRemain = 0; + valType = ADDITIVE_VALUE; + effectRange = NO_LIMIT; + limiter = NULL; +} + CSelector DLL_EXPORT operator&&(const CSelector &first, const CSelector &second) { return CSelectorsConjunction(first, second); } - namespace Selector { DLL_EXPORT CSelectFieldEqual type(&Bonus::type, 0); diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 3ece98ea2..128ea8a71 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -227,32 +227,9 @@ struct DLL_EXPORT Bonus std::string description; - Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype=-1) - :duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), description(Desc) - { - additionalInfo = -1; - turnsRemain = 0; - valType = ADDITIVE_VALUE; - effectRange = NO_LIMIT; - limiter = NULL; - } - Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1, ui8 ValType = ADDITIVE_VALUE) - :duration(Dur), type(Type), subtype(Subtype), source(Src), val(Val), id(ID), valType(ValType) - { - additionalInfo = -1; - turnsRemain = 0; - effectRange = NO_LIMIT; - limiter = NULL; - } - Bonus() - { - subtype = -1; - additionalInfo = -1; - turnsRemain = 0; - valType = ADDITIVE_VALUE; - effectRange = NO_LIMIT; - limiter = NULL; - } + Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype=-1); + Bonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1, ui8 ValType = ADDITIVE_VALUE); + Bonus(); // //comparison // bool operator==(const HeroBonus &other) diff --git a/lib/NetPacks.h b/lib/NetPacks.h index fca2d909d..1e6353eda 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -136,6 +136,7 @@ public: numbers.clear(); } DLL_EXPORT void toString(std::string &dst) const; + DLL_EXPORT std::string toString() const; void getLocalString(const std::pair &txt, std::string &dst) const; MetaString()