ManaPlus
questswindow.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2012-2017 The ManaPlus Developers
4  *
5  * This file is part of The ManaPlus Client.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
22 
23 #include "actormanager.h"
24 #include "configuration.h"
25 #include "effectmanager.h"
26 
27 #include "being/localplayer.h"
28 
29 #include "enums/gui/layouttype.h"
30 
31 #include "gui/gui.h"
32 
33 #include "gui/fonts/font.h"
34 
35 #include "gui/models/questsmodel.h"
36 
38 
39 #include "gui/widgets/button.h"
40 #include "gui/widgets/browserbox.h"
43 #include "gui/widgets/layout.h"
46 #include "gui/widgets/scrollarea.h"
47 
48 #include "utils/delete2.h"
49 #include "utils/foreach.h"
50 #include "utils/gettext.h"
51 
52 #include "resources/questeffect.h"
53 #include "resources/questitem.h"
54 
55 #include "resources/db/questdb.h"
56 
57 #include "resources/map/map.h"
58 
59 #include "debug.h"
60 
62 
64  // TRANSLATORS: quests window name
65  Window(_("Quests"), Modal_false, nullptr, "quests.xml"),
67  mQuestsModel(new QuestsModel),
68  mQuestsListBox(CREATEWIDGETR(ExtendedListBox,
69  this, mQuestsModel, "extendedlistbox.xml")),
70  mQuestScrollArea(new ScrollArea(this, mQuestsListBox,
71  fromBool(getOptionBool("showlistbackground"), Opaque),
72  "quests_list_background.xml")),
73  mItemLinkHandler(new ItemLinkHandler),
74  mText(new BrowserBox(this, Opaque_true,
75  "browserbox.xml")),
76  mTextScrollArea(new ScrollArea(this, mText,
77  fromBool(getOptionBool("showtextbackground"), Opaque),
78  "quests_text_background.xml")),
79  // TRANSLATORS: quests window button
80  mCloseButton(new Button(this, _("Close"), "close", this)),
81  mCompleteIcon(Theme::getImageFromThemeXml("complete_icon.xml", "")),
82  mIncompleteIcon(Theme::getImageFromThemeXml("incomplete_icon.xml", "")),
83  mMapEffects(),
84  mVars(nullptr),
87  mNpcEffects(),
88  mQuestLinks(),
89  mQuestReverseLinks(),
90  mNewQuestEffectId(paths.getIntValue("newQuestEffectId")),
91  mCompleteQuestEffectId(paths.getIntValue("completeQuestEffectId")),
92  mMap(nullptr)
93 {
94  setWindowName("Quests");
95  setResizable(true);
96  setCloseButton(true);
97  setStickyButtonLock(true);
98  setSaveVisible(true);
99 
101  setMinWidth(310);
102  setMinHeight(220);
103 
104  if (setupWindow != nullptr)
106 
107  mQuestsListBox->setActionEventId("select");
109 
114  mQuestsListBox->setWidth(500);
115  if ((gui == nullptr) || gui->getNpcFont()->getHeight() < 20)
117  else
119 
120  ContainerPlacer placer;
121  placer = getPlacer(0, 0);
122 
123  placer(0, 0, mQuestScrollArea, 4, 3).setPadding(3);
124  placer(4, 0, mTextScrollArea, 4, 3).setPadding(3);
125  placer(7, 3, mCloseButton);
126 
127  Layout &layout = getLayout();
128  layout.setRowHeight(0, LayoutType::SET);
129 
130  loadWindowState();
131  enableVisibleSound(true);
132  QuestDb::load();
136 }
137 
139 {
141 
142  QuestDb::unload();
143 
145  mQuestLinks.clear();
146  mQuestReverseLinks.clear();
147  if (mCompleteIcon != nullptr)
148  {
150  mCompleteIcon = nullptr;
151  }
152  if (mIncompleteIcon != nullptr)
153  {
155  mIncompleteIcon = nullptr;
156  }
157 }
158 
160 {
161  const std::string &eventId = event.getId();
162  if (eventId == "select")
163  {
164  const int id = mQuestsListBox->getSelected();
165  if (id < 0)
166  return;
167  showQuest(mQuestLinks[id]);
168  }
169  else if (eventId == "close")
170  {
172  }
173 }
174 
175 void QuestsWindow::updateQuest(const int var,
176  const int val1,
177  const int val2,
178  const int val3,
179  const int time1)
180 {
181  (*mVars)[var] = QuestVar(val1, val2, val3, time1);
182 }
183 
184 void QuestsWindow::rebuild(const bool playSound)
185 {
186  mQuestsModel->clear();
187  mQuestLinks.clear();
188  mQuestReverseLinks.clear();
189  StringVect &names = mQuestsModel->getNames();
190  STD_VECTOR<Image*> &images = mQuestsModel->getImages();
191  STD_VECTOR<QuestItem*> complete;
192  STD_VECTOR<QuestItem*> incomplete;
193  STD_VECTOR<QuestItem*> hidden;
194  int updatedQuest = -1;
195  int newCompleteStatus = -1;
196 
198  {
199  const int var = (*it).first;
200  const QuestVar &val = (*it).second;
201  const STD_VECTOR<QuestItem*> &quests = (*mQuests)[var];
202  FOR_EACH (STD_VECTOR<QuestItem*>::const_iterator, it2, quests)
203  {
204  if (*it2 == nullptr)
205  continue;
206  QuestItem *const quest = *it2;
207  // complete quest
208  if (quest->complete.find(val.var1) != quest->complete.end())
209  {
210  complete.push_back(quest);
211  }
212  // incomplete quest
213  else if (quest->incomplete.find(val.var1) !=
214  quest->incomplete.end())
215  {
216  incomplete.push_back(quest);
217  }
218  // hidden quest
219  else
220  {
221  hidden.push_back(quest);
222  }
223  }
224  }
225 
226  int k = 0;
227 
228  for (STD_VECTOR<QuestItem*>::const_iterator it = complete.begin(),
229  it_end = complete.end(); it != it_end; ++ it, k ++)
230  {
231  QuestItem *const quest = *it;
232  if (quest->completeFlag == 0 || (quest->broken
233  && quest->completeFlag == -1))
234  {
235  updatedQuest = k;
236  newCompleteStatus = 1;
237  }
238  quest->completeFlag = 1;
239  mQuestLinks.push_back(quest);
240  mQuestReverseLinks[quest->var] = k;
241  names.push_back(quest->name);
242  if (mCompleteIcon != nullptr)
243  {
245  images.push_back(mCompleteIcon);
246  }
247  else
248  {
249  images.push_back(nullptr);
250  }
251  }
252 
253  for (STD_VECTOR<QuestItem*>::const_iterator it = incomplete.begin(),
254  it_end = incomplete.end(); it != it_end; ++ it, k ++)
255  {
256  QuestItem *const quest = *it;
257  if (quest->completeFlag == -1)
258  {
259  updatedQuest = k;
260  newCompleteStatus = 0;
261  }
262  quest->completeFlag = 0;
263  mQuestLinks.push_back(quest);
264  mQuestReverseLinks[quest->var] = k;
265  names.push_back(quest->name);
266  if (mIncompleteIcon != nullptr)
267  {
269  images.push_back(mIncompleteIcon);
270  }
271  else
272  {
273  images.push_back(nullptr);
274  }
275  }
276 
277  FOR_EACH (STD_VECTOR<QuestItem*>::const_iterator, it, hidden)
278  (*it)->completeFlag = -1;
279 
280  if (updatedQuest == -1 || updatedQuest >= CAST_S32(
281  mQuestLinks.size()))
282  {
283  updatedQuest = CAST_S32(mQuestLinks.size() - 1);
284  }
285  if (updatedQuest >= 0)
286  {
287  mQuestsListBox->setSelected(updatedQuest);
288  showQuest(mQuestLinks[updatedQuest]);
289  if (playSound && (effectManager != nullptr))
290  {
291  switch (newCompleteStatus)
292  {
293  case 0:
295  break;
296  case 1:
298  localPlayer);
299  break;
300  default:
301  break;
302  }
303  }
304  }
305  updateEffects();
306 }
307 
308 void QuestsWindow::showQuest(const QuestItem *const quest)
309 {
310  if (quest == nullptr)
311  return;
312 
313  const STD_VECTOR<QuestItemText> &texts = quest->texts;
314  const QuestVar &var = (*mVars)[quest->var];
315  const std::string var1 = toString(var.var1);
316  const std::string var2 = toString(var.var2);
317  const std::string var3 = toString(var.var3);
318  const std::string timeStr = timeDiffToString(var.time1);
319  mText->clearRows();
320  FOR_EACH (STD_VECTOR<QuestItemText>::const_iterator, it, texts)
321  {
322  const QuestItemText &data = *it;
323  std::string text = data.text;
324  replaceAll(text, "{@@var1}", var1);
325  replaceAll(text, "{@@var2}", var2);
326  replaceAll(text, "{@@var3}", var3);
327  replaceAll(text, "{@@time}", timeStr);
328  switch (data.type)
329  {
330  case QuestType::TEXT:
331  default:
332  mText->addRow(text);
333  break;
334  case QuestType::NAME:
335  mText->addRow(std::string("[").append(text).append("]"));
336  break;
337  case QuestType::REWARD:
338  mText->addRow(std::string(
339  // TRANSLATORS: quest reward
340  _("Reward:")).append(
341  " ").append(
342  text));
343  break;
344  case QuestType::GIVER:
345  mText->addRow(std::string(
346  // TRANSLATORS: quest giver name
347  _("Quest Giver:")).append(
348  " ").append(
349  text));
350  break;
351  case QuestType::NPC:
352  mText->addRow(std::string(
353  // TRANSLATORS: quest npc name
354  _("Npc:")).append(
355  " ").append(
356  text));
357  break;
359  mText->addRow(std::string(
360  strprintf("%s [@@=navigate %s %s|%[email protected]@]",
361  // TRANSLATORS: quest coordinates
362  _("Coordinates:"),
363  data.data1.c_str(),
364  data.data2.c_str(),
365  text.c_str())));
366  break;
367  }
368  }
369  mText->updateHeight();
370 }
371 
372 void QuestsWindow::setMap(const Map *const map)
373 {
374  if (mMap != map)
375  {
376  mMap = map;
377  mMapEffects.clear();
378  if (mMap == nullptr)
379  return;
380 
381  const std::string name = mMap->getProperty("shortName");
382  FOR_EACHP (STD_VECTOR<QuestEffect*>::const_iterator, it, mAllEffects)
383  {
384  const QuestEffect *const effect = *it;
385  if ((effect != nullptr) && name == effect->map)
386  mMapEffects.push_back(effect);
387  }
388  updateEffects();
389  }
390 }
391 
393 {
395  mNpcEffects.clear();
396 
397  FOR_EACH (STD_VECTOR<const QuestEffect*>::const_iterator,
398  it, mMapEffects)
399  {
400  const QuestEffect *const effect = *it;
401  if (effect != nullptr)
402  {
403  const NpcQuestVarMapCIter varIt = mVars->find(effect->var);
404  if (varIt != mVars->end())
405  {
406  const std::set<int> &vals = effect->values;
407  if (vals.find((*mVars)[effect->var].var1) != vals.end())
408  mNpcEffects[effect->id] = effect;
409  }
410  }
411  }
412  if (actorManager == nullptr)
413  return;
414 
415  std::set<BeingTypeId> removeEffects;
416  std::map<BeingTypeId, int> addEffects;
417 
418  // for old effects
419  FOR_EACH (NpcQuestEffectMapCIter, it, oldNpc)
420  {
421  const BeingTypeId id = (*it).first;
422  const QuestEffect *const effect = (*it).second;
423 
424  const NpcQuestEffectMapCIter itNew = mNpcEffects.find(id);
425  if (itNew == mNpcEffects.end())
426  { // in new list no effect for this npc
427  removeEffects.insert(id);
428  }
429  else
430  { // in new list exists effect for this npc
431  const QuestEffect *const newEffect = (*itNew).second;
432  if (effect != newEffect)
433  { // new effects is not equal to old effect
434  addEffects[id] = newEffect->effectId;
435  removeEffects.insert(id);
436  }
437  }
438  }
439 
440  // for new effects
442  {
443  const BeingTypeId id = (*it).first;
444  const QuestEffect *const effect = (*it).second;
445 
446  const NpcQuestEffectMapCIter itNew = oldNpc.find(id);
447  // check if old effect was not present
448  if (itNew == oldNpc.end())
449  addEffects[id] = effect->effectId;
450  }
451  if (!removeEffects.empty() || !addEffects.empty())
452  actorManager->updateEffects(addEffects, removeEffects);
453 }
454 
455 void QuestsWindow::addEffect(Being *const being)
456 {
457  if (being == nullptr)
458  return;
459  const BeingTypeId id = being->getSubType();
460  const std::map<BeingTypeId, const QuestEffect*>::const_iterator
461  it = mNpcEffects.find(id);
462  if (it != mNpcEffects.end())
463  {
464  const QuestEffect *const effect = (*it).second;
465  if (effect != nullptr)
466  being->addSpecialEffect(effect->effectId);
467  }
468 }
469 
470 void QuestsWindow::selectQuest(const int varId)
471 {
472  std::map<int, int>::const_iterator it = mQuestReverseLinks.find(varId);
473  if (it == mQuestReverseLinks.end())
474  return;
475  if (mVisible == Visible_false)
477  const int listPos = (*it).second;
478  if (listPos < 0)
479  return;
480  showQuest(mQuestLinks[listPos]);
481  mQuestsListBox->setSelected(listPos);
483 }
std::string map
Definition: questeffect.h:44
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
void setDefaultSize()
Definition: window.cpp:1186
std::map< int, std::vector< QuestItem * > > * getQuests()
Definition: questdb.cpp:238
#define _(s)
Definition: gettext.h:34
void setSelected(const int selected)
Definition: listbox.cpp:392
std::vector< QuestEffect * > * mAllEffects
Definition: questswindow.h:92
#define FOR_EACHP(type, iter, array)
Definition: foreach.h:30
void setWidth(const int width)
Definition: widget.cpp:132
std::map< BeingTypeId, const QuestEffect * > NpcQuestEffectMap
Definition: questswindow.h:44
void load()
Definition: questdb.cpp:46
bool trigger(const int id, Being *const being, const int rotation=0)
Gui * gui
Definition: gui.cpp:110
BeingTypeId id
Definition: questeffect.h:46
ExtendedListBox * mQuestsListBox
Definition: questswindow.h:81
const bool Visible_true
Definition: visible.h:29
QuestsWindow * questsWindow
void loadWindowState()
Definition: window.cpp:1075
int time1
Definition: questvar.h:54
std::vector< QuestItemText > texts
Definition: questitem.h:53
int var
Definition: questitem.h:48
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:251
int var1
Definition: questvar.h:51
std::vector< QuestEffect * > * getAllEffects()
Definition: questdb.cpp:243
BrowserBox * mText
Definition: questswindow.h:84
virtual void requestMoveToTop()
Definition: widget.cpp:212
void setMinWidth(const int width)
Definition: window.cpp:579
Definition: window.h:98
Definition: button.h:94
std::set< int > incomplete
Definition: questitem.h:51
void showQuest(const QuestItem *const quest)
std::vector< Image * > & getImages()
std::string & replaceAll(std::string &context, const std::string &from, const std::string &to)
int var2
Definition: questvar.h:52
QuestsModel * mQuestsModel
Definition: questswindow.h:80
const std::string getProperty(const std::string &name, const std::string &def="") const
Definition: properties.h:58
void setActionEventId(const std::string &actionEventId)
Definition: widget.h:595
std::vector< std::string > StringVect
Definition: stringvector.h:28
NpcQuestVarMap * mVars
Definition: questswindow.h:90
#define delete2(var)
Definition: delete2.h:24
void updateEffects(const std::map< BeingTypeId, int > &addEffects, const std::set< BeingTypeId > &removeEffects) const
std::vector< const QuestEffect * > mMapEffects
Definition: questswindow.h:89
int mNewQuestEffectId
Definition: questswindow.h:98
NpcQuestVarMap::const_iterator NpcQuestVarMapCIter
Definition: questvar.h:58
NpcQuestEffectMap::const_iterator NpcQuestEffectMapCIter
Definition: questswindow.h:47
void registerWindowForReset(Window *const window)
int var3
Definition: questvar.h:53
std::string data1
Definition: questitemtext.h:47
void selectQuest(const int varId)
Visible mVisible
Definition: widget.h:962
void updateQuest(const int var, const int val1, const int val2, const int val3, const int time1)
std::vector< QuestItem * > mQuestLinks
Definition: questswindow.h:96
#define new
Definition: debug_new.h:147
std::vector< QuestEffect * > mAllEffects
Definition: questdb.cpp:43
#define CAST_S32
Definition: cast.h:29
void rebuild(const bool playSound)
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
const bool Visible_false
Definition: visible.h:29
#define fromBool(val, name)
Definition: booldefines.h:48
NpcQuestEffectMap mNpcEffects
Definition: questswindow.h:95
std::string name
Definition: questitem.h:49
uint32_t data
LocalPlayer * localPlayer
int getSelected() const
Definition: listbox.h:167
#define nullptr
Definition: localconsts.h:44
const bool Opaque_false
Definition: opaque.h:29
void action(const ActionEvent &event)
Definition: theme.h:52
int mCompleteQuestEffectId
Definition: questswindow.h:99
void setCloseButton(const bool flag)
Definition: window.cpp:737
void setMap(const Map *const map)
std::set< int > values
Definition: questeffect.h:48
void enableVisibleSound(bool b)
Definition: window.h:473
void setMinHeight(const int height)
Definition: window.cpp:592
ContainerPlacer getPlacer(const int x, const int y)
Definition: window.cpp:1379
Definition: map.h:68
Layout & getLayout()
Definition: window.cpp:1353
std::set< int > complete
Definition: questitem.h:52
Image * mCompleteIcon
Definition: questswindow.h:87
virtual void incRef()
Definition: resource.cpp:37
void setSaveVisible(const bool save)
Definition: window.h:298
Configuration paths
int completeFlag
Definition: questitem.h:54
ScrollArea * mQuestScrollArea
Definition: questswindow.h:82
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
bool broken
Definition: questitem.h:55
virtual void setVisible(Visible visible)
Definition: window.cpp:766
void addEffect(Being *const being)
void addSpecialEffect(const int effect)
Definition: being.cpp:4855
const Map * mMap
Definition: questswindow.h:100
void setLinkHandler(LinkHandler *linkHandler)
Definition: browserbox.cpp:160
std::string mMap
Definition: gamerecv.cpp:45
const bool Opaque_true
Definition: opaque.h:29
void unload()
Definition: questdb.cpp:215
ScrollArea * mTextScrollArea
Definition: questswindow.h:85
ItemLinkHandler * mItemLinkHandler
Definition: questswindow.h:83
Font * getNpcFont() const
Definition: gui.h:177
void setOpaque(Opaque opaque)
Definition: browserbox.h:74
Button * mCloseButton
Definition: questswindow.h:86
void setResizable(const bool resize)
Definition: window.cpp:615
Image * mIncompleteIcon
Definition: questswindow.h:88
void setStickyButtonLock(const bool sticky)
Definition: window.cpp:760
std::map< int, std::vector< QuestItem * > > * mQuests
Definition: questswindow.h:91
std::string text
Definition: questitemtext.h:45
SetupWindow * setupWindow
Definition: setupwindow.cpp:63
NpcQuestVarMap * getVars()
Definition: questdb.cpp:233
#define CREATEWIDGETR(type,...)
Definition: createwidget.h:35
int getHeight() const
Definition: font.cpp:360
Definition: layout.h:43
QuestTypeT type
Definition: questitemtext.h:46
StringVect & getNames()
int BeingTypeId
Definition: beingtypeid.h:29
Definition: being.h:93
void addRow(const std::string &row, const bool atTop=false)
Definition: browserbox.cpp:165
void setRowHeight(const int n, const int h)
Definition: layoutcell.cpp:127
std::map< int, int > mQuestReverseLinks
Definition: questswindow.h:97
EffectManager * effectManager
std::map< int, std::vector< QuestItem * > > mQuests
Definition: questdb.cpp:42
void decRef()
Definition: image.cpp:521
void updateEffects()
BeingTypeId getSubType() const
Definition: being.h:395
void updateHeight()
Definition: browserbox.cpp:844
void clearRows()
Definition: browserbox.cpp:352
void setRowHeight(unsigned int n)
Definition: listbox.h:158
ActorManager * actorManager
std::string timeDiffToString(int timeDiff)
void setWindowName(const std::string &name)
Definition: window.h:353
std::string data2
Definition: questitemtext.h:48
void setHorizontalScrollPolicy(const ScrollPolicy hPolicy)