Initial commit
This commit is contained in:
36
engines/mm/mm1/data/active_spells.cpp
Normal file
36
engines/mm/mm1/data/active_spells.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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 "mm/mm1/data/active_spells.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
void ActiveSpells::clear() {
|
||||
Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
|
||||
}
|
||||
|
||||
void ActiveSpells::synchronize(Common::Serializer &s) {
|
||||
s.syncBytes(_arr, ACTIVE_SPELLS_COUNT);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
73
engines/mm/mm1/data/active_spells.h
Normal file
73
engines/mm/mm1/data/active_spells.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_ACTIVE_SPELLS_H
|
||||
#define MM1_DATA_ACTIVE_SPELLS_H
|
||||
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define ACTIVE_SPELLS_COUNT 18
|
||||
|
||||
struct ActiveSpellsStruct {
|
||||
byte fear;
|
||||
byte cold;
|
||||
byte fire;
|
||||
byte poison;
|
||||
byte acid;
|
||||
byte electricity;
|
||||
byte magic;
|
||||
byte light;
|
||||
byte leather_skin;
|
||||
byte levitate;
|
||||
byte walk_on_water;
|
||||
byte guard_dog;
|
||||
byte psychic_protection;
|
||||
byte bless;
|
||||
byte invisbility;
|
||||
byte shield;
|
||||
byte power_shield;
|
||||
byte cursed;
|
||||
};
|
||||
|
||||
union ActiveSpells {
|
||||
ActiveSpellsStruct _s;
|
||||
byte _arr[ACTIVE_SPELLS_COUNT];
|
||||
|
||||
ActiveSpells() { clear(); }
|
||||
|
||||
/**
|
||||
* Clear the spells
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Synchronize spell data to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
754
engines/mm/mm1/data/character.cpp
Normal file
754
engines/mm/mm1/data/character.cpp
Normal file
@@ -0,0 +1,754 @@
|
||||
/* 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
|
||||
609
engines/mm/mm1/data/character.h
Normal file
609
engines/mm/mm1/data/character.h
Normal file
@@ -0,0 +1,609 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_CHAR_H
|
||||
#define MM1_DATA_CHAR_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/items.h"
|
||||
#include "mm/shared/xeen/sprites.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define INVENTORY_COUNT 6
|
||||
#define MAX_LEVEL 200
|
||||
#define NUM_PORTRAITS 12
|
||||
|
||||
enum CharacterClass {
|
||||
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
|
||||
SORCERER = 5, ROBBER = 6, NONE = 0
|
||||
};
|
||||
|
||||
enum Race {
|
||||
HUMAN = 1, ELF = 2, DWARF = 3, GNOME = 4, HALF_ORC = 5
|
||||
};
|
||||
|
||||
enum Alignment {
|
||||
GOOD = 1, NEUTRAL = 2, EVIL = 3
|
||||
};
|
||||
|
||||
enum Sex {
|
||||
MALE = 1, FEMALE = 2, YES_PLEASE = 3
|
||||
};
|
||||
|
||||
enum Condition {
|
||||
FINE = 0, BAD_CONDITION = 0x80, ERADICATED = 0xff,
|
||||
DEAD = 0x40, STONE = 0x20,
|
||||
UNCONSCIOUS = 0x40, PARALYZED = 0x20, POISONED = 0x10,
|
||||
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
|
||||
};
|
||||
|
||||
enum ConditionEnum {
|
||||
HEART_BROKEN = 1,
|
||||
C_BLINDED = 2, // WEAK condition in Xeen
|
||||
C_POISONED = 3,
|
||||
C_DISEASED = 4,
|
||||
C_ASLEEP = 8,
|
||||
DEPRESSED = 9,
|
||||
C_SILENCED = 10, // CONFUSED condition in Xeen
|
||||
C_PARALYZED = 11,
|
||||
C_UNCONSCIOUS = 12,
|
||||
C_DEAD = 13,
|
||||
C_STONE = 14,
|
||||
C_ERADICATED = 15,
|
||||
C_GOOD = 16
|
||||
};
|
||||
|
||||
enum Resistance {
|
||||
RESISTANCE_MAGIC = 0, RESISTANCE_FIRE = 1, RESISTANCE_COLD = 2,
|
||||
RESISTANCE_ELECTRICITY = 3, RESISTANCE_ACID = 4,
|
||||
RESISTANCE_FEAR = 5, RESISTANCE_POISON = 6,
|
||||
RESISTANCE_PSYCHIC = 7, RESISTANCE_15 = 15
|
||||
};
|
||||
|
||||
enum CharFlags0 {
|
||||
CHARFLAG0_COURIER1 = 1,
|
||||
CHARFLAG0_COURIER2 = 2,
|
||||
CHARFLAG0_COURIER3 = 4,
|
||||
CHARFLAG0_ZOM_CLUE = 8,
|
||||
CHARFLAG0_ZAM_CLUE = 0x10,
|
||||
CHARFLAG0_FOUND_CHEST = 0x20,
|
||||
CHARFLAG0_40 = 0x40,
|
||||
CHARFLAG0_DOG_STATUE = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags1 {
|
||||
CHARFLAG1_1 = 1,
|
||||
CHARFLAG1_2 = 2,
|
||||
CHARFLAG1_4 = 4,
|
||||
CHARFLAG1_8 = 8,
|
||||
CHARFLAG1_10 = 0x10,
|
||||
CHARFLAG1_20 = 0x20,
|
||||
CHARFLAG1_40 = 0x40,
|
||||
CHARFLAG1_WORTHY = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags2 {
|
||||
CHARFLAG2_1 = 1,
|
||||
CHARFLAG2_2 = 2,
|
||||
CHARFLAG2_4 = 4,
|
||||
CHARFLAG2_8 = 8,
|
||||
CHARFLAG2_10 = 0x10,
|
||||
CHARFLAG2_20 = 0x20,
|
||||
CHARFLAG2_40 = 0x40,
|
||||
CHARFLAG2_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags4 {
|
||||
CHARFLAG4_ASSIGNED = 8,
|
||||
CHARFLAG4_SIGN = 7,
|
||||
CHARFLAG4_COLOR = 0xf,
|
||||
CHARFLAG4_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags5 {
|
||||
CHARFLAG5_1 = 1,
|
||||
CHARFLAG5_2 = 2,
|
||||
CHARFLAG5_4 = 4,
|
||||
CHARFLAG5_8 = 8,
|
||||
CHARFLAG5_10 = 0x10,
|
||||
CHARFLAG5_20 = 0x20,
|
||||
CHARFLAG5_40 = 0x40,
|
||||
CHARFLAG5_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags6 {
|
||||
CHARFLAG6_1 = 1,
|
||||
CHARFLAG6_2 = 2,
|
||||
CHARFLAG6_4 = 4,
|
||||
CHARFLAG6_8 = 8,
|
||||
CHARFLAG6_10 = 0x10,
|
||||
CHARFLAG6_20 = 0x20,
|
||||
CHARFLAG6_40 = 0x40,
|
||||
CHARFLAG6_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags7 {
|
||||
CHARFLAG7_1 = 1,
|
||||
CHARFLAG7_2 = 2,
|
||||
CHARFLAG7_4 = 4,
|
||||
CHARFLAG7_8 = 8,
|
||||
CHARFLAG7_10 = 0x10,
|
||||
CHARFLAG7_20 = 0x20,
|
||||
CHARFLAG7_40 = 0x40,
|
||||
CHARFLAG7_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags8 {
|
||||
CHARFLAG8_1 = 1,
|
||||
CHARFLAG8_2 = 2,
|
||||
CHARFLAG8_4 = 4,
|
||||
CHARFLAG8_8 = 8,
|
||||
CHARFLAG8_10 = 0x10,
|
||||
CHARFLAG8_20 = 0x20,
|
||||
CHARFLAG8_40 = 0x40,
|
||||
CHARFLAG8_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags9 {
|
||||
CHARFLAG9_1 = 1,
|
||||
CHARFLAG9_2 = 2,
|
||||
CHARFLAG9_4 = 4,
|
||||
CHARFLAG9_8 = 8,
|
||||
CHARFLAG9_10 = 0x10,
|
||||
CHARFLAG9_20 = 0x20,
|
||||
CHARFLAG9_40 = 0x40,
|
||||
CHARFLAG9_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags10 {
|
||||
CHARFLAG10_1 = 1,
|
||||
CHARFLAG10_2 = 2,
|
||||
CHARFLAG10_4 = 4,
|
||||
CHARFLAG10_8 = 8,
|
||||
CHARFLAG10_10 = 0x10,
|
||||
CHARFLAG10_20 = 0x20,
|
||||
CHARFLAG10_40 = 0x40,
|
||||
CHARFLAG10_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags11 {
|
||||
CHARFLAG11_GOT_ENDURANCE = 1,
|
||||
CHARFLAG11_PERSONALITY = 2,
|
||||
CHARFLAG11_GOT_INTELLIGENCE = 4,
|
||||
CHARFLAG11_GOT_MIGHT = 8,
|
||||
CHARFLAG11_GOT_ACCURACY = 0x10,
|
||||
CHARFLAG11_GOT_SPEED = 0x20,
|
||||
CHARFLAG11_GOT_LUCK = 0x40,
|
||||
CHARFLAG11_CLERICS = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags12 {
|
||||
CHARFLAG12_1 = 1,
|
||||
CHARFLAG12_2 = 2,
|
||||
CHARFLAG12_4 = 4,
|
||||
CHARFLAG12_8 = 8,
|
||||
CHARFLAG12_10 = 0x10,
|
||||
CHARFLAG12_20 = 0x20,
|
||||
CHARFLAG12_40 = 0x40,
|
||||
CHARFLAG12_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags13 {
|
||||
CHARFLAG13_1 = 1,
|
||||
CHARFLAG13_2 = 2,
|
||||
CHARFLAG13_4 = 4,
|
||||
CHARFLAG13_8 = 8,
|
||||
CHARFLAG13_10 = 0x10,
|
||||
CHARFLAG13_20 = 0x20,
|
||||
CHARFLAG13_ALAMAR = 0x40,
|
||||
CHARFLAG13_80 = 0x80
|
||||
};
|
||||
|
||||
class Inventory {
|
||||
public:
|
||||
struct Entry {
|
||||
byte _id = 0;
|
||||
byte _charges = 0;
|
||||
operator bool() const { return _id != 0; }
|
||||
// bool operator!() const { return !_id; }
|
||||
// operator byte() const { return _id; }
|
||||
};
|
||||
private:
|
||||
Common::Array<Entry> _items;
|
||||
|
||||
/**
|
||||
* Used to test if the inventory has a category of item
|
||||
*/
|
||||
typedef bool (*CategoryFn)(byte id);
|
||||
bool hasCategory(CategoryFn fn) const;
|
||||
|
||||
/**
|
||||
* Returns the index of a free slot
|
||||
*/
|
||||
int getFreeSlot() const;
|
||||
|
||||
public:
|
||||
Inventory() {
|
||||
clear();
|
||||
}
|
||||
Entry &operator[](uint idx) {
|
||||
assert(idx < INVENTORY_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
const Entry &operator[](uint idx) const {
|
||||
assert(idx < INVENTORY_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves or loads the inventory data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, bool ids);
|
||||
|
||||
/**
|
||||
* Clears the inventory
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Returns true if the inventory is empty
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* Returns true if the inventory is full
|
||||
*/
|
||||
bool full() const;
|
||||
|
||||
/**
|
||||
* Returns the size of the backpack that's filled in
|
||||
*/
|
||||
uint size() const;
|
||||
|
||||
/**
|
||||
* Adds an item to the inventory
|
||||
*/
|
||||
uint add(byte id, byte charges);
|
||||
|
||||
/**
|
||||
* Removes an index from the inventory
|
||||
*/
|
||||
void removeAt(uint idx);
|
||||
|
||||
/**
|
||||
* Remove an entry from the inventory
|
||||
*/
|
||||
void remove(Entry *e);
|
||||
|
||||
/**
|
||||
* Returns the index of a given entry
|
||||
*/
|
||||
int indexOf(Entry *e) const;
|
||||
|
||||
/**
|
||||
* Returns the index of an entry with a given id
|
||||
*/
|
||||
int indexOf(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Decreases the charge on a magic item, and removes
|
||||
* it if the charges have run out
|
||||
*/
|
||||
void removeCharge(Entry *e);
|
||||
|
||||
/**
|
||||
* The following methods return true if any of
|
||||
* the contained items are of the given category
|
||||
*/
|
||||
bool hasWeapon() const { return hasCategory(isWeapon); }
|
||||
bool hasMissile() const { return hasCategory(isMissile); }
|
||||
bool hasTwoHanded() const { return hasCategory(isTwoHanded); }
|
||||
bool hasArmor() const { return hasCategory(isArmor); }
|
||||
bool hasShield() const { return hasCategory(isShield); }
|
||||
|
||||
size_t getPerformanceTotal() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute pair representing it's base value and the
|
||||
* current temporary value
|
||||
*/
|
||||
struct AttributePair {
|
||||
uint8 _current = 0;
|
||||
uint8 _base = 0;
|
||||
|
||||
operator uint8() const { return _current; }
|
||||
AttributePair &operator=(byte v) {
|
||||
_base = _current = v;
|
||||
return *this;
|
||||
}
|
||||
AttributePair &operator++() {
|
||||
if (_base < 255)
|
||||
_current = ++_base;
|
||||
return *this;
|
||||
}
|
||||
AttributePair &operator--() {
|
||||
if (_base > 0)
|
||||
_current = --_base;
|
||||
return *this;
|
||||
}
|
||||
void clear() { _current = _base = 0; }
|
||||
void reset() { _current = _base; }
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_base);
|
||||
s.syncAsByte(_current);
|
||||
}
|
||||
|
||||
size_t getPerformanceTotal() const {
|
||||
return (size_t)_base + (size_t)_current;
|
||||
}
|
||||
};
|
||||
|
||||
struct AttributePair16 {
|
||||
uint16 _current = 0;
|
||||
uint16 _base = 0;
|
||||
|
||||
void clear() { _current = _base = 0; }
|
||||
AttributePair16 &operator=(byte v) {
|
||||
_base = _current = v;
|
||||
return *this;
|
||||
}
|
||||
operator uint16() const {
|
||||
return _current;
|
||||
}
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_base);
|
||||
s.syncAsUint16LE(_current);
|
||||
}
|
||||
|
||||
size_t getPerformanceTotal() const {
|
||||
return (_base & 0xff) + (_base >> 8) +
|
||||
(_current & 0xff) + (_current >> 8);
|
||||
}
|
||||
};
|
||||
|
||||
struct ResistanceFields {
|
||||
AttributePair _magic;
|
||||
AttributePair _fire;
|
||||
AttributePair _cold;
|
||||
AttributePair _electricity;
|
||||
AttributePair _acid;
|
||||
AttributePair _fear;
|
||||
AttributePair _poison;
|
||||
AttributePair _psychic;
|
||||
};
|
||||
|
||||
union Resistances {
|
||||
ResistanceFields _s;
|
||||
AttributePair _arr[8];
|
||||
|
||||
Resistances();
|
||||
|
||||
/**
|
||||
* Handles save/loading resistances
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
size_t getPerformanceTotal() const;
|
||||
};
|
||||
|
||||
struct PrimaryAttributes {
|
||||
public:
|
||||
AttributePair _intelligence;
|
||||
AttributePair _might;
|
||||
AttributePair _personality;
|
||||
AttributePair _endurance;
|
||||
AttributePair _speed;
|
||||
AttributePair _accuracy;
|
||||
AttributePair _luck;
|
||||
AttributePair _level;
|
||||
|
||||
AttributePair &getAttribute(uint i) {
|
||||
return *_attributes[i];
|
||||
}
|
||||
private:
|
||||
AttributePair *_attributes[8] = {
|
||||
&_intelligence, &_might, &_personality, &_endurance,
|
||||
&_speed, &_accuracy, &_luck, &_level
|
||||
};
|
||||
};
|
||||
|
||||
struct Character : public PrimaryAttributes {
|
||||
char _name[16] = { 0 };
|
||||
Sex _sex = MALE;
|
||||
Alignment _alignmentInitial = GOOD;
|
||||
Alignment _alignment = GOOD;
|
||||
Race _race = HUMAN;
|
||||
CharacterClass _class = NONE;
|
||||
|
||||
byte _age = 0;
|
||||
int _ageDayCtr = 0;
|
||||
AttributePair16 _sp;
|
||||
AttributePair _spellLevel;
|
||||
AttributePair _ac;
|
||||
|
||||
uint32 _exp = 0;
|
||||
uint16 _gems = 0;
|
||||
uint16 _hpCurrent = 0, _hp = 0, _hpMax = 0;
|
||||
uint32 _gold = 0;
|
||||
uint8 _food = 0;
|
||||
uint8 _condition = 0;
|
||||
Inventory _equipped;
|
||||
Inventory _backpack;
|
||||
Resistances _resistances;
|
||||
|
||||
AttributePair _physicalAttr, _missileAttr;
|
||||
byte _trapCtr = 0;
|
||||
byte _quest = 0;
|
||||
byte _worthiness = 0;
|
||||
byte _alignmentCtr = 0;
|
||||
byte _flags[14];
|
||||
|
||||
byte _portrait = 0;
|
||||
Shared::Xeen::SpriteResource _faceSprites;
|
||||
|
||||
// Non persistent fields
|
||||
byte _numDrinks = 0;
|
||||
// Combat fields
|
||||
bool _checked = false;
|
||||
bool _canAttack = false;
|
||||
int _nonCombatSpell = -1;
|
||||
int _combatSpell = -1;
|
||||
|
||||
/**
|
||||
* Get the selected combat/noncombat spell number
|
||||
*/
|
||||
int spellNumber() const;
|
||||
|
||||
/**
|
||||
* Sets the selected spell
|
||||
*/
|
||||
void setSpellNumber(int spellNum);
|
||||
|
||||
Character();
|
||||
|
||||
/**
|
||||
* Handles save/loading a character
|
||||
* @param portraitNum Override for portrait to use for
|
||||
* a character being loaded from the game defaults
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, int portraitNum = -1);
|
||||
|
||||
/**
|
||||
* Equality test
|
||||
*/
|
||||
bool operator==(const Character &rhs) const {
|
||||
return !strcmp(_name, rhs._name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearing the character
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Gathers the party gold into the character
|
||||
*/
|
||||
void gatherGold();
|
||||
|
||||
/**
|
||||
* Trade an item to another
|
||||
*/
|
||||
enum TradeResult { TRADE_SUCCESS, TRADE_NO_ITEM, TRADE_FULL };
|
||||
TradeResult trade(int whoTo, int itemIndex);
|
||||
|
||||
/**
|
||||
* Increase the character's level by 1 at a trainer
|
||||
*/
|
||||
struct LevelIncrease {
|
||||
int _numHP;
|
||||
int _numSpells;
|
||||
};
|
||||
LevelIncrease increaseLevel();
|
||||
|
||||
/**
|
||||
* Buy an item
|
||||
*/
|
||||
enum BuyResult { BUY_SUCCESS, BUY_NOT_ENOUGH_GOLD, BUY_BACKPACK_FULL };
|
||||
BuyResult buyItem(byte itemId);
|
||||
|
||||
/**
|
||||
* Updates the current attribute levels to match
|
||||
* their base values
|
||||
*/
|
||||
void updateAttributes();
|
||||
|
||||
/**
|
||||
* Updates the character's AC
|
||||
*/
|
||||
void updateAC();
|
||||
|
||||
/**
|
||||
* Updates the character's SP
|
||||
*/
|
||||
void updateSP();
|
||||
|
||||
void updateResistances();
|
||||
|
||||
/**
|
||||
* Gets a character's condition string
|
||||
*/
|
||||
Common::String getConditionString() const;
|
||||
|
||||
/**
|
||||
* Rest the character
|
||||
*/
|
||||
void rest();
|
||||
|
||||
/**
|
||||
* Returns true if the character has a given item
|
||||
*/
|
||||
bool hasItem(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Gets the numeric value of every property a character
|
||||
* has and totals it up to give a stupid 'performance'
|
||||
* value for the party at the end of the game
|
||||
*/
|
||||
size_t getPerformanceTotal() const;
|
||||
|
||||
/**
|
||||
* Loads the face sprites for the character
|
||||
*/
|
||||
void loadFaceSprites();
|
||||
|
||||
/**
|
||||
* Returns the color to use in enhanced mode to
|
||||
* represent the color of a character attribute
|
||||
*/
|
||||
byte statColor(int amount, int threshold) const;
|
||||
|
||||
/**
|
||||
* Returns the condition color for display
|
||||
*/
|
||||
byte conditionColor() const;
|
||||
|
||||
/**
|
||||
* Returns the worst condition, if any, a character
|
||||
* currently has.
|
||||
*/
|
||||
ConditionEnum worstCondition() const;
|
||||
|
||||
/**
|
||||
* Returns a string for a given condition
|
||||
*/
|
||||
static Common::String getConditionString(ConditionEnum cond);
|
||||
|
||||
/**
|
||||
* Returns true if the character has a fatal condition
|
||||
*/
|
||||
bool hasBadCondition() const {
|
||||
return (_condition & BAD_CONDITION) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
33
engines/mm/mm1/data/game_state.cpp
Normal file
33
engines/mm/mm1/data/game_state.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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/game_state.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
GameState::GameState() {
|
||||
Common::fill(&_activeSpells._arr[0], &_activeSpells._arr[ACTIVE_SPELLS_COUNT], 0);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
51
engines/mm/mm1/data/game_state.h
Normal file
51
engines/mm/mm1/data/game_state.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_GAME_STATE_H
|
||||
#define MM1_DATA_GAME_STATE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/party.h"
|
||||
#include "mm/mm1/data/active_spells.h"
|
||||
#include "mm/mm1/data/spells_state.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
/**
|
||||
* This acts as a container for everything in the game
|
||||
* that is persisted to savegames
|
||||
*/
|
||||
struct GameState {
|
||||
Party _party;
|
||||
ActiveSpells _activeSpells;
|
||||
SpellsState _spellsState;
|
||||
|
||||
GameState();
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
71
engines/mm/mm1/data/int_array.h
Normal file
71
engines/mm/mm1/data/int_array.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_INT_ARRAY_H
|
||||
#define MM1_DATA_INT_ARRAY_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class IntArray : public Common::Array<uint> {
|
||||
public:
|
||||
IntArray() : Common::Array<uint>() {}
|
||||
|
||||
int indexOf(uint val) const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
if ((*this)[i] == val)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the array contains the value
|
||||
*/
|
||||
bool contains(uint val) {
|
||||
return indexOf(val) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a given item from the array
|
||||
*/
|
||||
void remove(uint val) {
|
||||
int idx = indexOf(val);
|
||||
if (idx != -1)
|
||||
remove_at(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the array
|
||||
*/
|
||||
void push_back(uint val) {
|
||||
assert(!contains(val));
|
||||
Common::Array<uint>::push_back(val);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
93
engines/mm/mm1/data/items.cpp
Normal file
93
engines/mm/mm1/data/items.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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 "mm/mm1/data/items.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
uint Item::getSellCost() const {
|
||||
uint cost = _cost;
|
||||
if (_maxCharges)
|
||||
cost /= 2;
|
||||
cost /= 2;
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
bool ItemsArray::load() {
|
||||
Common::File f;
|
||||
if (!f.open("items.txt"))
|
||||
return false;
|
||||
|
||||
resize(255);
|
||||
for (int lineNum = 0; lineNum < 255; ++lineNum) {
|
||||
Item &item = (*this)[lineNum];
|
||||
Common::String line = f.readLine();
|
||||
assert(line.size() > 20 && line[0] == '"' && line[15] == '"');
|
||||
|
||||
item._name = Common::String(line.c_str() + 1, line.c_str() + 15);
|
||||
line = Common::String(line.c_str() + 16);
|
||||
while (item._name.lastChar() == ' ')
|
||||
item._name.deleteLastChar();
|
||||
|
||||
item._disablements = getNextValue(line);
|
||||
item._constBonus_id = getNextValue(line);
|
||||
item._constBonus_value = getNextValue(line);
|
||||
item._tempBonus_id = getNextValue(line);
|
||||
|
||||
if (item._tempBonus_id != 0xff) {item._tempBonus_value = getNextValue(line);}
|
||||
else {item._spellId = getNextValue(line);}
|
||||
|
||||
item._maxCharges = getNextValue(line);
|
||||
item._cost = getNextValue(line);
|
||||
item._damage = getNextValue(line);
|
||||
item._AC_Dmg = getNextValue(line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Item *ItemsArray::getItem(byte index) const {
|
||||
assert(index > 0);
|
||||
g_globals->_currItem = (*this)[index - 1];
|
||||
|
||||
return &g_globals->_currItem;
|
||||
}
|
||||
|
||||
ItemCategory getItemCategory(byte itemId) {
|
||||
if (isWeapon(itemId))
|
||||
return ITEMCAT_WEAPON;
|
||||
if (isMissile(itemId))
|
||||
return ITEMCAT_MISSILE;
|
||||
if (isTwoHanded(itemId))
|
||||
return ITEMCAT_TWO_HANDED;
|
||||
if (isArmor(itemId))
|
||||
return ITEMCAT_ARMOR;
|
||||
if (isShield(itemId))
|
||||
return ITEMCAT_SHIELD;
|
||||
|
||||
return ITEMCAT_NONE;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
142
engines/mm/mm1/data/items.h
Normal file
142
engines/mm/mm1/data/items.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_ITEMS_H
|
||||
#define MM1_DATA_ITEMS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "mm/mm1/data/text_parser.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
enum ItemId {
|
||||
GARLIC_ID = 175,
|
||||
WOLFSBANE_ID = 176,
|
||||
BELLADONNA_ID = 177,
|
||||
VELLUM_SCROLL_ID = 231,
|
||||
RUBY_WHISTLE_ID = 232,
|
||||
KINGS_PASS_ID = 233,
|
||||
MERCHANTS_PASS_ID = 234,
|
||||
CRYSTAL_KEY_ID = 235,
|
||||
CORAL_KEY_ID = 236,
|
||||
BRONZE_KEY_ID = 237,
|
||||
SILVER_KEY_ID = 238,
|
||||
GOLD_KEY_ID = 239,
|
||||
DIAMOND_KEY_ID = 240,
|
||||
CACTUS_NECTAR_ID = 241,
|
||||
MAP_OF_DESERT_ID = 242,
|
||||
LASER_BLASTER_ID = 243,
|
||||
DRAGONS_TOOTH_ID = 244,
|
||||
WYVERN_EYE_ID = 245,
|
||||
MEDUSA_HEAD_ID = 246,
|
||||
RING_OF_OKRIM_ID = 247,
|
||||
B_QUEEN_IDOL_ID = 248,
|
||||
W_QUEEN_IDOL_ID = 249,
|
||||
PIRATES_MAP_A_ID = 250,
|
||||
PIRATES_MAP_B_ID = 251,
|
||||
THUNDRANIUM_ID = 252,
|
||||
KEY_CARD_ID = 253,
|
||||
EYE_OF_GOROS_ID = 254,
|
||||
USELESS_ITEM_ID = 255
|
||||
};
|
||||
|
||||
enum EnablementBit {
|
||||
KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
|
||||
CLERIC_BIT = 4, SORCERER_BIT = 2, ROBBER_BIT = 1,
|
||||
GOOD_BIT = 0x80, EVIL_BIT = 0x40,
|
||||
NEUTRAL_BIT = GOOD_BIT | EVIL_BIT
|
||||
};
|
||||
|
||||
enum ItemCategory {
|
||||
ITEMCAT_NONE, ITEMCAT_WEAPON, ITEMCAT_MISSILE,
|
||||
ITEMCAT_TWO_HANDED, ITEMCAT_ARMOR, ITEMCAT_SHIELD
|
||||
};
|
||||
|
||||
enum EquipMode {
|
||||
NO_EQUIP_BONUS = 0, IS_EQUIPPABLE = 1,
|
||||
EQUIP_CURSED = 0xff
|
||||
};
|
||||
|
||||
enum TransferKind {
|
||||
TK_GEMS = 1, TK_GOLD = 2, TK_FOOD = 3, TK_ITEM = 4
|
||||
};
|
||||
|
||||
|
||||
struct ItemData {
|
||||
byte _disablements = 0;
|
||||
byte _constBonus_id = 0; // id equals to character characteristic id, except special "EquipMode" values
|
||||
byte _constBonus_value = 0; // value to be added to character characteristic
|
||||
byte _tempBonus_id = 0; // id equals to character characteristic id, except 0xff
|
||||
byte _tempBonus_value = 0; // value to be added to character characteristic
|
||||
byte _spellId = 0;
|
||||
byte _maxCharges = 0; // for spells and tempBonus
|
||||
uint16 _cost = 0;
|
||||
byte _damage = 0;
|
||||
byte _AC_Dmg = 0; //it is AC for armor and additional damage for weapon
|
||||
};
|
||||
|
||||
struct Item : public ItemData {
|
||||
Common::String _name;
|
||||
|
||||
/**
|
||||
* Get the sell value
|
||||
*/
|
||||
uint getSellCost() const;
|
||||
};
|
||||
|
||||
struct ItemsArray : public Common::Array<Item>, public TextParser {
|
||||
ItemsArray() {}
|
||||
|
||||
/**
|
||||
* Loads the items array
|
||||
*/
|
||||
bool load();
|
||||
|
||||
/**
|
||||
* Gets an item
|
||||
*/
|
||||
Item *getItem(byte index) const;
|
||||
};
|
||||
|
||||
inline bool isWeapon(byte id) {
|
||||
return id >= 1 && id <= 60;
|
||||
}
|
||||
inline bool isMissile(byte id) {
|
||||
return id >= 61 && id <= 85;
|
||||
}
|
||||
inline bool isTwoHanded(byte id) {
|
||||
return id >= 86 && id <= 120;
|
||||
}
|
||||
inline bool isArmor(byte id) {
|
||||
return id >= 121 && id <= 155;
|
||||
}
|
||||
inline bool isShield(byte id) {
|
||||
return id >= 156 && id <= 170;
|
||||
}
|
||||
|
||||
extern ItemCategory getItemCategory(byte itemId);
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
33
engines/mm/mm1/data/locations.cpp
Normal file
33
engines/mm/mm1/data/locations.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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 "mm/mm1/data/locations.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
const byte TownData::TOWN_MAP_ID1[5] = { 4, 3, 3, 2, 0x1A };
|
||||
const byte TownData::TOWN_MAP_ID2[5] = { 6, 0xC, 2, 8, 0xB };
|
||||
const byte TownData::TOWN_MAP_X[5] = { 8, 1, 11, 12, 4 };
|
||||
const byte TownData::TOWN_MAP_Y[5] = { 5, 12, 13, 8, 6 };
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
106
engines/mm/mm1/data/locations.h
Normal file
106
engines/mm/mm1/data/locations.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_LOCATIONS_H
|
||||
#define MM1_DATA_LOCATIONS_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
struct BlacksmithData {
|
||||
const byte BLACKSMITH_CLASS_USAGE[6] = { 0x20, 0x10, 8, 4, 2, 1 };
|
||||
};
|
||||
|
||||
struct BuyWeaponData {
|
||||
const byte WEAPONS_TOWN1[6] = { 2, 3, 5, 61, 62, 86 };
|
||||
const byte WEAPONS_TOWN2[6] = { 4, 6, 8, 63, 87, 88 };
|
||||
const byte WEAPONS_TOWN3[6] = { 9, 10, 62, 64, 89, 91 };
|
||||
const byte WEAPONS_TOWN4[6] = { 23, 67, 69, 93, 97, 99 };
|
||||
const byte WEAPONS_TOWN5[6] = { 7, 11, 64, 65, 90, 92 };
|
||||
const byte *WEAPONS[5] = {
|
||||
WEAPONS_TOWN1, WEAPONS_TOWN2, WEAPONS_TOWN3,
|
||||
WEAPONS_TOWN4, WEAPONS_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
struct BuyArmorData {
|
||||
const byte ARMOR_TOWN1[6] = { 156, 121, 122, 123, 124, 125 };
|
||||
const byte ARMOR_TOWN2[6] = { 156, 157, 121, 122, 123, 124 };
|
||||
const byte ARMOR_TOWN3[6] = { 157, 121, 124, 125, 126, 127 };
|
||||
const byte ARMOR_TOWN4[6] = { 160, 128, 131, 132, 133, 134 };
|
||||
const byte ARMOR_TOWN5[6] = { 157, 123, 124, 125, 126, 127 };
|
||||
const byte *ARMOR[5] = {
|
||||
ARMOR_TOWN1, ARMOR_TOWN2, ARMOR_TOWN3,
|
||||
ARMOR_TOWN4, ARMOR_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
struct BuyMiscData {
|
||||
const byte MISC_TOWN1[6] = { 172, 171, 175, 178, 185, 192 };
|
||||
const byte MISC_TOWN2[6] = { 172, 171, 174, 183, 188, 195 };
|
||||
const byte MISC_TOWN3[6] = { 173, 175, 176, 179, 184, 195 };
|
||||
const byte MISC_TOWN4[6] = { 180, 196, 211, 215, 219, 223 };
|
||||
const byte MISC_TOWN5[6] = { 171, 173, 177, 185, 186, 192 };
|
||||
const byte *MISC[5] = {
|
||||
MISC_TOWN1, MISC_TOWN2, MISC_TOWN3,
|
||||
MISC_TOWN4, MISC_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
#define MAX_FOOD 40
|
||||
|
||||
struct MarketData {
|
||||
const byte FOOD_COST[5] = { 5, 10, 20, 200, 50 };
|
||||
};
|
||||
|
||||
struct TempleData {
|
||||
const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
|
||||
const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
|
||||
const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
|
||||
const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
|
||||
const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
|
||||
const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
|
||||
const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
|
||||
const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
|
||||
};
|
||||
|
||||
struct TrainingData {
|
||||
const int TRAINING_COSTS1[7] = {
|
||||
25, 50, 100, 200, 400, 800, 1500
|
||||
};
|
||||
const int TRAINING_COSTS2[7] = {
|
||||
40, 75, 150, 300, 600, 1200, 2500
|
||||
};
|
||||
};
|
||||
|
||||
struct TownData {
|
||||
static const byte TOWN_MAP_ID1[5];
|
||||
static const byte TOWN_MAP_ID2[5];
|
||||
static const byte TOWN_MAP_X[5];
|
||||
static const byte TOWN_MAP_Y[5];
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
106
engines/mm/mm1/data/monsters.cpp
Normal file
106
engines/mm/mm1/data/monsters.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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/file.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/gfx/dta.h"
|
||||
#include "mm/mm1/gfx/screen_decoder.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
static const uint16 PALETTE[76] = {
|
||||
0xf470, 0xf420, 0xfe20, 0xf630, 0xf420, 0xf620, 0xf460, 0xf6e0,
|
||||
0xf510, 0xfe40, 0xf420, 0xf410, 0xfd50, 0xfc90, 0xf430, 0xfc30,
|
||||
0xf770, 0xfc30, 0xf420, 0xf430, 0xf420, 0xf490, 0xf110, 0xf4e0,
|
||||
0xf430, 0xfd60, 0xf430, 0xfc20, 0xf2a0, 0xf470, 0xf4e0, 0xf250,
|
||||
0xf430, 0xf320, 0xfee0, 0xf420, 0xf220, 0xf420, 0xfdd0, 0xf420,
|
||||
0xf620, 0xfc20, 0xfc10, 0xf520, 0xf420, 0xf220, 0xf420, 0xfa50,
|
||||
0xfe20, 0xf620, 0xf470, 0xf420, 0xfe10, 0xf4e0, 0xfe40, 0xf140,
|
||||
0xf290, 0xf410, 0xf520, 0xf410, 0xfc10, 0xf120, 0xf420, 0xfe10,
|
||||
0xf520, 0xf4a0, 0xfe60, 0xfe60, 0xf620, 0xf620, 0xfce0, 0xf420,
|
||||
0xfc20, 0xfc20, 0xfd90, 0xf420
|
||||
};
|
||||
|
||||
Monsters::Monsters() : _monPix(MONPIX_DTA) {
|
||||
}
|
||||
|
||||
bool Monsters::load() {
|
||||
Common::File f;
|
||||
if (!f.open("monsters.txt"))
|
||||
return false;
|
||||
|
||||
for (int lineNum = 0; lineNum < MONSTERS_COUNT; ++lineNum) {
|
||||
Monster &mon = _monsters[lineNum];
|
||||
Common::String line = f.readLine();
|
||||
assert(line.size() > 20 && line[0] == '"' && line[16] == '"');
|
||||
|
||||
mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
|
||||
while (mon._name.hasSuffix(" "))
|
||||
mon._name.deleteLastChar();
|
||||
|
||||
line = Common::String(line.c_str() + 17);
|
||||
mon._count = getNextValue(line);
|
||||
mon._fleeThreshold = getNextValue(line);
|
||||
mon._defaultHP = getNextValue(line);
|
||||
mon._defaultAC = getNextValue(line);
|
||||
mon._maxDamage = getNextValue(line);
|
||||
mon._numberOfAttacks = getNextValue(line);
|
||||
mon._speed = getNextValue(line);
|
||||
mon._experience = getNextValue(line);
|
||||
mon._loot = getNextValue(line);
|
||||
mon._resistUndead = getNextValue(line);
|
||||
mon._resistances = getNextValue(line);
|
||||
mon._bonusOnTouch = getNextValue(line);
|
||||
mon._specialAbility = getNextValue(line);
|
||||
mon._specialThreshold = getNextValue(line);
|
||||
mon._counterFlags = getNextValue(line);
|
||||
mon._imgNum = getNextValue(line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface Monsters::getMonsterImage(int imgNum) {
|
||||
Common::SeekableReadStream *entry = _monPix.load(imgNum);
|
||||
entry->skip(2);
|
||||
|
||||
// Decode the image
|
||||
Graphics::ManagedSurface img;
|
||||
Gfx::ScreenDecoder decoder;
|
||||
|
||||
uint pal = PALETTE[imgNum];
|
||||
decoder._indexes[0] = pal & 0xf;
|
||||
decoder._indexes[1] = (pal >> 4) & 0xf;
|
||||
decoder._indexes[2] = (pal >> 8) & 0xf;
|
||||
decoder._indexes[3] = (pal >> 12) & 0xf;
|
||||
|
||||
if (!decoder.loadStream(*entry, 104, 96))
|
||||
error("Failed decoding monster image");
|
||||
|
||||
img.copyFrom(*decoder.getSurface());
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
140
engines/mm/mm1/data/monsters.h
Normal file
140
engines/mm/mm1/data/monsters.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_MONSTERS_H
|
||||
#define MM1_DATA_MONSTERS_H
|
||||
|
||||
#include "mm/mm1/gfx/dta.h"
|
||||
#include "mm/mm1/data/text_parser.h"
|
||||
#include "common/str.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define MONSTERS_COUNT 195
|
||||
|
||||
enum MonsterStatus {
|
||||
MON_PARALYZED = 0, MON_WEBBED = 1, MON_HELD = 2,
|
||||
MON_ASLEEP = 3, MON_MINDLESS = 4, MON_SILENCED = 5,
|
||||
MON_BLINDED = 6, MON_AFRAID = 7, MON_DEAD = 8
|
||||
};
|
||||
enum MonsterStatusFlag {
|
||||
MONFLAG_AFRAID = 1, MONFLAG_BLIND = 2, MONFLAG_SILENCED = 4,
|
||||
MONFLAG_MINDLESS = 8, MONFLAG_ASLEEP = 0x10,
|
||||
MONFLAG_HELD = 0x20, MONFLAG_WEBBED = 0x40,
|
||||
MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
|
||||
};
|
||||
|
||||
enum MonsterLoot {
|
||||
DROPS_GEMS = 0x1, // if 1 - a monster can drop gems
|
||||
GOLD_DROP = 0xfe>>1 // _loot>>1 - gold value that a monster drops
|
||||
};
|
||||
|
||||
enum MonsterResistUndead {
|
||||
MAGIC_RESISTANCE = 0x7f,
|
||||
IS_UNDEAD = 0x80
|
||||
};
|
||||
|
||||
enum MonsterBonusOnTouch {
|
||||
TOUCH_BONUS_VALUE = 0x7f,
|
||||
HAS_BONUS = 0x80
|
||||
};
|
||||
|
||||
enum MonsterResistances {
|
||||
MONRES_ASLEEP = 1, MONRES_FEAR = 2, MONRES_PARALYSIS = 4,
|
||||
MONRES_ENERGY = 8, MONRES_COLD = 0x10,
|
||||
MONRES_ELECTRICITY = 0x20, MONRES_FIRE = 0x40,
|
||||
MONRES_PHYSICAL_ATTACK = 0x80,
|
||||
};
|
||||
|
||||
enum MonsterSpecialAbility {
|
||||
HAS_RANGED_ATTACK = 0x80, // 1 if has ranged attack, 0 if has special attack
|
||||
ATTACK_VALUE = 0x7f // damage for ranged attack. Special attack id for special attack
|
||||
};
|
||||
|
||||
enum MonsterCounter {
|
||||
COUNTER_BITS = 0xf,
|
||||
COUNTER_THRESHOLD1 = 0x10, COUNTER_THRESHOLD2 = 0x20,
|
||||
COUNTER_REGENERATE = 0x40, COUNTER_ADVANCES = 0x80
|
||||
};
|
||||
|
||||
struct Monster {
|
||||
Common::String _name; // char _name[15];
|
||||
byte _count;
|
||||
byte _fleeThreshold;
|
||||
byte _defaultHP;
|
||||
byte _defaultAC;
|
||||
byte _maxDamage;
|
||||
byte _numberOfAttacks;
|
||||
byte _speed;
|
||||
uint16 _experience;
|
||||
byte _loot;
|
||||
byte _resistUndead;
|
||||
byte _resistances;
|
||||
byte _bonusOnTouch;
|
||||
byte _specialAbility;
|
||||
byte _specialThreshold; // % of luck of special attack
|
||||
byte _counterFlags;
|
||||
byte _imgNum;
|
||||
|
||||
// Runtime combat fields
|
||||
byte _level = 0;
|
||||
bool _checked = false;
|
||||
byte _status = 0;
|
||||
byte _hp = 0;
|
||||
byte _ac = 0;
|
||||
|
||||
Common::String getDisplayName() const {
|
||||
return _name;
|
||||
}
|
||||
};
|
||||
|
||||
class Monsters : public TextParser {
|
||||
private:
|
||||
Monster _monsters[MONSTERS_COUNT];
|
||||
Gfx::DTA _monPix;
|
||||
public:
|
||||
Monsters();
|
||||
|
||||
/**
|
||||
* Load the monster list
|
||||
*/
|
||||
bool load();
|
||||
|
||||
/**
|
||||
* Square brackets operator
|
||||
*/
|
||||
const Monster &operator[](uint i) {
|
||||
assert(i >= 1 && i <= MONSTERS_COUNT);
|
||||
return _monsters[i - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a monster image
|
||||
*/
|
||||
Graphics::ManagedSurface getMonsterImage(int imgNum);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
185
engines/mm/mm1/data/party.cpp
Normal file
185
engines/mm/mm1/data/party.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/* 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 "mm/mm1/data/party.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define SHARE_FIELD(FIELD) \
|
||||
for (uint i = 0; i < party.size(); ++i) \
|
||||
total += party[i].FIELD; \
|
||||
avg = total / party.size(); \
|
||||
party[0].FIELD = avg + (total % party.size()); \
|
||||
for (uint i = 1; i < party.size(); ++i) \
|
||||
party[i].FIELD = avg;
|
||||
|
||||
void Party::share(TransferKind shareType) {
|
||||
auto &party = g_globals->_party;
|
||||
int total = 0, avg;
|
||||
|
||||
switch (shareType) {
|
||||
case TK_GEMS:
|
||||
SHARE_FIELD(_gems);
|
||||
break;
|
||||
case TK_GOLD:
|
||||
SHARE_FIELD(_gold);
|
||||
break;
|
||||
case TK_FOOD:
|
||||
SHARE_FIELD(_food);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint Party::getPartyGold() const {
|
||||
uint total = 0;
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
total += (*this)[i]._gold;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void Party::clearPartyGold() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._gold = 0;
|
||||
}
|
||||
|
||||
void Party::clearPartyGems() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._gems = 0;
|
||||
}
|
||||
|
||||
void Party::clearPartyFood() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._food = 0;
|
||||
}
|
||||
|
||||
void Party::updateAC() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i].updateAC();
|
||||
}
|
||||
|
||||
void Party::combatDone() {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
Character &c = (*this)[i];
|
||||
c.updateAttributes();
|
||||
c.updateResistances();
|
||||
|
||||
if (!(c._condition & BAD_CONDITION))
|
||||
c._condition &= ~(ASLEEP | SILENCED);
|
||||
}
|
||||
}
|
||||
|
||||
bool Party::hasItem(byte itemId) const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
if (c._equipped.indexOf(itemId) != -1 ||
|
||||
c._backpack.indexOf(itemId) != -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Party::isPartyDead() const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
if (!(c._condition & (ASLEEP | PARALYZED | UNCONSCIOUS | BAD_CONDITION)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Party::checkPartyDead() const {
|
||||
if (isPartyDead()) {
|
||||
// At this point, there's no good characters.
|
||||
// So redirect to the death screen
|
||||
g_events->replaceView("Dead", true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Party::checkPartyIncapacitated() const {
|
||||
bool isActive = false;
|
||||
for (uint i = 0; i < size() && !isActive; ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
isActive = !(c._condition & (BAD_CONDITION | UNCONSCIOUS));
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
return false;
|
||||
} else {
|
||||
g_events->replaceView("Dead", true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Party::synchronize(Common::Serializer &s) {
|
||||
int partySize = size();
|
||||
s.syncAsByte(partySize);
|
||||
if (s.isLoading())
|
||||
resize(partySize);
|
||||
|
||||
for (int i = 0; i < partySize; ++i) {
|
||||
// Sync the common properties
|
||||
Character &c = (*this)[i];
|
||||
c.synchronize(s);
|
||||
|
||||
// Sync extra properties
|
||||
s.syncAsSByte(c._combatSpell);
|
||||
s.syncAsSByte(c._nonCombatSpell);
|
||||
}
|
||||
|
||||
if (s.isLoading())
|
||||
g_globals->_currCharacter = &front();
|
||||
}
|
||||
|
||||
void Party::rearrange(const Common::Array<Character *> &party) {
|
||||
assert(party.size() == size());
|
||||
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
for (uint j = i; j < size(); ++j) {
|
||||
if (party[i] == &(*this)[j]) {
|
||||
if (j != i)
|
||||
insert_at(i, remove_at(j));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Party::indexOf(const Character *c) {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
if (&(*this)[i] == c)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
110
engines/mm/mm1/data/party.h
Normal file
110
engines/mm/mm1/data/party.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_PARTY_H
|
||||
#define MM1_DATA_PARTY_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define MAX_PARTY_SIZE 6
|
||||
|
||||
struct Party : public Common::Array<Character> {
|
||||
/**
|
||||
* Share food, gold, gems between entire party
|
||||
*/
|
||||
static void share(TransferKind shareType);
|
||||
|
||||
/**
|
||||
* Get the party gold combined
|
||||
*/
|
||||
uint getPartyGold() const;
|
||||
|
||||
/**
|
||||
* Reset entire party's gold to zero
|
||||
*/
|
||||
void clearPartyGold();
|
||||
|
||||
/**
|
||||
* Reset entire party's gems to zero
|
||||
*/
|
||||
void clearPartyGems();
|
||||
|
||||
/**
|
||||
* Reset entire party's food to zero
|
||||
*/
|
||||
void clearPartyFood();
|
||||
|
||||
/**
|
||||
* Update the entire party AC
|
||||
*/
|
||||
void updateAC();
|
||||
|
||||
/**
|
||||
* Called to update the party after combat is done
|
||||
*/
|
||||
void combatDone();
|
||||
|
||||
/**
|
||||
* Returns true if any of the party has an item
|
||||
*/
|
||||
bool hasItem(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Returns true if the party is dead or out of action
|
||||
*/
|
||||
bool isPartyDead() const;
|
||||
|
||||
/**
|
||||
* Checks whether the party is dead or out of action,
|
||||
* and if so, switches to the death screen
|
||||
*/
|
||||
bool checkPartyDead() const;
|
||||
|
||||
/**
|
||||
* Checks whether the party is incapitated, and if so,
|
||||
* switches to the death screen
|
||||
*/
|
||||
bool checkPartyIncapacitated() const;
|
||||
|
||||
/**
|
||||
* Reorder the party based on a passed array of character pointers
|
||||
*/
|
||||
void rearrange(const Common::Array<Character *> &party);
|
||||
|
||||
/**
|
||||
* Synchronizes the party to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Return the index of a given character
|
||||
*/
|
||||
int indexOf(const Character *c);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
177
engines/mm/mm1/data/roster.cpp
Normal file
177
engines/mm/mm1/data/roster.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "mm/mm1/data/roster.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
static byte DEFAULT_PORTRAITS[6] = { 0, 11, 9, 7, 4, 3 };
|
||||
|
||||
void Roster::synchronize(Common::Serializer &s, bool isLoadingDefaults) {
|
||||
for (int i = 0; i < ROSTER_COUNT; ++i)
|
||||
_items[i].synchronize(s, s.isLoading() && isLoadingDefaults ?
|
||||
(i < 6 ? DEFAULT_PORTRAITS[i] : 0xff) : -1
|
||||
);
|
||||
|
||||
for (int i = 0; i < ROSTER_COUNT; ++i)
|
||||
s.syncAsByte(_towns[i]);
|
||||
}
|
||||
|
||||
void Roster::load() {
|
||||
Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(
|
||||
rosterSaveName());
|
||||
|
||||
if (sf) {
|
||||
Common::Serializer s(sf, nullptr);
|
||||
synchronize(s, false);
|
||||
|
||||
while (!sf->eos()) {
|
||||
uint32 chunk = sf->readUint32BE();
|
||||
if (!sf->eos() && chunk == MKTAG('M', 'A', 'P', 'S')) {
|
||||
sf->skip(4); // Skip chunk size
|
||||
g_maps->synchronize(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sf = g_system->getSavefileManager()->openForLoading("roster.dta");
|
||||
|
||||
if (sf) {
|
||||
Common::Serializer s(sf, nullptr);
|
||||
synchronize(s, true);
|
||||
|
||||
} else {
|
||||
Common::File f;
|
||||
if (!f.open("roster.dta"))
|
||||
error("Could not open roster.dta");
|
||||
|
||||
Common::Serializer s(&f, nullptr);
|
||||
synchronize(s, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Roster::update(const IntArray &charNums) {
|
||||
int fallbackIndex = ROSTER_COUNT - 1;
|
||||
|
||||
for (int i = (int)g_globals->_party.size() - 1; i >= 0; --i) {
|
||||
const Character &c = g_globals->_party[i];
|
||||
|
||||
int destIndex;
|
||||
if (charNums.size() == g_globals->_party.size() &&
|
||||
charNums[i] < ROSTER_COUNT &&
|
||||
!strcmp(_items[charNums[i]]._name, c._name)) {
|
||||
// Started game from title screen and set up party,
|
||||
// so we known the correct roster index already
|
||||
destIndex = charNums[i];
|
||||
|
||||
} else {
|
||||
for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
|
||||
if (!strcmp(_items[destIndex]._name, c._name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (destIndex == ROSTER_COUNT) {
|
||||
// Couldn't find a matching name in roster to update
|
||||
for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
|
||||
if (!_towns[destIndex])
|
||||
break;
|
||||
}
|
||||
|
||||
if (destIndex == ROSTER_COUNT)
|
||||
// Replace entries at the end of the roster
|
||||
destIndex = fallbackIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the entry into the roster
|
||||
_items[destIndex] = c;
|
||||
_towns[destIndex] = (Maps::TownId)g_maps->_currentMap->dataByte(Maps::MAP_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void Roster::save() {
|
||||
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
|
||||
rosterSaveName());
|
||||
Common::Serializer s(nullptr, sf);
|
||||
synchronize(s, false);
|
||||
|
||||
// Get automap data to save
|
||||
Common::MemoryWriteStreamDynamic mapData(DisposeAfterUse::YES);
|
||||
Common::Serializer s2(nullptr, &mapData);
|
||||
g_maps->synchronize(s2);
|
||||
|
||||
// Write out the map data
|
||||
sf->writeUint32BE(MKTAG('M', 'A', 'P', 'S'));
|
||||
sf->writeUint32LE(mapData.size());
|
||||
sf->write(mapData.getData(), mapData.size());
|
||||
|
||||
sf->finalize();
|
||||
delete sf;
|
||||
}
|
||||
|
||||
void Roster::saveOriginal() {
|
||||
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
|
||||
"roster.dta", false);
|
||||
Common::Serializer s(nullptr, sf);
|
||||
synchronize(s, false);
|
||||
|
||||
sf->finalize();
|
||||
delete sf;
|
||||
}
|
||||
|
||||
Common::String Roster::rosterSaveName() const {
|
||||
return Common::String::format("%s-roster.dta",
|
||||
g_engine->getTargetName().c_str());
|
||||
}
|
||||
|
||||
void Roster::remove(Character *entry) {
|
||||
entry->clear();
|
||||
|
||||
size_t idx = entry - _items;
|
||||
_towns[idx] = Maps::NO_TOWN;
|
||||
}
|
||||
|
||||
bool Roster::empty() const {
|
||||
for (uint i = 0; i < ROSTER_COUNT; ++i) {
|
||||
if (_towns[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Roster::full() const {
|
||||
for (uint i = 0; i < ROSTER_COUNT; ++i) {
|
||||
if (!_towns[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
93
engines/mm/mm1/data/roster.h
Normal file
93
engines/mm/mm1/data/roster.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_ROSTER_H
|
||||
#define MM1_DATA_ROSTER_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/int_array.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define ROSTER_COUNT 18
|
||||
|
||||
struct Roster {
|
||||
private:
|
||||
Common::String rosterSaveName() const;
|
||||
public:
|
||||
Character _items[ROSTER_COUNT];
|
||||
Maps::TownId _towns[ROSTER_COUNT] = { Maps::NO_TOWN };
|
||||
|
||||
Character &operator[](uint idx) {
|
||||
assert(idx < ROSTER_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the contents of the roster
|
||||
* @param isLoadingDefaults True if we're loading the
|
||||
* default roster of the game
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, bool isLoadingDefaults);
|
||||
|
||||
/**
|
||||
* Load the roster
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Updates the roster from the party
|
||||
*/
|
||||
void update(const IntArray &charNums);
|
||||
|
||||
/**
|
||||
* Save the roster
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Save the roster in the original format
|
||||
*/
|
||||
void saveOriginal();
|
||||
|
||||
/**
|
||||
* Deletes a character
|
||||
*/
|
||||
void remove(Character *entry);
|
||||
|
||||
/**
|
||||
* Returns true if the roster is empty
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* Returns true if the roster is full
|
||||
*/
|
||||
bool full() const;
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
61
engines/mm/mm1/data/spells_state.h
Normal file
61
engines/mm/mm1/data/spells_state.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_SPELLS_H
|
||||
#define MM1_DATA_SPELLS_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
struct SpellsState {
|
||||
byte _mmVal1 = 0;
|
||||
byte _resistanceIndex = 0;
|
||||
byte _mmVal5 = 0;
|
||||
byte _mmVal7 = 0;
|
||||
|
||||
// This can hold both a resistance type, or count of monsters to affect
|
||||
byte _resistanceTypeOrTargetCount = RESISTANCE_MAGIC;
|
||||
|
||||
// TODO: Is this variable different in different contexts?
|
||||
// In some places it's used to hold a new condition,
|
||||
// but others, like moonRay, uses it to hold Hp
|
||||
byte _damage = 0;
|
||||
|
||||
/**
|
||||
* Synchronize data to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_mmVal1);
|
||||
s.syncAsByte(_resistanceIndex);
|
||||
s.syncAsByte(_mmVal5);
|
||||
s.syncAsByte(_mmVal7);
|
||||
s.syncAsByte(_resistanceTypeOrTargetCount);
|
||||
s.syncAsByte(_damage);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
44
engines/mm/mm1/data/text_parser.cpp
Normal file
44
engines/mm/mm1/data/text_parser.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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 "mm/mm1/data/text_parser.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
uint TextParser::getNextValue(Common::String &line) {
|
||||
// Verify the next comma
|
||||
if (!line.hasPrefix(", "))
|
||||
return 0;
|
||||
line.deleteChar(0);
|
||||
line.deleteChar(0);
|
||||
|
||||
// Get the value
|
||||
int result = atoi(line.c_str());
|
||||
while (!line.empty() && Common::isDigit(line.firstChar()))
|
||||
line.deleteChar(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
40
engines/mm/mm1/data/text_parser.h
Normal file
40
engines/mm/mm1/data/text_parser.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_TEXT_PARSER_H
|
||||
#define MM1_DATA_TEXT_PARSER_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
/**
|
||||
* Get the next value from a read line
|
||||
*/
|
||||
struct TextParser {
|
||||
static uint getNextValue(Common::String &line);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
141
engines/mm/mm1/data/trap.cpp
Normal file
141
engines/mm/mm1/data/trap.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* 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 "mm/mm1/data/trap.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
int8 TrapData::RESISTANCE_INDEXES[11] = {
|
||||
-1, -1, -1, -1, -1, -1,
|
||||
1, // Fire
|
||||
3, // Electricity
|
||||
4, // Acid
|
||||
2, // Cold
|
||||
0 // Magic
|
||||
};
|
||||
byte TrapData::CONDITIONS1[11] = {
|
||||
16, 32, 16, 16, 2, 1, 2, 32, 2, 2, 2
|
||||
};
|
||||
byte TrapData::CONDITIONS2[11] = {
|
||||
16, 16, 16, 32, 2, 16, 64, 64, 2, 32, 32
|
||||
};
|
||||
byte TrapData::CONDITIONS3[11] = {
|
||||
64, 64, 64, 64, 64, 192, 192, 192, 255, 64, 224
|
||||
};
|
||||
byte TrapData::DAMAGE_TYPE[7] = {
|
||||
3, 0, 2, 5, 4, 1, 6
|
||||
};
|
||||
|
||||
|
||||
void TrapData::trap() {
|
||||
_trapType = getRandomNumber(11) - 1;
|
||||
|
||||
int maxVal = 4;
|
||||
for (int i = (int)g_globals->_treasure._container - 1; i > 0; i -= 2) {
|
||||
maxVal <<= 1;
|
||||
}
|
||||
maxVal += getRandomNumber(maxVal);
|
||||
|
||||
_resistanceIndex = RESISTANCE_INDEXES[_trapType];
|
||||
|
||||
if (g_globals->_treasure._container < WOODEN_BOX)
|
||||
_condition = 0;
|
||||
else if (g_globals->_treasure._container < SILVER_BOX)
|
||||
_condition = CONDITIONS1[_trapType];
|
||||
else if (g_globals->_treasure._container < BLACK_BOX)
|
||||
_condition = CONDITIONS2[_trapType];
|
||||
else
|
||||
_condition = CONDITIONS3[_trapType];
|
||||
|
||||
int idx = _trapType;
|
||||
if (idx >= 7)
|
||||
idx -= 5;
|
||||
else if (_condition == POISONED)
|
||||
idx = 0;
|
||||
else if (_condition == PARALYZED)
|
||||
idx = 1;
|
||||
else
|
||||
idx = -1;
|
||||
|
||||
int val4 = 0;
|
||||
_reduced = 0;
|
||||
if (idx >= 0) {
|
||||
int spellCount = g_globals->_activeSpells._arr[DAMAGE_TYPE[idx]];
|
||||
if (spellCount > 0 && getRandomNumber(100) < spellCount) {
|
||||
_reduced = val4 = 1;
|
||||
maxVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i, _reduced = val4) {
|
||||
_hpInitial = maxVal;
|
||||
damageChar(i);
|
||||
}
|
||||
}
|
||||
|
||||
void TrapData::damageChar(uint partyIndex) {
|
||||
Character &c = g_globals->_party[partyIndex];
|
||||
if (&c != g_globals->_currCharacter)
|
||||
_hpInitial >>= 1;
|
||||
|
||||
if (_resistanceIndex != -1 &&
|
||||
c._resistances._arr[_resistanceIndex] != 0 &&
|
||||
getRandomNumber(100) < c._resistances._arr[_resistanceIndex]) {
|
||||
_hpInitial >>= 1;
|
||||
++_reduced;
|
||||
}
|
||||
|
||||
int luckLevel1 = c._luck + c._level;
|
||||
int luckLevel2 = getRandomNumber(luckLevel1 + 20);
|
||||
|
||||
if (getRandomNumber(luckLevel2) < luckLevel1) {
|
||||
_hpInitial >>= 1;
|
||||
++_reduced;
|
||||
}
|
||||
|
||||
if (c._condition & BAD_CONDITION) {
|
||||
c._hpCurrent = 0;
|
||||
|
||||
} else if (c._condition & UNCONSCIOUS) {
|
||||
c._condition = BAD_CONDITION | DEAD;
|
||||
c._hpCurrent = 0;
|
||||
|
||||
} else {
|
||||
c._hpCurrent = MAX((int)c._hpCurrent - _hpInitial, 0);
|
||||
|
||||
if (c._hpCurrent == 0) {
|
||||
c._condition |= UNCONSCIOUS;
|
||||
|
||||
} else if (!_reduced && _condition &&
|
||||
getRandomNumber(luckLevel1 + 20) >= luckLevel1) {
|
||||
if (_condition >= UNCONSCIOUS)
|
||||
c._hpCurrent = 0;
|
||||
|
||||
if (!(c._condition & BAD_CONDITION))
|
||||
c._condition = _condition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
59
engines/mm/mm1/data/trap.h
Normal file
59
engines/mm/mm1/data/trap.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_TRAP_H
|
||||
#define MM1_DATA_TRAP_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class TrapData : public Game::GameLogic {
|
||||
private:
|
||||
/**
|
||||
* Damages a party member from the trap
|
||||
*/
|
||||
void damageChar(uint partyIndex);
|
||||
|
||||
protected:
|
||||
static int8 RESISTANCE_INDEXES[11];
|
||||
static byte CONDITIONS1[11];
|
||||
static byte CONDITIONS2[11];
|
||||
static byte CONDITIONS3[11];
|
||||
static byte DAMAGE_TYPE[7];
|
||||
|
||||
int _trapType = 0;
|
||||
int _hpInitial = 0;
|
||||
int _reduced = 0;
|
||||
int _resistanceIndex = 0;
|
||||
byte _condition = 0;
|
||||
|
||||
virtual void trap();
|
||||
public:
|
||||
virtual ~TrapData() {}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
80
engines/mm/mm1/data/treasure.cpp
Normal file
80
engines/mm/mm1/data/treasure.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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/treasure.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define TREASURE_COUNT 6
|
||||
#define ARRAY_COUNT (TREASURE_COUNT + 3)
|
||||
|
||||
void Treasure::clear() {
|
||||
Common::fill(&_data[0], &_data[ARRAY_COUNT], 0);
|
||||
}
|
||||
|
||||
void Treasure::clear0() {
|
||||
Common::fill(&_data[1], &_data[ARRAY_COUNT], 0);
|
||||
}
|
||||
|
||||
byte &Treasure::operator[](uint i) {
|
||||
assert(i < ARRAY_COUNT);
|
||||
return _data[i];
|
||||
}
|
||||
|
||||
bool Treasure::present() const {
|
||||
// Checks for items, treasure, and/or gems
|
||||
for (int i = 0; i < TREASURE_COUNT; ++i) {
|
||||
if (_data[i + 3])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Treasure::hasItems() const {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (_items[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
byte Treasure::removeItem() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (_items[i]) {
|
||||
byte result = _items[i];
|
||||
_items[i] = 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Treasure::synchronize(Common::Serializer &s) {
|
||||
s.syncBytes(_data, 9);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
114
engines/mm/mm1/data/treasure.h
Normal file
114
engines/mm/mm1/data/treasure.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_DATA_TREASURE_H
|
||||
#define MM1_DATA_TREASURE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
enum ContainerType {
|
||||
CLOTH_SACK = 0, LEATHER_SACK = 1, WOODEN_BOX = 2,
|
||||
WOODEN_CHEST = 3, IRON_BOX = 4, IRON_CHEST = 5,
|
||||
SILVER_BOX = 6, SILVER_CHEST = 7, GOLD_BOX = 8,
|
||||
GOLD_CHEST = 9, BLACK_BOX = 10
|
||||
};
|
||||
|
||||
class Treasure {
|
||||
private:
|
||||
byte _data[9];
|
||||
public:
|
||||
byte &_trapType = _data[1];
|
||||
byte &_container = _data[2];
|
||||
byte *const _items = &_data[3];
|
||||
|
||||
Treasure() {
|
||||
clear();
|
||||
}
|
||||
|
||||
byte &operator[](uint i);
|
||||
|
||||
/**
|
||||
* Clears the treasure list
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Clears everything except byte 0
|
||||
*/
|
||||
void clear0();
|
||||
|
||||
/**
|
||||
* Returns true if any treasure has been assigned
|
||||
*/
|
||||
bool present() const;
|
||||
|
||||
/**
|
||||
* Returns true if any items are present
|
||||
*/
|
||||
bool hasItems() const;
|
||||
|
||||
/**
|
||||
* Synchronize savegame data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Return the gold value for the treasure
|
||||
*/
|
||||
uint16 getGold() const {
|
||||
return READ_LE_UINT16(&_data[6]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gold value for the treasure
|
||||
*/
|
||||
void setGold(uint16 amount) {
|
||||
WRITE_LE_UINT16(&_data[6], amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the gems amount
|
||||
*/
|
||||
byte getGems() const {
|
||||
return _data[8];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gems amount
|
||||
*/
|
||||
void setGems(byte amount) {
|
||||
_data[8] = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any item, and remove it from the treasure
|
||||
*/
|
||||
byte removeItem();
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user