diff options
author | Paul Gilbert | 2015-02-20 21:55:40 -0500 |
---|---|---|
committer | Paul Gilbert | 2015-02-20 21:55:40 -0500 |
commit | 917b143ec9e7fd9f5c9b28088c2b7f6310c16cee (patch) | |
tree | 5ffef2a8c7e2563659a69cc7d90285bc612fbe0c /engines/xeen | |
parent | ebc134a267046d78b1cef125f2a318e497bdf45f (diff) | |
download | scummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.tar.gz scummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.tar.bz2 scummvm-rg350-917b143ec9e7fd9f5c9b28088c2b7f6310c16cee.zip |
XEEN: Implement attack method
Diffstat (limited to 'engines/xeen')
-rw-r--r-- | engines/xeen/character.cpp | 1 | ||||
-rw-r--r-- | engines/xeen/combat.cpp | 234 | ||||
-rw-r--r-- | engines/xeen/combat.h | 61 | ||||
-rw-r--r-- | engines/xeen/dialogs_spells.cpp | 8 | ||||
-rw-r--r-- | engines/xeen/interface_map.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/map.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/map.h | 2 | ||||
-rw-r--r-- | engines/xeen/scripts.cpp | 2 |
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> ¶ms) { 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; |