aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorPaul Gilbert2015-02-20 08:47:38 -0500
committerPaul Gilbert2015-02-20 08:47:38 -0500
commitcaf7f376b3fd8bb1bfd3e658139b547695033dde (patch)
tree6b0ed8edb2fcc94bbd75626ed40db57cf999edb2 /engines
parentb66bf1a838b01181c93b19e214c59c810e05955d (diff)
downloadscummvm-rg350-caf7f376b3fd8bb1bfd3e658139b547695033dde.tar.gz
scummvm-rg350-caf7f376b3fd8bb1bfd3e658139b547695033dde.tar.bz2
scummvm-rg350-caf7f376b3fd8bb1bfd3e658139b547695033dde.zip
XEEN: Implemented monsterAttack
Diffstat (limited to 'engines')
-rw-r--r--engines/xeen/combat.cpp184
-rw-r--r--engines/xeen/combat.h2
-rw-r--r--engines/xeen/map.h2
3 files changed, 187 insertions, 1 deletions
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index a9ead958a8..b6d1f7fe1d 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -236,6 +236,13 @@ loop:
}
}
+/**
+ * Do damage to a specific character
+ */
+void Combat::doCharDamage(Character *c, int monsterDataIndex) {
+ error("TODO");
+}
+
void Combat::moveMonsters() {
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
@@ -565,7 +572,184 @@ void Combat::monsterOvercome() {
}
void Combat::attackMonster(int monsterId) {
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+ int monRefId;
+
+ if (_monstersAttacking) {
+ warning("TODO: Original used uninitialized variables if flag was set");
+ return;
+ }
+
+ int monsterIndex;
+ switch (_whosTurn - _combatParty.size()) {
+ case 0:
+ monsterIndex = _attackMonsters[0];
+ intf._indoorList[156]._scale = 0;
+ break;
+ case 1:
+ monsterIndex = _attackMonsters[1];
+ intf._indoorList[150]._scale = 0;
+ break;
+ case 2:
+ default:
+ monsterIndex = _attackMonsters[2];
+ intf._indoorList[153]._scale = 0;
+ }
+
+ MazeMonster &monster = map._mobData._monsters[monsterIndex];
+ MonsterStruct &monsterData = map._monsterData[monster._spriteId];
+ if (monster._field7)
+ return;
+
+ monster._frame = 8;
+ monster._fieldA = 3;
+ monster._field9 = 0;
+ intf.draw3d(true);
+ intf.draw3d(true);
+
+ File f(monsterData._attackVoc);
+ sound.playSample(&f, 0);
+ bool flag = false;
+
+ for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) {
+ int charNum = -1;
+ bool isHated = false;
+
+ if (monsterData._hatesClass != -1) {
+ if (monsterData._hatesClass == 15)
+ // Monster hates all classes
+ goto loop;
+
+ for (uint charIndex = 0; charIndex < _combatParty.size(); ++charIndex) {
+ Character &c = *_combatParty[charIndex];
+ Condition cond = c.worstCondition();
+ if (cond >= PARALYZED && cond <= ERADICATED)
+ continue;
+
+ bool isHated = false;
+ switch (monsterData._hatesClass) {
+ case CLASS_KNIGHT:
+ case CLASS_PALADIN:
+ case CLASS_ARCHER:
+ case CLASS_CLERIC:
+ case CLASS_SORCERER:
+ case CLASS_ROBBER:
+ case CLASS_NINJA:
+ case CLASS_BARBARIAN:
+ case CLASS_DRUID:
+ case CLASS_RANGER:
+ isHated = c._class == monsterData._hatesClass;
+ break;
+ case 12:
+ isHated = c._race == DWARF;
+ break;
+ default:
+ break;
+ }
+
+ if (isHated) {
+ charNum = charIndex;
+ break;
+ }
+ }
+ }
+
+ if (!isHated) {
+ // No particularly hated foe, so decide which character to start with
+ switch (_combatParty.size()) {
+ case 1:
+ charNum = 0;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ charNum = _vm->getRandomNumber(0, _combatParty.size() - 1);
+ break;
+ case 6:
+ if (_vm->getRandomNumber(1, 6) == 6)
+ charNum = 5;
+ else
+ charNum = _vm->getRandomNumber(0, 4);
+ break;
+ }
+ }
+
+ // Attacking loop
+ do {
+ if (!flag) {
+ Condition cond = _combatParty[charNum]->worstCondition();
+
+ if (cond >= PARALYZED && cond <= ERADICATED) {
+ Common::Array<int> ableChars;
+ bool skip = false;
+
+ for (uint idx = 0; idx < _combatParty.size() && !skip; ++idx) {
+ switch (_combatParty[idx]->worstCondition()) {
+ case PARALYZED:
+ case UNCONSCIOUS:
+ if (flag)
+ skip = true;
+ break;
+ case DEAD:
+ case STONED:
+ case ERADICATED:
+ break;
+ default:
+ ableChars.push_back(idx);
+ break;
+ }
+ }
+
+ if (!skip) {
+ if (ableChars.size() == 0) {
+ party._dead = true;
+ _vm->_mode = MODE_1;
+ return;
+ }
+
+ charNum = ableChars[_vm->getRandomNumber(0, ableChars.size() - 1)];
+ }
+ }
+ }
+
+ // Unconditional if to get around goto initialization errors
+ if (true) {
+ Character &c = *_combatParty[charNum];
+ if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
+ doCharDamage(&c, monster._spriteId);
+ } else {
+ int v = _vm->getRandomNumber(1, 20);
+ if (v == 1) {
+ sound.playFX(6);
+ } else {
+ if (v == 20)
+ doCharDamage(&c, monster._spriteId);
+ v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
+ monsterData._hitChance);
+
+ int ac = c.getArmorClass() + (!_charsBlocked[charNum] ? 10 :
+ c.getCurrentLevel() / 2 + 15);
+ if (ac > v) {
+ sound.playFX(6);
+ } else {
+ doCharDamage(&c, monster._spriteId);
+ }
+ }
+ }
+
+ if (flag)
+ break;
+ }
+loop:
+ flag = true;
+ } while (++charNum < (int)_combatParty.size());
+ }
+ intf.drawParty(true);
}
int Combat::stopAttack(const Common::Point &diffPt) {
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index b9293233e7..df42a4031f 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -107,6 +107,8 @@ public:
void giveCharDamage(int damage, DamageType attackType, int charIndex);
+ void doCharDamage(Character *c, int monsterDataIndex);
+
void moveMonsters();
void setupCombatParty();
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index a43cef516e..05ead5b974 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -54,7 +54,7 @@ public:
int _accuracy;
int _speed;
int _numberOfAttacks;
- CharacterClass _hatesClass;
+ int _hatesClass;
int _strikes;
int _dmgPerStrike;
DamageType _attackType;