aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/xeen/character.h5
-rw-r--r--engines/xeen/combat.cpp225
-rw-r--r--engines/xeen/combat.h17
-rw-r--r--engines/xeen/items.cpp3
-rw-r--r--engines/xeen/items.h11
-rw-r--r--engines/xeen/module.mk1
-rw-r--r--engines/xeen/party.cpp7
-rw-r--r--engines/xeen/party.h14
-rw-r--r--engines/xeen/scripts.cpp11
-rw-r--r--engines/xeen/scripts.h2
-rw-r--r--engines/xeen/xeen.h1
11 files changed, 262 insertions, 35 deletions
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 6acd433adc..372014f7fc 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -74,11 +74,6 @@ enum Condition {
NO_CONDITION = 16
};
-enum ElementalCategory {
- ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2,
- ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5
-};
-
enum AttributeCategory {
ATTR_MIGHT = 0, ATTR_INTELLECT = 1, ATTR_PERSONALITY = 2, ATTR_SPEED = 3,
ATTR_ACCURACY = 4, ATTR_LUCK = 5, ATTR_HIT_POINTS = 6, ATTR_SPELL_POINTS = 7,
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 776821a5f4..a8b5a50a4e 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -77,16 +77,27 @@ static const int MONSTER_SHOOT_POW[7] = { 12, 14, 0, 4, 8, 10, 13 };
static const int COMBAT_SHOOTING[4] = { 1, 1, 2, 3 };
-#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + MONINDEX) <= MONINDEX)
+static const int DAMAGE_TYPE_EFFECTS[19] = {
+ 3, 10, 4, 11, 1, 2, 5, 9, 5, 14, 5, 14, 10, 8, 3, 9, 2, 2, 3
+};
+
+static const int POW_WEAPON_VOCS[35] = {
+ 0, 5, 4, 5, 5, 5, 5, 2, 4, 5, 3, 5, 4, 2, 3, 2, 2, 4, 5, 5,
+ 5, 5, 5, 1, 3, 2, 5, 1, 1, 1, 0, 0, 0, 2, 2
+};
+
+static const int MONSTER_ITEM_RANGES[6] = { 10, 20, 50, 100, 100, 100 };
+
+#define monsterSavingThrow(MONINDEX) (_vm->getRandomNumber(1, 50 + (MONINDEX)) <= (MONINDEX))
/*------------------------------------------------------------------------*/
-Combat::Combat(XeenEngine *vm): _vm(vm) {
+Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.voc") {
Common::fill(&_attackMonsters[0], &_attackMonsters[26], 0);
Common::fill(&_charsArray1[0], &_charsArray1[12], 0);
Common::fill(&_monPow[0], &_monPow[12], 0);
Common::fill(&_monsterScale[0], &_monsterScale[12], 0);
- Common::fill(&_elemPow[0], &_elemPow[12], 0);
+ Common::fill(&_elemPow[0], &_elemPow[12], ELEM_FIRE);
Common::fill(&_elemScale[0], &_elemScale[12], 0);
Common::fill(&_shooting[0], &_shooting[8], 0);
Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0);
@@ -108,6 +119,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
_shootType = 0;
_monsterDamage = 0;
_weaponDamage = 0;
+ _attackWeapon = nullptr;
}
void Combat::clear() {
@@ -1251,7 +1263,7 @@ void Combat::attack(Character &c, int ranged) {
}
}
} else {
- Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0);
+ Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], ELEM_FIRE);
damage = 0;
for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
@@ -1363,7 +1375,193 @@ void Combat::attack(Character &c, int ranged) {
}
void Combat::attack2(int damage, int ranged) {
- error("TODO");
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+ MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+ bool monsterDied = false;
+
+ if (!isDarkCc && damage && ranged && monster._spriteId == 89)
+ damage = 0;
+
+ if (!damage) {
+ sound.playSample(&_missVoc, 1);
+ sound.playFX(6);
+ } else {
+ if (!isDarkCc && monster._spriteId == 89)
+ damage += 100;
+ if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP)
+ monster._damageType = DT_PHYSICAL;
+
+ if ((!ranged || !_damageType) && _attackWeapon->_id != 34) {
+ if (monsterData._phsyicalResistence != 0) {
+ if (monsterData._phsyicalResistence == 100) {
+ damage = 0;
+ } else {
+ // This doesn't seem to have any effect?
+ damage = (damage * 100) / 100;
+ }
+ }
+ }
+
+ if (damage) {
+ _charsArray1[_monsterIndex] = 3;
+ _monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (ranged == 3 || ranged == 0);
+ monster._frame = 11;
+ monster._fieldA = 5;
+ }
+
+ int monsterResist = getMonsterResistence(ranged);
+ damage += monsterResist;
+ if (monsterResist > 0) {
+ _elemPow[_monsterIndex] = _attackWeapon->getElementalCategory();
+ _elemScale[_monsterIndex] = getDamageScale(monsterResist);
+ } else if (ranged != 3) {
+ _elemPow[_monsterIndex] = ELEM_FIRE;
+ }
+
+ if (ranged != 0 && ranged != 3) {
+ monster._effect2 = DAMAGE_TYPE_EFFECTS[_damageType];
+ monster._effect1 = 0;
+ }
+
+ if (ranged && monsterSavingThrow(monster._spriteId)) {
+ switch (_damageType) {
+ case DT_FINGEROFDEATH:
+ case DT_MASS_DISTORTION:
+ damage = 5;
+ break;
+ case DT_SLEEP:
+ case DT_HOLYWORD:
+ case DT_UNDEAD:
+ case DT_BEASTMASTER:
+ case DT_DRAGONSLEEP:
+ case DT_GOLEMSTOPPER:
+ case DT_HYPNOTIZE:
+ case DT_INSECT_SPRAY:
+ case DT_MAGIC_ARROW:
+ break;
+ default:
+ damage /= 2;
+ break;
+ }
+ }
+
+ if (damage < 1) {
+ sound.playSample(&_missVoc, 1);
+ sound.playFX(6);
+ } else {
+ _monsterScale[_monsterIndex] = getDamageScale(damage);
+ intf.draw3d(true);
+
+ sound.playSample(nullptr, 0);
+ File powVoc(Common::String::format("pow%d.voc",
+ POW_WEAPON_VOCS[_attackWeapon->_id]));
+ sound.playFX(60 + POW_WEAPON_VOCS[_attackWeapon->_id]);
+ sound.playSample(&powVoc, 1);
+
+ if (monster._hp > damage) {
+ monster._hp -= damage;
+ } else {
+ monster._hp = 0;
+ monsterDied = true;
+ }
+ }
+ }
+
+ intf.draw3d(true);
+
+ if (monsterDied) {
+ if (!isDarkCc) {
+ if (_monster2Attack == 20 && party._mazeId == 41)
+ party._gameFlags[11] = true;
+ if (_monster2Attack == 8 && party._mazeId == 78) {
+ party._gameFlags[60] = true;
+ party._quests[23] = false;
+
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx)
+ party._activeParty[idx].setAward(42, true);
+
+ if (_monster2Attack == 27 && party._mazeId == 29)
+ party._gameFlags[104] = true;
+ }
+ }
+
+ giveExperience(monsterData._experience);
+
+ if (party._mazeId != 85) {
+ party._treasure._gold = monsterData._gold;
+ party._treasure._gems = monsterData._gems;
+
+ if (!isDarkCc && monster._spriteId == 89) {
+ party._treasure._weapons[0]._id = 90;
+ party._treasure._weapons[0]._bonusFlags = 0;
+ party._treasure._weapons[0]._material = 0;
+ party._treasure._hasItems = true;
+ party._questItems[8]++;
+ }
+
+ int itemDrop = monsterData._itemDrop;
+ if (itemDrop) {
+ if (MONSTER_ITEM_RANGES[itemDrop] >= _vm->getRandomNumber(1, 100)) {
+ Character tempChar;
+ int category = tempChar.makeItem(itemDrop, 0, 0);
+
+ switch (category) {
+ case CATEGORY_WEAPON:
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ if (party._treasure._weapons[idx]._id == 0) {
+ party._treasure._weapons[idx] = tempChar._weapons[0];
+ party._treasure._hasItems = 1;
+ break;
+ }
+ }
+ break;
+ case CATEGORY_ARMOR:
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ if (party._treasure._armor[idx]._id == 0) {
+ party._treasure._armor[idx] = tempChar._armor[0];
+ party._treasure._hasItems = 1;
+ break;
+ }
+ }
+ break;
+ case CATEGORY_ACCESSORY:
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ if (party._treasure._accessories[idx]._id == 0) {
+ party._treasure._accessories[idx] = tempChar._accessories[0];
+ party._treasure._hasItems = 1;
+ break;
+ }
+ }
+ break;
+ case CATEGORY_MISC:
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ if (party._treasure._accessories[idx]._id == 0) {
+ party._treasure._accessories[idx] = tempChar._accessories[0];
+ party._treasure._hasItems = 1;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ monster._position = Common::Point(0x80, 0x80);
+ _charsArray1[_monsterIndex] = 0;
+ _monster2Attack = -1;
+ intf.draw3d(true);
+
+ if (_attackMonsters[0] != -1) {
+ _monster2Attack = _attackMonsters[0];
+ _monsterIndex = 0;
+ }
+ }
}
/**
@@ -1434,5 +1632,22 @@ int Combat::getMonsterDamage(Character &c) {
error("TODO");
}
+int Combat::getDamageScale(int v) {
+ if (v < 10)
+ return 5;
+ else if (v < 100)
+ return 0;
+ else
+ return 0x8000;
+}
+
+int Combat::getMonsterResistence(int ranged) {
+ error("TODO");
+}
+
+void Combat::giveExperience(int experience) {
+ error("TODO");
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 1e1ca82808..75614ccdf7 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "common/rect.h"
+#include "xeen/files.h"
#include "xeen/sprites.h"
namespace Xeen {
@@ -50,8 +51,14 @@ enum SpecialAttack {
SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22
};
+enum ElementalCategory {
+ ELEM_FIRE = 0, ELEM_ELECTRICITY = 1, ELEM_COLD = 2,
+ ELEM_ACID_POISON = 3, ELEM_ENERGY = 4, ELEM_MAGIC = 5
+};
+
class XeenEngine;
class Character;
+class XeenItem;
class Combat {
private:
@@ -64,6 +71,12 @@ private:
bool getWeaponDamage(Character &c, int ranged);
int getMonsterDamage(Character &c);
+
+ int getDamageScale(int v);
+
+ int getMonsterResistence(int ranged);
+
+ void giveExperience(int experience);
public:
Common::Array<Character *> _combatParty;
Common::Array<bool> _charsBlocked;
@@ -74,7 +87,7 @@ public:
int _charsArray1[PARTY_AND_MONSTERS];
bool _monPow[PARTY_AND_MONSTERS];
int _monsterScale[PARTY_AND_MONSTERS];
- int _elemPow[PARTY_AND_MONSTERS];
+ ElementalCategory _elemPow[PARTY_AND_MONSTERS];
int _elemScale[PARTY_AND_MONSTERS];
int _missedShot[8];
Common::Array<int> _speedTable;
@@ -96,6 +109,8 @@ public:
int _shootType;
int _monsterDamage;
int _weaponDamage;
+ XeenItem *_attackWeapon;
+ File _missVoc, _pow1Voc;
public:
Combat(XeenEngine *vm);
diff --git a/engines/xeen/items.cpp b/engines/xeen/items.cpp
index b9b531db7b..e8c0249803 100644
--- a/engines/xeen/items.cpp
+++ b/engines/xeen/items.cpp
@@ -25,8 +25,5 @@
namespace Xeen {
-Treasure::Treasure() {
- _hasItems = false;
-}
} // End of namespace Xeen
diff --git a/engines/xeen/items.h b/engines/xeen/items.h
index 1e208615f8..bfbd9e4481 100644
--- a/engines/xeen/items.h
+++ b/engines/xeen/items.h
@@ -27,18 +27,7 @@
namespace Xeen {
-#define TOTAL_ITEMS 10
-class Treasure {
-public:
- XeenItem _misc[TOTAL_ITEMS];
- XeenItem _accessories[TOTAL_ITEMS];
- XeenItem _armor[TOTAL_ITEMS];
- XeenItem _weapons[TOTAL_ITEMS];
- bool _hasItems;
-public:
- Treasure();
-};
} // End of namespace Xeen
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index a17311c6af..1fe29c6a8e 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -32,7 +32,6 @@ MODULE_OBJS := \
font.o \
interface.o \
interface_map.o \
- items.o \
map.o \
party.o \
resources.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 993f156204..ab8abd7f92 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -57,6 +57,13 @@ void Roster::synchronize(Common::Serializer &s) {
/*------------------------------------------------------------------------*/
+Treasure::Treasure() {
+ _hasItems = false;
+ _gold = _gems = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
XeenEngine *Party::_vm;
Party::Party(XeenEngine *vm) {
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 5d98c55b82..841fcd393a 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -48,6 +48,7 @@ enum Difficulty { ADVENTURER = 0, WARRIOR = 1 };
#define TOTAL_STATS 7
#define TOTAL_QUEST_ITEMS 85
#define TOTAL_QUEST_FLAGS 56
+#define MAX_TREASURE_ITEMS 10
class Roster: public Common::Array<Character> {
public:
@@ -58,6 +59,18 @@ public:
void synchronize(Common::Serializer &s);
};
+class Treasure {
+public:
+ XeenItem _misc[MAX_TREASURE_ITEMS];
+ XeenItem _accessories[MAX_TREASURE_ITEMS];
+ XeenItem _armor[MAX_TREASURE_ITEMS];
+ XeenItem _weapons[MAX_TREASURE_ITEMS];
+ bool _hasItems;
+ int _gems, _gold;
+public:
+ Treasure();
+};
+
class Party {
friend class Character;
friend class InventoryItems;
@@ -124,6 +137,7 @@ public:
int _fallDamage;
DamageType _damageType;
bool _dead;
+ Treasure _treasure;
public:
Party(XeenEngine *vm);
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 8b3888934b..7aab04c4c4 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -92,8 +92,6 @@ Scripts::Scripts(XeenEngine *vm) : _vm(vm) {
_whoWill = 0;
_itemType = 0;
_treasureItems = 0;
- _treasureGold = 0;
- _treasureGems = 0;
_lineNum = 0;
_charIndex = 0;
_v2 = 0;
@@ -125,7 +123,7 @@ int Scripts::checkEvents() {
Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
//int items = _treasureItems;
- if (_treasureGold & _treasureItems) {
+ if (party._treasure._gold & party._treasure._gems) {
// TODO
} else {
// TODO
@@ -591,6 +589,7 @@ void Scripts::cmdGiveExtended(Common::Array<byte> &params) {
void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
Common::String msg1 = params[2] ? map._events._text[params[2]] :
_vm->_interface->_interfaceText;
Common::String msg2;
@@ -621,13 +620,13 @@ void Scripts::cmdConfirmWord(Common::Array<byte> &params) {
doWorldEnd();
} else {
if (result == 59 && !_vm->_files->_isDarkCc) {
- for (int idx = 0; idx < TOTAL_ITEMS; ++idx) {
- XeenItem &item = _vm->_treasure._weapons[idx];
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ XeenItem &item = party._treasure._weapons[idx];
if (!item._id) {
item._id = 34;
item._material = 0;
item._bonusFlags = 0;
- _vm->_treasure._hasItems = true;
+ party._treasure._hasItems = true;
cmdExit(params);
return;
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index cc32a9667f..1db672bd18 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -141,8 +141,6 @@ private:
XeenEngine *_vm;
int _charFX[6];
int _treasureItems;
- int _treasureGold;
- int _treasureGems;
int _lineNum;
int _charIndex;
int _mirrorId;
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index d0a72f5868..76cb1c1159 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -149,7 +149,6 @@ public:
SoundManager *_sound;
Spells *_spells;
Town *_town;
- Treasure _treasure;
Mode _mode;
GameEvent _gameEvent;
Common::SeekableReadStream *_eventData;