aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/xeen/combat.h2
-rw-r--r--engines/xeen/items.cpp18
-rw-r--r--engines/xeen/items.h4
-rw-r--r--engines/xeen/map.cpp14
-rw-r--r--engines/xeen/party.cpp372
-rw-r--r--engines/xeen/party.h26
-rw-r--r--engines/xeen/resources.cpp62
-rw-r--r--engines/xeen/resources.h32
-rw-r--r--engines/xeen/scripts.cpp16
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<PlayerStruct> {
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<byte> &params) {
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<byte> &params) {
// 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)