From 07f504fe160d051c458e1f0035d4784ac74e2530 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 28 Feb 2015 22:53:17 -0500 Subject: [PATCH] XEEN: Fix ordering of spell list and methods --- engines/xeen/combat.cpp | 6 +- engines/xeen/dialogs_spells.cpp | 31 +- engines/xeen/dialogs_spells.h | 12 + engines/xeen/interface.cpp | 4 +- engines/xeen/resources.cpp | 6 +- engines/xeen/resources.h | 2 + engines/xeen/spells.cpp | 618 ++++++++++++++++++++------------ engines/xeen/spells.h | 156 ++++---- 8 files changed, 520 insertions(+), 315 deletions(-) diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp index 7cc2ab6b22b..1d03a5128de 100644 --- a/engines/xeen/combat.cpp +++ b/engines/xeen/combat.cpp @@ -64,10 +64,6 @@ static const int MONSTER_GRID_BITINDEX2[48] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const int MONSTER_GRID_BITMASK[12] = { - 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 -}; - static const int ATTACK_TYPE_FX[23] = { 49, 18, 13, 14, 15, 17, 16, 0, 6, 1, 2, 3, 4, 5, 4, 9, 27, 29, 44, 51, 53, 61, 71 @@ -1598,7 +1594,7 @@ void Combat::quickFight() { break; case QUICK_SPELL: if (c->_currentSpell != -1) { - spells.castSpell(c, SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); + spells.castSpell(c, (MagicSpell)SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]); } break; case QUICK_BLOCK: diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp index 3aa0cfa4ad1..dfc72aa4b1b 100644 --- a/engines/xeen/dialogs_spells.cpp +++ b/engines/xeen/dialogs_spells.cpp @@ -658,7 +658,6 @@ int SelectElement::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[15]; @@ -727,4 +726,34 @@ void SelectElement::loadButtons() { addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites); } +/*------------------------------------------------------------------------*/ + +void NotWhileEngaged::show(XeenEngine *vm, int spellId) { + NotWhileEngaged *dlg = new NotWhileEngaged(vm); + dlg->execute(spellId); + delete dlg; +} + +void NotWhileEngaged::execute(int spellId) { + EventsManager &events = *_vm->_events; + Screen &screen = *_vm->_screen; + Spells &spells = *_vm->_spells; + Window &w = screen._windows[6]; + Mode oldMode = _vm->_mode; + _vm->_mode = MODE_3; + + w.open(); + w.writeString(Common::String::format(CANT_CAST_WHILE_ENGAGED, + spells._spellNames[spellId].c_str())); + w.update(); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + events.clearEvents(); + + w.close(); + _vm->_mode = oldMode; +} + + } // End of namespace Xeen diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h index 6bbdb3cddce..b23f62b22f1 100644 --- a/engines/xeen/dialogs_spells.h +++ b/engines/xeen/dialogs_spells.h @@ -98,6 +98,18 @@ public: static int show(XeenEngine *vm, int spellId); }; +class NotWhileEngaged : public ButtonContainer { +private: + XeenEngine *_vm; + + NotWhileEngaged(XeenEngine *vm) : ButtonContainer(), _vm(vm) {} + + void execute(int spellId); +public: + static void 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 923eaeac0b0..d1a1478d951 100644 --- a/engines/xeen/interface.cpp +++ b/engines/xeen/interface.cpp @@ -541,7 +541,7 @@ void Interface::perform() { if (spellId == -1 || c == nullptr) break; - result = spells.castSpell(c, spellId); + result = spells.castSpell(c, (MagicSpell)spellId); } while (result != -1); if (result == 1) { @@ -2008,7 +2008,7 @@ void Interface::doCombat() { int spellId = CastSpell::show(_vm); if (spellId != -1) { Character *c = combat._combatParty[combat._whosTurn]; - spells.castSpell(c, spellId); + spells.castSpell(c, (MagicSpell)spellId); nextChar(); } else { highlightChar(combat._combatParty[combat._whosTurn]->_rosterId); diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp index 3a751b7ad92..228c5f64499 100644 --- a/engines/xeen/resources.cpp +++ b/engines/xeen/resources.cpp @@ -438,6 +438,10 @@ const int8 SCREEN_POSITIONING_Y[4][48] = { } }; +const int MONSTER_GRID_BITMASK[12] = { + 0xC, 8, 4, 0, 0xF, 0xF000, 0xF00, 0xF0, 0xF00, 0xF0, 0x0F, 0xF000 +}; + const int INDOOR_OBJECT_X[2][12] = { { 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 }, { -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 } @@ -827,7 +831,7 @@ const int MISC_SPELL_INDEX[74] = { MS_Levitate, MS_WizardEye, MS_Bless, MS_IdentifyMonster, MS_LightningBolt, MS_HolyBonus, MS_PowerCure, MS_NaturesCure, MS_LloydsBeacon, MS_PowerShield, MS_Heroism, MS_Hynotize, - MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_FireBall, + MS_WalkOnWater, MS_FrostBite, MS_DetectMonster, MS_Fireball, MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, MS_DragonSleep, MS_CureDisease, MS_Teleport, MS_FingerOfDeath, MS_CureParalysis, MS_GolemStopper, MS_PoisonVolley, MS_DeadlySwarm, diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h index fed249108df..84a4648e841 100644 --- a/engines/xeen/resources.h +++ b/engines/xeen/resources.h @@ -127,6 +127,8 @@ extern const int8 SCREEN_POSITIONING_X[4][48]; extern const int8 SCREEN_POSITIONING_Y[4][48]; +extern const int MONSTER_GRID_BITMASK[12]; + extern const int INDOOR_OBJECT_X[2][12]; extern const int MAP_OBJECT_Y[2][12]; diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp index b2b477e54d0..f5f6428b9f6 100644 --- a/engines/xeen/spells.cpp +++ b/engines/xeen/spells.cpp @@ -54,43 +54,34 @@ int Spells::calcSpellPoints(int spellId, int expenseFactor) const { typedef void(Spells::*SpellMethodPtr)(); -void Spells::executeSpell(int spellId) { - static const SpellMethodPtr SPELL_LIST[73] = { - &Spells::light, &Spells::awaken, &Spells::magicArrow, &Spells::firstAid, - &Spells::flyingFist, &Spells::energyBlast, &Spells::sleep, - &Spells::revitalize, &Spells::cureWounds, &Spells::sparks, - - &Spells::shrapMetal, &Spells::insectSpray, &Spells::toxicCloud, - &Spells::protectionFromElements, &Spells::pain, &Spells::jump, - &Spells::beastMaster, &Spells::clairvoyance, &Spells::turnUndead, - &Spells::levitate, - - &Spells::wizardEye, &Spells::bless, &Spells::identifyMonster, - &Spells::lightningBolt, &Spells::holyBonus, &Spells::powerCure, - &Spells::naturesCure, &Spells::lloydsBeacon, &Spells::powerShield, - &Spells::heroism, - - &Spells::hypnotize, &Spells::walkOnWater, &Spells::frostByte, - &Spells::detectMonster, &Spells::fireball, &Spells::coldRay, - &Spells::curePoison, &Spells::acidSpray, &Spells::timeDistortion, - &Spells::dragonSleep, - - &Spells::suppressPoison, &Spells::teleport, &Spells::fingerOfDeath, - &Spells::cureParalysis, &Spells::golemStopper, &Spells::poisonVolley, - &Spells::deadlySwarm, &Spells::superShelter, &Spells::dayOfProtection, - &Spells::dayOfSorcery, - - &Spells::createFood, &Spells::fieryFlail, &Spells::rechargeItem, - &Spells::fantasticFreeze, &Spells::townPortal, &Spells::stoneToFlesh, - &Spells::raiseDead, &Spells::etherialize, &Spells::dancingSword, - &Spells::moonRay, - - &Spells::massDistortion, &Spells::prismaticLight, &Spells::enchantItem, - &Spells::incinerate, &Spells::holyWord, &Spells::resurrection, - &Spells::elementalStorm, &Spells::megaVolts, &Spells::inferno, - &Spells::sunRay, - - &Spells::implosion, &Spells::starBurst, &Spells::divineIntervention +void Spells::executeSpell(MagicSpell spellId) { + static const SpellMethodPtr SPELL_LIST[76] = { + &Spells::acidSpray, &Spells::awaken, &Spells::beastMaster, + &Spells::bless, &Spells::clairvoyance, &Spells::coldRay, + &Spells::createFood, &Spells::cureDisease, &Spells::cureParalysis, + &Spells::curePoison, &Spells::cureWounds, &Spells::dancingSword, + &Spells::dayOfProtection, &Spells::dayOfSorcery, &Spells::deadlySwarm, + &Spells::detectMonster, &Spells::divineIntervention, &Spells::dragonSleep, + &Spells::elementalStorm, &Spells::enchantItem, &Spells::energyBlast, + &Spells::etherialize, &Spells::fantasticFreeze, &Spells::fieryFlail, + &Spells::fingerOfDeath, &Spells::fireball, &Spells::firstAid, + &Spells::flyingFist, &Spells::frostbite, &Spells::golemStopper, + &Spells::heroism, &Spells::holyBonus, &Spells::holyWord, + &Spells::hypnotize, &Spells::identifyMonster, &Spells::implosion, + &Spells::incinerate, &Spells::inferno, &Spells::insectSpray, + &Spells::itemToGold, &Spells::jump, &Spells::levitate, + &Spells::light, &Spells::lightningBolt, &Spells::lloydsBeacon, + &Spells::magicArrow, &Spells::massDistortion, &Spells::megaVolts, + &Spells::moonRay, &Spells::naturesCure, &Spells::pain, + &Spells::poisonVolley, &Spells::powerCure, &Spells::powerShield, + &Spells::prismaticLight, &Spells::protectionFromElements, &Spells::raiseDead, + &Spells::rechargeItem, &Spells::resurrection, &Spells::revitalize, + &Spells::shrapMetal, &Spells::sleep, &Spells::sparks, + &Spells::starBurst, &Spells::stoneToFlesh, &Spells::sunRay, + &Spells::superShelter, &Spells::suppressDisease, &Spells::suppressPoison, + &Spells::teleport, &Spells::timeDistortion, &Spells::townPortal, + &Spells::toxicCloud, &Spells::turnUndead, &Spells::walkOnWater, + &Spells::wizardEye }; (this->*SPELL_LIST[spellId])(); @@ -106,23 +97,82 @@ void Spells::spellFailed() { /** * 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 - || spellId == 47 || spellId == 54 || spellId == 57) { - ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId].c_str())); +void Spells::castItemSpell(int itemSpellId) { + switch (itemSpellId) { + case 15: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Jump); return; } + break; + case 20: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_WizardEye); + return; + } + break; + case 27: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_LloydsBeacon); + return; + } + break; + case 32: + frostbite2(); + break; + case 41: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Teleport); + return; + } + break; + case 47: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_SuperShelter); + return; + } + break; + case 54: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_TownPortal); + return; + } + break; + case 57: + if (_vm->_mode == MODE_COMBAT) { + NotWhileEngaged::show(_vm, MS_Etheralize); + return; + } + break; + default: + break; } - executeSpell(spellId); + static const MagicSpell spells[73] = { + MS_Light, MS_Awaken, MS_MagicArrow, MS_FirstAid, MS_FlyingFist, + MS_EnergyBlast, MS_Sleep, MS_Revitalize, MS_CureWounds, MS_Sparks, + MS_Shrapmetal, MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain, + MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead, MS_Levitate, + MS_WizardEye, MS_Bless, MS_IdentifyMonster, MS_LightningBolt, MS_HolyBonus, + MS_PowerCure, MS_NaturesCure, MS_LloydsBeacon, MS_PowerShield, MS_Heroism, + MS_Hynotize, MS_WalkOnWater, NO_SPELL, MS_DetectMonster, MS_Fireball, + MS_ColdRay, MS_CurePoison, MS_AcidSpray, MS_TimeDistortion, MS_DragonSleep, + MS_CureDisease, MS_Teleport, MS_FingerOfDeath, MS_CureParalysis, MS_GolemStopper, + MS_PoisonVolley, MS_DeadlySwarm, MS_SuperShelter, MS_DayOfProtection, MS_DayOfProtection, + MS_CreateFood, MS_FieryFlail, MS_RechargeItem, MS_FantasticFreeze, MS_TownPortal, + MS_StoneToFlesh, MS_RaiseDead, MS_Etheralize, MS_DancingSword, MS_MoonRay, + MS_MassDistortion, MS_PrismaticLight, MS_EnchantItem, MS_Incinerate, MS_HolyWord, + MS_Resurrection, MS_ElementalStorm, MS_MegaVolts, MS_Inferno, MS_SunRay, + MS_Implosion, MS_StarBurst, MS_DivineIntervention + }; + + executeSpell(spells[itemSpellId]); } /** * Cast a given spell */ -int Spells::castSpell(Character *c, int spellId) { +int Spells::castSpell(Character *c, MagicSpell spellId) { Combat &combat = *_vm->_combat; Interface &intf = *_vm->_interface; int oldTillMove = intf._tillMove; @@ -137,21 +187,20 @@ int Spells::castSpell(Character *c, int spellId) { } else { // Some spells have special handling switch (spellId) { - case 19: // Enchant item - case 21: // Etherialize - case 40: // Jump - case 44: // Lloyd's Beacon - case 66: // Super Shelter - case 69: // Teleport - case 71: // Town Portal - case 75: // Wizard Eye + case MS_EnchantItem: + case MS_Etheralize: + case MS_Jump: + case MS_LloydsBeacon: + case MS_SuperShelter: + case MS_Teleport: + case MS_TownPortal: + case MS_WizardEye: if (_vm->_mode != MODE_COMBAT) { executeSpell(spellId); } else { // Return the spell costs and flag that another spell can be selected addSpellCost(*c, spellId); - ErrorDialog::show(_vm, Common::String::format(CANT_CAST_WHILE_ENGAGED, - _spellNames[spellId].c_str())); + NotWhileEngaged::show(_vm, spellId); result = -1; } break; @@ -209,18 +258,9 @@ void Spells::addSpellCost(Character &c, int spellId) { party._gems += gemCost; } -void Spells::light() { - Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; - SoundManager &sound = *_vm->_sound; +void Spells::acidSpray() { error("TODO: spell"); } - ++party._lightCount; - if (intf._intrIndex1) - party._stepped = true; - sound.playFX(39); -} - -void Spells::awaken() { +void Spells::awaken() { Interface &intf = *_vm->_interface; Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; @@ -236,14 +276,82 @@ void Spells::awaken() { sound.playFX(30); } -void Spells::magicArrow() { +void Spells::beastMaster() { error("TODO: spell"); } + +void Spells::bless() { error("TODO: spell"); } + +void Spells::clairvoyance() { error("TODO: spell"); } + +void Spells::coldRay() { error("TODO: spell"); } + +void Spells::createFood() { error("TODO: spell"); } + +void Spells::cureDisease() { error("TODO: spell"); } + +void Spells::cureParalysis() { error("TODO: spell"); } + +void Spells::curePoison() { error("TODO: spell"); } + +void Spells::cureWounds() { Combat &combat = *_vm->_combat; - combat._monsterDamage = 0; - combat._damageType = DT_MAGIC_ARROW; - combat._rangeType = RT_SINGLE; - combat.multiAttack(11); + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + 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(15); + } } +void Spells::dancingSword() { error("TODO: spell"); } + +void Spells::dayOfProtection() { error("TODO: spell"); } + +void Spells::dayOfSorcery() { error("TODO: spell"); } + +void Spells::deadlySwarm() { error("TODO: spell"); } + +void Spells::detectMonster() { error("TODO: spell"); } + +void Spells::divineIntervention() { error("TODO: spell"); } + +void Spells::dragonSleep() { error("TODO: spell"); } + +void Spells::elementalStorm() { error("TODO: spell"); } + +void Spells::enchantItem() { error("TODO: spell"); } + +void Spells::energyBlast() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_ENERGY; + combat._rangeType = RT_SINGLE; + sound.playFX(16); + combat.multiAttack(13); +} + +void Spells::etherialize() { error("TODO: spell"); } // Not while engaged + +void Spells::fantasticFreeze() { error("TODO: spell"); } + +void Spells::fieryFlail() { error("TODO: spell"); } + +void Spells::fingerOfDeath() { error("TODO: spell"); } + +void Spells::fireball() { error("TODO: spell"); } + void Spells::firstAid() { Combat &combat = *_vm->_combat; Party &party = *_vm->_party; @@ -258,7 +366,8 @@ void Spells::firstAid() { if (c.isDead()) { spellFailed(); - } else { + } + else { sound.playFX(30); c.addHitPoints(6); } @@ -275,117 +384,119 @@ void Spells::flyingFist() { combat.multiAttack(14); } -void Spells::energyBlast() { - Combat &combat = *_vm->_combat; +void Spells::frostbite() { error("TODO: spell"); } + +void Spells::golemStopper() { error("TODO: spell"); } + +void Spells::heroism() { error("TODO: spell"); } + +void Spells::holyBonus() { error("TODO: spell"); } + +void Spells::holyWord() { error("TODO: spell"); } + +void Spells::hypnotize() { error("TODO: spell"); } + +void Spells::identifyMonster() { error("TODO: spell"); } + +void Spells::implosion() { error("TODO: spell"); } + +void Spells::incinerate() { error("TODO: spell"); } + +void Spells::inferno() { error("TODO: spell"); } + +void Spells::insectSpray() { error("TODO: spell"); } + +void Spells::itemToGold() { error("TODO: spell"); } + +void Spells::jump() { + Map &map = *_vm->_map; + Party &party = *_vm->_party; SoundManager &sound = *_vm->_sound; - combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; - combat._damageType = DT_ENERGY; - combat._rangeType = RT_SINGLE; - sound.playFX(16); - combat.multiAttack(13); + if (map._isOutdoors) { + map.getCell(7); + if (map._currentWall != 1) { + map.getCell(14); + if (map._currentSurfaceId != 0 && map._currentWall != 1) { + party._mazePosition += Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][14], + SCREEN_POSITIONING_Y[party._mazeDirection][14] + ); + sound.playFX(51); + party._stepped = true; + return; + } + } + } else { + Common::Point pt = party._mazePosition + Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][7], + SCREEN_POSITIONING_Y[party._mazeDirection][7]); + if (!map.mazeLookup(party._mazePosition, MONSTER_GRID_BITMASK[party._mazeDirection]) && + !map.mazeLookup(pt, MONSTER_GRID_BITMASK[party._mazeDirection])) { + party._mazePosition += Common::Point( + SCREEN_POSITIONING_X[party._mazeDirection][14], + SCREEN_POSITIONING_Y[party._mazeDirection][14] + ); + sound.playFX(51); + party._stepped = true; + return; + } + } + + spellFailed(); } -void Spells::sleep() { +void Spells::levitate() { error("TODO: spell"); } + +void Spells::light() { + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + ++party._lightCount; + if (intf._intrIndex1) + party._stepped = true; + sound.playFX(39); +} + +void Spells::lightningBolt() { error("TODO: spell"); } + +void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged + +void Spells::magicArrow() { + Combat &combat = *_vm->_combat; + combat._monsterDamage = 0; + combat._damageType = DT_MAGIC_ARROW; + combat._rangeType = RT_SINGLE; + combat.multiAttack(11); +} + +void Spells::massDistortion() { error("TODO: spell"); } + +void Spells::megaVolts() { error("TODO: spell"); } + +void Spells::moonRay() { error("TODO: spell"); } + +void Spells::naturesCure() { error("TODO: spell"); } + +void Spells::pain() { Combat &combat = *_vm->_combat; SoundManager &sound = *_vm->_sound; combat._monsterDamage = 0; - combat._damageType = DT_SLEEP; + combat._damageType = DT_PHYSICAL; combat._rangeType = RT_GROUP; sound.playFX(18); - combat.multiAttack(7); + combat.multiAttack(14); } -void Spells::revitalize() { - Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; - Party &party = *_vm->_party; - SoundManager &sound = *_vm->_sound; +void Spells::poisonVolley() { error("TODO: spell"); } - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - if (charIndex == -1) - return; +void Spells::powerCure() { error("TODO: spell"); } - Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : - party._activeParty[charIndex]; +void Spells::powerShield() { error("TODO: spell"); } - sound.playFX(30); - c.addHitPoints(0); - c._conditions[WEAK] = 0; - intf.drawParty(true); -} - -void Spells::cureWounds() { - Combat &combat = *_vm->_combat; - Party &party = *_vm->_party; - SoundManager &sound = *_vm->_sound; - - int charIndex = SpellOnWho::show(_vm, MS_Revitalize); - 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(15); - } -} - -void Spells::sparks() { - Combat &combat = *_vm->_combat; - SoundManager &sound = *_vm->_sound; - - combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; - combat._damageType = DT_ELECTRICAL; - combat._rangeType = RT_GROUP; - sound.playFX(14); - combat.multiAttack(5); -} - -void Spells::shrapMetal() { error("TODO: spell"); } -void Spells::insectSpray() { error("TODO: spell"); } - -void Spells::toxicCloud() { - Combat &combat = *_vm->_combat; - SoundManager &sound = *_vm->_sound; - - combat._monsterDamage = 10; - combat._damageType = DT_POISON; - combat._rangeType = RT_GROUP; - sound.playFX(17); - combat.multiAttack(10); -} - -void Spells::suppressPoison() { - Combat &combat = *_vm->_combat; - Interface &intf = *_vm->_interface; - 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._conditions[POISONED]) { - if (c._conditions[POISONED] >= 4) { - c._conditions[POISONED] -= 2; - } else { - c._conditions[POISONED] = 1; - } - } - - sound.playFX(20); - c.addHitPoints(0); - intf.drawParty(1); -} +void Spells::prismaticLight() { error("TODO: spell"); } void Spells::protectionFromElements() { Combat &combat = *_vm->_combat; @@ -419,79 +530,132 @@ void Spells::protectionFromElements() { } } -void Spells::pain() { +void Spells::raiseDead() { error("TODO: spell"); } + +void Spells::rechargeItem() { error("TODO: spell"); } + +void Spells::resurrection() { error("TODO: spell"); } + +void Spells::revitalize() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + SoundManager &sound = *_vm->_sound; + + int charIndex = SpellOnWho::show(_vm, MS_Revitalize); + if (charIndex == -1) + return; + + Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] : + party._activeParty[charIndex]; + + sound.playFX(30); + c.addHitPoints(0); + c._conditions[WEAK] = 0; + intf.drawParty(true); +} + +void Spells::shrapMetal() { error("TODO: spell"); } + +void Spells::sleep() { Combat &combat = *_vm->_combat; SoundManager &sound = *_vm->_sound; combat._monsterDamage = 0; - combat._damageType = DT_PHYSICAL; + combat._damageType = DT_SLEEP; combat._rangeType = RT_GROUP; sound.playFX(18); - combat.multiAttack(14); + combat.multiAttack(7); } -void Spells::jump() { error("TODO: spell"); } // Not while engaged -void Spells::beastMaster() { error("TODO: spell"); } -void Spells::clairvoyance() { error("TODO: spell"); } -void Spells::turnUndead() { error("TODO: spell"); } -void Spells::levitate() { error("TODO: spell"); } +void Spells::sparks() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; -void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged -void Spells::bless() { error("TODO: spell"); } -void Spells::identifyMonster() { error("TODO: spell"); } -void Spells::lightningBolt() { error("TODO: spell"); } -void Spells::holyBonus() { error("TODO: spell"); } -void Spells::powerCure() { error("TODO: spell"); } -void Spells::naturesCure() { error("TODO: spell"); } -void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged -void Spells::powerShield() { error("TODO: spell"); } -void Spells::heroism() { error("TODO: spell"); } + combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2; + combat._damageType = DT_ELECTRICAL; + combat._rangeType = RT_GROUP; + sound.playFX(14); + combat.multiAttack(5); +} -void Spells::hypnotize() { error("TODO: spell"); } -void Spells::walkOnWater() { error("TODO: spell"); } -void Spells::frostByte() { error("TODO: spell"); } -void Spells::detectMonster() { error("TODO: spell"); } -void Spells::fireball() { error("TODO: spell"); } -void Spells::coldRay() { error("TODO: spell"); } -void Spells::curePoison() { error("TODO: spell"); } -void Spells::acidSpray() { error("TODO: spell"); } -void Spells::timeDistortion() { error("TODO: spell"); } -void Spells::dragonSleep() { error("TODO: spell"); } +void Spells::starBurst() { error("TODO: spell"); } -void Spells::teleport() { error("TODO: spell"); } // Not while engaged -void Spells:: fingerOfDeath() { error("TODO: spell"); } -void Spells::cureParalysis() { error("TODO: spell"); } -void Spells::golemStopper() { error("TODO: spell"); } -void Spells::poisonVolley() { error("TODO: spell"); } -void Spells::deadlySwarm() { error("TODO: spell"); } -void Spells::superShelter() { error("TODO: spell"); } // Not while engaged -void Spells::dayOfProtection() { error("TODO: spell"); } -void Spells::dayOfSorcery() { error("TODO: spell"); } - -void Spells::createFood() { error("TODO: spell"); } -void Spells::fieryFlail() { error("TODO: spell"); } -void Spells::rechargeItem() { error("TODO: spell"); } -void Spells::fantasticFreeze() { error("TODO: spell"); } -void Spells::townPortal() { error("TODO: spell"); } // Not while engaged void Spells::stoneToFlesh() { error("TODO: spell"); } -void Spells::raiseDead() { error("TODO: spell"); } -void Spells::etherialize() { error("TODO: spell"); } // Not while engaged -void Spells::dancingSword() { error("TODO: spell"); } -void Spells::moonRay() { error("TODO: spell"); } -void Spells::massDistortion() { error("TODO: spell"); } -void Spells::prismaticLight() { error("TODO: spell"); } -void Spells::enchantItem() { error("TODO: spell"); } -void Spells::incinerate() { error("TODO: spell"); } -void Spells::holyWord() { error("TODO: spell"); } -void Spells::resurrection() { error("TODO: spell"); } -void Spells::elementalStorm() { error("TODO: spell"); } -void Spells::megaVolts() { error("TODO: spell"); } -void Spells::inferno() { error("TODO: spell"); } void Spells::sunRay() { error("TODO: spell"); } -void Spells::implosion() { error("TODO: spell"); } -void Spells::starBurst() { error("TODO: spell"); } -void Spells::divineIntervention() { error("TODO: spell"); } +void Spells::superShelter() { error("TODO: spell"); } + +void Spells::suppressDisease() { error("TODO: spell"); } + +void Spells::suppressPoison() { + Combat &combat = *_vm->_combat; + Interface &intf = *_vm->_interface; + 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._conditions[POISONED]) { + if (c._conditions[POISONED] >= 4) { + c._conditions[POISONED] -= 2; + } else { + c._conditions[POISONED] = 1; + } + } + + sound.playFX(20); + c.addHitPoints(0); + intf.drawParty(1); +} + +void Spells::teleport() { error("TODO: spell"); } // Not while engaged + +void Spells::timeDistortion() { error("TODO: spell"); } + +void Spells::townPortal() { error("TODO: spell"); } // Not while engaged + +void Spells::toxicCloud() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 10; + combat._damageType = DT_POISON; + combat._rangeType = RT_GROUP; + sound.playFX(17); + combat.multiAttack(10); +} + +void Spells::turnUndead() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 0; + combat._damageType = DT_UNDEAD; + combat._rangeType = RT_GROUP; + sound.playFX(18); + combat.multiAttack(13); +} + +void Spells::walkOnWater() { error("TODO: spell"); } + +void Spells::wizardEye() { error("TODO: spell"); } // Not while engaged + +void Spells::frostbite2() { + Combat &combat = *_vm->_combat; + SoundManager &sound = *_vm->_sound; + + combat._monsterDamage = 35; + combat._damageType = DT_COLD; + combat._rangeType = RT_SINGLE; + sound.playFX(15); + combat.multiAttack(9); +} } // End of namespace Xeen diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h index f71f1fd458a..1af4fb222f0 100644 --- a/engines/xeen/spells.h +++ b/engines/xeen/spells.h @@ -42,7 +42,7 @@ enum MagicSpell { MS_DivineIntervention = 16, MS_DragonSleep = 17, MS_ElementalStorm = 18, MS_EnchantItem = 19, MS_EnergyBlast = 20, MS_Etheralize = 21, MS_FantasticFreeze = 22, MS_FieryFlail = 23, MS_FingerOfDeath = 24, - MS_FireBall = 25, MS_FirstAid = 26, MS_FlyingFist = 27, + MS_Fireball = 25, MS_FirstAid = 26, MS_FlyingFist = 27, MS_FrostBite = 28, MS_GolemStopper = 29, MS_Heroism = 30, MS_HolyBonus = 31, MS_HolyWord = 32, MS_Hynotize = 33, MS_IdentifyMonster = 34, MS_Implosion = 35, MS_Incinerate = 36, @@ -67,91 +67,89 @@ private: void load(); - void executeSpell(int spellId); + void executeSpell(MagicSpell spellId); void spellFailed(); // Spell list - void light(); - void awaken(); - void magicArrow(); - void firstAid(); - void flyingFist(); - void energyBlast(); - void sleep(); - void revitalize(); - void cureWounds(); - void sparks(); - - void shrapMetal(); - void insectSpray(); - void toxicCloud(); - void protectionFromElements(); - void pain(); - void jump(); // Not while engaged - void beastMaster(); - void clairvoyance(); - void turnUndead(); - void levitate(); - - void wizardEye(); // Not while engaged - void bless(); - void identifyMonster(); - void lightningBolt(); - void holyBonus(); - void powerCure(); - void naturesCure(); - void lloydsBeacon(); // Not while engaged - void powerShield(); - void heroism(); - - void hypnotize(); - void walkOnWater(); - void frostByte(); - void detectMonster(); - void fireball(); - void coldRay(); - void curePoison(); void acidSpray(); - void timeDistortion(); - void dragonSleep(); - - void suppressPoison(); - void teleport(); // Not while engaged - void fingerOfDeath(); + void awaken(); + void beastMaster(); + void bless(); + void clairvoyance(); + void coldRay(); + void createFood(); + void cureDisease(); void cureParalysis(); - void golemStopper(); - void poisonVolley(); - void deadlySwarm(); - void superShelter(); // Not while engaged + void curePoison(); + void cureWounds(); + void dancingSword(); void dayOfProtection(); void dayOfSorcery(); - - void createFood(); - void fieryFlail(); - void rechargeItem(); - void fantasticFreeze(); - void townPortal(); // Not while engaged - void stoneToFlesh(); - void raiseDead(); - void etherialize(); // Not while engaged - void dancingSword(); - void moonRay(); - - void massDistortion(); - void prismaticLight(); - void enchantItem(); - void incinerate(); - void holyWord(); - void resurrection(); - void elementalStorm(); - void megaVolts(); - void inferno(); - void sunRay(); - - void implosion(); - void starBurst(); + void deadlySwarm(); + void detectMonster(); void divineIntervention(); + void dragonSleep(); + void elementalStorm(); + void enchantItem(); + void energyBlast(); + void etherialize(); + void fantasticFreeze(); + void fieryFlail(); + void fingerOfDeath(); + void fireball(); + void firstAid(); + void flyingFist(); + void frostbite(); + void golemStopper(); + void heroism(); + void holyBonus(); + void holyWord(); + void hypnotize(); + void identifyMonster(); + void implosion(); + void incinerate(); + void inferno(); + void insectSpray(); + void itemToGold(); + void jump(); + void levitate(); + void light(); + void lightningBolt(); + void lloydsBeacon(); + void magicArrow(); + void massDistortion(); + void megaVolts(); + void moonRay(); + void naturesCure(); + void pain(); + void poisonVolley(); + void powerCure(); + void powerShield(); + void prismaticLight(); + void protectionFromElements(); + void raiseDead(); + void rechargeItem(); + void resurrection(); + void revitalize(); + void shrapMetal(); + void sleep(); + void sparks(); + void starBurst(); + void stoneToFlesh(); + void sunRay(); + void superShelter(); + void suppressDisease(); + void suppressPoison(); + void teleport(); + void timeDistortion(); + void townPortal(); + void toxicCloud(); + void turnUndead(); + void walkOnWater(); + void wizardEye(); + + void frostbite2(); public: Common::StringArray _spellNames; int _lastCaster; @@ -162,9 +160,9 @@ public: int calcSpellPoints(int spellId, int expenseFactor) const; - void castItemSpell(int spellId); + void castItemSpell(int itemSpellId); - int castSpell(Character *c, int spellId); + int castSpell(Character *c, MagicSpell spellId); int subSpellCost(Character &c, int spellId);