diff options
Diffstat (limited to 'engines/xeen/combat.cpp')
-rw-r--r-- | engines/xeen/combat.cpp | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 6a0aa20169..8900d13e9e 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -98,7 +98,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo Common::fill(&_monsterScale[0], &_monsterScale[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(&_shootingRow[0], &_shootingRow[MAX_PARTY_COUNT], 0); Common::fill(&_monsterMap[0][0], &_monsterMap[32][32], 0); Common::fill(&_monsterMoved[0], &_monsterMoved[MAX_NUM_MONSTERS], false); Common::fill(&_rangeAttacking[0], &_rangeAttacking[MAX_NUM_MONSTERS], false); @@ -135,7 +135,12 @@ void Combat::clearBlocked() { Common::fill(_charsBlocked, _charsBlocked + PARTY_AND_MONSTERS, false); } +void Combat::clearShooting() { + Common::fill(_shootingRow, _shootingRow + MAX_PARTY_COUNT, 0); +} + void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) { + Interface &intf = *_vm->_interface; Party &party = *_vm->_party; Scripts &scripts = *_vm->_scripts; Sound &sound = *_vm->_sound; @@ -224,7 +229,7 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) { // Draw the attack effect on the character sprite sound.playFX(fx); - _powSprites.draw(0, frame, Common::Point(Res.CHAR_FACES_X[selectedIndex1], 150)); + intf._charPowSprites.draw(0, frame, Common::Point(Res.CHAR_FACES_X[selectedIndex1], 150)); windows[33].update(); // Reduce damage if power shield active, and set it zero @@ -263,6 +268,7 @@ loop: } void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) { + Debugger &debugger = *g_vm->_debugger; EventsManager &events = *_vm->_events; Interface &intf = *_vm->_interface; Map &map = *_vm->_map; @@ -430,7 +436,12 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) { break; } - c.subtractHitPoints(damage); + if (debugger._invincible) + // Invincibility mode is on, so reset conditions that were set + c.clearConditions(); + else + // Standard gameplay, deal out the damage + c.subtractHitPoints(damage); } events.ipause(2); @@ -564,7 +575,7 @@ void Combat::monstersAttack() { sound.playFX(ATTACK_TYPE_FX[monsterData->_attackType]); for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) { - if (!_shooting[charNum]) + if (!_shootingRow[charNum]) continue; if (map._isOutdoors) { @@ -577,7 +588,7 @@ void Combat::monstersAttack() { outdoorList._attackImgs3[charNum]._sprites = nullptr; outdoorList._attackImgs4[charNum]._sprites = nullptr; - switch (_shooting[charNum]) { + switch (_shootingRow[charNum]) { case 1: outdoorList._attackImgs1[charNum]._sprites = &_powSprites; break; @@ -598,7 +609,7 @@ void Combat::monstersAttack() { indoorList._attackImgs3[charNum]._sprites = nullptr; indoorList._attackImgs4[charNum]._sprites = nullptr; - switch (_shooting[charNum]) { + switch (_shootingRow[charNum]) { case 1: indoorList._attackImgs1[charNum]._sprites = &_powSprites; break; @@ -657,12 +668,15 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) { if (result != 1) { for (int charNum = 0; charNum < MAX_PARTY_COUNT; ++charNum) { - if (!_shooting[charNum]) { - _shooting[charNum] = COMBAT_SHOOTING[result - 1]; + if (!_shootingRow[charNum]) { + _shootingRow[charNum] = COMBAT_SHOOTING[result - 1]; + break; } } } } + + break; } } } @@ -753,7 +767,7 @@ void Combat::endAttack() { } } - Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], false); + clearShooting(); } void Combat::monsterOvercome() { @@ -801,7 +815,7 @@ void Combat::doMonsterTurn(int monsterId) { return; monster._frame = 8; - monster._fieldA = 3; + monster._postAttackDelay = 3; monster._field9 = 0; intf.draw3d(true); intf.draw3d(true); @@ -922,9 +936,11 @@ void Combat::doMonsterTurn(int monsterId) { } else { int v = _vm->getRandomNumber(1, 20); if (v == 1) { + // Critical Save sound.playFX(6); } else { if (v == 20) + // Critical failure doCharDamage(c, charNum, monsterId); v += monsterData._hitChance / 4 + _vm->getRandomNumber(1, monsterData._hitChance); @@ -1070,8 +1086,8 @@ void Combat::setupCombatParty() { void Combat::setSpeedTable() { Map &map = *_vm->_map; Common::Array<int> charSpeeds; - bool hasSpeed = _whosSpeed != -1 && _whosSpeed < (int)_speedTable.size(); - int oldSpeed = hasSpeed ? _speedTable[_whosSpeed] : 0; + bool hasSpeed = _whosSpeed != -1; + int oldSpeed = hasSpeed && _whosSpeed < (int)_speedTable.size() ? _speedTable[_whosSpeed] : 0; // Set up speeds for party membres int maxSpeed = 0; @@ -1107,18 +1123,23 @@ void Combat::setSpeedTable() { if (hasSpeed) { if (_speedTable[_whosSpeed] != oldSpeed) { - for (uint idx = 0; idx < charSpeeds.size(); ++idx) { - if (oldSpeed == _speedTable[idx]) { - _whosSpeed = idx; + for (_whosSpeed = 0; _whosSpeed < (int)charSpeeds.size(); ++_whosSpeed) { + if (oldSpeed == _speedTable[_whosSpeed]) break; - } } + + if (_whosSpeed == (int)charSpeeds.size()) + error("Could not reset next speedy character. Beep beep."); } } } bool Combat::allHaveGone() const { - for (uint idx = 0; idx < _charsGone.size(); ++idx) { + int monsCount = (_attackMonsters[0] != -1 ? 1 : 0) + + (_attackMonsters[1] != -1 ? 1 : 0) + + (_attackMonsters[2] != -1 ? 1 : 0); + + for (uint idx = 0; idx < (_combatParty.size() + monsCount); ++idx) { if (!_charsGone[idx]) { if (idx >= _combatParty.size()) { return false; @@ -1192,7 +1213,6 @@ void Combat::attack(Character &c, RangeType rangeType) { _vm->getRandomNumber(1, 100 + _oldCharacter->getCurrentLevel())) { if (_monsterDamage != 0) { attack2(damage, rangeType); - setSpeedTable(); } else { switch (_damageType) { case DT_SLEEP: @@ -1206,18 +1226,15 @@ void Combat::attack(Character &c, RangeType rangeType) { && !monsterSavingThrow(monsterDataIndex)) { damage = MIN(monster._hp, 50); attack2(damage, RT_ALL); - setSpeedTable(); } break; case DT_HOLYWORD: if (monsterData._monsterType == MONSTER_UNDEAD) { attack2(monster._hp, RT_ALL); - setSpeedTable(); } break; case DT_MASS_DISTORTION: attack2(MAX(monster._hp / 2, 1), RT_ALL); - setSpeedTable(); break; case DT_UNDEAD: if (monsterData._monsterType == MONSTER_UNDEAD) @@ -1225,7 +1242,6 @@ void Combat::attack(Character &c, RangeType rangeType) { else rangeType = RT_ALL; attack2(damage, rangeType); - setSpeedTable(); break; case DT_BEASTMASTER: if ((monsterData._monsterType == MONSTER_ANIMAL || monsterData._monsterType == MONSTER_HUMANOID) @@ -1240,7 +1256,6 @@ void Combat::attack(Character &c, RangeType rangeType) { case DT_GOLEMSTOPPER: if (monsterData._monsterType == MONSTER_GOLEM) { attack2(100, rangeType); - setSpeedTable(); } break; case DT_HYPNOTIZE: @@ -1252,12 +1267,10 @@ void Combat::attack(Character &c, RangeType rangeType) { case DT_INSECT_SPRAY: if (monsterData._monsterType == MONSTER_INSECT) { attack2(25, rangeType); - setSpeedTable(); } break; case DT_MAGIC_ARROW: attack2(8, rangeType); - setSpeedTable(); break; default: break; @@ -1271,13 +1284,13 @@ void Combat::attack(Character &c, RangeType rangeType) { for (uint charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { Character &ch = party._activeParty[charIndex]; - if (_shooting[charIndex] && !_missedShot[charIndex]) { + if (_shootingRow[charIndex] && !_missedShot[charIndex]) { if (!hitMonster(ch, rangeType)) { ++_missedShot[charIndex]; } else { damage = _monsterDamage ? _monsterDamage : _weaponDamage; - _shooting[charIndex] = 0; - attack2(damage, rangeType); + _shootingRow[charIndex] = 0; + attack2(damage, RT_HIT); if (map._isOutdoors) { intf._outdoorList._attackImgs1[charIndex]._scale = 0; @@ -1374,8 +1387,9 @@ void Combat::attack(Character &c, RangeType rangeType) { } attack2(damage, rangeType); - setSpeedTable(); } + + setSpeedTable(); } void Combat::attack2(int damage, RangeType rangeType) { @@ -1415,7 +1429,7 @@ void Combat::attack2(int damage, RangeType rangeType) { _charsArray1[_monsterIndex] = 3; _monPow[_monsterIndex] = _damageType == DT_PHYSICAL && (rangeType == 3 || rangeType == 0); monster._frame = 11; - monster._fieldA = 5; + monster._postAttackDelay = 5; } int monsterResist = getMonsterResistence(rangeType); @@ -1723,7 +1737,7 @@ int Combat::getMonsterResistence(RangeType rangeType) { MonsterStruct &monsterData = *monster._monsterData; int resistence = 0, damage = 0; - if (rangeType != RT_SINGLE && rangeType != RT_3) { + if (rangeType != RT_SINGLE && rangeType != RT_HIT) { switch (_damageType) { case DT_PHYSICAL: resistence = monsterData._phsyicalResistence; @@ -1815,7 +1829,7 @@ void Combat::rangedAttack(PowType powNum) { if (_damageType == DT_POISON_VOLLEY) { _damageType = DT_POISON; _shootType = ST_1; - Common::fill(&_shooting[0], &_shooting[6], 1); + Common::fill(&_shootingRow[0], &_shootingRow[MAX_ACTIVE_PARTY], 1); } else if (powNum == POW_ARROW) { _shootType = ST_1; bool flag = false; @@ -1824,12 +1838,12 @@ void Combat::rangedAttack(PowType powNum) { for (uint idx = 0; idx < party._activeParty.size(); ++idx) { Character &c = party._activeParty[idx]; if (c.hasMissileWeapon()) { - _shooting[idx] = 1; + _shootingRow[idx] = 1; flag = true; } } } else { - _shooting[0] = 1; + _shootingRow[0] = 1; flag = true; } @@ -1840,7 +1854,7 @@ void Combat::rangedAttack(PowType powNum) { sound.playFX(49); } else { - _shooting[0] = 1; + _shootingRow[0] = 1; _shootType = ST_0; } @@ -1865,7 +1879,7 @@ void Combat::rangedAttack(PowType powNum) { } for (uint idx = 0; idx < party._activeParty.size(); ++idx) { - if (_shooting[idx]) { + if (_shootingRow[idx]) { if (map._isOutdoors) { intf._outdoorList._attackImgs1[idx]._scale = 0; intf._outdoorList._attackImgs2[idx]._scale = 4; @@ -1892,7 +1906,7 @@ void Combat::rangedAttack(PowType powNum) { ++_monsterIndex; for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { - Common::fill(&_missedShot[0], &_missedShot[8], false); + Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], false); _monster2Attack = attackMonsters[monIdx]; attack(*_oldCharacter, RT_GROUP); attackedFlag = true; @@ -1942,7 +1956,7 @@ void Combat::rangedAttack(PowType powNum) { ++_monsterIndex; for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { - Common::fill(&_missedShot[0], &_missedShot[8], false); + Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], false); _monster2Attack = attackMonsters[monIdx]; attack(*_oldCharacter, RT_GROUP); attackedFlag = true; @@ -1992,7 +2006,7 @@ void Combat::rangedAttack(PowType powNum) { ++_monsterIndex; for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { - Common::fill(&_missedShot[0], &_missedShot[8], false); + Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], false); _monster2Attack = attackMonsters[monIdx]; attack(*_oldCharacter, RT_GROUP); attackedFlag = true; @@ -2042,7 +2056,7 @@ void Combat::rangedAttack(PowType powNum) { ++_monsterIndex; for (uint monIdx = 0; monIdx < attackMonsters.size(); ++monIdx, ++_monsterIndex) { - Common::fill(&_missedShot[0], &_missedShot[8], false); + Common::fill(&_missedShot[0], &_missedShot[MAX_PARTY_COUNT], false); _monster2Attack = attackMonsters[monIdx]; attack(*_oldCharacter, RT_GROUP); attackedFlag = true; @@ -2057,8 +2071,9 @@ void Combat::rangedAttack(PowType powNum) { finished: endAttack(); + done: - Common::fill(&_shooting[0], &_shooting[MAX_PARTY_COUNT], 0); + clearShooting(); _monster2Attack = monster2Attack; _monsterIndex = monsterIndex; party.giveTreasure(); |