diff options
-rw-r--r-- | engines/xeen/character.cpp | 35 | ||||
-rw-r--r-- | engines/xeen/character.h | 4 | ||||
-rw-r--r-- | engines/xeen/combat.cpp | 3 | ||||
-rw-r--r-- | engines/xeen/combat.h | 6 | ||||
-rw-r--r-- | engines/xeen/dialogs_spells.cpp | 67 | ||||
-rw-r--r-- | engines/xeen/dialogs_spells.h | 11 | ||||
-rw-r--r-- | engines/xeen/interface.cpp | 54 | ||||
-rw-r--r-- | engines/xeen/interface.h | 3 | ||||
-rw-r--r-- | engines/xeen/resources.cpp | 2 | ||||
-rw-r--r-- | engines/xeen/resources.h | 2 | ||||
-rw-r--r-- | engines/xeen/scripts.cpp | 5 | ||||
-rw-r--r-- | engines/xeen/scripts.h | 1 | ||||
-rw-r--r-- | engines/xeen/spells.cpp | 32 | ||||
-rw-r--r-- | engines/xeen/spells.h | 2 |
14 files changed, 217 insertions, 10 deletions
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp index d95e061515..ea0f9f532e 100644 --- a/engines/xeen/character.cpp +++ b/engines/xeen/character.cpp @@ -876,6 +876,15 @@ bool Character::isDisabledOrDead() const { } /** + * Returns whether the given character has a dead condition + */ +bool Character::isDead() const { + Condition condition = worstCondition(); + + return condition >= DEAD && condition <= ERADICATED; +} + +/** * Get the character's age */ int Character::getAge(bool ignoreTemp) const { @@ -1810,6 +1819,32 @@ int Character::makeItem(int p1, int itemIndex, int p3) { return category; } +/** + * Add hit points to a character + */ +void Character::addHitPoints(int amount) { + Interface &intf = *Party::_vm->_interface; + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); + + if (!isDead()) { + int maxHp = getMaxHP(); + if (_currentHp <= maxHp) { + _currentHp = MIN(_currentHp + amount, maxHp); + intf.spellFX(this); + } + + if (_currentHp > 0) + _conditions[UNCONSCIOUS] = 0; + + intf.drawParty(true); + } + + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); +} + +/** + * Remove hit points fromo the character + */ void Character::subtractHitPoints(int amount) { SoundManager &sound = *Party::_vm->_sound; _currentHp -= amount; diff --git a/engines/xeen/character.h b/engines/xeen/character.h index 77ab882305..f1243f1568 100644 --- a/engines/xeen/character.h +++ b/engines/xeen/character.h @@ -278,6 +278,8 @@ public: bool isDisabledOrDead() const; + bool isDead() const; + int getAge(bool ignoreTemp = false) const; int getMaxHP() const; @@ -322,6 +324,8 @@ public: int makeItem(int p1, int itemIndex, int p3); + void addHitPoints(int amount); + void subtractHitPoints(int amount); bool hasSpecialItem() const; diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 74e098cdd4..7cc2ab6b22 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -109,7 +109,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc"), _pow1Voc("pow1.vo _whosTurn = -1; _itemFlag = false; _monstersAttacking = false; - _combatMode = 0; + _combatMode = COMBATMODE_0; _monsterIndex = 0; _partyRan = false; _monster2Attack = -1; @@ -1883,7 +1883,6 @@ void Combat::multiAttack(int powNum) { } for (uint idx = 0; idx < party._activeParty.size(); ++idx) { - Character &c = party._activeParty[idx]; if (_shooting[idx]) { if (map._isOutdoors) { intf._outdoorList._attackImgs1[idx]._scale = 0; diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h index cff9261b05..33309b243b 100644 --- a/engines/xeen/combat.h +++ b/engines/xeen/combat.h @@ -64,6 +64,10 @@ enum ShootType { ST_0 = 0, ST_1 = 1 }; +enum CombatMode { + COMBATMODE_0 = 0, COMBATMODE_1 = 1, COMBATMODE_2 = 2 +}; + class XeenEngine; class Character; class XeenItem; @@ -108,7 +112,7 @@ public: bool _rangeAttacking[MAX_NUM_MONSTERS]; int _gmonHit[36]; bool _monstersAttacking; - int _combatMode; + CombatMode _combatMode; int _monsterIndex; bool _partyRan; int _whosSpeed; diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 9a19ac2042..08828a0c8d 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -577,4 +577,71 @@ void CastSpell::loadButtons() { addPartyButtons(_vm); } +/*------------------------------------------------------------------------*/ + +int SpellOnWho::show(XeenEngine *vm, int spellId) { + SpellOnWho *dlg = new SpellOnWho(vm); + int result = dlg->execute(spellId); + delete dlg; + + return result; +} + +int SpellOnWho::execute(int spellId) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[16]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; + int result = 999; + + w.open(); + w.writeString(ON_WHO); + w.update(); + addPartyButtons(_vm); + + while (result == 999) { + do { + events.updateGameCounter(); + intf.draw3d(true); + + do { + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + return -1; + + checkEvents(_vm); + } while (!_buttonValue && events.timeElapsed() < 1); + } while (!_buttonValue); + + switch (_buttonValue) { + case Common::KEYCODE_ESCAPE: + result = -1; + spells.addSpellCost(*combat._oldCharacter, spellId); + break; + + case Common::KEYCODE_F1: + case Common::KEYCODE_F2: + case Common::KEYCODE_F3: + case Common::KEYCODE_F4: + case Common::KEYCODE_F5: + case Common::KEYCODE_F6: + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < (int)(combat._combatMode == 2 ? combat._combatParty.size() : + party._activeParty.size())) { + result = _buttonValue; + } + break; + } + } + + w.close(); + _vm->_mode = oldMode; + return result; +} + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 6a9e43f416..660f2ef1de 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -73,6 +73,17 @@ public: static int show(XeenEngine *vm, Character *&c); }; +class SpellOnWho : public ButtonContainer { +private: + XeenEngine *_vm; + + SpellOnWho(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + int execute(int spellId); +public: + static int show(XeenEngine *vm, int spellId); +}; + } // End of namespace Xeen #endif /* XEEN_DIALOGS_SPELLS_H */ diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp index cc027b8676..923eaeac0b 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -149,6 +149,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(), InterfaceMap(vm), _face1State = _face2State = 0; _upDoorText = false; _tillMove = 0; + Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); initDrawStructs(); } @@ -1891,7 +1892,7 @@ void Interface::doCombat() { bool reloadMap = false; _upDoorText = false; - combat._combatMode = 2; + combat._combatMode = COMBATMODE_2; _vm->_mode = MODE_COMBAT; _iconSprites.load("combat.icn"); @@ -2182,7 +2183,7 @@ void Interface::doCombat() { DIR_EAST : DIR_SOUTH; } - combat._combatMode = 1; + combat._combatMode = COMBATMODE_1; } /** @@ -2262,4 +2263,53 @@ void Interface::nextChar() { } } +void Interface::spellFX(Character *c) { + Combat &combat = *_vm->_combat; + EventsManager &events = *_vm->_events; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + + // Ensure there's no alraedy running effect for the given character + uint charIndex; + for (charIndex = 0; charIndex < party._activeParty.size(); ++charIndex) { + if (&party._activeParty[charIndex] == c) + break; + } + if (charIndex == party._activeParty.size() || _charFX[charIndex]) + return; + + if (screen._windows[12]._enabled) + screen._windows[12].close(); + + if (combat._combatMode == COMBATMODE_2) { + for (uint idx = 0; idx < combat._combatParty.size(); ++idx) { + if (combat._combatParty[idx]->_rosterId == c->_rosterId) { + charIndex = idx; + break; + } + } + } + + int tillMove = _tillMove; + _tillMove = 0; + sound.playFX(20); + + for (int frameNum = 0; frameNum < 4; ++frameNum) { + events.updateGameCounter(); + _spellFxSprites.draw(screen, frameNum, Common::Point( + CHAR_FACES_X[charIndex], 150)); + + if (!screen._windows[11]._enabled) + draw3d(false); + + screen._windows[0].update(); + events.wait(screen._windows[11]._enabled ? 2 : 1); + } + + drawParty(true); + _tillMove = tillMove; +} + + } // End of namespace Xeen diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h index f5e5cc34ee..24edf9d23d 100644 --- a/engines/xeen/interface.h +++ b/engines/xeen/interface.h @@ -119,6 +119,7 @@ public: bool _upDoorText; Common::String _screenText; byte _tillMove; + int _charFX[6]; public: Interface(XeenEngine *vm); @@ -145,6 +146,8 @@ public: void assembleBorder(); void doCombat(); + + void spellFX(Character *c); }; } // End of namespace Xeen diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 5c76d29173..5893403ebd 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -1528,4 +1528,6 @@ const char *const GIVE_TREASURE_FORMATTING = const char *const X_FOUND_Y = "\v060\t000\x03c%s found: %s"; +const char *const ON_WHO = "\x3""c\v009On Who?"; + } // End of namespace Xeen diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index c98db7f0f9..b908d91cf9 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -539,6 +539,8 @@ extern const char *const GIVE_TREASURE_FORMATTING; extern const char *const X_FOUND_Y; +extern const char *const ON_WHO; + } // End of namespace Xeen #endif /* XEEN_RESOURCES_H */ diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 4af7af1d6a..ec00327205 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -88,7 +88,6 @@ bool MirrorEntry::synchronize(Common::SeekableReadStream &s) { /*------------------------------------------------------------------------*/ Scripts::Scripts(XeenEngine *vm) : _vm(vm) { - Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); _whoWill = 0; _itemType = 0; _treasureItems = 0; @@ -120,7 +119,7 @@ int Scripts::checkEvents() { _var50 = false; _whoWill = 0; Mode oldMode = _vm->_mode; - Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0); + Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0); //int items = _treasureItems; if (party._treasure._gold & party._treasure._gems) { @@ -202,7 +201,7 @@ int Scripts::checkEvents() { } _v2 = 1; - Common::fill(&_charFX[0], &_charFX[6], 0); + Common::fill(&intf._charFX[0], &intf._charFX[6], 0); return _scriptResult; } diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h index 3a835d88b5..29de5b8b37 100644 --- a/engines/xeen/scripts.h +++ b/engines/xeen/scripts.h @@ -139,7 +139,6 @@ struct MirrorEntry { class Scripts { private: XeenEngine *_vm; - int _charFX[6]; int _treasureItems; int _lineNum; int _charIndex; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index 53c43b5233..d446b3ce6e 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -21,6 +21,7 @@ */ #include "xeen/spells.h" +#include "xeen/dialogs_spells.h" #include "xeen/files.h" #include "xeen/resources.h" #include "xeen/xeen.h" @@ -95,6 +96,16 @@ void Spells::executeSpell(int spellId) { (this->*SPELL_LIST[spellId])(); } +/** + * Spell being cast failed + */ +void Spells::spellFailed() { + ErrorScroll::show(_vm, SPELL_FAILED, WT_NONFREEZED_WAIT); +} + +/** + * Cast a spell associated with an item + */ void Spells::castItemSpell(int spellId) { if (_vm->_mode == MODE_COMBAT) { if (spellId == 15 || spellId == 20 || spellId == 27 || spellId == 41 @@ -233,7 +244,26 @@ void Spells::magicArrow() { combat.multiAttack(11); } -void Spells::firstAid() { error("TODO: spell"); } +void Spells::firstAid() { + Combat &combat = *_vm->_combat; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_FirstAid); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + if (c.isDead()) { + spellFailed(); + } else { + sound.playFX(30); + c.addHitPoints(6); + } +} + void Spells::flyingFist() { error("TODO: spell"); } void Spells::energyBlast() { error("TODO: spell"); } void Spells::sleep() { error("TODO: spell"); } diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index af52511efa..2f79670df0 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -69,6 +69,8 @@ private: void executeSpell(int spellId); + void spellFailed(); + // Spell list void light(); void awaken(); |