initial commit, lordsawar source, slightly modified
[lordsawar] / src / QKillHero.cpp
1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2004 Andrea Paternesi
3 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
4 // Copyright (C) 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 <iostream>
22 #include <sstream>
23 #include <assert.h>
24 #include <sigc++/functors/mem_fun.h>
25 #include "ucompose.hpp"
26
27 #include "history.h"
28 #include "QKillHero.h"
29 #include "QuestsManager.h"
30 #include "playerlist.h"
31 #include "stacklist.h"
32
33 using namespace std;
34
35 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<endl<<flush;}
36 //#define debug(x)
37
38 QuestKillHero::QuestKillHero(QuestsManager& mgr, guint32 hero) 
39   : Quest(mgr, hero, Quest::KILLHERO)
40 {
41   // find a suitable hero for us
42   Hero *hunted = chooseToKill();
43   assert(hunted);         // should never fail, since isFeasible is checked
44
45   d_victim = hunted->getId();
46   d_targets.push_back(hunted->getOwner()->getStacklist()->getPosition(d_victim));
47   initDescription();
48 }
49
50 QuestKillHero::QuestKillHero(QuestsManager& q_mgr, XML_Helper* helper) 
51   : Quest(q_mgr, helper)
52 {
53   helper->getData(d_victim, "to_kill");
54   debug("load: hero_to_kill = " << d_victim);
55
56   // double and triple check :)
57   Hero *hero = Quest::getHeroById(d_victim);
58   assert(hero);
59   d_targets.push_back(hero->getOwner()->getStacklist()->getPosition(d_victim));
60
61   initDescription();
62 }
63
64 QuestKillHero::QuestKillHero(QuestsManager& q_mgr, guint32 hero, guint32 victim) 
65   : Quest(q_mgr, hero, Quest::KILLHERO)
66 {
67   d_victim = victim;
68
69   // double and triple check :)
70   Hero *h = Quest::getHeroById(d_victim);
71   assert(h);
72   d_targets.push_back(h->getOwner()->getStacklist()->getPosition(d_victim));
73
74   initDescription();
75 }
76
77 bool QuestKillHero::isFeasible(guint32 heroId)
78 {
79   // chooseToKill returns 0 if no enemy heroes exist
80   return (chooseToKill() != 0);
81 }
82
83 bool QuestKillHero::save(XML_Helper* helper) const
84 {
85   bool retval = true;
86
87   retval &= helper->openTag(Quest::d_tag);
88   retval &= Quest::save(helper);
89   retval &= helper->saveData("to_kill", d_victim);
90   retval &= helper->closeTag();
91
92   return retval;
93 }
94
95 std::string QuestKillHero::getProgress() const
96 {
97   std::stringstream ss;
98
99   // add info about the location of the hunted:
100   Stack* s = 0;
101   Quest::getHeroById(d_victim, &s);
102
103   ss <<_("You're still searching for him...");
104   ss << _("Seen lately near (") << s->getPos().x << ", " << s->getPos().y
105     << ")";
106   return ss.str();
107 }
108
109 void QuestKillHero::getSuccessMsg(std::queue<std::string>& msgs) const
110 {
111   std::string name = getHeroNameForDeadHero(d_victim);
112   msgs.push(String::ucompose(_("You have slain the wicked hero %1."), name));
113 }
114
115 void QuestKillHero::getExpiredMsg(std::queue<std::string>& msgs) const
116 {
117   msgs.push(String::ucompose(_("You could not slay the wicked hero %1"),
118                              getHeroNameForDeadHero(d_victim)));
119   msgs.push(_("The hero was slain by someone else!"));
120 }
121
122 void QuestKillHero::initDescription()
123 {
124   Hero* v = Quest::getHeroById(d_victim);
125   d_description = String::ucompose(_("Kill the hero named %1, servant of player %2."),
126                                    v->getName(), v->getOwner()->getName());
127 }
128
129 Hero* QuestKillHero::chooseToKill()
130 {
131   std::vector<Hero*> heroes;
132
133   // Collect all enemy heroes in the vector
134   const Playerlist* pl = Playerlist::getInstance();
135   Player* active = Playerlist::getActiveplayer();
136
137   for (Playerlist::const_iterator pit = pl->begin(); pit != pl->end(); pit++)
138     {
139       if ((*pit) == active)
140         continue;
141
142       const Stacklist* sl = (*pit)->getStacklist();
143       for (Stacklist::const_iterator it = sl->begin(); it != sl->end(); it++)
144         for (Stack::iterator sit = (*it)->begin(); sit != (*it)->end(); sit++)
145           if ((*sit)->isHero()) 
146             heroes.push_back(dynamic_cast<Hero*>(*sit));
147     }
148
149   // isFeasible() should depend on this behaviour...
150   if (heroes.empty())
151     return NULL;
152
153   // Now pick a hero:
154   return heroes[rand() % heroes.size()];
155 }
156
157 void QuestKillHero::armyDied(Army *a, bool heroIsCulprit)
158 {
159   if (!isPendingDeletion())
160     return;
161   Hero *h = getHero();
162   if (!h || h->getHP() <= 0)
163     {
164       deactivate();
165       return;
166     }
167
168   // is it a hero we were hunting for?
169   if (a->getId() != d_victim)
170     return;
171
172   // Answer: yes; now check if he was killed by our hero
173   if (heroIsCulprit == false)
174     {
175       /*The Hero was killed by a stack without heroes so the quest expires*/
176       //debug("SORRY: YOUR QUEST 'KILL HERO' HS EXPIRED BECAUSE THE HERO TO KILL WAS KILLED BY ANOTHER ONE");
177       d_q_mgr.questExpired(d_hero);
178       //hopefully this is handled by questsmanager, and not here!
179       return;
180     }
181   else
182     {
183       debug("CONGRATULATIONS: QUEST 'KILL HERO' IS COMPLETED!");
184       d_q_mgr.questCompleted(d_hero);
185       return;
186     }
187
188   return;
189 }
190
191 void QuestKillHero::cityAction(City *c, CityDefeatedAction action, 
192                                bool heroIsCulprit, int gold)
193 {
194   ;//this quest doesn't care what happens to cities
195 }