1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
3 // Copyright (C) 2007-2009, 2011, 2014, 2015, 2017 Ben Asselstine
4 // Copyright (C) 2007, 2008 Ole Laursen
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Library General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 // 02110-1301, USA.
20
21 #include <sigc++/functors/mem_fun.h>
22
23 #include "QuestsManager.h"
24
25 #include "Quest.h"
26 #include "QKillHero.h"
27 #include "QEnemyArmies.h"
28 #include "QCitySack.h"
29 #include "QCityRaze.h"
30 #include "QCityOccupy.h"
31 #include "QEnemyArmytype.h"
32 #include "QPillageGold.h"
33 #include "stacklist.h"
34 #include "SightMap.h"
35 #include "rewardlist.h"
36 #include "army.h"
37 #include "xmlhelper.h"
38 #include "history.h"
39 #include "stackreflist.h"
40 #include "hero.h"
41 #include "rnd.h"
42
43 Glib::ustring QuestsManager::d_tag = "questlist";
44
45 QuestsManager* QuestsManager::s_instance = NULL;
46
47 //#define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
48 #define debug(x)
49
50
getInstance()51 QuestsManager* QuestsManager::getInstance()
52 {
53 if (s_instance == 0)
54 s_instance = new QuestsManager();
55 return s_instance;
56 }
57
getInstance(XML_Helper * helper)58 QuestsManager* QuestsManager::getInstance(XML_Helper* helper)
59 {
60 if (s_instance)
61 deleteInstance();
62
63 s_instance = new QuestsManager(helper);
64 return s_instance;
65 }
66
deleteInstance()67 void QuestsManager::deleteInstance()
68 {
69 debug("QuestsManager: deleteInstance")
70 delete s_instance;
71 s_instance = 0;
72 }
73
QuestsManager()74 QuestsManager::QuestsManager()
75 {
76 sharedInit();
77 }
78
QuestsManager(XML_Helper * helper)79 QuestsManager::QuestsManager(XML_Helper* helper)
80 {
81 sharedInit();
82 debug("QuestsManager: registerTag!");
83 helper->registerTag(Quest::d_tag, sigc::mem_fun(this, &QuestsManager::load));
84 }
85
~QuestsManager()86 QuestsManager::~QuestsManager()
87 {
88 d_completed_quests.unique ();
89 for (auto q : d_completed_quests)
90 delete q;
91
92 for (std::map<guint32,Quest*>::iterator it = d_quests.begin();
93 it != d_quests.end(); it++)
94 delete (*it).second;
95 cleanup();
96 }
97
createNewQuest(guint32 heroId,bool razing_possible)98 Quest* QuestsManager::createNewQuest(guint32 heroId, bool razing_possible)
99 {
100 // don't let a hero have more than one quest
101 if (d_quests.count(heroId))
102 return NULL;
103
104 int which = 0;
105 while (!which)
106 {
107 which = 1 + Rnd::rand() % 7;
108 // if this quest is not feasible - try again with another
109 // quest:
110 if ((*(d_questsFeasible[which-1]))(heroId) == 0)
111 which = 0;
112 }
113 // ok - this quest can be completed
114
115 Quest *quest = NULL;
116 switch (which)
117 {
118 case 1:
119 quest = new QuestKillHero(*this, heroId);
120 break;
121 case 2:
122 quest = new QuestEnemyArmies(*this, heroId);
123 break;
124 case 3:
125 quest = new QuestCitySack(*this, heroId);
126 break;
127 case 4:
128 if (razing_possible)
129 quest = new QuestCityRaze(*this, heroId);
130 else
131 quest = new QuestCitySack(*this, heroId);
132 break;
133 case 5:
134 quest = new QuestCityOccupy(*this, heroId);
135 break;
136 case 6:
137 quest = new QuestEnemyArmytype(*this, heroId);
138 break;
139 case 7:
140 quest = new QuestPillageGold(*this, heroId);
141 break;
142 }
143
144 if (quest)
145 {
146 d_quests[heroId] = quest;
147 }
148
149 return quest;
150 }
151
createNewKillHeroQuest(guint32 heroId,guint32 targetHeroId)152 Quest* QuestsManager::createNewKillHeroQuest(guint32 heroId, guint32 targetHeroId)
153 {
154 Quest *quest = new QuestKillHero(*this, heroId, targetHeroId);
155
156 d_quests[heroId] = quest;
157
158 return quest;
159 }
160
createNewEnemyArmiesQuest(guint32 heroId,guint32 num_armies,guint32 victim_player_id)161 Quest* QuestsManager::createNewEnemyArmiesQuest(guint32 heroId,
162 guint32 num_armies,
163 guint32 victim_player_id)
164 {
165 Quest *quest = new QuestEnemyArmies(*this, heroId, num_armies,
166 victim_player_id);
167
168 d_quests[heroId] = quest;
169
170 return quest;
171 }
172
createNewCitySackQuest(guint32 heroId,guint32 cityId)173 Quest* QuestsManager::createNewCitySackQuest(guint32 heroId, guint32 cityId)
174 {
175 Quest *quest = new QuestCitySack(*this, heroId, cityId);
176
177 d_quests[heroId] = quest;
178
179 return quest;
180 }
181
createNewCityRazeQuest(guint32 heroId,guint32 cityId)182 Quest* QuestsManager::createNewCityRazeQuest(guint32 heroId, guint32 cityId)
183 {
184 Quest *quest = new QuestCityRaze(*this, heroId, cityId);
185
186 d_quests[heroId] = quest;
187
188 return quest;
189 }
190
createNewCityOccupyQuest(guint32 heroId,guint32 cityId)191 Quest* QuestsManager::createNewCityOccupyQuest(guint32 heroId, guint32 cityId)
192 {
193 Quest *quest = new QuestCityOccupy(*this, heroId, cityId);
194
195 d_quests[heroId] = quest;
196
197 return quest;
198 }
199
createNewEnemyArmytypeQuest(guint32 heroId,guint32 armyTypeId)200 Quest* QuestsManager::createNewEnemyArmytypeQuest(guint32 heroId,
201 guint32 armyTypeId)
202 {
203 Quest *quest = new QuestEnemyArmytype(*this, heroId, armyTypeId);
204
205 d_quests[heroId] = quest;
206
207 return quest;
208 }
209
createNewPillageGoldQuest(guint32 heroId,guint32 amount)210 Quest* QuestsManager::createNewPillageGoldQuest(guint32 heroId, guint32 amount)
211 {
212 Quest *quest = new QuestPillageGold(*this, heroId, amount);
213
214 d_quests[heroId] = quest;
215
216 return quest;
217 }
218
questCompleted(guint32 heroId)219 void QuestsManager::questCompleted(guint32 heroId)
220 {
221 Quest *quest = getHeroQuest (heroId);
222 Player *p = quest->getHero()->getOwner();
223
224 p->heroCompletesQuest(quest->getHero());
225 Stack *stack = p->getStacklist()->getArmyStackById(heroId);
226
227 Reward *reward = Reward::createRandomReward(true, true);
228 StackReflist *stacks = new StackReflist();
229 p->giveReward(stack, reward, stacks, true);
230 quest_completed.emit(quest, reward);
231 if (reward->getType() == Reward::ALLIES)
232 p->addHistory(new History_HeroFindsAllies(quest->getHero()));
233 else if (reward->getType() == Reward::RUIN)
234 {
235 Ruin *r = dynamic_cast<Reward_Ruin*>(reward)->getRuin();
236 p->addHistory(new History_HeroRewardRuin(dynamic_cast<Hero*>(quest->getHero()), r));
237 }
238 delete reward;
239 delete stacks;
240
241 //debug("deactivate quest");
242
243 quest->deactivate ();
244 d_quests.erase(heroId);
245 d_completed_quests.push_back (quest);
246 //debug("quest deactivated");
247 }
248
questExpired(guint32 heroId)249 void QuestsManager::questExpired(guint32 heroId)
250 {
251 Quest *quest = getHeroQuest (heroId);
252
253 if (quest == 0)
254 return;
255
256 //quest_expired.emit(quest);
257
258 debug("deactivate quest");
259 deactivateQuest(heroId);
260 debug("quest deactivated");
261 }
262
getPlayerQuests(const Player * player) const263 std::vector<Quest*> QuestsManager::getPlayerQuests(const Player *player) const
264 {
265 std::vector<Quest*> res;
266 // loop through the player's heroes
267 // for every hero check any pending quests
268 const Stacklist* sl = player->getStacklist();
269 std::list<Hero*> heroes = sl->getHeroes();
270 for (std::list<Hero*>::iterator it = heroes.begin(); it != heroes.end(); it++)
271 {
272 guint32 heroId = (*it)->getId();
273
274 if (d_quests.count(heroId) > 0)
275 {
276 std::map<guint32, Quest*>::const_iterator qit = d_quests.find(heroId);
277 if (qit == d_quests.end())
278 continue;
279 Quest *q = (*qit).second;
280 if (q && q->isPendingDeletion() == true)
281 continue;
282 if (!q)
283 continue;
284 debug("heroId = " << heroId << " - has quest: " << q);
285 res.push_back(q);
286 }
287 }
288 return res;
289 }
290
getHeroQuest(guint32 hero_id) const291 Quest* QuestsManager::getHeroQuest(guint32 hero_id) const
292 {
293 std::map<guint32, Quest*>::const_iterator qit;
294 qit = d_quests.find(hero_id);
295 if (qit == d_quests.end())
296 return NULL;
297 Quest *q = (*qit).second;
298 if (q && q->isPendingDeletion() == true)
299 return NULL;
300 return (*qit).second;
301 }
302
save(XML_Helper * helper) const303 bool QuestsManager::save(XML_Helper* helper) const
304 {
305 debug("Saving quests\n");
306
307 bool retval = true;
308 retval &= helper->openTag(QuestsManager::d_tag);
309
310 for (std::map<guint32,Quest*>::const_iterator it = d_quests.begin();
311 it != d_quests.end(); it++)
312 {
313 if ((*it).second == NULL)
314 continue;
315 retval &= ((*it).second)->save(helper);
316 }
317 for (std::list<Quest *>::const_iterator it = d_inactive_quests.begin();
318 it != d_inactive_quests.end(); it++)
319 retval &= (*it)->save(helper);
320
321 debug("Quests saved\n");
322 retval &= helper->closeTag();
323 return retval;
324 }
325
load(Glib::ustring tag,XML_Helper * helper)326 bool QuestsManager::load(Glib::ustring tag, XML_Helper* helper)
327 {
328 debug("QuestsManager: load tag = " << tag);
329
330 if (tag == Quest::d_tag)
331 {
332 guint32 questType, hero;
333 Glib::ustring quest_type_str;
334 helper->getData(quest_type_str, "type");
335 questType = Quest::questTypeFromString(quest_type_str);
336 helper->getData(hero, "hero");
337
338 debug("quest load: type = " << questType << ", heroId = " << hero);
339
340 Quest *quest=0;
341 switch (static_cast<Quest::Type>(questType)) {
342 case Quest::KILLHERO:
343 quest = new QuestKillHero(*this, helper);
344 break;
345 case Quest::KILLARMIES:
346 quest = new QuestEnemyArmies(*this, helper);
347 break;
348 case Quest::CITYSACK:
349 quest = new QuestCitySack(*this, helper);
350 break;
351 case Quest::CITYRAZE:
352 quest = new QuestCityRaze(*this, helper);
353 break;
354 case Quest::CITYOCCUPY:
355 quest = new QuestCityOccupy(*this, helper);
356 break;
357 case Quest::KILLARMYTYPE:
358 quest = new QuestEnemyArmytype(*this, helper);
359 break;
360 case Quest::PILLAGEGOLD:
361 quest = new QuestPillageGold(*this, helper);
362 break;
363 }
364
365 debug("quest created: q = " << quest);
366 if (quest)
367 {
368 if (quest->isPendingDeletion())
369 d_inactive_quests.push_back(quest);
370 else
371 d_quests[hero] = quest;
372 }
373 return true;
374 }
375 return false;
376 }
377
sharedInit()378 void QuestsManager::sharedInit()
379 {
380 debug("QuestsManager constructor")
381
382 // now prepare the vector of pointers to the
383 // functions (class static members) checking feasibility
384 // for every quest
385 d_questsFeasible.push_back(&(QuestKillHero::isFeasible));
386 d_questsFeasible.push_back(&(QuestEnemyArmies::isFeasible));
387 d_questsFeasible.push_back(&(QuestCitySack::isFeasible));
388 d_questsFeasible.push_back(&(QuestCityRaze::isFeasible));
389 d_questsFeasible.push_back(&(QuestCityOccupy::isFeasible));
390 d_questsFeasible.push_back(&(QuestEnemyArmytype::isFeasible));
391 d_questsFeasible.push_back(&(QuestPillageGold::isFeasible));
392 }
393
deactivateQuest(guint32 heroId)394 void QuestsManager::deactivateQuest(guint32 heroId)
395 {
396 Quest *q = getHeroQuest (heroId);
397 q->deactivate();
398 d_inactive_quests.push_back(q);
399 // delete it from hash of active quests
400 d_quests.erase(heroId);
401 }
402
cleanup()403 void QuestsManager::cleanup()
404 {
405 debug("QuestsManager: cleanup!");
406
407 std::list<Quest *>::iterator it = d_inactive_quests.begin();
408 while(it != d_inactive_quests.end())
409 {
410 Quest *q =(*it);
411 it = d_inactive_quests.erase(it);
412 if (q)
413 delete q;
414 }
415 }
416
getActiveQuests()417 std::vector<Quest*> QuestsManager::getActiveQuests ()
418 {
419 std::vector<Quest*> quests;
420 for (std::map<guint32,Quest*>::iterator it = d_quests.begin();
421 it != d_quests.end(); it++)
422 {
423 if ((*it).second == NULL)
424 continue;
425 if ((*it).second->isPendingDeletion() == true)
426 continue;
427 quests.push_back ((*it).second);
428 }
429 return quests;
430 }
431
armyDied(Army * a,std::vector<guint32> & culprits)432 void QuestsManager::armyDied(Army *a, std::vector<guint32>& culprits)
433 {
434 //tell all quests that an army died
435 //each quest takes care of what happens when an army dies
436 std::vector<Quest *> quests = getActiveQuests ();
437 for (auto q : quests)
438 {
439 //was this hero a perpetrator?
440 bool heroIsCulprit = false;
441 for (unsigned int i = 0; i <culprits.size(); i++)
442 {
443 if (culprits[i] == q->getHeroId())
444 {
445 heroIsCulprit = true;
446 break;
447 }
448 }
449 q->armyDied(a, heroIsCulprit);
450 }
451
452 //is it a hero that has an outstanding quest?
453 //this is what deactivates a quest upon hero death
454 Quest *quest = getHeroQuest (a->getId());
455 if (quest && quest->isPendingDeletion() == false)
456 questExpired(a->getId());
457 }
458
cityAction(City * c,Stack * s,CityDefeatedAction action,int gold)459 void QuestsManager::cityAction(City *c, Stack *s,
460 CityDefeatedAction action, int gold)
461 {
462 std::vector<Quest *> quests = getActiveQuests ();
463 for (auto q : quests)
464 {
465 if (!s)
466 q->cityAction(c, action, false, gold);
467 else
468 {
469 //XXX XXX XXX why do we have to check for null here?
470 for (Stack::iterator sit = s->begin(); sit != s->end(); sit++)
471 {
472 if (q->isPendingDeletion())
473 break;
474 if ((*sit)->getId() == q->getHeroId())
475 q->cityAction(c, action, true, gold);
476 }
477 for (Stack::iterator sit = s->begin(); sit != s->end(); sit++)
478 {
479 if (q->isPendingDeletion())
480 break;
481 if ((*sit)->getId() != q->getHeroId())
482 q->cityAction(c, action, false, gold);
483 }
484 }
485 }
486 }
487
cityRazed(City * c,Stack * s)488 void QuestsManager::cityRazed(City *c, Stack *s)
489 {
490 cityAction(c, s, CITY_DEFEATED_RAZE, 0);
491 //did we raze a city we care about in another quest?
492 }
493
citySacked(City * c,Stack * s,int gold)494 void QuestsManager::citySacked(City *c, Stack *s, int gold)
495 {
496 cityAction(c, s, CITY_DEFEATED_SACK, gold);
497 }
498
cityPillaged(City * c,Stack * s,int gold)499 void QuestsManager::cityPillaged(City *c, Stack *s, int gold)
500 {
501 cityAction(c, s, CITY_DEFEATED_PILLAGE, gold);
502 }
503
cityOccupied(City * c,Stack * s)504 void QuestsManager::cityOccupied(City *c, Stack *s)
505 {
506 cityAction(c, s, CITY_DEFEATED_OCCUPY, 0);
507 }
508
nextTurn(Player * p)509 void QuestsManager::nextTurn(Player *p)
510 {
511 d_completed_quests.unique ();
512 for (auto q : d_completed_quests)
513 delete q;
514 d_completed_quests.clear ();
515 // go through our inactive list and remove quests belonging to us
516 for (std::list<Quest*>::iterator it = d_inactive_quests.begin();
517 it != d_inactive_quests.end(); it++)
518 {
519 if ((*it)->getOwner() == p)
520 {
521 Quest *q = *it;
522 quest_expired.emit(q);
523 it = d_inactive_quests.erase(it);
524 if (q)
525 delete q;
526 }
527 }
528 }
529