Merge lp:~nha/widelands/soldier-cleanup into lp:widelands

Proposed by Nicolai Hähnle
Status: Merged
Merged at revision: 5317
Proposed branch: lp:~nha/widelands/soldier-cleanup
Merge into: lp:widelands
Diff against target: 527 lines (+74/-266)
7 files modified
src/logic/soldier.cc (+42/-68)
src/logic/soldier.h (+15/-23)
src/map_io/widelands_map_bobdata_data_packet.cc (+12/-170)
src/writeHTML.cc (+2/-2)
tribes/atlanteans/soldier/conf (+1/-1)
tribes/barbarians/soldier/conf (+1/-1)
tribes/empire/soldier/conf (+1/-1)
To merge this branch: bzr merge lp:~nha/widelands/soldier-cleanup
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+24946@code.launchpad.net

Description of the change

Let soldier attributes be computed directly from their respective level. Reduces the number of variables stored in Soldier.

Gameplay is affected in that the max HP of soldiers is no longer random, but always the same (depending obviously on the soldier's level). See http://wl.widelands.org/forum/topic/469/?page=1#post-2525

To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

seems clear enough to me

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/logic/soldier.cc'
2--- src/logic/soldier.cc 2010-04-13 16:47:49 +0000
3+++ src/logic/soldier.cc 2010-05-08 19:52:28 +0000
4@@ -55,28 +55,7 @@
5 {
6 add_attribute(Map_Object::SOLDIER);
7
8- try { // hitpoints
9- const char * const hp = global_s.get_safe_string("hp");
10- std::vector<std::string> list(split_string(hp, "-"));
11- if (list.size() != 2)
12- throw game_data_error
13- (_("expected %s but found \"%s\""), _("\"min-max\""), hp);
14- container_iterate(std::vector<std::string>, list, i)
15- remove_spaces(*i.current);
16- char * endp;
17- m_min_hp = strtol(list[0].c_str(), &endp, 0);
18- if (*endp or 0 == m_min_hp)
19- throw game_data_error
20- (_("expected %s but found \"%s\""),
21- _("positive integer"), list[0].c_str());
22- m_max_hp = strtol(list[1].c_str(), &endp, 0);
23- if (*endp or m_max_hp < m_min_hp)
24- throw game_data_error
25- (_("expected positive integer >= %u but found \"%s\""),
26- m_min_hp, list[1].c_str());
27- } catch (_wexception const & e) {
28- throw game_data_error("hp: %s", e.what());
29- }
30+ m_base_hp = global_s.get_safe_positive("hp");
31
32 try { // parse attack
33 const char * const attack = global_s.get_safe_string("attack");
34@@ -343,23 +322,7 @@
35 m_defense_level = 0;
36 m_evade_level = 0;
37
38- m_hp_max = 0;
39- m_min_attack = descr().get_min_attack();
40- m_max_attack = descr().get_max_attack();
41- m_defense = descr().get_defense ();
42- m_evade = descr().get_evade ();
43- {
44- const uint32_t min_hp = descr().get_min_hp();
45- assert(min_hp);
46- assert(min_hp <= descr().get_max_hp());
47- m_hp_max =
48- min_hp
49- +
50- ref_cast<Game, Editor_Game_Base>(egbase).logic_rand()
51- %
52- (descr().get_max_hp() - (min_hp - 1));
53- }
54- m_hp_current = m_hp_max;
55+ m_hp_current = get_max_hitpoints();
56
57 m_combat_walking = CD_NONE;
58 m_combat_walkstart = 0;
59@@ -391,39 +354,25 @@
60 assert(m_hp_level <= hp);
61 assert (hp <= descr().get_max_hp_level());
62
63- while (m_hp_level < hp) {
64- ++m_hp_level;
65- m_hp_max += descr().get_hp_incr_per_level();
66- m_hp_current += descr().get_hp_incr_per_level();
67- }
68+ m_hp_level = hp;
69 }
70 void Soldier::set_attack_level(const uint32_t attack) {
71 assert(m_attack_level <= attack);
72 assert (attack <= descr().get_max_attack_level());
73
74- while (m_attack_level < attack) {
75- ++m_attack_level;
76- m_min_attack += descr().get_attack_incr_per_level();
77- m_max_attack += descr().get_attack_incr_per_level();
78- }
79+ m_attack_level = attack;
80 }
81 void Soldier::set_defense_level(const uint32_t defense) {
82 assert(m_defense_level <= defense);
83 assert (defense <= descr().get_max_defense_level());
84
85- while (m_defense_level < defense) {
86- ++m_defense_level;
87- m_defense += descr().get_defense_incr_per_level();
88- }
89+ m_defense_level = defense;
90 }
91 void Soldier::set_evade_level(const uint32_t evade) {
92 assert(m_evade_level <= evade);
93 assert (evade <= descr().get_max_evade_level());
94
95- while (m_evade_level < evade) {
96- ++m_evade_level;
97- m_evade += descr().get_evade_incr_per_level();
98- }
99+ m_evade_level = evade;
100 }
101
102 uint32_t Soldier::get_level(tAttribute const at) const {
103@@ -453,13 +402,38 @@
104 return Worker::get_tattribute(attr);
105 }
106
107+uint32_t Soldier::get_max_hitpoints() const
108+{
109+ return descr().get_base_hp() + m_hp_level*descr().get_hp_incr_per_level();
110+}
111+
112+uint32_t Soldier::get_min_attack() const
113+{
114+ return descr().get_base_min_attack() + m_attack_level*descr().get_attack_incr_per_level();
115+}
116+
117+uint32_t Soldier::get_max_attack() const
118+{
119+ return descr().get_base_max_attack() + m_attack_level*descr().get_attack_incr_per_level();
120+}
121+
122+uint32_t Soldier::get_defense() const
123+{
124+ return descr().get_base_defense() + m_defense_level*descr().get_defense_incr_per_level();
125+}
126+
127+uint32_t Soldier::get_evade() const
128+{
129+ return descr().get_base_evade() + m_evade_level*descr().get_evade_incr_per_level();
130+}
131+
132 // Unsignedness ensures that we can only heal, not hurt through this method.
133 void Soldier::heal (const uint32_t hp) {
134- molog ("[soldier] healing (%d+)%d/%d\n", hp, m_hp_current, m_hp_max);
135+ molog ("[soldier] healing (%d+)%d/%d\n", hp, m_hp_current, get_max_hitpoints());
136 assert(hp);
137- assert(m_hp_current < m_hp_max);
138- m_hp_current += std::min(hp, m_hp_max - m_hp_current);
139- assert(m_hp_current <= m_hp_max);
140+ assert(m_hp_current < get_max_hitpoints());
141+ m_hp_current += std::min(hp, get_max_hitpoints() - m_hp_current);
142+ assert(m_hp_current <= get_max_hitpoints());
143 }
144
145 /**
146@@ -469,7 +443,7 @@
147 {
148 assert (m_hp_current > 0);
149
150- molog ("[soldier] damage %d(-%d)/%d\n", m_hp_current, value, m_hp_max);
151+ molog ("[soldier] damage %d(-%d)/%d\n", m_hp_current, value, get_max_hitpoints());
152 if (m_hp_current < value)
153 m_hp_current = 0;
154 else
155@@ -564,8 +538,8 @@
156 Rect r(Point(drawpos.x - w, drawpos.y - h - 7), w * 2, 5);
157 dst.draw_rect(r, HP_FRAMECOLOR);
158 // Draw the actual bar
159- assert(m_hp_max);
160- const float fraction = static_cast<float>(m_hp_current) / m_hp_max;
161+ assert(get_max_hitpoints());
162+ const float fraction = static_cast<float>(m_hp_current) / get_max_hitpoints();
163 RGBColor color(owner().get_playercolor()[2]);
164 assert(2 <= r.w);
165 assert(2 <= r.h);
166@@ -1619,10 +1593,10 @@
167 molog
168 ("Levels: %d/%d/%d/%d\n",
169 m_hp_level, m_attack_level, m_defense_level, m_evade_level);
170- molog ("HitPoints: %d/%d\n", m_hp_current, m_hp_max);
171- molog ("Attack : %d-%d\n", m_min_attack, m_max_attack);
172- molog ("Defense : %d%%\n", m_defense);
173- molog ("Evade: %d%%\n", m_evade);
174+ molog ("HitPoints: %d/%d\n", m_hp_current, get_max_hitpoints());
175+ molog ("Attack : %d-%d\n", get_min_attack(), get_max_attack());
176+ molog ("Defense : %d%%\n", get_defense());
177+ molog ("Evade: %d%%\n", get_evade());
178 molog ("CombatWalkingDir: %i\n", m_combat_walking);
179 molog ("CombatWalkingStart: %i\n", m_combat_walkstart);
180 molog ("CombatWalkEnd: %i\n", m_combat_walkend);
181
182=== modified file 'src/logic/soldier.h'
183--- src/logic/soldier.h 2010-03-14 16:44:43 +0000
184+++ src/logic/soldier.h 2010-05-08 19:52:28 +0000
185@@ -54,12 +54,11 @@
186 uint32_t get_max_defense_level () const {return m_max_defense_level;}
187 uint32_t get_max_evade_level () const {return m_max_evade_level;}
188
189- uint32_t get_min_hp () const {return m_min_hp;}
190- uint32_t get_max_hp () const {return m_max_hp;}
191- uint32_t get_min_attack () const {return m_min_attack;}
192- uint32_t get_max_attack () const {return m_max_attack;}
193- uint32_t get_defense () const {return m_defense;}
194- uint32_t get_evade () const {return m_evade;}
195+ uint32_t get_base_hp () const {return m_base_hp;}
196+ uint32_t get_base_min_attack() const {return m_min_attack;}
197+ uint32_t get_base_max_attack() const {return m_max_attack;}
198+ uint32_t get_base_defense () const {return m_defense;}
199+ uint32_t get_base_evade () const {return m_evade;}
200
201 uint32_t get_hp_incr_per_level () const {return m_hp_incr;}
202 uint32_t get_attack_incr_per_level () const {return m_attack_incr;}
203@@ -90,8 +89,7 @@
204 virtual Bob & create_object() const;
205
206 // start values
207- uint32_t m_min_hp;
208- uint32_t m_max_hp;
209+ uint32_t m_base_hp;
210 uint32_t m_min_attack;
211 uint32_t m_max_attack;
212 uint32_t m_defense;
213@@ -110,10 +108,10 @@
214 uint32_t m_max_evade_level;
215
216 // level pictures
217- std::vector<PictureID> m_hp_pics;
218- std::vector<PictureID> m_attack_pics;
219- std::vector<PictureID> m_evade_pics;
220- std::vector<PictureID> m_defense_pics;
221+ std::vector<PictureID> m_hp_pics;
222+ std::vector<PictureID> m_attack_pics;
223+ std::vector<PictureID> m_evade_pics;
224+ std::vector<PictureID> m_defense_pics;
225 std::vector<std::string> m_hp_pics_fn;
226 std::vector<std::string> m_attack_pics_fn;
227 std::vector<std::string> m_evade_pics_fn;
228@@ -217,11 +215,11 @@
229 }
230
231 uint32_t get_current_hitpoints() const {return m_hp_current;}
232- uint32_t get_max_hitpoints () const {return m_hp_max;}
233- uint32_t get_min_attack () const {return m_min_attack;}
234- uint32_t get_max_attack () const {return m_max_attack;}
235- uint32_t get_defense () const {return m_defense;}
236- uint32_t get_evade () const {return m_evade;}
237+ uint32_t get_max_hitpoints() const;
238+ uint32_t get_min_attack() const;
239+ uint32_t get_max_attack() const;
240+ uint32_t get_defense() const;
241+ uint32_t get_evade() const;
242
243 PictureID get_hp_level_pic () const {
244 return descr().get_hp_level_pic (m_hp_level);
245@@ -286,12 +284,6 @@
246
247 private:
248 uint32_t m_hp_current;
249- uint32_t m_hp_max;
250- uint32_t m_min_attack;
251- uint32_t m_max_attack;
252- uint32_t m_defense;
253- uint32_t m_evade;
254-
255 uint32_t m_hp_level;
256 uint32_t m_attack_level;
257 uint32_t m_defense_level;
258
259=== modified file 'src/map_io/widelands_map_bobdata_data_packet.cc'
260--- src/map_io/widelands_map_bobdata_data_packet.cc 2010-05-01 13:54:47 +0000
261+++ src/map_io/widelands_map_bobdata_data_packet.cc 2010-05-08 19:52:28 +0000
262@@ -51,7 +51,7 @@
263 #define WORKER_BOB_PACKET_VERSION 1
264
265 // Worker subtype versions
266-#define SOLDIER_WORKER_BOB_PACKET_VERSION 6
267+#define SOLDIER_WORKER_BOB_PACKET_VERSION 7
268 #define CARRIER_WORKER_BOB_PACKET_VERSION 1
269
270
271@@ -432,29 +432,16 @@
272 {
273 Soldier_Descr const & descr = soldier->descr();
274
275- uint32_t min_hp = descr.get_min_hp();
276- assert(min_hp);
277 soldier->m_hp_current = fr.Unsigned32();
278- soldier->m_hp_max = fr.Unsigned32();
279- // This has been commented because now exists a 'die' task,
280- // so a soldier can have 0 hitpoints if it's dying.
281- //if (not soldier->m_hp_current)
282- // throw game_data_error("no hitpoints (should be dead)");
283- if (soldier->m_hp_max < soldier->m_hp_current)
284- throw game_data_error
285- ("hp_max (%u) < hp_current (%u)",
286- soldier->m_hp_max, soldier->m_hp_current);
287-
288- soldier->m_min_attack = fr.Unsigned32();
289- soldier->m_max_attack = fr.Unsigned32();
290- if (soldier->m_max_attack < soldier->m_min_attack)
291- throw game_data_error
292- ("max_attack = %u but must be at least %u",
293- soldier->m_max_attack, soldier->m_min_attack);
294-
295- soldier->m_defense = fr.Unsigned32();
296-
297- soldier->m_evade = fr.Unsigned32();
298+
299+ if (soldier_worker_bob_packet_version <= 6) {
300+ // no longer used values
301+ fr.Unsigned32(); // max hp
302+ fr.Unsigned32(); // min attack
303+ fr.Unsigned32(); // max attack
304+ fr.Unsigned32(); // defense
305+ fr.Unsigned32(); // evade
306+ }
307
308 #define READLEVEL(variable, pn, maxfunction) \
309 soldier->variable = fr.Unsigned32(); \
310@@ -478,148 +465,8 @@
311 READLEVEL(m_defense_level, "defense", get_max_defense_level);
312 READLEVEL(m_evade_level, "evade", get_max_evade_level);
313
314- { // validate hp values
315- uint32_t const level_increase =
316- descr.get_hp_incr_per_level() * soldier->m_hp_level;
317- min_hp += level_increase;
318- uint32_t const max = descr.get_max_hp() + level_increase;
319- if (soldier->m_hp_max < min_hp) {
320- // The soldier's type's definition may have changed,
321- // so that max_hp must be larger. Adjust it and scale
322- // up the current amount of hitpoints proportionally.
323- uint32_t const new_current =
324- soldier->m_hp_current * min_hp / soldier->m_hp_max;
325- log
326- ("WARNING: %s %s (%u) of player %u has hp_max = %u "
327- "but it must be at least %u (= %u + %u * %u), "
328- "changing it to that value and increasing current "
329- "hp from %u to %u\n",
330- descr.tribe().name().c_str(),
331- descr.descname().c_str(), soldier->serial(),
332- soldier->owner().player_number(),
333- soldier->m_hp_max, min_hp,
334- descr.get_min_hp(),
335- descr.get_hp_incr_per_level(), soldier->m_hp_level,
336- soldier->m_hp_current, new_current);
337- soldier->m_hp_current = new_current;
338- soldier->m_hp_max = min_hp;
339- } else if (max < soldier->m_hp_max) {
340- // The soldier's type's definition may have changed,
341- // so that max_hp must be smaller. Adjust it and scale
342- // down the current amount of hitpoints
343- // proportionally. Round to the soldier's favour and
344- // make sure that the scaling does not kill the
345- // soldier.
346- uint32_t const new_current =
347- 1
348- +
349- (soldier->m_hp_current * max - 1)
350- /
351- soldier->m_hp_max;
352- assert(new_current);
353- assert(new_current <= soldier->m_hp_max);
354- log
355- ("WARNING: %s %s (%u) of player %u has hp_max = %u "
356- "but it can be at most %u (= %u + %u * %u), "
357- "changing it to that value and decreasing current "
358- "hp from %u to %u\n",
359- descr.tribe().name().c_str(),
360- descr.descname().c_str(), soldier->serial(),
361- soldier->owner().player_number(),
362- soldier->m_hp_max, max,
363- descr.get_max_hp(),
364- descr.get_hp_incr_per_level(), soldier->m_hp_level,
365- soldier->m_hp_current, new_current);
366- soldier->m_hp_current = new_current;
367- soldier->m_hp_max = max;
368- }
369- }
370-
371- { // validate attack values
372- uint32_t const level_increase =
373- descr.get_attack_incr_per_level()
374- *
375- soldier->m_attack_level;
376- {
377- uint32_t const min =
378- descr.get_min_attack() + level_increase;
379- if (soldier->m_min_attack < min) {
380- log
381- ("WARNING: %s %s (%u) of player %u has "
382- "min_attack = %u but it must be at least %u (= "
383- "%u + %u * %u), changing it to that value\n",
384- descr.tribe().name().c_str(),
385- descr.descname().c_str(), soldier->serial(),
386- soldier->owner().player_number(),
387- soldier->m_min_attack, min,
388- descr.get_min_attack(),
389- descr.get_attack_incr_per_level(),
390- soldier->m_attack_level);
391- soldier->m_min_attack = min;
392- if (soldier->m_max_attack < min) {
393- log
394- (" (and changing max_attack from %u to the "
395- "same value)",
396- soldier->m_max_attack);
397- soldier->m_max_attack = min;
398- }
399- log("\n");
400- }
401- }
402- {
403- uint32_t const max =
404- descr.get_max_attack() + level_increase;
405- if (max < soldier->m_max_attack) {
406- log
407- ("WARNING: %s %s (%u) of player %u has "
408- "max_attack = %u but it can be at most %u (= "
409- "%u + %u * %u), changing it to that value",
410- descr.tribe().name().c_str(),
411- descr.descname().c_str(), soldier->serial(),
412- soldier->owner().player_number(),
413- soldier->m_max_attack, max,
414- descr.get_max_attack(),
415- descr.get_attack_incr_per_level(),
416- soldier->m_attack_level);
417- soldier->m_max_attack = max;
418- if (max < soldier->m_min_attack) {
419- log
420- (" (and changing min_attack from %u to the "
421- "same value)",
422- soldier->m_min_attack);
423- soldier->m_min_attack = max;
424- }
425- log("\n");
426- }
427- }
428- assert(soldier->m_min_attack <= soldier->m_max_attack);
429- }
430-
431-#define VALIDATE_VALUE(pn, valuefunct, incrfunct, level_variable, variable) \
432- { \
433- uint32_t const value = \
434- descr.valuefunct() + descr.incrfunct() * soldier->level_variable; \
435- if (value != soldier->variable) { \
436- log \
437- ("WARNING: %s %s (%u) of player %u has " \
438- pn \
439- " = %u but it must be %u (= %u + %u * %u), changing it to that " \
440- "value\n", \
441- descr.tribe().name().c_str(), descr.descname().c_str(), \
442- soldier->serial(), soldier->owner().player_number(), \
443- soldier->variable, value, \
444- descr.valuefunct(), descr.incrfunct(), soldier->level_variable); \
445- soldier->variable = value; \
446- } \
447- } \
448-
449- VALIDATE_VALUE
450- ("defense", get_defense, get_defense_incr_per_level,
451- m_defense_level, m_defense);
452-
453- VALIDATE_VALUE
454- ("evade", get_evade, get_evade_incr_per_level,
455- m_evade_level, m_evade);
456+ if (soldier->m_hp_current > soldier->get_max_hitpoints())
457+ soldier->m_hp_current = soldier->get_max_hitpoints();
458
459 if (Serial const battle = fr.Unsigned32())
460 soldier->m_battle = &mol.get<Battle>(battle);
461@@ -882,11 +729,6 @@
462 if (upcast(Soldier const, soldier, &worker)) {
463 fw.Unsigned16(SOLDIER_WORKER_BOB_PACKET_VERSION);
464 fw.Unsigned32(soldier->m_hp_current);
465- fw.Unsigned32(soldier->m_hp_max);
466- fw.Unsigned32(soldier->m_min_attack);
467- fw.Unsigned32(soldier->m_max_attack);
468- fw.Unsigned32(soldier->m_defense);
469- fw.Unsigned32(soldier->m_evade);
470 fw.Unsigned32(soldier->m_hp_level);
471 fw.Unsigned32(soldier->m_attack_level);
472 fw.Unsigned32(soldier->m_defense_level);
473
474=== modified file 'src/writeHTML.cc'
475--- src/writeHTML.cc 2010-04-01 10:59:34 +0000
476+++ src/writeHTML.cc 2010-05-08 19:52:28 +0000
477@@ -592,9 +592,9 @@
478 snprintf
479 (buffer, sizeof(buffer),
480 _
481- ("Hitpoints is between %u and %u, plus %u for each level above 0 "
482+ ("Hitpoints is %u, plus %u for each level above 0 "
483 "(maximum level is %u)."),
484- m_min_hp, m_max_hp, m_hp_incr, m_max_hp_level);
485+ m_base_hp, m_hp_incr, m_max_hp_level);
486 fw.Text(buffer);
487 fw.Text
488 ("</p>\n"
489
490=== modified file 'tribes/atlanteans/soldier/conf'
491--- tribes/atlanteans/soldier/conf 2009-12-14 11:04:15 +0000
492+++ tribes/atlanteans/soldier/conf 2010-05-08 19:52:28 +0000
493@@ -5,7 +5,7 @@
494 max_evade_level=2
495
496 # initial values and per level increasements
497-hp=120-150
498+hp=135
499 hp_incr_per_level=40
500 attack=12-16
501 attack_incr_per_level=8
502
503=== modified file 'tribes/barbarians/soldier/conf'
504--- tribes/barbarians/soldier/conf 2009-12-14 11:04:15 +0000
505+++ tribes/barbarians/soldier/conf 2010-05-08 19:52:28 +0000
506@@ -7,7 +7,7 @@
507 max_evade_level=2
508
509 # initial values and per level increasements
510-hp=110-150
511+hp=130
512 hp_incr_per_level=28
513 attack=12-16
514 attack_incr_per_level=7
515
516=== modified file 'tribes/empire/soldier/conf'
517--- tribes/empire/soldier/conf 2009-12-14 11:04:15 +0000
518+++ tribes/empire/soldier/conf 2010-05-08 19:52:28 +0000
519@@ -8,7 +8,7 @@
520 max_evade_level=2
521
522 # initial values and per level increasements
523-hp=110-150
524+hp=130
525 hp_incr_per_level=21
526 attack=13-15
527 attack_incr_per_level=8

Subscribers

People subscribed via source and target branches

to status/vote changes: