From b533822c0666ade51d2da2047e87351d3047fb58 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 24 Jan 2015 09:27:48 -0500 Subject: XEEN: Implement lots of stubbed PlayerStruct methods --- engines/xeen/combat.h | 2 +- engines/xeen/items.cpp | 18 +++ engines/xeen/items.h | 4 + engines/xeen/map.cpp | 14 +- engines/xeen/party.cpp | 372 ++++++++++++++++++++++++++++++++++++++++++--- engines/xeen/party.h | 26 +++- engines/xeen/resources.cpp | 62 +++++++- engines/xeen/resources.h | 32 +++- engines/xeen/scripts.cpp | 16 +- 9 files changed, 501 insertions(+), 45 deletions(-) diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index 882f90e604..550b39fd2e 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -28,7 +28,7 @@ namespace Xeen { enum DamageType { - DT_PHYSICAL = 0, DT_1 = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, + DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, DT_UNDED = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp index e9425f7ee9..f7dfeccbb1 100644 --- a/engines/xeen/items.cpp +++ b/engines/xeen/items.cpp @@ -21,6 +21,7 @@ */ #include "xeen/items.h" +#include "xeen/resources.h" namespace Xeen { @@ -36,6 +37,23 @@ void XeenItem::synchronize(Common::Serializer &s) { s.syncAsByte(_equipped); } +int XeenItem::getElementalCategory() const { + int idx; + for (idx = 0; ELEMENTAL_CATEGORIES[idx] < _material; ++idx) + ; + + return idx; +} + +int XeenItem::getAttributeCategory() const { + int m = _material - 59; + int idx; + for (idx = 0; ATTRIBUTE_CATEGORIES[idx] < m; ++idx) + ; + + return idx; +} + Treasure::Treasure() { _hasItems = false; } diff --git a/engines/xeen/items.h b/engines/xeen/items.h index 6fa57b922a..9141deffa2 100644 --- a/engines/xeen/items.h +++ b/engines/xeen/items.h @@ -40,6 +40,10 @@ public: XeenItem(); void synchronize(Common::Serializer &s); + + int getElementalCategory() const; + + int getAttributeCategory() const; }; class Treasure { diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp index ca22b38d93..750e6347fb 100644 --- a/engines/xeen/map.cpp +++ b/engines/xeen/map.cpp @@ -170,7 +170,7 @@ MonsterData::MonsterData() { 10, 100, 10, 10, 10, 10, 0, 0, 0, 10, 0, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mok Heretic", 50000, 150, 12, 50, 1, CLASS_CLERIC, - 500, 1, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, + 500, 1, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 20, 50, 20, 20, 20, 30, 0, 0, 0, 25, 4, false, 8, 0, 0, 117, "cleric")); push_back(MonsterStruct("Mantis Ant", 40000, 300, 30, 40, 2, CLASS_16, 2, 100, @@ -226,7 +226,7 @@ MonsterData::MonsterData() { DT_PHYSICAL, SA_NONE, 1, 0, MONSTER_0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 25, 0, 0, 131, "gremlin")); push_back(MonsterStruct("Onyx Golem", 1000000, 10000, 50, 100, 1, CLASS_15, 2, - 250, DT_1, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, + 250, DT_MAGICAL, SA_DRAINSP, 1, 0, MONSTER_GOLEM, 100, 100, 100, 100, 100, 100, 50, 0, 0, 100, 0, true, 24, 0, 10, 100, "golem")); push_back(MonsterStruct("Gremlin", 2000, 20, 7, 35, 2, CLASS_16, 2, 10, @@ -260,7 +260,7 @@ MonsterData::MonsterData() { DT_FIRE, SA_NONE, 1, 0, MONSTER_INSECT, 100, 100, 0, 100, 0, 0, 0, 0, 0, 0, 0, false, 33, 0, 0, 131, "Phantom")); push_back(MonsterStruct("Power Lich", 200000, 500, 20, 60, 1, CLASS_15, 10, 10, - DT_1, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, + DT_MAGICAL, SA_UNCONSCIOUS, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, 80, 70, 0, 0, 0, 0, true, 34, 0, 0, 141, "lich")); push_back(MonsterStruct("Mystic Mage", 100000, 200, 20, 70, 1, CLASS_15, 10, 20, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 50, 100, @@ -317,7 +317,7 @@ MonsterData::MonsterData() { 10, 100, 10, 10, 10, 20, 0, 0, 0, 20, 0, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Sorceress", 80000, 200, 30, 80, 1, CLASS_15, 2, 50, - DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, + DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 10, 20, 10, 10, 10, 80, 0, 0, 0, 50, 5, false, 50, 0, 0, 163, "disint")); push_back(MonsterStruct("Arachnoid", 4000, 50, 10, 40, 1, CLASS_16, 3, 5, DT_POISON, SA_POISON, 1, 0, MONSTER_INSECT, 0, 0, 0, @@ -367,7 +367,7 @@ MonsterData::MonsterData() { 50, 50, 50, 50, 50, 0, 0, 0, 50, 0, false, 64, 0, 0, 163, "boltelec")); push_back(MonsterStruct("Wizard", 60000, 250, 20, 125, 1, CLASS_PALADIN, 10, - 25, DT_1, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, + 25, DT_MAGICAL, SA_NONE, 1, 1, MONSTER_HUMANOID, 50, 30, 30, 30, 30, 30, 0, 0, 0, 20, 0, false, 65, 0, 0, 163, "wizard")); push_back(MonsterStruct("Dark Wolf", 10000, 70, 10, 70, 3, CLASS_16, 3, 8, DT_PHYSICAL, SA_NONE, 10, 0, MONSTER_ANIMAL, 0, 0, 0, @@ -391,7 +391,7 @@ MonsterData::MonsterData() { MONSTER_HUMANOID, 80, 80, 80, 80, 80, 20, 0, 0, 200, 0, 7, false, 30, 0, 10, 100, "knight")); push_back(MonsterStruct("Sandro", 200000, 1000, 20, 75, 1, CLASS_15, 10, 10, - DT_1, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, + DT_MAGICAL, SA_DEATH, 1, 1, MONSTER_UNDEAD, 0, 0, 0, 0, 0, 90, 80, 0, 0, 100, 7, true, 34, 0, 10, 100, "lich")); push_back(MonsterStruct("Mega Mage", 500000, 500, 35, 100, 1, CLASS_15, 10, 40, DT_ELECTRICAL, SA_NONE, 1, 1, MONSTER_0, 80, 100, 80, @@ -439,7 +439,7 @@ MonsterData::MonsterData() { 0, MONSTER_UNDEAD, 80, 80, 80, 80, 80, 80, 90, 0, 0, 0, 0, false, 58, 0, 0, 100, "vamp")); push_back(MonsterStruct("Valio", 60000, 150, 15, 60, 1, CLASS_PALADIN, 10, 25, - DT_1, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, + DT_MAGICAL, SA_NONE, 1, 0, MONSTER_HUMANOID, 50, 30, 30, 30, 40, 30, 0, 0, 0, 0, 0, false, 65, 0, 0, 100, "wizard")); push_back(MonsterStruct("Sky Golem", 200000, 1000, 50, 100, 1, CLASS_15, 2, 100, DT_COLD, SA_NONE, 1, 1, MONSTER_GOLEM, 50, 50, diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp index 43c2ecabab..b19e39aa2e 100644 --- a/engines/xeen/party.cpp +++ b/engines/xeen/party.cpp @@ -165,28 +165,194 @@ int PlayerStruct::getAge(bool ignoreTemp) const { } int PlayerStruct::getMaxHP() const { - warning("TODO: getMaxHp"); - return 20; + int hp = BASE_HP_BY_CLASS[_class]; + hp += statBonus(getStat(ENDURANCE, false)); + hp += RACE_HP_BONUSES[_race]; + if (_skills[BODYBUILDER]) + ++hp; + if (hp < 1) + hp = 1; + + hp *= getCurrentLevel(); + hp += itemScan(7); + + if (hp < 0) + hp = 0; + + return hp; } int PlayerStruct::getMaxSP() const { - warning("TODO: getMaxSP"); - return 20; + int result = 0; + bool flag = false; + int amount; + Attribute attrib; + Skill skill; + + if (_hasSpells) + return 0; + + if (_class == CLASS_SORCERER || _class == CLASS_ARCHER) { + attrib = INTELLECT; + skill = PRESTIDIGITATION; + } else { + attrib = PERSONALITY; + skill = PRAYER_MASTER; + } + if (_class == CLASS_DRUID || _class == CLASS_RANGER) + skill = ASTROLOGER; + + for (;;) { + // Get the base number of spell points + result = statBonus(getStat(attrib, false)); + result += RACE_SP_BONUSES[_race][attrib - 1]; + + if (_skills[skill]) + result += 2; + if (result < 1) + result = 1; + + // Multiply it by the character's level + result *= getCurrentLevel(); + + // Classes other than sorcerer, clerics, and druids only get half the SP + if (_class != CLASS_SORCERER && _class != CLASS_CLERIC && _class != CLASS_DRUID) + result /= 2; + + if (flag || (_class != CLASS_DRUID && _class != CLASS_RANGER)) + break; + + // Druids and rangers get bonuses averaged on both personality and intellect + attrib = INTELLECT; + flag = true; + amount = result; + } + if (flag) + result = (amount + result) / 2; + + result += itemScan(8); + if (result < 0) + result = 0; + + return result; +} + +/** + * Get the effective value of a given stat for the character + */ +int PlayerStruct::getStat(Attribute attrib, bool applyMod) const { + AttributePair attr; + int mode = 0; + + switch (attrib) { + case MIGHT: + attr = _might; + break; + case INTELLECT: + attr = _intellect; + mode = 1; + break; + case PERSONALITY: + attr = _personality; + mode = 1; + break; + case ENDURANCE: + attr = _endurance; + break; + case SPEED: + attr = _speed; + break; + case ACCURACY: + attr = _accuracy; + break; + case LUCK: + attr = _luck; + mode = 2; + break; + default: + return 0; + } + + // All the attributes except luck are affected by the character's age + if (mode < 2) { + int age = getAge(false); + int ageIndex = 0; + while (AGE_RANGES[ageIndex] < age) + ++ageIndex; + + attr._permanent += AGE_RANGES_ADJUST[mode][ageIndex]; + } + + if (applyMod) { + attr._permanent += conditionMod(attrib); + attr._permanent += attr._temporary; + } + + return (attr._permanent >= 1) ? attr._permanent : 0; } -int PlayerStruct::getStat(int statNum, int v2) { - // TODO - return 10; +int PlayerStruct::statBonus(int statValue) const { + for (int idx = 0; STAT_VALUES[idx] <= statValue; ++idx) + return STAT_BONUSES[idx]; + + return 0; } -bool PlayerStruct::charSavingThrow() { - // TODO - return false; +bool PlayerStruct::charSavingThrow(DamageType attackType) const { + int v, vMax; + + if (attackType == DT_PHYSICAL) { + v = statBonus(getStat(LUCK, false)) + getCurrentLevel(); + vMax = v + 20; + } else { + switch (attackType) { + case DT_MAGICAL: + v = _magicResistence._permanent + _magicResistence._temporary + itemScan(16); + break; + case DT_FIRE: + v = _fireResistence._permanent + _fireResistence._temporary + itemScan(11); + break; + case DT_ELECTRICAL: + v = _electricityResistence._permanent + _electricityResistence._temporary + itemScan(12); + break; + case DT_COLD: + v = _coldResistence._permanent + _coldResistence._temporary + itemScan(13); + break; + case DT_POISON: + v = _poisonResistence._permanent + _poisonResistence._temporary + itemScan(14); + break; + case DT_ENERGY: + v = _energyResistence._permanent + _energyResistence._temporary + itemScan(15); + break; + default: + v = 0; + break; + } + + vMax = v + 40; + } + + return Party::_vm->getRandomNumber(1, vMax) <= v; } bool PlayerStruct::noActions() { - // TODO - return false; + Condition condition = worstCondition(); + + switch (condition) { + case CURSED: + case POISONED: + case DISEASED: + case INSANE: + case IN_LOVE: + case DRUNK: { + Common::String msg = Common::String::format(IN_NO_CONDITION, _name.c_str()); + ErrorScroll::show(Party::_vm, msg, + Party::_vm->_mode == 17 ? WT_2 : WT_NONFREEZED_WAIT); + return true; + } + default: + return false; + } } void PlayerStruct::setAward(int awardId, bool value) { @@ -210,13 +376,177 @@ bool PlayerStruct::hasAward(int awardId) const { } int PlayerStruct::getArmorClass(bool baseOnly) const { - // TODO - return 1; + Party &party = *Party::_vm->_party; + + int result = statBonus(getStat(SPEED, false)) + itemScan(9); + if (!baseOnly) + result += (party._blessedActive ? 1 : 0) + _ACTemp; + + return MAX(result, 0); } +/** + * Returns the thievery skill level, adjusted by class and race + */ int PlayerStruct::getThievery() const { - // TODO - return 1; + int result = getCurrentLevel() * 2; + + if (_class == CLASS_NINJA) + result += 15; + else if (_class == CLASS_ROBBER) + result += 30; + + switch (_race) { + case ELF: + case GNOME: + result += 10; + break; + case DWARF: + result += 5; + break; + case HALF_ORC: + result -= 10; + break; + default: + break; + } + + result += itemScan(10); + + // If the character doesn't have a thievery skill, then do'nt allow any result + if (!_skills[THIEVERY]) + result = 0; + + return MAX(result, 0); +} + +int PlayerStruct::getCurrentLevel() const { + return MAX(_level._permanent + _level._temporary, 0); +} + +int PlayerStruct::itemScan(int itemId) const { + int result = 0; + + for (int accessIdx = 0; accessIdx < 3; ++accessIdx) { + switch (accessIdx) { + case 0: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _weapons[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 + && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + break; + + case 1: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _armor[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0)) { + if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) { + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + + if (itemId == 9) { + result += ARMOR_STRENGTHS[item._name]; + + if (item._material >= 37 && item._material <= 58) + result += METAL_LAC[item._material - 37]; + } + } + } + break; + + case 2: + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + const XeenItem &item = _accessories[idx]; + + if (item._equipped && !(item._bonusFlags & 0xC0) && itemId < 11 && itemId != 3) { + if (item._material >= 59 && item._material <= 130) { + int mIndex = item.getAttributeCategory(); + if (mIndex > 2) + ++mIndex; + + if (mIndex == itemId) { + result += ATTRIBUTE_BONUSES[item._material - 59]; + } + } + + if (itemId > 10 && item._material < 37) { + int mIndex = item.getElementalCategory() + 11; + + if (mIndex == itemId) + result += ELEMENTAL_RESISTENCES[item._material]; + } + } + } + break; + } + }; + + return result; +} + +/** + * Modifies a passed attribute value based on player's condition + */ +int PlayerStruct::conditionMod(Attribute attrib) const { + if (_conditions[DEAD] || _conditions[STONED] || _conditions[ERADICATED]) + return 0; + + int v[7]; + Common::fill(&v[0], &v[7], 0); + if (_conditions[CURSED]) + v[6] -= _conditions[CURSED]; + + if (_conditions[INSANE]) { + v[2] -= _conditions[INSANE]; + v[1] -= _conditions[INSANE]; + v[5] -= _conditions[INSANE]; + v[0] -= _conditions[INSANE]; + v[4] -= _conditions[INSANE]; + } + + if (_conditions[POISONED]) { + v[0] -= _conditions[POISONED]; + v[4] -= _conditions[POISONED]; + v[5] -= _conditions[POISONED]; + } + + if (_conditions[DISEASED]) { + v[3] -= _conditions[DISEASED]; + v[2] -= _conditions[DISEASED]; + v[1] -= _conditions[DISEASED]; + } + + for (int idx = 0; idx < 7; ++idx) { + v[idx] -= _conditions[HEART_BROKEN]; + v[idx] -= _conditions[IN_LOVE]; + v[idx] -= _conditions[WEAK]; + v[idx] -= _conditions[DRUNK]; + } + + return v[attrib]; } /*------------------------------------------------------------------------*/ @@ -432,7 +762,7 @@ void Party::changeTime(int numMinutes) { if (!player._conditions[DEAD] && !player._conditions[STONED] && !player._conditions[ERADICATED]) { for (int statNum = 0; statNum < TOTAL_STATS; ++statNum) { - int statVal = player.getStat(statNum, 0); + int statVal = player.getStat((Attribute)statNum, false); if (statVal < 1) player._conditions[DEAD] = 1; } @@ -448,16 +778,16 @@ void Party::changeTime(int numMinutes) { // Handle poisoning if (!player._conditions[POISONED]) { - if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + if (_vm->getRandomNumber(1, 10) != 1 || !player.charSavingThrow(DT_ELECTRICAL)) player._conditions[POISONED] *= 2; else // Poison wears off player._conditions[POISONED] = 0; } - // Handle poisoning + // Handle disease if (!player._conditions[DISEASED]) { - if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow()) + if (_vm->getRandomNumber(9) != 1 || !player.charSavingThrow(DT_COLD)) player._conditions[DISEASED] *= 2; else // Disease wears off @@ -506,7 +836,7 @@ void Party::changeTime(int numMinutes) { PlayerStruct &player = _activeParty[idx]; if (player._conditions[CONFUSED] && _vm->getRandomNumber(2) == 1) { - if (player.charSavingThrow()) { + if (player.charSavingThrow(DT_PHYSICAL)) { player._conditions[CONFUSED] = 0; } else { player._conditions[CONFUSED]--; diff --git a/engines/xeen/party.h b/engines/xeen/party.h index 2677813228..5d35b0f726 100644 --- a/engines/xeen/party.h +++ b/engines/xeen/party.h @@ -49,6 +49,11 @@ enum CharacterClass { CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16 }; +enum Attribute{ + MIGHT = 0, INTELLECT = 1, PERSONALITY = 2, ENDURANCE = 3, SPEED = 4, + ACCURACY = 5, LUCK = 6 +}; + enum Skill { THIEVERY = 0, ARMS_MASTER = 1, ASTROLOGER = 2, BODYBUILDER = 3, CARTOGRAPHER = 4, CRUSADER = 5, DIRECTION_SENSE = 6, LINGUIST = 7, MERCHANT = 8, MOUNTAINEER = 9, NAVIGATOR = 10, PATHFINDER = 11, @@ -68,6 +73,7 @@ enum Condition { CURSED = 0, HEART_BROKEN = 1, WEAK = 2, POISONED = 3, #define XEEN_TOTAL_CHARACTERS 24 #define MAX_ACTIVE_PARTY 6 #define TOTAL_STATS 7 +#define INV_ITEMS_TOTAL 9 class XeenEngine; @@ -81,6 +87,8 @@ public: }; class PlayerStruct { +private: + int conditionMod(Attribute attrib) const; public: Common::String _name; Sex _sex; @@ -106,10 +114,10 @@ public: bool _hasSpells; int _currentSpell; int _quickOption; - XeenItem _weapons[9]; - XeenItem _armor[9]; - XeenItem _accessories[9]; - XeenItem _misc[9]; + XeenItem _weapons[INV_ITEMS_TOTAL]; + XeenItem _armor[INV_ITEMS_TOTAL]; + XeenItem _accessories[INV_ITEMS_TOTAL]; + XeenItem _misc[INV_ITEMS_TOTAL]; int _lloydSide; AttributePair _fireResistence; AttributePair _coldResistence; @@ -138,9 +146,11 @@ public: int getMaxSP() const; - int getStat(int statNum, int v2); + int getStat(Attribute attrib, bool applyMod) const; - bool charSavingThrow(); + int statBonus(int statValue) const; + + bool charSavingThrow(DamageType attackType) const; bool noActions(); @@ -151,6 +161,10 @@ public: int getArmorClass(bool baseOnly) const; int getThievery() const; + + int getCurrentLevel() const; + + int itemScan(int itemId) const; }; class Roster: public Common::Array { diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 837ff15d36..993bf2f546 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -73,6 +73,8 @@ const char *const WHO_WILL = "\X03""c\X0B""000\x09""000%s\x0A\x0A" const char *const WHATS_THE_PASSWORD = "What's the Password?"; +const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!"; + const char *const TERRAIN_TYPES[6] = { "town", "cave", "towr", "cstl", "dung", "scfi" }; @@ -271,6 +273,12 @@ const char *const DIRECTION_TEXT[4] = { "NORTH", "EAST", "SOUTH", "WEST" }; const char *const RACE_NAMES[5] = { "Human", "Elf", "Dwarf", "Gnome", "H-Orc" }; +const int RACE_HP_BONUSES[5] = { 0, -2, 1, -1, 2 }; + +const int RACE_SP_BONUSES[5][2] = { + { 0, 0 }, { 2, 0 }, { -1, -1 }, { 1, 1 }, { -2, -2 } +}; + const char *const ALIGNMENT_NAMES[3] = { "Good", "Neutral", "Evil" }; const char *const SEX_NAMES[2] = { "Male", "Female" }; @@ -471,7 +479,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = { { 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 } }; -const int SPELLS_ALLOWED[3][40] = { +const uint SPELLS_ALLOWED[3][40] = { { 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 14, 16, 23, 26, 27, 28, 30, 31, 32, @@ -490,4 +498,56 @@ const int SPELLS_ALLOWED[3][40] = { } }; +const int BASE_HP_BY_CLASS[10] = { 10, 8, 7, 5, 4, 8, 7, 12, 6, 9 }; + +const int AGE_RANGES[10] = { 1, 6, 11, 18, 36, 51, 76, 101, 201, 0xffff }; + +const int AGE_RANGES_ADJUST[2][10] = { + { -250, -50, -20, -10, 0, -2, -5, -10, -20, -50 }, + { -250, -50, -20, -10, 0, 2, 5, 10, 20, 50 } +}; + +const int STAT_VALUES[24] = { + 11, 13, 15, 17, 19, 21, 25, 30, 35, 40, 50, 75, + 100, 125, 150, 175, 200, 225, 250, 65535 +}; + +const int STAT_BONUSES[24] = { + 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20 +}; + +const int ELEMENTAL_CATEGORIES[6] = { 8, 15, 20, 25, 33, 36 }; + +const int ATTRIBUTE_CATEGORIES[10] = { + 9, 17, 25, 33, 39, 45, 50, 56, 61, 72 }; + +const int ATTRIBUTE_BONUSES[72] = { + 2, 3, 5, 8, 12, 17, 23, 30, 38, 47, // Might bonus + 2, 3, 5, 8, 12, 17, 23, 30, // INT bonus + 2, 3, 5, 8, 12, 17, 23, 30, // PER bonus + 2, 3, 5, 8, 12, 17, 23, 30, // SPD bonus + 3, 5, 10, 15, 20, 30, // ACC bonus + 5, 10, 15, 20, 25, 30, // LUC bonus + 4, 6, 10, 20, 50, // HP bonus + 4, 8, 12, 16, 20, 25, // SP bonus + 2, 4, 6, 10, 16, // AC bonus + 4, 6, 8, 10, 12, 14, 16, 18, 20, 25 // Thievery bonus +}; + +const int ELEMENTAL_RESISTENCES[37] = { + 0, 5, 7, 9, 12, 15, 20, 25, 30, 5, 7, 9, 12, 15, 20, 25, + 5, 10, 15, 20, 25, 10, 15, 20, 25, 40, 5, 7, 9, 11, 13, 15, 20, 25, + 5, 10, 20 +}; + +const int ELEMENTAL_DAMAGE[37] = { + 0, 2, 3, 4, 5, 10, 15, 20, 30, 2, 3, 4, 5, 10, 15, 20, 2, 4, 5, 10, 20, + 2, 4, 8, 16, 32, 2, 3, 4, 5, 10, 15, 20, 30, 5, 10, 25 +}; + +const int METAL_LAC[9] = { -3, 0, -2, -1, 1, 2, 4, 6, 8 }; + +const int ARMOR_STRENGTHS[14] = { 0, 2, 4, 5, 6, 7, 8, 10, 4, 2, 1, 1, 1, 1 }; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index 36ac6b2a21..b1c972069c 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -38,6 +38,8 @@ extern const char *const WHO_WILL; extern const char *const WHATS_THE_PASSWORD; +extern const char *const IN_NO_CONDITION; + extern const char *const TERRAIN_TYPES[6]; extern const char *const SURFACE_TYPE_NAMES[15]; @@ -56,6 +58,10 @@ extern const char *const DIRECTION_TEXT[4]; extern const char *const RACE_NAMES[5]; +extern const int RACE_HP_BONUSES[5]; + +extern const int RACE_SP_BONUSES[5][2]; + extern const char *const CLASS_NAMES[11]; extern const char *const ALIGNMENT_NAMES[3]; @@ -110,7 +116,31 @@ extern const int COMBAT_FLOAT_Y[8]; extern const int MONSTER_EFFECT_FLAGS[15][8]; -extern const int SPELLS_ALLOWED[3][40]; +extern const uint SPELLS_ALLOWED[3][40]; + +extern const int BASE_HP_BY_CLASS[10]; + +extern const int AGE_RANGES[10]; + +extern const int AGE_RANGES_ADJUST[2][10]; + +extern const int STAT_VALUES[24]; + +extern const int STAT_BONUSES[24]; + +extern const int ELEMENTAL_CATEGORIES[6]; + +extern const int ATTRIBUTE_CATEGORIES[10]; + +extern const int ATTRIBUTE_BONUSES[72]; + +extern const int ELEMENTAL_RESISTENCES[37]; + +extern const int ELEMENTAL_DAMAGE[37]; + +extern const int METAL_LAC[9]; + +extern const int ARMOR_STRENGTHS[14]; } // End of namespace Xeen diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index ffe5441b2c..6f14be20b7 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -86,7 +86,7 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { void Scripts::checkEvents() { Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; +// Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; @@ -415,7 +415,7 @@ void Scripts::cmdGiveExtended(Common::Array ¶ms) { break; } - if ((_charIndex != 0 & _charIndex != 8) || params[0] == 44) { + if ((_charIndex != 0 && _charIndex != 8) || params[0] == 44) { result = ifProc(params[0], mask, _event->_opcode - OP_If1, _charIndex - 1); } else { result = false; @@ -566,7 +566,7 @@ void Scripts::cmdMakeNothingHere(Common::Array ¶ms) { // Scan through the event list and mark the opcodes for all the lines of any scripts // on the party's current cell as having no operation, effectively disabling them - for (int idx = 0; idx < map._events.size(); ++idx) { + for (uint idx = 0; idx < map._events.size(); ++idx) { MazeEvent &evt = map._events[idx]; if (evt._position == party._mazePosition) evt._opcode = OP_None; @@ -804,22 +804,22 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { if (mask < 82) { for (int idx = 0; idx < 9; ++idx) { if (mask == 35) { - if (ps._weapons[idx]._name == mask) { + if ((int)ps._weapons[idx]._name == mask) { v = mask; break; } } else if (mask < 49) { - if (ps._armor[idx]._name == (mask - 35)) { + if ((int)ps._armor[idx]._name == (mask - 35)) { v = mask; break; } } else if (mask < 60) { - if (ps._accessories[idx]._name == (mask - 49)) { + if ((int)ps._accessories[idx]._name == (mask - 49)) { v = mask; break; } } else { - if (ps._misc[idx]._name == (mask - 60)) { + if ((int)ps._misc[idx]._name == (mask - 60)) { v = mask; break; } @@ -1020,7 +1020,7 @@ bool Scripts::ifProc(int action, uint32 mask, int mode, int charIndex) { case 91: case 92: // Get a player stat - v = ps.getStat(action - 86, 0); + v = ps.getStat((Attribute)(action - 86), 0); break; case 93: // Current day of the week (10 days per week) -- cgit v1.2.3