aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen
diff options
context:
space:
mode:
authorPaul Gilbert2015-03-01 08:31:03 -0500
committerPaul Gilbert2015-03-01 08:31:03 -0500
commitb243768887c3aabbc6fe57e83971562bf2eba0f5 (patch)
tree27dc39fde26b03f5425efc654788afc2c4027b95 /engines/xeen
parent07f504fe160d051c458e1f0035d4784ac74e2530 (diff)
downloadscummvm-rg350-b243768887c3aabbc6fe57e83971562bf2eba0f5.tar.gz
scummvm-rg350-b243768887c3aabbc6fe57e83971562bf2eba0f5.tar.bz2
scummvm-rg350-b243768887c3aabbc6fe57e83971562bf2eba0f5.zip
XEEN: Implementing spells
Diffstat (limited to 'engines/xeen')
-rw-r--r--engines/xeen/dialogs_spells.cpp107
-rw-r--r--engines/xeen/dialogs_spells.h13
-rw-r--r--engines/xeen/resources.cpp10
-rw-r--r--engines/xeen/resources.h4
-rw-r--r--engines/xeen/spells.cpp573
5 files changed, 662 insertions, 45 deletions
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
index dfc72aa4b1..f5357766ba 100644
--- a/engines/xeen/dialogs_spells.cpp
+++ b/engines/xeen/dialogs_spells.cpp
@@ -755,5 +755,112 @@ void NotWhileEngaged::execute(int spellId) {
_vm->_mode = oldMode;
}
+/*------------------------------------------------------------------------*/
+
+bool LloydsBeacon::show(XeenEngine *vm) {
+ LloydsBeacon *dlg = new LloydsBeacon(vm);
+ bool result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+bool LloydsBeacon::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Screen &screen = *_vm->_screen;
+ SoundManager &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ Window &w = screen._windows[10];
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ Character &c = *combat._oldCharacter;
+
+ loadButtons();
+
+ if (!c._lloydMap) {
+ // No destination previously set, so have a default ready
+ if (isDarkCc) {
+ c._lloydSide = 1;
+ c._lloydPosition = Common::Point(25, 21);
+ c._lloydMap = 29;
+ } else {
+ c._lloydSide = 0;
+ c._lloydPosition = Common::Point(18, 4);
+ c._lloydMap = 28;
+ }
+ }
+
+ // Open up the text file for the destination map and read in it's name
+ File textFile(Common::String::format("%s%c%03d.txt",
+ c._lloydSide == 0 ? "xeen" : "dark",
+ c._lloydMap >= 100 ? 'x' : '0',
+ c._lloydMap));
+ Common::String mapName = textFile.readString();
+ textFile.close();
+
+ // Display the dialog
+ w.open();
+ w.writeString(Common::String::format(LLOYDS_BEACON,
+ mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y));
+ drawButtons(&screen);
+ w.update();
+
+ bool result = true;
+ do {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldQuit())
+ return true;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_r:
+ if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) {
+ result = false;
+ } else {
+ sound.playFX(51);
+ map._loadDarkSide = isDarkCc;
+ if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) {
+ map.load(c._lloydMap);
+ }
+
+ party._mazePosition = c._lloydPosition;
+ }
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_s:
+ case Common::KEYCODE_t:
+ sound.playFX(20);
+ c._lloydMap = party._mazeId;
+ c._lloydPosition = party._mazePosition;
+ c._lloydSide = isDarkCc ? 1 : 0;
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+ }
+ } while (_buttonValue != Common::KEYCODE_ESCAPE);
+
+ w.close();
+ return result;
+}
+
+void LloydsBeacon::loadButtons() {
+ _iconSprites.load("lloyds.icn");
+
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_r, &_iconSprites);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites);
+}
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
index b23f62b22f..ca7bb17b5e 100644
--- a/engines/xeen/dialogs_spells.h
+++ b/engines/xeen/dialogs_spells.h
@@ -109,6 +109,19 @@ public:
static void show(XeenEngine *vm, int spellId);
};
+class LloydsBeacon : public ButtonContainer {
+private:
+ XeenEngine *_vm;
+ SpriteResource _iconSprites;
+
+ LloydsBeacon(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+ bool execute();
+
+ void loadButtons();
+public:
+ static bool show(XeenEngine *vm);
+};
} // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 228c5f6449..a75f77ba5c 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -1544,4 +1544,14 @@ const char *const WHICH_ELEMENT2 =
"\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044"
"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
+const char *const DETECT_MONSTERS = "\x3""cDetect Monsters";
+
+const char *const LLOYDS_BEACON =
+ "\r\x3""c\v000\t000\x1Lloyd's Beacon\n"
+ "\n"
+ "Last Location\n"
+ "\n"
+ "%s\x3l\n"
+ "x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1";
+
} // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 84a4648e84..89dc74a4fe 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -546,6 +546,10 @@ extern const char *const ON_WHO;
extern const char *const WHICH_ELEMENT1;
extern const char *const WHICH_ELEMENT2;
+extern const char *const DETECT_MONSTERS;
+
+extern const char *const LLOYDS_BEACON;
+
} // End of namespace Xeen
#endif /* XEEN_RESOURCES_H */
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index f5f6428b9f..e3978aef65 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -21,6 +21,7 @@
*/
#include "xeen/spells.h"
+#include "xeen/dialogs_items.h"
#include "xeen/dialogs_spells.h"
#include "xeen/files.h"
#include "xeen/resources.h"
@@ -258,7 +259,16 @@ void Spells::addSpellCost(Character &c, int spellId) {
party._gems += gemCost;
}
-void Spells::acidSpray() { error("TODO: spell"); }
+void Spells::acidSpray() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 15;
+ combat._damageType = DT_POISON;
+ combat._rangeType = RT_ALL;
+ sound.playFX(17);
+ combat.multiAttack(10);
+}
void Spells::awaken() {
Interface &intf = *_vm->_interface;
@@ -276,21 +286,106 @@ void Spells::awaken() {
sound.playFX(30);
}
-void Spells::beastMaster() { error("TODO: spell"); }
+void Spells::beastMaster() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::bless() { error("TODO: spell"); }
+ combat._monsterDamage = 0;
+ combat._damageType = DT_BEASTMASTER;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(7);
+}
-void Spells::clairvoyance() { error("TODO: spell"); }
+void Spells::bless() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
-void Spells::coldRay() { error("TODO: spell"); }
+ sound.playFX(30);
+ party._blessed = combat._oldCharacter->getCurrentLevel();
+}
-void Spells::createFood() { error("TODO: spell"); }
+void Spells::clairvoyance() {
+ _vm->_party->_clairvoyanceActive = true;
+ _vm->_sound->playFX(20);
+}
-void Spells::cureDisease() { error("TODO: spell"); }
+void Spells::coldRay() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::cureParalysis() { error("TODO: spell"); }
+ combat._monsterDamage = _vm->getRandomNumber(2, 4) * combat._oldCharacter->getCurrentLevel();
+ combat._damageType = DT_COLD;
+ combat._rangeType = RT_ALL;
+ sound.playFX(15);
+ combat.multiAttack(8);
+}
-void Spells::curePoison() { error("TODO: spell"); }
+void Spells::createFood() {
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+
+ party._food += party._activeParty.size();
+ sound.playFX(20);
+}
+
+void Spells::cureDisease() {
+ 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[DISEASED] = 0;
+ intf.drawParty(true);
+}
+
+void Spells::cureParalysis() {
+ 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[PARALYZED] = 0;
+ intf.drawParty(true);
+}
+
+void Spells::curePoison() {
+ 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[POISONED] = 0;
+ intf.drawParty(true);
+}
void Spells::cureWounds() {
Combat &combat = *_vm->_combat;
@@ -306,30 +401,178 @@ void Spells::cureWounds() {
if (c.isDead()) {
spellFailed();
- }
- else {
+ } else {
sound.playFX(30);
c.addHitPoints(15);
}
}
-void Spells::dancingSword() { error("TODO: spell"); }
+void Spells::dancingSword() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = _vm->getRandomNumber(6, 14) * combat._oldCharacter->getCurrentLevel();
+ combat._damageType = DT_PHYSICAL;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(14);
+}
+
+void Spells::dayOfProtection() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+
+ int lvl = combat._oldCharacter->getCurrentLevel();
+ party._walkOnWaterActive = true;
+ party._heroism = lvl;
+ party._holyBonus = lvl;
+ party._blessed = lvl;
+ party._poisonResistence = lvl;
+ party._coldResistence = lvl;
+ party._electricityResistence = lvl;
+ party._fireResistence = lvl;
+ party._lightCount = lvl;
+ sound.playFX(20);
+}
+
+void Spells::dayOfSorcery() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+
+ int lvl = combat._oldCharacter->getCurrentLevel();
+ party._powerShield = lvl;
+ party._clairvoyanceActive = true;
+ party._wizardEyeActive = true;
+ party._levitateActive = true;
+ party._lightCount = lvl;
+ party._automapOn = false;
+ sound.playFX(20);
+}
+
+void Spells::deadlySwarm() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 40;
+ combat._damageType = DT_PHYSICAL;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(13);
+ combat.multiAttack(15);
+}
+
+void Spells::detectMonster() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Screen &screen = *_vm->_screen;
+ SoundManager &sound = *_vm->_sound;
+ Window &w = screen._windows[19];
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int grid[7][7];
+
+ SpriteResource sprites(isDarkCc ? "detectmn.icn" : "detctmon.icn");
+ Common::fill(&grid[0][0], &grid[7][7], 0);
+
+ w.open();
+ w.writeString(DETECT_MONSTERS);
+ sprites.draw(w, 0, Common::Point(243, 80));
+
+ for (int yDiff = 3; yDiff >= -3; --yDiff) {
+ for (int xDiff = -3; xDiff <= 3; ++xDiff) {
+ for (uint monIndex = 0; monIndex < map._mobData._monsters.size(); ++monIndex) {
+ MazeMonster &monster = map._mobData._monsters[monIndex];
+ Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
+ if (monster._position == pt) {
+ if (++grid[yDiff][xDiff] > 3)
+ grid[yDiff][xDiff] = 3;
+
+ sprites.draw(w, grid[yDiff][xDiff], Common::Point(xDiff * 9 + 244,
+ yDiff * 7 + 81));
+ }
+ }
+ }
+ }
+
+ sprites.draw(w, party._mazeDirection + 1, Common::Point(270, 101));
+ sound.playFX(20);
+ w.update();
+
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ events.wait(1);
+ } while (!events.isKeyMousePressed());
+
+ w.close();
+}
+
+void Spells::divineIntervention() {
+ Combat &combat = *_vm->_combat;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+ Character &castChar = *combat._oldCharacter;
-void Spells::dayOfProtection() { error("TODO: spell"); }
+ if ((castChar._tempAge + 5) > 250) {
+ castChar._tempAge = 250;
+ } else {
+ castChar._tempAge += 5;
+ }
-void Spells::dayOfSorcery() { error("TODO: spell"); }
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ Character &c = party._activeParty[idx];
+ Common::fill(&c._conditions[CURSED], &c._conditions[ERADICATED], 0);
+ if (!c._conditions[ERADICATED])
+ c._currentHp = c.getMaxHP();
+ }
-void Spells::deadlySwarm() { error("TODO: spell"); }
+ sound.playFX(20);
+ intf.drawParty(true);
+}
+
+void Spells::dragonSleep() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 0;
+ combat._damageType = DT_DRAGONSLEEP;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(18);
+ combat.multiAttack(7);
+}
-void Spells::detectMonster() { error("TODO: spell"); }
+void Spells::elementalStorm() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+ static const int STORM_FX_LIST[4] = { 13, 14, 15, 17 };
+ static const int STORM_MA_LIST[4] = { 0, 5, 9, 10 };
+
+ combat._monsterDamage = 150;
+ combat._damageType = (DamageType)_vm->getRandomNumber(DT_FIRE, DT_POISON);
+ combat._rangeType = RT_ALL;
+ sound.playFX(STORM_FX_LIST[combat._damageType]);
+ combat.multiAttack(STORM_MA_LIST[combat._damageType]);
+}
-void Spells::divineIntervention() { error("TODO: spell"); }
+void Spells::enchantItem() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ Mode oldMode = _vm->_mode;
-void Spells::dragonSleep() { error("TODO: spell"); }
+ int charIndex = SpellOnWho::show(_vm, MS_FirstAid);
+ if (charIndex == -1)
+ return;
-void Spells::elementalStorm() { error("TODO: spell"); }
+ Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+ party._activeParty[charIndex];
+ ItemsDialog::show(_vm, &c, ITEMMODE_ENCHANT);
-void Spells::enchantItem() { error("TODO: spell"); }
+ _vm->_mode = oldMode;
+}
void Spells::energyBlast() {
Combat &combat = *_vm->_combat;
@@ -342,15 +585,67 @@ void Spells::energyBlast() {
combat.multiAttack(13);
}
-void Spells::etherialize() { error("TODO: spell"); } // Not while engaged
+void Spells::etherialize() {
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+ Common::Point pt = party._mazePosition + Common::Point(
+ SCREEN_POSITIONING_X[party._mazeDirection][7],
+ SCREEN_POSITIONING_Y[party._mazeDirection][7]
+ );
-void Spells::fantasticFreeze() { error("TODO: spell"); }
+ if ((map.mazeData()._mazeFlags & RESTRICTION_ETHERIALIZE) ||
+ map.mazeLookup(pt, 0, 0xffff) == INVALID_CELL) {
+ spellFailed();
+ } else {
+ party._mazePosition = pt;
+ sound.playFX(51);
+ }
+}
-void Spells::fieryFlail() { error("TODO: spell"); }
+void Spells::fantasticFreeze() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::fingerOfDeath() { error("TODO: spell"); }
+ combat._monsterDamage = 40;
+ combat._damageType = DT_COLD;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(15);
+ combat.multiAttack(8);
+}
+
+void Spells::fieryFlail() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 100;
+ combat._damageType = DT_FIRE;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(13);
+ combat.multiAttack(2);
+}
+
+void Spells::fingerOfDeath() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::fireball() { error("TODO: spell"); }
+ combat._monsterDamage = 0;
+ combat._damageType = DT_FINGEROFDEATH;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(14);
+}
+
+void Spells::fireball() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = _vm->getRandomNumber(3, 7) * combat._oldCharacter->getCurrentLevel();
+ combat._damageType = DT_FIRE;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(13);
+ combat.multiAttack(0);
+}
void Spells::firstAid() {
Combat &combat = *_vm->_combat;
@@ -384,29 +679,132 @@ void Spells::flyingFist() {
combat.multiAttack(14);
}
-void Spells::frostbite() { error("TODO: spell"); }
+void Spells::frostbite() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::golemStopper() { error("TODO: spell"); }
+ combat._monsterDamage = 35;
+ combat._damageType = DT_COLD;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(8);
+ combat.multiAttack(8);
+}
-void Spells::heroism() { error("TODO: spell"); }
+void Spells::golemStopper() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::holyBonus() { error("TODO: spell"); }
+ combat._monsterDamage = 0;
+ combat._damageType = DT_GOLEMSTOPPER;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(16);
+ combat.multiAttack(6);
+}
-void Spells::holyWord() { error("TODO: spell"); }
+void Spells::heroism() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
-void Spells::hypnotize() { error("TODO: spell"); }
+ sound.playFX(30);
+ party._heroism = combat._oldCharacter->getCurrentLevel();
+}
+
+void Spells::holyBonus() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+
+ sound.playFX(30);
+ party._holyBonus = combat._oldCharacter->getCurrentLevel();
+}
+
+void Spells::holyWord() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 0;
+ combat._damageType = DT_HOLYWORD;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(13);
+}
+
+void Spells::hypnotize() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 0;
+ combat._damageType = DT_HYPNOTIZE;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(7);
+}
void Spells::identifyMonster() { error("TODO: spell"); }
-void Spells::implosion() { error("TODO: spell"); }
+void Spells::implosion() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::incinerate() { error("TODO: spell"); }
+ combat._monsterDamage = 1000;
+ combat._damageType = DT_ENERGY;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(18);
+ combat.multiAttack(6);
+}
-void Spells::inferno() { error("TODO: spell"); }
+void Spells::incinerate() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
-void Spells::insectSpray() { error("TODO: spell"); }
+ combat._monsterDamage = 250;
+ combat._damageType = DT_FIRE;
+ combat._rangeType = RT_SINGLE;
+ sound.playFX(22);
+ combat.multiAttack(1);
+}
-void Spells::itemToGold() { error("TODO: spell"); }
+void Spells::inferno() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 250;
+ combat._damageType = DT_FIRE;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(13);
+ combat.multiAttack(1);
+}
+
+void Spells::insectSpray() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 0;
+ combat._damageType = DT_INSECT_SPRAY;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(17);
+ combat.multiAttack(10);
+}
+
+void Spells::itemToGold() {
+ Combat &combat = *_vm->_combat;
+ Party &party = *_vm->_party;
+
+ int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+ if (charIndex == -1)
+ return;
+
+ Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+ party._activeParty[charIndex];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_FF;
+
+ _vm->_screen->_windows[11].close();
+ ItemsDialog::show(_vm, &c, ITEMMODE_TO_GOLD);
+
+ _vm->_mode = oldMode;
+}
void Spells::jump() {
Map &map = *_vm->_map;
@@ -446,7 +844,10 @@ void Spells::jump() {
spellFailed();
}
-void Spells::levitate() { error("TODO: spell"); }
+void Spells::levitate() {
+ _vm->_party->_levitateActive = true;
+ _vm->_sound->playFX(20);
+}
void Spells::light() {
Interface &intf = *_vm->_interface;
@@ -459,9 +860,25 @@ void Spells::light() {
sound.playFX(39);
}
-void Spells::lightningBolt() { error("TODO: spell"); }
+void Spells::lightningBolt() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = _vm->getRandomNumber(4, 6) * combat._oldCharacter->getCurrentLevel();
+ combat._damageType = DT_ELECTRICAL;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(14);
+ combat.multiAttack(3);
+}
-void Spells::lloydsBeacon() { error("TODO: spell"); } // Not while engaged
+void Spells::lloydsBeacon() {
+ if (_vm->_map->mazeData()._mazeFlags & RESTRICTION_LLOYDS_BEACON) {
+ spellFailed();
+ } else {
+ if (!LloydsBeacon::show(_vm))
+ spellFailed();
+ }
+}
void Spells::magicArrow() {
Combat &combat = *_vm->_combat;
@@ -471,13 +888,68 @@ void Spells::magicArrow() {
combat.multiAttack(11);
}
-void Spells::massDistortion() { error("TODO: spell"); }
+void Spells::massDistortion() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 0;
+ combat._damageType = DT_MASS_DISTORTION;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(18);
+ combat.multiAttack(6);
+}
+
+void Spells::megaVolts() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 150;
+ combat._damageType = DT_ELECTRICAL;
+ combat._rangeType = RT_GROUP;
+ sound.playFX(14);
+ combat.multiAttack(4);
+}
+
+void Spells::moonRay() {
+ Combat &combat = *_vm->_combat;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 30;
+ combat._damageType = DT_ENERGY;
+ combat._rangeType = RT_ALL;
+ sound.playFX(16);
+ combat.multiAttack(13);
+
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ sound.playFX(30);
+ party._activeParty[idx].addHitPoints(_vm->getRandomNumber(1, 30));
+ }
+
+ intf.drawParty(true);
+}
+
+void Spells::naturesCure() {
+ Combat &combat = *_vm->_combat;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ SoundManager &sound = *_vm->_sound;
-void Spells::megaVolts() { error("TODO: spell"); }
+ int charIndex = SpellOnWho::show(_vm, MS_Revitalize);
+ if (charIndex == -1)
+ return;
-void Spells::moonRay() { error("TODO: spell"); }
+ Character &c = combat._combatMode == 2 ? *combat._combatParty[charIndex] :
+ party._activeParty[charIndex];
-void Spells::naturesCure() { error("TODO: spell"); }
+ if (c.isDead()) {
+ spellFailed();
+ } else {
+ sound.playFX(30);
+ c.addHitPoints(25);
+ }
+}
void Spells::pain() {
Combat &combat = *_vm->_combat;
@@ -490,9 +962,20 @@ void Spells::pain() {
combat.multiAttack(14);
}
-void Spells::poisonVolley() { error("TODO: spell"); }
+void Spells::poisonVolley() {
+ Combat &combat = *_vm->_combat;
+ SoundManager &sound = *_vm->_sound;
+
+ combat._monsterDamage = 10;
+ combat._damageType = DT_POISON_VOLLEY;
+ combat._rangeType = RT_ALL;
+ sound.playFX(49);
+ combat.multiAttack(11);
+}
-void Spells::powerCure() { error("TODO: spell"); }
+void Spells::powerCure() {
+
+}
void Spells::powerShield() { error("TODO: spell"); }