From b28da1a5d37146c7538acd5735fde61b3090bfb2 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sun, 8 Jul 2012 16:36:20 +0000 Subject: [PATCH] - Quest log minimap now has clickable icons - Border guard & border gate inherit Quest interface - Lots of tweaks --- client/AdventureMapClasses.cpp | 26 ++++++---- client/AdventureMapClasses.h | 6 ++- client/CQuestLog.cpp | 89 +++++++++++++++++++++++++++++++--- client/CQuestLog.h | 22 +++++++-- lib/CGameState.h | 5 ++ lib/CGeneralTextHandler.cpp | 9 ++++ lib/CGeneralTextHandler.h | 1 + lib/CObjectHandler.cpp | 41 ++++++++++++++-- lib/CObjectHandler.h | 9 +++- lib/GameConstants.h | 1 + lib/NetPacksLib.cpp | 7 ++- lib/map.cpp | 2 + 12 files changed, 189 insertions(+), 29 deletions(-) diff --git a/client/AdventureMapClasses.cpp b/client/AdventureMapClasses.cpp index 3f12d3a18..29dbf8340 100644 --- a/client/AdventureMapClasses.cpp +++ b/client/AdventureMapClasses.cpp @@ -376,21 +376,24 @@ const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos) else return parent->colors.find(tile->tertype)->second.first; } - -void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY) +void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY) { - //method is mostly copy-pasted from drawScaled() int3 mapSizes = LOCPLINT->cb->getMapSize(); double stepX = double(pos.w) / mapSizes.x; double stepY = double(pos.h) / mapSizes.y; + x = toX + stepX * tile.x; + y = toY + stepY * tile.y; +} + +void CMinimapInstance::blitTileWithColor(const SDL_Color &color, const int3 &tile, SDL_Surface *to, int toX, int toY) +{ //coordinates of rectangle on minimap representing this tile // begin - first to blit, end - first NOT to blit - int xBegin = toX + stepX * tile.x; - int yBegin = toY + stepY * tile.y; - int xEnd = toX + stepX * (tile.x + 1); - int yEnd = toY + stepY * (tile.y + 1); + int xBegin, yBegin, xEnd, yEnd; + tileToPixels (tile, xBegin, yBegin, toX, toY); + tileToPixels (int3 (tile.x + 1, tile.y + 1, tile.z), xEnd, yEnd, toX, toY); for (int y=yBegin; ymotion.x - pos.x) / pos.w; @@ -524,8 +527,13 @@ void CMinimap::moveAdvMapSelection() int3 mapSizes = LOCPLINT->cb->getMapSize(); - int3 newLocation (mapSizes.x * dx, mapSizes.y * dy, level); + int3 tile (mapSizes.x * dx, mapSizes.y * dy, level); + return tile; +} +void CMinimap::moveAdvMapSelection() +{ + int3 newLocation = translateMousePosition(); adventureInt->centerOn(newLocation); redraw(); diff --git a/client/AdventureMapClasses.h b/client/AdventureMapClasses.h index 3f455d02c..320c39fe0 100644 --- a/client/AdventureMapClasses.h +++ b/client/AdventureMapClasses.h @@ -195,6 +195,7 @@ public: ~CMinimapInstance(); void showAll(SDL_Surface *to); + void tileToPixels (const int3 &tile, int &x, int &y,int toX = 0, int toY = 0); void refreshTile(const int3 &pos); }; @@ -202,6 +203,8 @@ public: /// Minimap which is displayed at the right upper corner of adventure map class CMinimap : public CIntObject { +protected: + CPicture *aiShield; //the graphic displayed during AI turn CMinimapInstance * minimap; int level; @@ -214,8 +217,6 @@ class CMinimap : public CIntObject void hover (bool on); void mouseMoved (const SDL_MouseMotionEvent & sEvent); -protected: - void moveAdvMapSelection(); public: @@ -225,6 +226,7 @@ public: CMinimap(const Rect & position); //should be called to invalidate whole map - different player or level + int3 translateMousePosition(); void update(); void setLevel(int level); void setAIRadar(bool on); diff --git a/client/CQuestLog.cpp b/client/CQuestLog.cpp index 387e89f0e..3100e8a5f 100644 --- a/client/CQuestLog.cpp +++ b/client/CQuestLog.cpp @@ -46,15 +46,78 @@ void CQuestLabel::showAll(SDL_Surface * to) CBoundedLabel::showAll (to); } -void CQuestMinimap::clickLeft(tribool down, bool previousState) +CQuestIcon::CQuestIcon (const std::string &bmpname, int x, int y) : + CPicture (bmpname, x, y) +{ + addUsedEvents(LCLICK); +} + +void CQuestIcon::clickLeft(tribool down, bool previousState) { if (down) + callback(); +} + +void CQuestIcon::showAll(SDL_Surface * to) +{ + if(bg) { - moveAdvMapSelection(); - update(); + if(srcRect) + { + SDL_Rect srcRectCpy = *srcRect; + SDL_Rect dstRect = srcRectCpy; + dstRect.x = pos.x; + dstRect.y = pos.y; + + CSDL_Ext::blitSurface(bg, &srcRectCpy, to, &dstRect); + } + else //TODO: allow blitting with offset correction (center of picture on the center of pos) + { + SDL_Rect dstRect = pos; + dstRect.x -= pos.w + 2; + dstRect.y -= pos.h + 2; + blitAt(bg, dstRect, to); + } } } +CQuestMinimap::CQuestMinimap (const Rect & position) : +CMinimap (position), + currentQuest (NULL) +{ +} + +void CQuestMinimap::addQuestMarks (const QuestInfo * q) +{ + OBJ_CONSTRUCTION_CAPTURING_ALL; + icons.clear(); + + int3 tile; + if (q->obj) + { + tile = q->obj->pos; + } + else + { + tile = q->tile; + } + CQuestIcon * pic = new CQuestIcon ("", 0, 0); + CDefHandler * def = CDefHandler::giveDef("VwSymbol.def"); + CSDL_Ext::alphaTransform(def->ourImages[3].bitmap); + pic->bg = def->ourImages[3].bitmap; + pic->pos.w = 8; + pic->pos.h = 8; + + int x, y; + minimap->tileToPixels (tile, x, y); + pic->moveTo (Point (minimap->pos.x, minimap->pos.y), true); + pic->pos.x += x - pic->pos.w / 2 - 1; + pic->pos.y += y - pic->pos.h / 2 - 1; + + pic->callback = boost::bind (&CQuestMinimap::iconClicked, this); + icons.push_back(pic); +} + void CQuestMinimap::update() { CMinimap::update(); @@ -62,6 +125,20 @@ void CQuestMinimap::update() addQuestMarks (currentQuest); } +void CQuestMinimap::iconClicked() +{ + if (currentQuest->obj) + adventureInt->centerOn (currentQuest->obj->pos); + moveAdvMapSelection(); +} + +void CQuestMinimap::showAll(SDL_Surface * to) +{ + CMinimap::showAll(to); + BOOST_FOREACH (auto pic, icons) + pic->showAll(to); +} + CQuestLog::CQuestLog (const std::vector & Quests) : CWindowObject(PLAYER_COLORED, "QuestLog.pcx"), quests (Quests), slider (NULL), @@ -116,6 +193,7 @@ void CQuestLog::showAll(SDL_Surface * to) } description->show(to); minimap->update(); + minimap->show(to); } void CQuestLog::recreateQuestList (int newpos) @@ -139,10 +217,7 @@ void CQuestLog::selectQuest (int which) questIndex = which; currentQuest = &quests[which]; minimap->currentQuest = currentQuest; - if (currentQuest->obj) - { - adventureInt->centerOn (currentQuest->obj->pos); - } + MetaString text; std::vector components; //TODO: display them currentQuest->quest->getVisitText (text, components , currentQuest->quest->isCustomFirst, true); diff --git a/client/CQuestLog.h b/client/CQuestLog.h index 02a59aee4..9906b0311 100644 --- a/client/CQuestLog.h +++ b/client/CQuestLog.h @@ -44,22 +44,36 @@ public: void showAll(SDL_Surface * to); }; +class CQuestIcon : public CPicture +{ +public: + boost::function callback; //TODO: merge with other similiar classes? + + CQuestIcon (const std::string &bmpname, int x=0, int y=0); + + void clickLeft(tribool down, bool previousState); + void showAll(SDL_Surface * to); +}; + class CQuestMinimap : public CMinimap { - void clickLeft(tribool down, bool previousState); + std::vector icons; + + void clickLeft(tribool down, bool previousState){}; //minimap ignores clicking on its surface + void iconClicked(); void mouseMoved (const SDL_MouseMotionEvent & sEvent){}; public: const QuestInfo * currentQuest; - CQuestMinimap (const Rect & position) : CMinimap (position){}; + CQuestMinimap (const Rect & position); //should be called to invalidate whole map - different player or level void update(); void setLevel(int level); - void addQuestMarks (const QuestInfo * q){}; + void addQuestMarks (const QuestInfo * q); - //void showAll(SDL_Surface * to){}; + void showAll(SDL_Surface * to); }; class CQuestLog : public CWindowObject diff --git a/lib/CGameState.h b/lib/CGameState.h index f08bdd6be..6c33a1a95 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -453,6 +453,11 @@ struct DLL_LINKAGE QuestInfo //universal interface for human and AI QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) : quest (Quest), obj (Obj), tile (Tile){}; + bool operator== (const QuestInfo qi) const + { + return (quest == qi.quest && obj == qi.obj); + } + //std::vector > texts //allow additional info for quest log? template void serialize(Handler &h, const int version) diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp index 343b36f86..e73cdb19c 100644 --- a/lib/CGeneralTextHandler.cpp +++ b/lib/CGeneralTextHandler.cpp @@ -502,6 +502,15 @@ void CGeneralTextHandler::load() for (i = 0; i < 48; ++i) loadToIt(seerNames[i], buf, it, 3); + buf = bitmaph->getTextFile("TENTCOLR.TXT"); + itr=0; + while(itrgetTextFile ("CAMPTEXT.TXT"); it = 0; diff --git a/lib/CGeneralTextHandler.h b/lib/CGeneralTextHandler.h index 36046ea50..406e81ed4 100644 --- a/lib/CGeneralTextHandler.h +++ b/lib/CGeneralTextHandler.h @@ -66,6 +66,7 @@ public: std::vector > > quests; //[quest][type][index] //type: quest, progress, complete, rollover, log OR time limit //index: 0-2 seer hut, 3-5 border guard std::vector seerNames; + std::vector tentColors; std::vector threat; //power rating for neutral stacks //sec skills diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 1f22cef67..95ac1702a 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -4420,6 +4420,13 @@ void CGSeerHut::initObj() } +void CGSeerHut::getRolloverText (MetaString &text, bool onHover) const +{ + CQuest::getRolloverText (text, onHover);//TODO: simplify? + if (!onHover) + text.addReplacement(seerName); +} + const std::string & CGSeerHut::getHoverText() const { switch (ID) @@ -6244,9 +6251,16 @@ bool CGKeys::wasMyColorVisited (int player) const return false; } +const std::string CGKeys::getName() const +{ + std::string name; + name = VLC->generaltexth->tentColors[subID] + " " + VLC->generaltexth->names[ID]; + return name; +} + const std::string & CGKeymasterTent::getHoverText() const { - hoverName = VLC->generaltexth->names[ID]; + hoverName = getName(); if (wasMyColorVisited (cb->getCurrentPlayer()) )//TODO: use local player, not current hoverName += "\n" + VLC->generaltexth->allTexts[352]; else @@ -6276,12 +6290,13 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const void CGBorderGuard::initObj() { + ui32 m13489val = subID; //store color as quest info blockVisit = true; } const std::string & CGBorderGuard::getHoverText() const { - hoverName = VLC->generaltexth->names[ID]; + hoverName = getName(); if (wasMyColorVisited (cb->getCurrentPlayer()) )//TODO: use local player, not current hoverName += "\n" + VLC->generaltexth->allTexts[352]; else @@ -6289,6 +6304,17 @@ const std::string & CGBorderGuard::getHoverText() const return hoverName; } +void CGBorderGuard::getVisitText (MetaString &text, std::vector &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const +{ + text << std::pair(11,18); +} + +void CGBorderGuard::getRolloverText (MetaString &text, bool onHover) const +{ + if (!onHover) + text << VLC->generaltexth->tentColors[subID] << " " << VLC->generaltexth->names[Obj::KEYMASTER]; +} + void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const { if (wasMyColorVisited (h->getOwner()) ) @@ -6307,7 +6333,11 @@ void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const iw.text << std::pair(11,18); cb->showInfoDialog (&iw); - //TODO: implement QuestInfo + AddQuest aq; + aq.quest = QuestInfo (this, this, pos); + aq.player = h->tempOwner; + cb->sendAndApply (&aq); + //TODO: add this quest only once OR check for multiple instances later } } @@ -6325,6 +6355,11 @@ void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passabi iw.player = h->getOwner(); iw.text << std::pair(11,18); cb->showInfoDialog(&iw); + + AddQuest aq; + aq.quest = QuestInfo (this, this, pos); + aq.player = h->tempOwner; + cb->sendAndApply (&aq); } } diff --git a/lib/CObjectHandler.h b/lib/CObjectHandler.h index 565e5c409..f83d64514 100644 --- a/lib/CObjectHandler.h +++ b/lib/CObjectHandler.h @@ -58,7 +58,7 @@ class DLL_LINKAGE CQuest { public: enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4, - MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9};//MISSION_KEYMASTER = 10}; //TODO? + MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10}; si32 qid; //unique quets id for serialization / identification @@ -776,6 +776,7 @@ public: int checkDirection() const; //calculates the region of map where monster is placed void newTurn() const; void onHeroVisit (const CGHeroInstance * h) const; + void getRolloverText (MetaString &text, bool onHover) const; void getCompletionText(MetaString &text, std::vector &components, bool isCustom, const CGHeroInstance * h = NULL) const; void finishQuest (const CGHeroInstance * h, ui32 accept) const; //common for both objects void completeQuest (const CGHeroInstance * h) const; @@ -1047,6 +1048,7 @@ public: //SubID 0 - lightblue, 1 - green, 2 - red, 3 - darkblue, 4 - brown, 5 - purple, 6 - white, 7 - black void setPropertyDer (ui8 what, ui32 val); + const std::string getName() const; //depending on color bool wasMyColorVisited (int player) const; template void serialize(Handler &h, const int version) { @@ -1067,16 +1069,19 @@ public: } }; -class DLL_LINKAGE CGBorderGuard : public CGKeys +class DLL_LINKAGE CGBorderGuard : public CGKeys, public CQuest { public: void initObj(); const std::string & getHoverText() const; + void getVisitText (MetaString &text, std::vector &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = NULL) const; + void getRolloverText (MetaString &text, bool onHover) const; void onHeroVisit(const CGHeroInstance * h) const; void openGate(const CGHeroInstance *h, ui32 accept) const; template void serialize(Handler &h, const int version) { + h & static_cast(*this); h & static_cast(*this); h & blockVisit; } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 46503c869..6b11fc6cb 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -186,6 +186,7 @@ namespace Obj enum { BOAT = 8, + KEYMASTER = 10, CREATURE_BANK = 16, CREATURE_GENERATOR1 = 17, CURSED_GROUND1 = 21, diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index dfa71452c..08921c3e7 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -108,8 +108,11 @@ DLL_LINKAGE void SetCommanderProperty::applyGs(CGameState *gs) DLL_LINKAGE void AddQuest::applyGs(CGameState *gs) { assert (vstd::contains(gs->players, player)); - //TODO: check for duplicates? - gs->players[player].quests.push_back (quest); + auto vec = &gs->players[player].quests; + if (!vstd::contains(*vec, quest)) + vec->push_back (quest); + else + tlog2 << "Warning! Attempt to add duplicated quest\n"; } DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs ) diff --git a/lib/map.cpp b/lib/map.cpp index edf3505dd..af7e45250 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -1804,11 +1804,13 @@ void Mapa::readObjects( const ui8 * bufor, int &i) case 9: //Border Guard { nobj = new CGBorderGuard(); + addQuest (dynamic_cast(nobj)); break; } case 212: //Border Gate { nobj = new CGBorderGate(); + addQuest (dynamic_cast(nobj)); break; } case 27: case 37: //Eye and Hut of Magi