aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-02-20 21:55:40 -0500
committerPaul Gilbert2015-02-20 21:55:40 -0500
commit917b143ec9e7fd9f5c9b28088c2b7f6310c16cee (patch)
tree5ffef2a8c7e2563659a69cc7d90285bc612fbe0c
parentebc134a267046d78b1cef125f2a318e497bdf45f (diff)
downloadscummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.tar.gz
scummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.tar.bz2
scummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.zip
XEEN: Implement attack method
-rw-r--r--engines/xeen/character.cpp1
-rw-r--r--engines/xeen/combat.cpp234
-rw-r--r--engines/xeen/combat.h61
-rw-r--r--engines/xeen/dialogs_spells.cpp8
-rw-r--r--engines/xeen/interface_map.cpp2
-rw-r--r--engines/xeen/map.cpp2
-rw-r--r--engines/xeen/map.h2
-rw-r--r--engines/xeen/scripts.cpp2
8 files changed, 273 insertions, 39 deletions
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 04f83253d4..737c36ab30 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -1855,5 +1855,4 @@ int Character::getClassCategory() const {
}
}
-
} // End of namespace Xeen
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 514201565a..776821a5f4 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -77,6 +77,8 @@ 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)
+
/*------------------------------------------------------------------------*/
Combat::Combat(XeenEngine *vm): _vm(vm) {
@@ -91,6 +93,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false);
Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false);
Common::fill(&_gmonHit[0], &_gmonHit[36], 0);
+ Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], 0);
_globalCombat = 0;
_whosTurn = -1;
_itemFlag = false;
@@ -102,6 +105,9 @@ Combat::Combat(XeenEngine *vm): _vm(vm) {
_whosSpeed = 0;
_damageType = DT_PHYSICAL;
_oldCharacter = nullptr;
+ _shootType = 0;
+ _monsterDamage = 0;
+ _weaponDamage = 0;
}
void Combat::clear() {
@@ -455,7 +461,7 @@ void Combat::moveMonsters() {
// Check for range attacks
if (monsterData._rangeAttack && !_rangeAttacking[idx]
&& _attackMonsters[0] != idx && _attackMonsters[1] != idx
- && _attackMonsters[2] != idx && !monster._field7) {
+ && _attackMonsters[2] != idx && !monster._damageType) {
// Setup monster for attacking
setupMonsterAttack(monster._spriteId, pt);
_rangeAttacking[idx] = true;
@@ -683,7 +689,7 @@ void Combat::moveMonster(int monsterId, const Common::Point &pt) {
Map &map = *_vm->_map;
MazeMonster &monster = map._mobData._monsters[monsterId];
- if (_monsterMap[pt.y][pt.x] < 3 && !monster._field7 && _vm->_moveMonsters) {
+ if (_monsterMap[pt.y][pt.x] < 3 && !monster._damageType && _vm->_moveMonsters) {
++_monsterMap[pt.y][pt.x];
--_monsterMap[monster._position.y][monster._position.x];
monster._position = pt;
@@ -731,10 +737,10 @@ void Combat::monsterOvercome() {
MazeMonster &monster = map._mobData._monsters[idx];
int dataIndex = monster._spriteId;
- if (monster._field7 != 0 && monster._field7 != 13) {
+ if (monster._damageType != 0 && monster._damageType != 13) {
// Do a saving throw for monster
if (dataIndex <= _vm->getRandomNumber(1, dataIndex + 50))
- monster._field7 = 0;
+ monster._damageType = 0;
}
}
}
@@ -768,7 +774,7 @@ void Combat::attackMonster(int monsterId) {
MazeMonster &monster = map._mobData._monsters[monsterIndex];
MonsterStruct &monsterData = map._monsterData[monster._spriteId];
- if (monster._field7)
+ if (monster._damageType)
return;
monster._frame = 8;
@@ -1153,7 +1159,210 @@ Common::String Combat::getMonsterDescriptions() {
lines[1].c_str(), lines[2].c_str());
}
-void Combat::attack(Character &c, int v2) {
+void Combat::attack(Character &c, int ranged) {
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ int damage = _monsterDamage;
+
+ if (_monster2Attack == -1)
+ return;
+
+ MazeMonster &monster = map._mobData._monsters[_monster2Attack];
+ int monsterDataIndex = monster._spriteId;
+ MonsterStruct &monsterData = map._monsterData[monsterDataIndex];
+
+ if (ranged) {
+ if (_shootType != 1 || _damageType == DT_MAGIC_ARROW) {
+ if (!monsterData._magicResistence || monsterData._magicResistence <=
+ _vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) {
+ if (_monsterDamage != 0) {
+ attack2(damage, ranged);
+ setSpeedTable();
+ } else {
+ switch (_damageType) {
+ case DT_SLEEP:
+ if (monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) {
+ if (_vm->getRandomNumber(1, 50 + monsterDataIndex) > monsterDataIndex)
+ monster._damageType = DT_SLEEP;
+ }
+ break;
+ case DT_FINGEROFDEATH:
+ if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+ && !monsterSavingThrow(monsterDataIndex)) {
+ damage = MIN(monster._hp, 50);
+ attack2(damage, 2);
+ setSpeedTable();
+ }
+ break;
+ case DT_HOLYWORD:
+ if (monsterData._monsterType == MONSTER_UNDEAD) {
+ attack2(monster._hp, 2);
+ setSpeedTable();
+ }
+ break;
+ case DT_MASS_DISTORTION:
+ attack2(MAX(monster._hp / 2, 1), 2);
+ setSpeedTable();
+ break;
+ case DT_UNDEAD:
+ if (monsterData._monsterType == MONSTER_UNDEAD)
+ damage = 25;
+ else
+ ranged = 2;
+ attack2(damage, ranged);
+ setSpeedTable();
+ break;
+ case DT_BEASTMASTER:
+ if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+ && !monsterSavingThrow(monsterDataIndex)) {
+ monster._damageType = DT_BEASTMASTER;
+ }
+ break;
+ case DT_DRAGONSLEEP:
+ if (monsterData._monsterType == MONSTER_DRAGON && !monsterSavingThrow(monsterDataIndex))
+ monster._damageType = DT_DRAGONSLEEP;
+ break;
+ case DT_GOLEMSTOPPER:
+ if (monsterData._monsterType == MONSTER_GOLEM) {
+ attack2(100, ranged);
+ setSpeedTable();
+ }
+ break;
+ case DT_HYPNOTIZE:
+ if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID)
+ && !monsterSavingThrow(monsterDataIndex)) {
+ monster._damageType = _damageType;
+ }
+ break;
+ case DT_INSECT_SPRAY:
+ if (monsterData._monsterType == MONSTER_INSECT) {
+ attack2(25, ranged);
+ setSpeedTable();
+ }
+ break;
+ case DT_MAGIC_ARROW:
+ attack2(8, ranged);
+ setSpeedTable();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ } else {
+ Common::fill(&_elemPow[0], &_elemPow[PARTY_AND_MONSTERS], 0);
+ damage = 0;
+
+ for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) {
+ Character &c = party._activeParty[charIndex];
+
+ if (_shooting[charIndex] && !_missedShot[charIndex]) {
+ if (!hitMonster(c, ranged)) {
+ ++_missedShot[charIndex];
+ } else {
+ damage = _monsterDamage ? _monsterDamage : _weaponDamage;
+ _shooting[charIndex] = 0;
+ attack2(damage, ranged);
+
+ if (map._isOutdoors) {
+ intf._outdoorList._attackImgs1[charIndex]._scale = 0;
+ intf._outdoorList._attackImgs1[charIndex]._sprites = nullptr;
+ intf._outdoorList._attackImgs2[charIndex]._scale = 0;
+ intf._outdoorList._attackImgs2[charIndex]._sprites = nullptr;
+ intf._outdoorList._attackImgs3[charIndex]._scale = 0;
+ intf._outdoorList._attackImgs3[charIndex]._sprites = nullptr;
+ intf._outdoorList._attackImgs4[charIndex]._scale = 0;
+ intf._outdoorList._attackImgs4[charIndex]._sprites = nullptr;
+ } else {
+ intf._indoorList._attackImgs1[charIndex]._scale = 0;
+ intf._indoorList._attackImgs1[charIndex]._sprites = nullptr;
+ intf._indoorList._attackImgs2[charIndex]._scale = 0;
+ intf._indoorList._attackImgs2[charIndex]._sprites = nullptr;
+ intf._indoorList._attackImgs3[charIndex]._scale = 0;
+ intf._indoorList._attackImgs3[charIndex]._sprites = nullptr;
+ intf._indoorList._attackImgs4[charIndex]._scale = 0;
+ intf._indoorList._attackImgs4[charIndex]._sprites = nullptr;
+ }
+
+ if (_monster2Attack == -1)
+ return;
+ }
+ }
+ }
+ }
+ } else {
+ _damageType = DT_PHYSICAL;
+ int divisor = 0;
+ switch (c._class) {
+ case CLASS_BARBARIAN:
+ divisor = 4;
+ break;
+ case CLASS_KNIGHT:
+ case CLASS_NINJA:
+ divisor = 5;
+ break;
+ case CLASS_PALADIN:
+ case CLASS_ARCHER:
+ case CLASS_ROBBER:
+ case CLASS_RANGER:
+ divisor = 6;
+ break;
+ case CLASS_CLERIC:
+ case CLASS_DRUID:
+ divisor = 7;
+ break;
+ case CLASS_SORCERER:
+ divisor = 8;
+ break;
+ }
+
+ int numberOfAttacks = c.getCurrentLevel() / divisor;
+ damage = 0;
+
+ while (numberOfAttacks-- > 0) {
+ if (hitMonster(c, 0))
+ damage += getMonsterDamage(c);
+ }
+
+ for (int itemIndex = 0; itemIndex < INV_ITEMS_TOTAL; ++itemIndex) {
+ XeenItem &weapon = c._weapons[itemIndex];
+ if (weapon._frame != 0) {
+ switch (weapon._bonusFlags & ITEMFLAG_BONUS_MASK) {
+ case 1:
+ if (monsterData._monsterType == MONSTER_DRAGON)
+ damage *= 3;
+ break;
+ case 2:
+ if (monsterData._monsterType == MONSTER_UNDEAD)
+ damage *= 3;
+ break;
+ case 3:
+ if (monsterData._monsterType == MONSTER_GOLEM)
+ damage *= 3;
+ break;
+ case 4:
+ if (monsterData._monsterType == MONSTER_INSECT)
+ damage *= 3;
+ break;
+ case 5:
+ if (monsterData._monsterType == MONSTER_0)
+ damage *= 3;
+ break;
+ case 6:
+ if (monsterData._monsterType == MONSTER_ANIMAL)
+ damage *= 3;
+ break;
+ }
+ }
+ }
+
+ attack2(damage, ranged);
+ setSpeedTable();
+ }
+}
+
+void Combat::attack2(int damage, int ranged) {
error("TODO");
}
@@ -1213,4 +1422,17 @@ void Combat::run() {
}
}
+bool Combat::hitMonster(Character &c, int ranged) {
+ error("TODO");
+}
+
+bool Combat::getWeaponDamage(Character &c, int ranged) {
+ error("TODO");
+}
+
+int Combat::getMonsterDamage(Character &c) {
+ error("TODO");
+}
+
+
} // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 60adbca063..1e1ca82808 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -30,12 +30,13 @@
namespace Xeen {
#define MAX_NUM_MONSTERS 107
+#define PARTY_AND_MONSTERS 11
enum DamageType {
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,
+ DT_UNDEAD = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13,
DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16,
DT_POISON_VALLEY = 17, DT_MAGIC_ARROW = 18
};
@@ -55,6 +56,14 @@ class Character;
class Combat {
private:
XeenEngine *_vm;
+
+ void attack2(int damage, int ranged);
+
+ bool hitMonster(Character &c, int ranged);
+
+ bool getWeaponDamage(Character &c, int ranged);
+
+ int getMonsterDamage(Character &c);
public:
Common::Array<Character *> _combatParty;
Common::Array<bool> _charsBlocked;
@@ -62,11 +71,12 @@ public:
SpriteResource _powSprites;
int _attackMonsters[26];
int _monster2Attack;
- int _charsArray1[12];
- bool _monPow[12];
- int _monsterScale[12];
- int _elemPow[12];
- int _elemScale[12];
+ int _charsArray1[PARTY_AND_MONSTERS];
+ bool _monPow[PARTY_AND_MONSTERS];
+ int _monsterScale[PARTY_AND_MONSTERS];
+ int _elemPow[PARTY_AND_MONSTERS];
+ int _elemScale[PARTY_AND_MONSTERS];
+ int _missedShot[8];
Common::Array<int> _speedTable;
int _shooting[8];
int _globalCombat;
@@ -83,23 +93,9 @@ public:
int _whosSpeed;
DamageType _damageType;
Character *_oldCharacter;
-
- void monstersAttack();
-
- void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
-
- bool monsterCanMove(const Common::Point &pt, int wallShift,
- int v1, int v2, int monsterId);
-
- void moveMonster(int monsterId, const Common::Point &pt);
-
- void attackMonster(int monsterId);
-
- void endAttack();
-
- void monsterOvercome();
-
- int stopAttack(const Common::Point &diffPt);
+ int _shootType;
+ int _monsterDamage;
+ int _weaponDamage;
public:
Combat(XeenEngine *vm);
@@ -121,7 +117,7 @@ public:
Common::String getMonsterDescriptions();
- void attack(Character &c, int v2);
+ void attack(Character &c, int ranged);
void block();
@@ -130,6 +126,23 @@ public:
void giveTreasure();
void run();
+
+ void monstersAttack();
+
+ void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt);
+
+ bool monsterCanMove(const Common::Point &pt, int wallShift,
+ int v1, int v2, int monsterId);
+
+ void moveMonster(int monsterId, const Common::Point &pt);
+
+ void attackMonster(int monsterId);
+
+ void endAttack();
+
+ void monsterOvercome();
+
+ int stopAttack(const Common::Point &diffPt);
};
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index 0383886c4d..ea423aac72 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -51,7 +51,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
int castingCopy = isCasting;
isCasting &= 0x7f;
int selection = -1;
- uint topIndex = 0;
+ int topIndex = 0;
int newSelection;
screen._windows[25].open();
@@ -87,7 +87,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
Common::fill(&colors[0], &colors[10], 9);
for (int idx = 0; idx < 10; ++idx) {
- if ((topIndex + idx) < _spells.size()) {
+ if ((topIndex + idx) < (int)_spells.size()) {
names[idx] = _spells[topIndex + idx]._name.c_str();
colors[idx] = _spells[topIndex + idx]._color;
}
@@ -256,7 +256,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
case Common::KEYCODE_PAGEDOWN:
case Common::KEYCODE_KP3:
- topIndex = MIN(topIndex + 10, ((_spells.size() - 1) / 10) * 10);
+ topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
break;
case Common::KEYCODE_UP:
@@ -267,7 +267,7 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
case Common::KEYCODE_DOWN:
case Common::KEYCODE_KP2:
- if (topIndex < (_spells.size() - 10))
+ if (topIndex < ((int)_spells.size() - 10))
++topIndex;
break;
}
diff --git a/engines/xeen/interface_map.cpp b/engines/xeen/interface_map.cpp
index d6d15d691f..8032369cc6 100644
--- a/engines/xeen/interface_map.cpp
+++ b/engines/xeen/interface_map.cpp
@@ -705,7 +705,7 @@ void InterfaceMap::animate3d() {
for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
MazeMonster &monster = map._mobData._monsters[idx];
- if (!monster._field7) {
+ if (!monster._damageType) {
if (monster._frame < 8) {
MonsterStruct &monsterData = map._monsterData[monster._spriteId];
if (!monsterData._loopAnimation) {
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index 01c050a10a..10fba6d6b0 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -652,7 +652,7 @@ MazeMonster::MazeMonster() {
_id = 0;
_spriteId = 0;
_isAttacking = false;
- _field7 = 0;
+ _damageType = DT_PHYSICAL;
_field9 = 0;
_fieldA = 0;
_hp = 0;
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index 05ead5b974..7faf59fc04 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -245,7 +245,7 @@ struct MazeMonster {
int _id;
int _spriteId;
bool _isAttacking;
- int _field7;
+ int _damageType;
int _field9;
int _fieldA;
int _hp;
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 37222a3d76..8b3888934b 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -508,7 +508,7 @@ void Scripts::cmdSpawn(Common::Array<byte> &params) {
monster._position.x = params[1];
monster._position.y = params[2];
monster._frame = _vm->getRandomNumber(7);
- monster._field7 = 0;
+ monster._damageType = 0;
monster._isAttacking = params[1] != 0;
monster._hp = monsterData._hp;