1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- Quest log minimap now has clickable icons

- Border guard & border gate inherit Quest interface
- Lots of tweaks
This commit is contained in:
DjWarmonger 2012-07-08 16:36:20 +00:00
parent 32d1a08470
commit b28da1a5d3
12 changed files with 189 additions and 29 deletions

View File

@ -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; y<yEnd; y++)
{
@ -516,7 +519,7 @@ CMinimap::CMinimap(const Rect &position):
pos.h = position.h;
}
void CMinimap::moveAdvMapSelection()
int3 CMinimap::translateMousePosition()
{
// 0 = top-left corner, 1 = bottom-right corner
double dx = double(GH.current->motion.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();

View File

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

View File

@ -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<QuestInfo> & 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<Component> components; //TODO: display them
currentQuest->quest->getVisitText (text, components , currentQuest->quest->isCustomFirst, true);

View File

@ -44,22 +44,36 @@ public:
void showAll(SDL_Surface * to);
};
class CQuestIcon : public CPicture
{
public:
boost::function<void()> 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 <CQuestIcon *> 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

View File

@ -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<std::string> > texts //allow additional info for quest log?
template <typename Handler> void serialize(Handler &h, const int version)

View File

@ -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(itr<buf.length()-1)
{
std::string tmp;
loadToIt(tmp, buf, itr, 3);
tentColors.push_back(tmp);
}
//campaigns
buf = bitmaph->getTextFile ("CAMPTEXT.TXT");
it = 0;

View File

@ -66,6 +66,7 @@ public:
std::vector <std::vector <std::vector <std::string> > > quests; //[quest][type][index]
//type: quest, progress, complete, rollover, log OR time limit //index: 0-2 seer hut, 3-5 border guard
std::vector<std::string> seerNames;
std::vector<std::string> tentColors;
std::vector<std::string> threat; //power rating for neutral stacks
//sec skills

View File

@ -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<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const
{
text << std::pair<ui8,ui32>(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<ui8,ui32>(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<ui8,ui32>(11,18);
cb->showInfoDialog(&iw);
AddQuest aq;
aq.quest = QuestInfo (this, this, pos);
aq.player = h->tempOwner;
cb->sendAndApply (&aq);
}
}

View File

@ -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<Component> &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 <typename Handler> 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<Component> &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 <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CQuest&>(*this);
h & static_cast<CGObjectInstance&>(*this);
h & blockVisit;
}

View File

@ -186,6 +186,7 @@ namespace Obj
enum
{
BOAT = 8,
KEYMASTER = 10,
CREATURE_BANK = 16,
CREATURE_GENERATOR1 = 17,
CURSED_GROUND1 = 21,

View File

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

View File

@ -1804,11 +1804,13 @@ void Mapa::readObjects( const ui8 * bufor, int &i)
case 9: //Border Guard
{
nobj = new CGBorderGuard();
addQuest (dynamic_cast<CQuest *>(nobj));
break;
}
case 212: //Border Gate
{
nobj = new CGBorderGate();
addQuest (dynamic_cast<CQuest *>(nobj));
break;
}
case 27: case 37: //Eye and Hut of Magi