initial commit, lordsawar source, slightly modified
[lordsawar] / src / hero.cpp
1 // Copyright (C) 2003, 2004, 2005, 2006 Ulf Lorenz
2 // Copyright (C) 2004, 2005 Andrea Paternesi
3 // Copyright (C) 2007, 2008 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 <stdlib.h>
22 #include <sstream>
23 #include <fstream>
24 #include <sigc++/functors/mem_fun.h>
25
26 #include "hero.h"
27 #include "stacklist.h"
28 #include "templelist.h"
29 #include "heroproto.h"
30 #include "counter.h"
31 #include "Backpack.h"
32 #include "xmlhelper.h"
33 #include "playerlist.h"
34 #include "QuestsManager.h"
35
36 std::string Hero::d_tag = "hero";
37 using namespace std;
38
39 Hero::Hero(const HeroProto& a)
40   : Army (dynamic_cast<const ArmyProto&>(a)), d_name(a.getName()),
41     d_gender(Gender(a.getGender()))
42 {
43   d_level = 1;
44   d_backpack = new Backpack();
45   d_owner = Playerlist::getInstance()->getPlayer(a.getOwnerId());
46 }
47
48 Hero::Hero(Hero& h)
49   : Army(h, h.d_owner), d_name(h.d_name), d_gender(h.d_gender)
50 {
51   d_backpack = new Backpack(*h.d_backpack);
52 }
53
54 Hero::Hero(XML_Helper* helper)
55     :Army(helper)
56 {
57   helper->getData(d_name, "name");
58   std::string gender_str;
59   if (!helper->getData(gender_str, "gender"))
60     d_gender = NONE;
61   else
62     d_gender = genderFromString(gender_str);
63   helper->registerTag(Backpack::d_tag, 
64                       sigc::mem_fun(*this, &Hero::loadBackpack));
65 }
66
67
68 Hero::~Hero()
69 {
70   delete d_backpack;
71 }
72
73 bool Hero::save(XML_Helper* helper) const
74 {
75     bool retval = true;
76     std::list<Item*>::const_iterator it;
77
78     retval &= helper->openTag(Hero::d_tag);
79
80     retval &= helper->saveData("name", d_name);
81     std::string gender_str = genderToString(Hero::Gender(d_gender));
82     retval &= helper->saveData("gender", gender_str);
83     retval &= saveData(helper);
84
85     // Now save the backpack
86     retval &= d_backpack->save(helper);
87
88     retval &= helper->closeTag();
89
90     return retval;
91 }
92
93 bool Hero::loadBackpack(std::string tag, XML_Helper* helper)
94 {
95   if (tag == Backpack::d_tag)
96     {
97       d_backpack = new Backpack(helper);
98       return true;
99     }
100   return false;
101 }
102
103 guint32 Hero::getStat(Stat stat, bool modified) const
104 {
105     guint32 bonus = 0;
106     guint32 value = Army::getStat(stat, modified);
107
108     if (!modified)
109         return value;
110
111     // Add item bonuses that affect only this hero
112     if (stat == STRENGTH)
113       bonus += d_backpack->countStrengthBonuses();
114
115     return value + bonus;
116 }
117
118 guint32 Hero::calculateNaturalCommand()
119 {
120   guint32 command = 0;
121   guint32 strength = getStat(STRENGTH, true);
122   if (strength == 9)
123     command += 3;
124   else if (strength > 6)
125     command += 2;
126   else if (strength > 3)
127     command += 1;
128   return command;
129 }
130
131
132 std::string Hero::genderToString(const Hero::Gender gender)
133 {
134   switch (gender)
135     {
136     case Hero::NONE:
137       return "Hero::NONE";
138       break;
139     case Hero::MALE:
140       return "Hero::MALE";
141       break;
142     case Hero::FEMALE:
143       return "Hero::FEMALE";
144       break;
145     }
146   return "Hero::FEMALE";
147 }
148
149 Hero::Gender Hero::genderFromString(const std::string str)
150 {
151   if (str.size() > 0 && isdigit(str.c_str()[0]))
152     return Hero::Gender(atoi(str.c_str()));
153   if (str == "Hero::MALE")
154     return Hero::MALE;
155   else if (str == "Hero::NONE")
156     return Hero::NONE;
157   else if (str == "Hero::FEMALE")
158     return Hero::FEMALE;
159   return Hero::FEMALE;
160 }
161
162 bool Hero::canGainLevel() const
163 {
164   return getXP() >= getXpNeededForNextLevel();
165 }
166
167 guint32 Hero::getXpNeededForNextLevel() const
168 {
169   return xp_per_level * getLevel();
170 }
171
172 int Hero::computeLevelGain(Stat stat) const
173 {
174   if (stat == MOVE_BONUS || stat == ARMY_BONUS || stat == SHIP)
175     return -1;
176
177   switch (stat)
178     {
179     case STRENGTH:
180     case SIGHT:
181       return 1;
182     case HP:
183     case MOVES:
184       return 4;
185     default:
186       return -1;
187     }
188 }
189
190 int Hero::gainLevel(Stat stat)
191 {
192   if (!canGainLevel())
193     return -1;
194
195   if (stat == MOVE_BONUS || stat == ARMY_BONUS || stat == SHIP ||
196       stat == MOVES_MULTIPLIER)
197     return -1;
198
199   d_level++;
200   d_xp_value *= 1.2;
201
202   int delta = computeLevelGain(stat);
203   switch (stat)
204     {
205     case STRENGTH:
206       d_strength += delta;
207       if (d_strength > MAX_ARMY_STRENGTH)
208         d_strength = MAX_ARMY_STRENGTH;
209       break;
210     case HP:
211       d_max_hp += delta;
212       break;
213     case MOVES:
214       d_max_moves += delta;
215       break;
216     case SIGHT:
217       d_sight += delta;
218       break;
219     default:
220       break;
221     }
222
223   return delta;
224 }
225
226 bool Hero::hasQuest() const
227 {
228   return QuestsManager::getInstance()->getHeroQuest(getId()) != NULL;
229 }
230