mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
754 lines
17 KiB
C++
754 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/algorithm.h"
|
|
#include "mm/mm1/data/character.h"
|
|
#include "mm/shared/utils/strings.h"
|
|
#include "mm/mm1/mm1.h"
|
|
|
|
namespace MM {
|
|
namespace MM1 {
|
|
|
|
static const int CLASS_HP_PER_LEVEL[6] = {
|
|
12, 10, 10, 8, 6, 8
|
|
};
|
|
|
|
Resistances::Resistances() {
|
|
for (int i = 0; i < 8; ++i)
|
|
_arr[i].clear();
|
|
}
|
|
|
|
void Resistances::synchronize(Common::Serializer &s) {
|
|
for (int i = 0; i < 8; ++i)
|
|
_arr[i].synchronize(s);
|
|
}
|
|
|
|
size_t Resistances::getPerformanceTotal() const {
|
|
size_t total = 0;
|
|
for (int i = 0; i < 8; ++i)
|
|
total += _arr[i].getPerformanceTotal();
|
|
return total;
|
|
}
|
|
|
|
void Inventory::clear() {
|
|
_items.clear();
|
|
_items.resize(INVENTORY_COUNT);
|
|
}
|
|
|
|
void Inventory::synchronize(Common::Serializer &s, bool ids) {
|
|
for (int i = 0; i < INVENTORY_COUNT; ++i)
|
|
s.syncAsByte(ids ? _items[i]._id : _items[i]._charges);
|
|
}
|
|
|
|
bool Inventory::empty() const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (_items[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Inventory::full() const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (!_items[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint Inventory::size() const {
|
|
for (int i = INVENTORY_COUNT - 1; i >= 0; --i) {
|
|
if (_items[i])
|
|
return i + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint Inventory::add(byte id, byte charges) {
|
|
uint idx = getFreeSlot();
|
|
_items[idx]._id = id;
|
|
_items[idx]._charges = charges;
|
|
|
|
return idx;
|
|
}
|
|
|
|
int Inventory::getFreeSlot() const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (!_items[i])
|
|
return i;
|
|
}
|
|
|
|
error("Inventory is full");
|
|
return -1;
|
|
}
|
|
|
|
|
|
void Inventory::removeAt(uint idx) {
|
|
_items.remove_at(idx);
|
|
_items.push_back(Entry());
|
|
}
|
|
|
|
void Inventory::remove(Entry *e) {
|
|
int index = indexOf(e);
|
|
assert(index >= 0);
|
|
removeAt(index);
|
|
}
|
|
|
|
int Inventory::indexOf(Entry *e) const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (e == &_items[i])
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int Inventory::indexOf(byte itemId) const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (_items[i]._id == itemId)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool Inventory::hasCategory(CategoryFn fn) const {
|
|
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
|
if (fn(_items[i]._id))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Inventory::removeCharge(Entry *e) {
|
|
if (e->_charges) {
|
|
if (--e->_charges == 0)
|
|
remove(e);
|
|
}
|
|
}
|
|
|
|
size_t Inventory::getPerformanceTotal() const {
|
|
size_t total = 0;
|
|
for (uint i = 0; i < size(); ++i)
|
|
total += (size_t)(*this)[i]._id + (size_t)(*this)[i]._charges;
|
|
|
|
return total;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
Character::Character() : PrimaryAttributes() {
|
|
Common::fill(&_flags[0], &_flags[14], 0);
|
|
}
|
|
|
|
void Character::synchronize(Common::Serializer &s, int portraitNum) {
|
|
char name[16];
|
|
if (s.isSaving()) {
|
|
// Save the name in uppercase to match original
|
|
Common::strlcpy(name, uppercase(_name).c_str(), 16);
|
|
s.syncBytes((byte *)name, 16);
|
|
} else {
|
|
s.syncBytes((byte *)name, 16);
|
|
name[15] = '\0';
|
|
|
|
if (g_engine->isEnhanced())
|
|
Common::strlcpy(_name, camelCase(name).c_str(), 16);
|
|
else
|
|
Common::strlcpy(_name, uppercase(name).c_str(), 16);
|
|
}
|
|
|
|
s.syncAsByte(_sex);
|
|
s.syncAsByte(_alignmentInitial);
|
|
s.syncAsByte(_alignment);
|
|
s.syncAsByte(_race);
|
|
s.syncAsByte(_class);
|
|
|
|
_intelligence.synchronize(s);
|
|
_might.synchronize(s);
|
|
_personality.synchronize(s);
|
|
_endurance.synchronize(s);
|
|
_speed.synchronize(s);
|
|
_accuracy.synchronize(s);
|
|
_luck.synchronize(s);
|
|
_level.synchronize(s);
|
|
s.syncAsByte(_age);
|
|
s.syncAsByte(_ageDayCtr);
|
|
|
|
s.syncAsUint32LE(_exp);
|
|
s.syncAsUint16LE(_sp._current);
|
|
s.syncAsUint16LE(_sp._base);
|
|
_spellLevel.synchronize(s);
|
|
|
|
s.syncAsUint16LE(_gems);
|
|
s.syncAsUint16LE(_hpCurrent);
|
|
s.syncAsUint16LE(_hp);
|
|
s.syncAsUint16LE(_hpMax);
|
|
|
|
// Gold field is annoying by being 3 bytes
|
|
uint goldLo = _gold & 0xffff;
|
|
uint goldHi = _gold >> 16;
|
|
s.syncAsUint16LE(goldLo);
|
|
s.syncAsByte(goldHi);
|
|
if (s.isLoading())
|
|
_gold = goldLo | (goldHi << 16);
|
|
|
|
_ac.synchronize(s);
|
|
s.syncAsByte(_food);
|
|
s.syncAsByte(_condition);
|
|
|
|
_equipped.synchronize(s, true);
|
|
_backpack.synchronize(s, true);
|
|
_equipped.synchronize(s, false);
|
|
_backpack.synchronize(s, false);
|
|
|
|
_resistances.synchronize(s);
|
|
_physicalAttr.synchronize(s);
|
|
_missileAttr.synchronize(s);
|
|
|
|
s.syncAsByte(_trapCtr);
|
|
s.syncAsByte(_quest);
|
|
s.syncAsByte(_worthiness);
|
|
s.syncAsByte(_alignmentCtr);
|
|
s.syncBytes(_flags, 14);
|
|
|
|
s.syncAsByte(_portrait);
|
|
if (s.isLoading()) {
|
|
if (portraitNum != -1)
|
|
_portrait = portraitNum;
|
|
if (_portrait >= NUM_PORTRAITS)
|
|
// Ensure portrait number is valid
|
|
_portrait = 0;
|
|
}
|
|
|
|
if (s.isLoading())
|
|
loadFaceSprites();
|
|
}
|
|
|
|
void Character::loadFaceSprites() {
|
|
if (_portrait != 0xff && g_engine->isEnhanced()) {
|
|
Common::Path cname(Common::String::format("char%02d.fac",
|
|
_portrait * 2 + (_sex == MALE ? 0 : 1) + 1));
|
|
_faceSprites.load(cname);
|
|
}
|
|
}
|
|
|
|
void Character::clear() {
|
|
Common::fill(_name, _name + 16, 0);
|
|
_sex = (Sex)0;
|
|
_alignmentInitial = (Alignment)0;
|
|
_alignment = (Alignment)0;
|
|
_race = (Race)0;
|
|
_class = (CharacterClass)0;
|
|
_intelligence = _might = _personality = _endurance = 0;
|
|
_speed = _accuracy = _luck = 0;
|
|
_level = 1;
|
|
_age = _ageDayCtr = 0;
|
|
_exp = 0;
|
|
_sp = 0;
|
|
_spellLevel = 0;
|
|
_gems = 0;
|
|
_hpCurrent = _hp = _hpMax = 0;
|
|
_gold = 0;
|
|
_ac = 0;
|
|
_food = 0;
|
|
_condition = 0;
|
|
_quest = 0;
|
|
_equipped.clear();
|
|
_backpack.clear();
|
|
|
|
_alignmentInitial = GOOD;
|
|
_alignment = GOOD;
|
|
_resistances._s._magic.clear();
|
|
_resistances._s._fear.clear();
|
|
_resistances._s._poison.clear();
|
|
_resistances._s._psychic.clear();
|
|
_trapCtr = _alignmentCtr = 0;
|
|
|
|
Common::fill(&_flags[0], &_flags[8], 0);
|
|
}
|
|
|
|
|
|
void Character::gatherGold() {
|
|
uint total = 0;
|
|
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
|
total += g_globals->_party[i]._gold;
|
|
g_globals->_party[i]._gold = 0;
|
|
}
|
|
|
|
_gold = total;
|
|
}
|
|
|
|
Character::TradeResult Character::trade(int whoTo, int itemIndex) {
|
|
Character &dest = g_globals->_party[whoTo];
|
|
if (&dest == this)
|
|
return TRADE_SUCCESS;
|
|
|
|
if (dest._backpack.full())
|
|
return TRADE_FULL;
|
|
if (!_backpack[itemIndex])
|
|
return TRADE_NO_ITEM;
|
|
|
|
Inventory::Entry e = _backpack[itemIndex];
|
|
_backpack.removeAt(itemIndex);
|
|
dest._backpack.add(e._id, e._charges);
|
|
|
|
return TRADE_SUCCESS;
|
|
}
|
|
|
|
Character::LevelIncrease Character::increaseLevel() {
|
|
++_level;
|
|
++_age;
|
|
if (_age > 220)
|
|
_age = 220;
|
|
_trapCtr += 2;
|
|
|
|
int classNum = _class == NONE ? ROBBER : _class;
|
|
int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
|
|
|
|
if (_endurance._base >= 40)
|
|
newHP += 10;
|
|
else if (_endurance._base >= 35)
|
|
newHP += 9;
|
|
else if (_endurance._base >= 30)
|
|
newHP += 8;
|
|
else if (_endurance._base >= 27)
|
|
newHP += 7;
|
|
else if (_endurance._base >= 24)
|
|
newHP += 6;
|
|
else if (_endurance._base >= 21)
|
|
newHP += 5;
|
|
else if (_endurance._base >= 19)
|
|
newHP += 4;
|
|
else if (_endurance._base >= 17)
|
|
newHP += 3;
|
|
else if (_endurance._base >= 15)
|
|
newHP += 2;
|
|
else if (_endurance._base >= 13)
|
|
newHP += 1;
|
|
else if (_endurance._base >= 9)
|
|
newHP += 0;
|
|
else if (_endurance._base >= 7)
|
|
newHP = MAX(newHP - 1, 1);
|
|
else if (_endurance._base >= 5)
|
|
newHP = MAX(newHP - 2, 1);
|
|
else
|
|
newHP = MAX(newHP - 3, 1);
|
|
|
|
_hpCurrent += newHP;
|
|
_hp = _hpMax = _hpCurrent;
|
|
|
|
int gainedSpells = 0;
|
|
if (classNum < ARCHER) {
|
|
if (_level._base < 7)
|
|
gainedSpells = 0;
|
|
else if (_level._base == 7)
|
|
gainedSpells = 1;
|
|
else if (_level._base == 9)
|
|
gainedSpells = 2;
|
|
else if (_level._base == 11)
|
|
gainedSpells = 3;
|
|
else if (_level._base == 13)
|
|
gainedSpells = 4;
|
|
} else if (classNum < SORCERER) {
|
|
if (_level._base == 3)
|
|
gainedSpells = 2;
|
|
else if (_level._base == 5)
|
|
gainedSpells = 3;
|
|
else if (_level._base == 7)
|
|
gainedSpells = 4;
|
|
else if (_level._base == 9)
|
|
gainedSpells = 5;
|
|
else if (_level._base == 11)
|
|
gainedSpells = 6;
|
|
else if (_level._base == 13)
|
|
gainedSpells = 7;
|
|
}
|
|
|
|
LevelIncrease result;
|
|
result._numHP = newHP;
|
|
result._numSpells = gainedSpells;
|
|
return result;
|
|
}
|
|
|
|
Character::BuyResult Character::buyItem(byte itemId) {
|
|
// Check if backpack is full
|
|
if (_backpack.full())
|
|
return BUY_BACKPACK_FULL;
|
|
|
|
// Check character has enough gold
|
|
g_globals->_items.getItem(itemId);
|
|
Item &item = g_globals->_currItem;
|
|
if (_gold < item._cost)
|
|
return BUY_NOT_ENOUGH_GOLD;
|
|
|
|
// Add the item
|
|
_gold -= item._cost;
|
|
_backpack.add(itemId, item._maxCharges);
|
|
|
|
return BUY_SUCCESS;
|
|
}
|
|
|
|
void Character::updateAttributes() {
|
|
_intelligence.reset();
|
|
_might.reset();
|
|
_personality.reset();
|
|
_endurance.reset();
|
|
_speed.reset();
|
|
_personality.reset();
|
|
_endurance.reset();
|
|
_speed.reset();
|
|
_accuracy.reset();
|
|
_luck.reset();
|
|
_level.reset();
|
|
_spellLevel.reset();
|
|
}
|
|
|
|
void Character::updateAC() {
|
|
int ac = _ac._base;
|
|
|
|
if (_speed >= 40)
|
|
ac += 9;
|
|
else if (_speed >= 35)
|
|
ac += 8;
|
|
else if (_speed >= 30)
|
|
ac += 7;
|
|
else if (_speed >= 25)
|
|
ac += 6;
|
|
else if (_speed >= 21)
|
|
ac += 5;
|
|
else if (_speed >= 19)
|
|
ac += 4;
|
|
else if (_speed >= 17)
|
|
ac += 3;
|
|
else if (_speed >= 15)
|
|
ac += 2;
|
|
else if (_speed >= 13)
|
|
ac += 1;
|
|
else if (_speed >= 9)
|
|
ac += 0;
|
|
else if (_speed >= 7)
|
|
ac = MAX(ac - 1, 0);
|
|
else if (_speed >= 5)
|
|
ac = MAX(ac - 2, 0);
|
|
else
|
|
ac = MAX(ac - 3, 0);
|
|
|
|
_ac._current = ac;
|
|
}
|
|
|
|
void Character::updateSP() {
|
|
int intelligence = _intelligence._current;
|
|
int personality = _personality._current;
|
|
int level = _level._current;
|
|
int index = 3;
|
|
AttributePair newSP;
|
|
|
|
// Spell points only relevant for spell casters
|
|
if (_spellLevel._current) {
|
|
int threshold = -1;
|
|
if (_class == CLERIC)
|
|
threshold = personality;
|
|
else if (_class == SORCERER)
|
|
threshold = intelligence;
|
|
else if (level < 7)
|
|
threshold = -1;
|
|
else {
|
|
level -= 6;
|
|
threshold = (_class == PALADIN) ?
|
|
personality : intelligence;
|
|
}
|
|
|
|
if (threshold >= 40)
|
|
index += 10;
|
|
else if (threshold >= 35)
|
|
index += 9;
|
|
else if (threshold >= 30)
|
|
index += 8;
|
|
else if (threshold >= 27)
|
|
index += 7;
|
|
else if (threshold >= 24)
|
|
index += 6;
|
|
else if (threshold >= 21)
|
|
index += 5;
|
|
else if (threshold >= 19)
|
|
index += 4;
|
|
else if (threshold >= 17)
|
|
index += 3;
|
|
else if (threshold >= 15)
|
|
index += 2;
|
|
else if (threshold >= 13)
|
|
index += 1;
|
|
else if (threshold < 5)
|
|
index -= 3;
|
|
else if (threshold < 7)
|
|
index -= 2;
|
|
else if (threshold < 9)
|
|
index -= 1;
|
|
|
|
// Calculate the SP
|
|
newSP._base += index * level;
|
|
newSP._current = newSP._base;
|
|
}
|
|
|
|
// Set the character's new SP
|
|
_sp = newSP;
|
|
}
|
|
|
|
void Character::updateResistances() {
|
|
for (int i = 0; i < 8; ++i)
|
|
_resistances._arr[i]._current = _resistances._arr[i]._base;
|
|
}
|
|
|
|
Common::String Character::getConditionString() const {
|
|
Common::String result;
|
|
int cond = _condition;
|
|
|
|
if (cond == 0) {
|
|
result += STRING["stats.conditions.good"];
|
|
} else if (cond == ERADICATED) {
|
|
result += STRING["stats.conditions.eradicated"];
|
|
} else {
|
|
if (cond & BAD_CONDITION) {
|
|
// Fatal conditions
|
|
if (cond & DEAD)
|
|
result += STRING["stats.conditions.dead"] + ",";
|
|
if (cond & STONE)
|
|
result += STRING["stats.conditions.stone"] + ",";
|
|
} else {
|
|
if (cond & UNCONSCIOUS)
|
|
result += STRING["stats.conditions.unconscious"] + ",";
|
|
if (cond & PARALYZED)
|
|
result += STRING["stats.conditions.paralyzed"] + ",";
|
|
if (cond & POISONED)
|
|
result += STRING["stats.conditions.poisoned"] + ",";
|
|
if (cond & DISEASED)
|
|
result += STRING["stats.conditions.diseased"] + ",";
|
|
if (cond & SILENCED)
|
|
result += STRING["stats.conditions.silenced"] + ",";
|
|
if (cond & BLINDED)
|
|
result += STRING["stats.conditions.blinded"] + ",";
|
|
if (cond & ASLEEP)
|
|
result += STRING["stats.conditions.asleep"] + ",";
|
|
}
|
|
|
|
result.deleteLastChar();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void Character::rest() {
|
|
// Characters with a bad condition like
|
|
// being stoned can't rest
|
|
if (_condition & BAD_CONDITION)
|
|
return;
|
|
|
|
updateSP();
|
|
updateAttributes();
|
|
updateAC();
|
|
updateResistances();
|
|
|
|
_condition &= ~(ASLEEP | BLINDED | SILENCED |
|
|
PARALYZED | UNCONSCIOUS);
|
|
|
|
if (_hpCurrent == 0)
|
|
_hpCurrent = 1;
|
|
|
|
// Increment the day counter. When it overflows,
|
|
// it's time to increment the character's age by a year
|
|
if (_ageDayCtr++ > 255) {
|
|
_ageDayCtr = 0;
|
|
if (_age < 255)
|
|
++_age;
|
|
}
|
|
|
|
if ((g_engine->getRandomNumber(70) + 80) < _age) {
|
|
// Older characters have a chance of falling unconscious
|
|
_condition = UNCONSCIOUS | BAD_CONDITION;
|
|
return;
|
|
}
|
|
|
|
// Fun fact: in the original if any of the attributes reach zero,
|
|
// then it jumps to an instruction that jumps to itself, freezing the game.
|
|
// For ScummVM, I just limit the minimum to 1 instead
|
|
if (_age >= 60) {
|
|
_might._current = MAX(_might._current - 1, 1);
|
|
_endurance._current = MAX(_endurance._current - 1, 1);
|
|
_speed._current = MAX(_speed._current - 1, 1);
|
|
}
|
|
if (_age >= 70) {
|
|
_might._current = MAX(_might._current - 1, 1);
|
|
_endurance._current = MAX(_endurance._current - 1, 1);
|
|
_speed._current = MAX(_speed._current - 1, 1);
|
|
}
|
|
|
|
if (_age >= 80) {
|
|
_might._current = MAX((int)_might._current - 2, 1);
|
|
}
|
|
|
|
if (_food > 0) {
|
|
--_food;
|
|
|
|
if (_condition & POISONED) {
|
|
_hpMax /= 2;
|
|
} else {
|
|
_hpMax = _hp;
|
|
}
|
|
|
|
if (!(_condition & DISEASED)) {
|
|
_hpCurrent = _hpMax;
|
|
_sp._current = _sp._base;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool Character::hasItem(byte itemId) const {
|
|
return _backpack.indexOf(itemId) != -1 ||
|
|
_equipped.indexOf(itemId) != -1;
|
|
}
|
|
|
|
#define PERF16(x) ((x & 0xff) + ((x >> 8) & 0xff))
|
|
#define PERF32(x) ((x & 0xff) + ((x >> 8) & 0xff) + \
|
|
((x >> 16) & 0xff) + ((x >> 24) & 0xff))
|
|
|
|
size_t Character::getPerformanceTotal() const {
|
|
size_t totalFlags = 0;
|
|
for (int i = 0; i < 14; ++i)
|
|
totalFlags += _flags[i];
|
|
|
|
return (int)_sex
|
|
+ _alignmentInitial
|
|
+ _alignment
|
|
+ _race
|
|
+ _class
|
|
+ _intelligence.getPerformanceTotal()
|
|
+ _might.getPerformanceTotal()
|
|
+ _personality.getPerformanceTotal()
|
|
+ _endurance.getPerformanceTotal()
|
|
+ _speed.getPerformanceTotal()
|
|
+ _accuracy.getPerformanceTotal()
|
|
+ _luck.getPerformanceTotal()
|
|
+ _level.getPerformanceTotal()
|
|
+ (int)_age + (int)_ageDayCtr
|
|
+ PERF32(_exp)
|
|
+ _sp.getPerformanceTotal()
|
|
+ _spellLevel.getPerformanceTotal()
|
|
+ PERF16(_gems)
|
|
+ PERF16(_hpCurrent)
|
|
+ PERF16(_hp)
|
|
+ PERF16(_hpMax)
|
|
+ PERF32(_gold)
|
|
+ _ac
|
|
+ _food
|
|
+ _condition
|
|
+ _equipped.getPerformanceTotal()
|
|
+ _backpack.getPerformanceTotal()
|
|
+ _resistances.getPerformanceTotal()
|
|
+ _physicalAttr.getPerformanceTotal()
|
|
+ _missileAttr.getPerformanceTotal()
|
|
+ _trapCtr
|
|
+ _quest
|
|
+ _worthiness
|
|
+ _alignmentCtr
|
|
+ totalFlags;
|
|
}
|
|
|
|
byte Character::statColor(int amount, int threshold) const {
|
|
if (amount < 1)
|
|
return 6;
|
|
else if (amount > threshold)
|
|
return 2;
|
|
else if (amount == threshold)
|
|
return 15;
|
|
else if (amount >= (threshold / 4))
|
|
return 9;
|
|
else
|
|
return 32;
|
|
}
|
|
|
|
byte Character::conditionColor() const {
|
|
if (_condition == ERADICATED)
|
|
return 32;
|
|
else if (_condition == FINE)
|
|
return 15;
|
|
else if (_condition & BAD_CONDITION)
|
|
return 6;
|
|
else
|
|
return 9;
|
|
}
|
|
|
|
ConditionEnum Character::worstCondition() const {
|
|
if (_condition == ERADICATED) {
|
|
return C_ERADICATED;
|
|
} else if (_condition & BAD_CONDITION) {
|
|
if (_condition & DEAD)
|
|
return C_DEAD;
|
|
if (_condition & STONE)
|
|
return C_STONE;
|
|
if (_condition & UNCONSCIOUS)
|
|
return C_UNCONSCIOUS;
|
|
} else {
|
|
if (_condition & PARALYZED)
|
|
return C_PARALYZED;
|
|
if (_condition & POISONED)
|
|
return C_POISONED;
|
|
if (_condition & DISEASED)
|
|
return C_DISEASED;
|
|
if (_condition & SILENCED)
|
|
return C_SILENCED;
|
|
if (_condition & BLINDED)
|
|
return C_BLINDED;
|
|
if (_condition & ASLEEP)
|
|
return C_ASLEEP;
|
|
}
|
|
|
|
return C_GOOD;
|
|
}
|
|
|
|
Common::String Character::getConditionString(ConditionEnum cond) {
|
|
switch (cond) {
|
|
case C_ERADICATED: return STRING["stats.conditions.eradicated"];
|
|
case C_DEAD: return STRING["stats.conditions.dead"];
|
|
case C_STONE: return STRING["stats.conditions.stone"];
|
|
case C_UNCONSCIOUS: return STRING["stats.conditions.unconscious"];
|
|
case C_PARALYZED: return STRING["stats.conditions.paralyzed"];
|
|
case C_POISONED: return STRING["stats.conditions.poisoned"];
|
|
case C_DISEASED: return STRING["stats.conditions.diseased"];
|
|
case C_SILENCED: return STRING["stats.conditions.silenced"];
|
|
case C_BLINDED: return STRING["stats.conditions.blinded"];
|
|
case C_ASLEEP: return STRING["stats.conditions.asleep"];
|
|
default: return STRING["stats.conditions.good"];
|
|
}
|
|
}
|
|
|
|
int Character::spellNumber() const {
|
|
return g_events->isInCombat() ? _combatSpell : _nonCombatSpell;
|
|
}
|
|
|
|
void Character::setSpellNumber(int spellNum) {
|
|
if (g_events->isInCombat())
|
|
_combatSpell = spellNum;
|
|
else
|
|
_nonCombatSpell = spellNum;
|
|
}
|
|
|
|
} // namespace MM1
|
|
} // namespace MM
|