aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen/combat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/xeen/combat.cpp')
-rw-r--r--engines/xeen/combat.cpp97
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();