ScummVM API documentation
character.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
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 3 of the License, or
10  * (at your option) 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  */
21 
22 #ifndef MM1_DATA_CHAR_H
23 #define MM1_DATA_CHAR_H
24 
25 #include "common/array.h"
26 #include "common/serializer.h"
27 #include "mm/mm1/data/items.h"
28 #include "mm/shared/xeen/sprites.h"
29 
30 namespace MM {
31 namespace MM1 {
32 
33 #define INVENTORY_COUNT 6
34 #define MAX_LEVEL 200
35 #define NUM_PORTRAITS 12
36 
37 enum CharacterClass {
38  KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
39  SORCERER = 5, ROBBER = 6, NONE = 0
40 };
41 
42 enum Race {
43  HUMAN = 1, ELF = 2, DWARF = 3, GNOME = 4, HALF_ORC = 5
44 };
45 
46 enum Alignment {
47  GOOD = 1, NEUTRAL = 2, EVIL = 3
48 };
49 
50 enum Sex {
51  MALE = 1, FEMALE = 2, YES_PLEASE = 3
52 };
53 
54 enum Condition {
55  FINE = 0, BAD_CONDITION = 0x80, ERADICATED = 0xff,
56  DEAD = 0x40, STONE = 0x20,
57  UNCONSCIOUS = 0x40, PARALYZED = 0x20, POISONED = 0x10,
58  DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
59 };
60 
61 enum ConditionEnum {
62  HEART_BROKEN = 1,
63  C_BLINDED = 2, // WEAK condition in Xeen
64  C_POISONED = 3,
65  C_DISEASED = 4,
66  C_ASLEEP = 8,
67  DEPRESSED = 9,
68  C_SILENCED = 10, // CONFUSED condition in Xeen
69  C_PARALYZED = 11,
70  C_UNCONSCIOUS = 12,
71  C_DEAD = 13,
72  C_STONE = 14,
73  C_ERADICATED = 15,
74  C_GOOD = 16
75 };
76 
77 enum Resistance {
78  RESISTANCE_MAGIC = 0, RESISTANCE_FIRE = 1, RESISTANCE_COLD = 2,
79  RESISTANCE_ELECTRICITY = 3, RESISTANCE_ACID = 4,
80  RESISTANCE_FEAR = 5, RESISTANCE_POISON = 6,
81  RESISTANCE_PSYCHIC = 7, RESISTANCE_15 = 15
82 };
83 
84 enum CharFlags0 {
85  CHARFLAG0_COURIER1 = 1,
86  CHARFLAG0_COURIER2 = 2,
87  CHARFLAG0_COURIER3 = 4,
88  CHARFLAG0_ZOM_CLUE = 8,
89  CHARFLAG0_ZAM_CLUE = 0x10,
90  CHARFLAG0_FOUND_CHEST = 0x20,
91  CHARFLAG0_40 = 0x40,
92  CHARFLAG0_DOG_STATUE = 0x80
93 };
94 
95 enum CharFlags1 {
96  CHARFLAG1_1 = 1,
97  CHARFLAG1_2 = 2,
98  CHARFLAG1_4 = 4,
99  CHARFLAG1_8 = 8,
100  CHARFLAG1_10 = 0x10,
101  CHARFLAG1_20 = 0x20,
102  CHARFLAG1_40 = 0x40,
103  CHARFLAG1_WORTHY = 0x80
104 };
105 
106 enum CharFlags2 {
107  CHARFLAG2_1 = 1,
108  CHARFLAG2_2 = 2,
109  CHARFLAG2_4 = 4,
110  CHARFLAG2_8 = 8,
111  CHARFLAG2_10 = 0x10,
112  CHARFLAG2_20 = 0x20,
113  CHARFLAG2_40 = 0x40,
114  CHARFLAG2_80 = 0x80
115 };
116 
117 enum CharFlags4 {
118  CHARFLAG4_ASSIGNED = 8,
119  CHARFLAG4_SIGN = 7,
120  CHARFLAG4_COLOR = 0xf,
121  CHARFLAG4_80 = 0x80
122 };
123 
124 enum CharFlags5 {
125  CHARFLAG5_1 = 1,
126  CHARFLAG5_2 = 2,
127  CHARFLAG5_4 = 4,
128  CHARFLAG5_8 = 8,
129  CHARFLAG5_10 = 0x10,
130  CHARFLAG5_20 = 0x20,
131  CHARFLAG5_40 = 0x40,
132  CHARFLAG5_80 = 0x80
133 };
134 
135 enum CharFlags6 {
136  CHARFLAG6_1 = 1,
137  CHARFLAG6_2 = 2,
138  CHARFLAG6_4 = 4,
139  CHARFLAG6_8 = 8,
140  CHARFLAG6_10 = 0x10,
141  CHARFLAG6_20 = 0x20,
142  CHARFLAG6_40 = 0x40,
143  CHARFLAG6_80 = 0x80
144 };
145 
146 enum CharFlags7 {
147  CHARFLAG7_1 = 1,
148  CHARFLAG7_2 = 2,
149  CHARFLAG7_4 = 4,
150  CHARFLAG7_8 = 8,
151  CHARFLAG7_10 = 0x10,
152  CHARFLAG7_20 = 0x20,
153  CHARFLAG7_40 = 0x40,
154  CHARFLAG7_80 = 0x80
155 };
156 
157 enum CharFlags8 {
158  CHARFLAG8_1 = 1,
159  CHARFLAG8_2 = 2,
160  CHARFLAG8_4 = 4,
161  CHARFLAG8_8 = 8,
162  CHARFLAG8_10 = 0x10,
163  CHARFLAG8_20 = 0x20,
164  CHARFLAG8_40 = 0x40,
165  CHARFLAG8_80 = 0x80
166 };
167 
168 enum CharFlags9 {
169  CHARFLAG9_1 = 1,
170  CHARFLAG9_2 = 2,
171  CHARFLAG9_4 = 4,
172  CHARFLAG9_8 = 8,
173  CHARFLAG9_10 = 0x10,
174  CHARFLAG9_20 = 0x20,
175  CHARFLAG9_40 = 0x40,
176  CHARFLAG9_80 = 0x80
177 };
178 
179 enum CharFlags10 {
180  CHARFLAG10_1 = 1,
181  CHARFLAG10_2 = 2,
182  CHARFLAG10_4 = 4,
183  CHARFLAG10_8 = 8,
184  CHARFLAG10_10 = 0x10,
185  CHARFLAG10_20 = 0x20,
186  CHARFLAG10_40 = 0x40,
187  CHARFLAG10_80 = 0x80
188 };
189 
190 enum CharFlags11 {
191  CHARFLAG11_GOT_ENDURANCE = 1,
192  CHARFLAG11_PERSONALITY = 2,
193  CHARFLAG11_GOT_INTELLIGENCE = 4,
194  CHARFLAG11_GOT_MIGHT = 8,
195  CHARFLAG11_GOT_ACCURACY = 0x10,
196  CHARFLAG11_GOT_SPEED = 0x20,
197  CHARFLAG11_GOT_LUCK = 0x40,
198  CHARFLAG11_CLERICS = 0x80
199 };
200 
201 enum CharFlags12 {
202  CHARFLAG12_1 = 1,
203  CHARFLAG12_2 = 2,
204  CHARFLAG12_4 = 4,
205  CHARFLAG12_8 = 8,
206  CHARFLAG12_10 = 0x10,
207  CHARFLAG12_20 = 0x20,
208  CHARFLAG12_40 = 0x40,
209  CHARFLAG12_80 = 0x80
210 };
211 
212 enum CharFlags13 {
213  CHARFLAG13_1 = 1,
214  CHARFLAG13_2 = 2,
215  CHARFLAG13_4 = 4,
216  CHARFLAG13_8 = 8,
217  CHARFLAG13_10 = 0x10,
218  CHARFLAG13_20 = 0x20,
219  CHARFLAG13_ALAMAR = 0x40,
220  CHARFLAG13_80 = 0x80
221 };
222 
223 class Inventory {
224 public:
225  struct Entry {
226  byte _id = 0;
227  byte _charges = 0;
228  operator bool() const { return _id != 0; }
229 // bool operator!() const { return !_id; }
230 // operator byte() const { return _id; }
231  };
232 private:
233  Common::Array<Entry> _items;
234 
238  typedef bool (*CategoryFn)(byte id);
239  bool hasCategory(CategoryFn fn) const;
240 
244  int getFreeSlot() const;
245 
246 public:
247  Inventory() {
248  clear();
249  }
250  Entry &operator[](uint idx) {
251  assert(idx < INVENTORY_COUNT);
252  return _items[idx];
253  }
254  const Entry &operator[](uint idx) const {
255  assert(idx < INVENTORY_COUNT);
256  return _items[idx];
257  }
258 
262  void synchronize(Common::Serializer &s, bool ids);
263 
267  void clear();
268 
272  bool empty() const;
273 
277  bool full() const;
278 
282  uint size() const;
283 
287  uint add(byte id, byte charges);
288 
292  void removeAt(uint idx);
293 
297  void remove(Entry *e);
298 
302  int indexOf(Entry *e) const;
303 
307  int indexOf(byte itemId) const;
308 
313  void removeCharge(Entry *e);
314 
319  bool hasWeapon() const { return hasCategory(isWeapon); }
320  bool hasMissile() const { return hasCategory(isMissile); }
321  bool hasTwoHanded() const { return hasCategory(isTwoHanded); }
322  bool hasArmor() const { return hasCategory(isArmor); }
323  bool hasShield() const { return hasCategory(isShield); }
324 
325  size_t getPerformanceTotal() const;
326 };
327 
333  uint8 _current = 0;
334  uint8 _base = 0;
335 
336  operator uint8() const { return _current; }
337  AttributePair &operator=(byte v) {
338  _base = _current = v;
339  return *this;
340  }
341  AttributePair &operator++() {
342  if (_base < 255)
343  _current = ++_base;
344  return *this;
345  }
346  AttributePair &operator--() {
347  if (_base > 0)
348  _current = --_base;
349  return *this;
350  }
351  void clear() { _current = _base = 0; }
352  void reset() { _current = _base; }
354  s.syncAsByte(_base);
355  s.syncAsByte(_current);
356  }
357 
358  size_t getPerformanceTotal() const {
359  return (size_t)_base + (size_t)_current;
360  }
361 };
362 
364  uint16 _current = 0;
365  uint16 _base = 0;
366 
367  void clear() { _current = _base = 0; }
368  AttributePair16 &operator=(byte v) {
369  _base = _current = v;
370  return *this;
371  }
372  operator uint16() const {
373  return _current;
374  }
376  s.syncAsUint16LE(_base);
377  s.syncAsUint16LE(_current);
378  }
379 
380  size_t getPerformanceTotal() const {
381  return (_base & 0xff) + (_base >> 8) +
382  (_current & 0xff) + (_current >> 8);
383  }
384 };
385 
387  AttributePair _magic;
388  AttributePair _fire;
389  AttributePair _cold;
390  AttributePair _electricity;
391  AttributePair _acid;
392  AttributePair _fear;
393  AttributePair _poison;
394  AttributePair _psychic;
395 };
396 
397 union Resistances {
398  ResistanceFields _s;
399  AttributePair _arr[8];
400 
401  Resistances();
402 
407 
408  size_t getPerformanceTotal() const;
409 };
410 
412 public:
413  AttributePair _intelligence;
414  AttributePair _might;
415  AttributePair _personality;
416  AttributePair _endurance;
417  AttributePair _speed;
418  AttributePair _accuracy;
419  AttributePair _luck;
420  AttributePair _level;
421 
422  AttributePair &getAttribute(uint i) {
423  return *_attributes[i];
424  }
425 private:
426  AttributePair *_attributes[8] = {
427  &_intelligence, &_might, &_personality, &_endurance,
428  &_speed, &_accuracy, &_luck, &_level
429  };
430 };
431 
432 struct Character : public PrimaryAttributes {
433  char _name[16] = { 0 };
434  Sex _sex = MALE;
435  Alignment _alignmentInitial = GOOD;
436  Alignment _alignment = GOOD;
437  Race _race = HUMAN;
438  CharacterClass _class = NONE;
439 
440  byte _age = 0;
441  int _ageDayCtr = 0;
442  AttributePair16 _sp;
443  AttributePair _spellLevel;
444  AttributePair _ac;
445 
446  uint32 _exp = 0;
447  uint16 _gems = 0;
448  uint16 _hpCurrent = 0, _hp = 0, _hpMax = 0;
449  uint32 _gold = 0;
450  uint8 _food = 0;
451  uint8 _condition = 0;
452  Inventory _equipped;
453  Inventory _backpack;
454  Resistances _resistances;
455 
456  AttributePair _physicalAttr, _missileAttr;
457  byte _trapCtr = 0;
458  byte _quest = 0;
459  byte _worthiness = 0;
460  byte _alignmentCtr = 0;
461  byte _flags[14];
462 
463  byte _portrait = 0;
464  Shared::Xeen::SpriteResource _faceSprites;
465 
466  // Non persistent fields
467  byte _numDrinks = 0;
468  // Combat fields
469  bool _checked = false;
470  bool _canAttack = false;
471  int _nonCombatSpell = -1;
472  int _combatSpell = -1;
473 
477  int spellNumber() const;
478 
482  void setSpellNumber(int spellNum);
483 
484  Character();
485 
491  void synchronize(Common::Serializer &s, int portraitNum = -1);
492 
496  bool operator==(const Character &rhs) const {
497  return !strcmp(_name, rhs._name);
498  }
499 
503  void clear();
504 
508  void gatherGold();
509 
513  enum TradeResult { TRADE_SUCCESS, TRADE_NO_ITEM, TRADE_FULL };
514  TradeResult trade(int whoTo, int itemIndex);
515 
519  struct LevelIncrease {
520  int _numHP;
521  int _numSpells;
522  };
523  LevelIncrease increaseLevel();
524 
528  enum BuyResult { BUY_SUCCESS, BUY_NOT_ENOUGH_GOLD, BUY_BACKPACK_FULL };
529  BuyResult buyItem(byte itemId);
530 
535  void updateAttributes();
536 
540  void updateAC();
541 
545  void updateSP();
546 
547  void updateResistances();
548 
552  Common::String getConditionString() const;
553 
557  void rest();
558 
562  bool hasItem(byte itemId) const;
563 
569  size_t getPerformanceTotal() const;
570 
574  void loadFaceSprites();
575 
580  byte statColor(int amount, int threshold) const;
581 
585  byte conditionColor() const;
586 
591  ConditionEnum worstCondition() const;
592 
596  static Common::String getConditionString(ConditionEnum cond);
597 
601  bool hasBadCondition() const {
602  return (_condition & BAD_CONDITION) != 0;
603  }
604 };
605 
606 } // namespace MM1
607 } // namespace MM
608 
609 #endif
Definition: str.h:59
uint size() const
void removeAt(uint idx)
Definition: character.h:363
Definition: character.h:225
int indexOf(Entry *e) const
Definition: sprites.h:52
bool operator==(const Character &rhs) const
Definition: character.h:496
Definition: serializer.h:79
Definition: character.h:519
Definition: character.h:411
Definition: character.h:397
bool hasWeapon() const
Definition: character.h:319
Definition: detection.h:27
uint add(byte id, byte charges)
BuyResult
Definition: character.h:528
bool empty() const
Definition: character.h:432
void removeCharge(Entry *e)
bool hasBadCondition() const
Definition: character.h:601
Definition: character.h:386
bool full() const
TradeResult
Definition: character.h:513
Definition: character.h:332
void synchronize(Common::Serializer &s, bool ids)
Definition: character.h:223