mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 01:08:25 +00:00
22456b345f
Originally the flag was whether the party was on the Dark Side, but as a bool I was having to cast it to an int side/cc number in more and more places. So now I've converted it to _ccNum, and it can be used directly as an int
1334 lines
31 KiB
C++
1334 lines
31 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "xeen/spells.h"
|
|
#include "xeen/dialogs/dialogs_items.h"
|
|
#include "xeen/dialogs/dialogs_spells.h"
|
|
#include "xeen/files.h"
|
|
#include "xeen/resources.h"
|
|
#include "xeen/xeen.h"
|
|
|
|
namespace Xeen {
|
|
|
|
Spells::Spells(XeenEngine *vm) : _vm(vm) {
|
|
_lastCaster = 0;
|
|
|
|
load();
|
|
}
|
|
|
|
void Spells::load() {
|
|
File f1((g_vm->getGameID() == GType_Clouds) ? "spells.cld" : "spells.xen", 1);
|
|
while (f1.pos() < f1.size())
|
|
_spellNames.push_back(f1.readString());
|
|
f1.close();
|
|
}
|
|
|
|
int Spells::calcSpellCost(int spellId, int expenseFactor) const {
|
|
int amount = Res.SPELL_COSTS[spellId];
|
|
return (amount >= 0) ? (amount * 100) << expenseFactor :
|
|
(amount * -500) << expenseFactor;
|
|
}
|
|
|
|
int Spells::calcSpellPoints(int spellId, int expenseFactor) const {
|
|
int amount = Res.SPELL_COSTS[spellId];
|
|
return (amount >= 0) ? amount : amount * -1 * expenseFactor;
|
|
}
|
|
|
|
typedef void(Spells::*SpellMethodPtr)();
|
|
|
|
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])();
|
|
}
|
|
|
|
void Spells::spellFailed() {
|
|
ErrorScroll::show(_vm, Res.SPELL_FAILED, WT_NONFREEZED_WAIT);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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]);
|
|
}
|
|
|
|
int Spells::castSpell(Character *c, MagicSpell spellId) {
|
|
Combat &combat = *_vm->_combat;
|
|
Interface &intf = *_vm->_interface;
|
|
int oldTillMove = intf._tillMove;
|
|
int result = 1;
|
|
combat._oldCharacter = c;
|
|
|
|
// Try and subtract the SP and gem requirements for the spell
|
|
int resultError = subSpellCost(*c, spellId);
|
|
if (resultError) {
|
|
CantCast::show(_vm, spellId, resultError);
|
|
result = -1;
|
|
} else {
|
|
// Some spells have special handling
|
|
switch (spellId) {
|
|
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);
|
|
NotWhileEngaged::show(_vm, spellId);
|
|
result = -1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
executeSpell(spellId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
combat._moveMonsters = 1;
|
|
intf._tillMove = oldTillMove;
|
|
return result;
|
|
}
|
|
|
|
int Spells::subSpellCost(Character &c, int spellId) {
|
|
Party &party = *_vm->_party;
|
|
int gemCost = Res.SPELL_GEM_COST[spellId];
|
|
int spCost = Res.SPELL_COSTS[spellId];
|
|
|
|
// Negative SP costs indicate it's dependent on the character's level
|
|
if (spCost <= 0) {
|
|
spCost = c.getCurrentLevel() * (spCost * -1);
|
|
}
|
|
|
|
if (spCost > c._currentSp)
|
|
// Not enough SP
|
|
return 1;
|
|
if (gemCost > (int)party._gems)
|
|
// Not enough gems
|
|
return 2;
|
|
|
|
c._currentSp -= spCost;
|
|
party._gems -= gemCost;
|
|
return 0;
|
|
}
|
|
|
|
void Spells::addSpellCost(Character &c, int spellId) {
|
|
Party &party = *_vm->_party;
|
|
int gemCost = Res.SPELL_GEM_COST[spellId];
|
|
int spCost = Res.SPELL_COSTS[spellId];
|
|
|
|
if (spCost < 1)
|
|
spCost *= -1 * c.getCurrentLevel();
|
|
|
|
c._currentSp += spCost;
|
|
party._gems += gemCost;
|
|
}
|
|
|
|
void Spells::acidSpray() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 15;
|
|
combat._damageType = DT_POISON;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(17);
|
|
combat.rangedAttack(POW_SPRAY);
|
|
}
|
|
|
|
void Spells::awaken() {
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
|
|
Character &c = party._activeParty[idx];
|
|
c._conditions[ASLEEP] = 0;
|
|
if (c._currentHp > 0)
|
|
c._conditions[UNCONSCIOUS] = 0;
|
|
}
|
|
|
|
intf.drawParty(true);
|
|
sound.playFX(30);
|
|
}
|
|
|
|
void Spells::beastMaster() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_BEASTMASTER;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_MAGIC_ORB);
|
|
}
|
|
|
|
void Spells::bless() {
|
|
Combat &combat = *_vm->_combat;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
sound.playFX(30);
|
|
party._blessed = combat._oldCharacter->getCurrentLevel();
|
|
}
|
|
|
|
void Spells::clairvoyance() {
|
|
_vm->_party->_clairvoyanceActive = true;
|
|
_vm->_sound->playFX(20);
|
|
}
|
|
|
|
void Spells::coldRay() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = _vm->getRandomNumber(2, 4) * combat._oldCharacter->getCurrentLevel();
|
|
combat._damageType = DT_COLD;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(15);
|
|
combat.rangedAttack(POW_COLD_RAY);
|
|
}
|
|
|
|
void Spells::createFood() {
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
party._food += party._activeParty.size();
|
|
sound.playFX(20);
|
|
}
|
|
|
|
void Spells::cureDisease() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_CureDisease);
|
|
if (!c)
|
|
return;
|
|
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[DISEASED] = 0;
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::cureParalysis() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_CureParalysis);
|
|
if (!c)
|
|
return;
|
|
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[PARALYZED] = 0;
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::curePoison() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_CurePoison);
|
|
if (!c)
|
|
return;
|
|
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[POISONED] = 0;
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::cureWounds() {
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_CureWounds);
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->isDead()) {
|
|
spellFailed();
|
|
} else {
|
|
sound.playFX(30);
|
|
c->addHitPoints(15);
|
|
}
|
|
}
|
|
|
|
void Spells::dancingSword() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = _vm->getRandomNumber(6, 14) * combat._oldCharacter->getCurrentLevel();
|
|
combat._damageType = DT_PHYSICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_SPARKLES);
|
|
}
|
|
|
|
void Spells::dayOfProtection() {
|
|
Combat &combat = *_vm->_combat;
|
|
Party &party = *_vm->_party;
|
|
Sound &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;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
int lvl = combat._oldCharacter->getCurrentLevel();
|
|
party._powerShield = lvl;
|
|
party._clairvoyanceActive = true;
|
|
party._wizardEyeActive = true;
|
|
party._levitateCount = 1;
|
|
party._lightCount = lvl;
|
|
party._automapOn = false;
|
|
sound.playFX(20);
|
|
}
|
|
|
|
void Spells::deadlySwarm() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 40;
|
|
combat._damageType = DT_PHYSICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(13);
|
|
combat.rangedAttack(POW_DEADLY_SWARM);
|
|
}
|
|
|
|
void Spells::detectMonster() {
|
|
EventsManager &events = *_vm->_events;
|
|
Interface &intf = *_vm->_interface;
|
|
Map &map = *_vm->_map;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
Windows &windows = *_vm->_windows;
|
|
Window &w = windows[19];
|
|
int ccNum = _vm->_files->_ccNum;
|
|
int grid[7][7];
|
|
|
|
SpriteResource sprites(ccNum ? "detectmn.icn" : "detctmon.icn");
|
|
Common::fill(&grid[0][0], &grid[6][6], 0);
|
|
|
|
w.open();
|
|
w.writeString(Res.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) {
|
|
int &gridEntry = grid[yDiff + 3][xDiff + 3];
|
|
if (++gridEntry > 3)
|
|
gridEntry = 3;
|
|
|
|
sprites.draw(w, gridEntry, 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, false);
|
|
} while (!events.isKeyMousePressed());
|
|
|
|
w.close();
|
|
}
|
|
|
|
void Spells::divineIntervention() {
|
|
Combat &combat = *_vm->_combat;
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
Character &castChar = *combat._oldCharacter;
|
|
|
|
if ((castChar._tempAge + 5) > 250) {
|
|
castChar._tempAge = 250;
|
|
} else {
|
|
castChar._tempAge += 5;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
sound.playFX(20);
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::dragonSleep() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_DRAGONSLEEP;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_MAGIC_ORB);
|
|
}
|
|
|
|
void Spells::elementalStorm() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
static const int STORM_FX_LIST[4] = { 13, 14, 15, 17 };
|
|
static const PowType STORM_MA_LIST[4] = {
|
|
POW_FIREBALL, POW_SPARKS, POW_FROST_WAVE, POW_SPRAY
|
|
};
|
|
|
|
combat._monsterDamage = 150;
|
|
combat._damageType = (DamageType)_vm->getRandomNumber(DT_FIRE, DT_POISON);
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(STORM_FX_LIST[combat._damageType]);
|
|
combat.rangedAttack(STORM_MA_LIST[combat._damageType]);
|
|
}
|
|
|
|
void Spells::enchantItem() {
|
|
Mode oldMode = _vm->_mode;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_EnchantItem);
|
|
if (!c)
|
|
return;
|
|
|
|
ItemsDialog::show(_vm, c, ITEMMODE_ENCHANT);
|
|
|
|
_vm->_mode = oldMode;
|
|
}
|
|
|
|
void Spells::energyBlast() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
|
|
combat._damageType = DT_ENERGY;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(16);
|
|
combat.rangedAttack(POW_ENERGY_BLAST);
|
|
}
|
|
|
|
void Spells::etherialize() {
|
|
Map &map = *_vm->_map;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
Common::Point pt = party._mazePosition + Common::Point(
|
|
Res.SCREEN_POSITIONING_X[party._mazeDirection][7],
|
|
Res.SCREEN_POSITIONING_Y[party._mazeDirection][7]
|
|
);
|
|
|
|
if ((map.mazeData()._mazeFlags & RESTRICTION_ETHERIALIZE) ||
|
|
map.mazeLookup(pt, 0, 0xffff) == INVALID_CELL) {
|
|
spellFailed();
|
|
} else {
|
|
party._mazePosition = pt;
|
|
sound.playFX(51);
|
|
}
|
|
}
|
|
|
|
void Spells::fantasticFreeze() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 40;
|
|
combat._damageType = DT_COLD;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(15);
|
|
combat.rangedAttack(POW_COLD_RAY);
|
|
}
|
|
|
|
void Spells::fieryFlail() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 100;
|
|
combat._damageType = DT_FIRE;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(13);
|
|
combat.rangedAttack(POW_FIERY_FLAIL);
|
|
}
|
|
|
|
void Spells::fingerOfDeath() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_FINGEROFDEATH;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_SPARKLES);
|
|
}
|
|
|
|
void Spells::fireball() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = _vm->getRandomNumber(3, 7) * combat._oldCharacter->getCurrentLevel();
|
|
combat._damageType = DT_FIRE;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(13);
|
|
combat.rangedAttack(POW_FIREBALL);
|
|
}
|
|
|
|
void Spells::firstAid() {
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_FirstAid);
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->isDead()) {
|
|
spellFailed();
|
|
} else {
|
|
sound.playFX(30);
|
|
c->addHitPoints(6);
|
|
}
|
|
}
|
|
|
|
void Spells::flyingFist() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 6;
|
|
combat._damageType = DT_PHYSICAL;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_SPARKLES);
|
|
}
|
|
|
|
void Spells::frostbite() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 35;
|
|
combat._damageType = DT_COLD;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(8);
|
|
combat.rangedAttack(POW_COLD_RAY);
|
|
}
|
|
|
|
void Spells::golemStopper() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_GOLEMSTOPPER;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(16);
|
|
combat.rangedAttack(POW_STOPPER);
|
|
}
|
|
|
|
void Spells::heroism() {
|
|
Combat &combat = *_vm->_combat;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
sound.playFX(30);
|
|
party._heroism = combat._oldCharacter->getCurrentLevel();
|
|
}
|
|
|
|
void Spells::holyBonus() {
|
|
Combat &combat = *_vm->_combat;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
sound.playFX(30);
|
|
party._holyBonus = combat._oldCharacter->getCurrentLevel();
|
|
}
|
|
|
|
void Spells::holyWord() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_HOLYWORD;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_ENERGY_BLAST);
|
|
}
|
|
|
|
void Spells::hypnotize() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_HYPNOTIZE;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_MAGIC_ORB);
|
|
}
|
|
|
|
void Spells::identifyMonster() {
|
|
Combat &combat = *_vm->_combat;
|
|
|
|
if (combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1
|
|
&& combat._attackMonsters[2] == -1) {
|
|
spellFailed();
|
|
} else {
|
|
IdentifyMonster::show(_vm);
|
|
}
|
|
}
|
|
|
|
void Spells::implosion() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 1000;
|
|
combat._damageType = DT_ENERGY;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_STOPPER);
|
|
}
|
|
|
|
void Spells::incinerate() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 250;
|
|
combat._damageType = DT_FIRE;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(22);
|
|
combat.rangedAttack(POW_INCINERATE);
|
|
}
|
|
|
|
void Spells::inferno() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 250;
|
|
combat._damageType = DT_FIRE;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(13);
|
|
combat.rangedAttack(POW_INCINERATE);
|
|
}
|
|
|
|
void Spells::insectSpray() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_INSECT_SPRAY;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(17);
|
|
combat.rangedAttack(POW_SPRAY);
|
|
}
|
|
|
|
void Spells::itemToGold() {
|
|
Windows &windows = *_vm->_windows;
|
|
Character *c = SpellOnWho::show(_vm, MS_ItemToGold);
|
|
if (!c)
|
|
return;
|
|
|
|
Mode oldMode = _vm->_mode;
|
|
_vm->_mode = MODE_FF;
|
|
|
|
windows[11].close();
|
|
ItemsDialog::show(_vm, c, ITEMMODE_TO_GOLD);
|
|
|
|
_vm->_mode = oldMode;
|
|
}
|
|
|
|
void Spells::jump() {
|
|
Map &map = *_vm->_map;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (map._isOutdoors) {
|
|
map.getCell(7);
|
|
if (map._currentWall != 1) {
|
|
map.getCell(14);
|
|
if (map._currentSurfaceId != 0 && map._currentWall != 1) {
|
|
party._mazePosition += Common::Point(
|
|
Res.SCREEN_POSITIONING_X[party._mazeDirection][14],
|
|
Res.SCREEN_POSITIONING_Y[party._mazeDirection][14]
|
|
);
|
|
sound.playFX(51);
|
|
party._stepped = true;
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
Common::Point pt = party._mazePosition + Common::Point(
|
|
Res.SCREEN_POSITIONING_X[party._mazeDirection][7],
|
|
Res.SCREEN_POSITIONING_Y[party._mazeDirection][7]);
|
|
if (!map.mazeLookup(party._mazePosition, Res.MONSTER_GRID_BITMASK[party._mazeDirection]) &&
|
|
!map.mazeLookup(pt, Res.MONSTER_GRID_BITMASK[party._mazeDirection])) {
|
|
party._mazePosition += Common::Point(
|
|
Res.SCREEN_POSITIONING_X[party._mazeDirection][14],
|
|
Res.SCREEN_POSITIONING_Y[party._mazeDirection][14]
|
|
);
|
|
sound.playFX(51);
|
|
party._stepped = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
spellFailed();
|
|
}
|
|
|
|
void Spells::levitate() {
|
|
_vm->_party->_levitateCount = 1;
|
|
_vm->_sound->playFX(20);
|
|
}
|
|
|
|
void Spells::light() {
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
++party._lightCount;
|
|
if (intf._obscurity != OBSCURITY_BLACK)
|
|
party._stepped = true;
|
|
sound.playFX(39);
|
|
}
|
|
|
|
void Spells::lightningBolt() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = _vm->getRandomNumber(4, 6) * combat._oldCharacter->getCurrentLevel();
|
|
combat._damageType = DT_ELECTRICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(14);
|
|
combat.rangedAttack(POW_LIGHTNING);
|
|
}
|
|
|
|
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;
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_MAGIC_ARROW;
|
|
combat._rangeType = RT_SINGLE;
|
|
combat.rangedAttack(POW_ARROW);
|
|
}
|
|
|
|
void Spells::massDistortion() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_MASS_DISTORTION;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_STOPPER);
|
|
}
|
|
|
|
void Spells::megaVolts() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 150;
|
|
combat._damageType = DT_ELECTRICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(14);
|
|
combat.rangedAttack(POW_MEGAVOLTS);
|
|
}
|
|
|
|
void Spells::moonRay() {
|
|
Combat &combat = *_vm->_combat;
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 30;
|
|
combat._damageType = DT_ENERGY;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(16);
|
|
combat.rangedAttack(POW_ENERGY_BLAST);
|
|
|
|
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() {
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_NaturesCure);
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->isDead()) {
|
|
spellFailed();
|
|
} else {
|
|
sound.playFX(30);
|
|
c->addHitPoints(25);
|
|
}
|
|
}
|
|
|
|
void Spells::pain() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_PHYSICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_SPARKLES);
|
|
}
|
|
|
|
void Spells::poisonVolley() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 10;
|
|
combat._damageType = DT_POISON_VOLLEY;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(49);
|
|
combat.rangedAttack(POW_ARROW);
|
|
}
|
|
|
|
void Spells::powerCure() {
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_PowerCure);
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->isDead()) {
|
|
spellFailed();
|
|
} else {
|
|
sound.playFX(30);
|
|
c->addHitPoints(_vm->getRandomNumber(2, 12) * _vm->_combat->_oldCharacter->getCurrentLevel());
|
|
}
|
|
}
|
|
|
|
void Spells::powerShield() {
|
|
Combat &combat = *_vm->_combat;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
sound.playFX(20);
|
|
party._powerShield = combat._oldCharacter->getCurrentLevel();
|
|
}
|
|
|
|
void Spells::prismaticLight() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 80;
|
|
combat._damageType = (DamageType)_vm->getRandomNumber(DT_PHYSICAL, DT_ENERGY);
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_SPARKLES);
|
|
}
|
|
|
|
void Spells::protectionFromElements() {
|
|
Combat &combat = *_vm->_combat;
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
Character &c = *combat._oldCharacter;
|
|
int resist = MIN(c.getCurrentLevel() * 2 + 5, (uint)200);
|
|
|
|
int elementType = SelectElement::show(_vm, MS_ProtFromElements);
|
|
if (elementType != -1) {
|
|
switch (elementType) {
|
|
case DT_FIRE:
|
|
party._fireResistence = resist;
|
|
break;
|
|
case DT_ELECTRICAL:
|
|
party._fireResistence = resist;
|
|
break;
|
|
case DT_COLD:
|
|
party._coldResistence = resist;
|
|
break;
|
|
case DT_POISON:
|
|
party._poisonResistence = resist;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
sound.playFX(20);
|
|
intf.drawParty(true);
|
|
}
|
|
}
|
|
|
|
void Spells::raiseDead() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_RaiseDead);
|
|
if (!c)
|
|
return;
|
|
|
|
if (!c->_conditions[DEAD]) {
|
|
spellFailed();
|
|
} else {
|
|
c->_conditions[DEAD] = 0;
|
|
c->_conditions[UNCONSCIOUS] = 0;
|
|
c->_currentHp = 0;
|
|
sound.playFX(30);
|
|
c->addHitPoints(1);
|
|
if (--c->_endurance._permanent < 1)
|
|
c->_endurance._permanent = 1;
|
|
|
|
intf.drawParty(true);
|
|
}
|
|
}
|
|
|
|
void Spells::rechargeItem() {
|
|
Mode oldMode = _vm->_mode;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_RechargeItem);
|
|
if (!c)
|
|
return;
|
|
|
|
ItemsDialog::show(_vm, c, ITEMMODE_RECHARGE);
|
|
_vm->_mode = oldMode;
|
|
}
|
|
|
|
void Spells::resurrection() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_RaiseDead);
|
|
if (!c)
|
|
return;
|
|
|
|
if (!c->_conditions[ERADICATED]) {
|
|
spellFailed();
|
|
sound.playFX(30);
|
|
} else {
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[ERADICATED] = 0;
|
|
|
|
if (--c->_endurance._permanent < 1)
|
|
c->_endurance._permanent = 1;
|
|
if ((c->_tempAge + 5) >= 250)
|
|
c->_tempAge = 250;
|
|
else
|
|
c->_tempAge += 5;
|
|
|
|
intf.drawParty(true);
|
|
}
|
|
}
|
|
|
|
void Spells::revitalize() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_Revitalize);
|
|
if (!c)
|
|
return;
|
|
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[WEAK] = 0;
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::shrapMetal() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
|
|
combat._damageType = DT_PHYSICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(16);
|
|
combat.rangedAttack(POW_DEADLY_SWARM);
|
|
}
|
|
|
|
void Spells::sleep() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_SLEEP;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_MAGIC_ORB);
|
|
}
|
|
|
|
void Spells::sparks() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = combat._oldCharacter->getCurrentLevel() * 2;
|
|
combat._damageType = DT_ELECTRICAL;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(14);
|
|
combat.rangedAttack(POW_SPARKS);
|
|
}
|
|
|
|
void Spells::starBurst() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 500;
|
|
combat._damageType = DT_FIRE;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(13);
|
|
combat.rangedAttack(POW_DEADLY_SWARM);
|
|
}
|
|
|
|
void Spells::stoneToFlesh() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_StoneToFlesh);
|
|
if (!c)
|
|
return;
|
|
|
|
sound.playFX(30);
|
|
c->addHitPoints(0);
|
|
c->_conditions[STONED] = 0;
|
|
intf.drawParty(true);
|
|
}
|
|
|
|
void Spells::sunRay() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 200;
|
|
combat._damageType = DT_ENERGY;
|
|
combat._rangeType = RT_ALL;
|
|
sound.playFX(16);
|
|
combat.rangedAttack(POW_ENERGY_BLAST);
|
|
}
|
|
|
|
void Spells::superShelter() {
|
|
Interface &intf = *_vm->_interface;
|
|
Map &map = *_vm->_map;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (map.mazeData()._mazeFlags & RESTRICTION_SUPER_SHELTER) {
|
|
spellFailed();
|
|
} else {
|
|
Mode oldMode = _vm->_mode;
|
|
_vm->_mode = MODE_12;
|
|
sound.playFX(30);
|
|
intf.rest();
|
|
_vm->_mode = oldMode;
|
|
}
|
|
}
|
|
|
|
void Spells::suppressDisease() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_SuppressDisease);
|
|
if (!c)
|
|
return;
|
|
|
|
if (c->_conditions[DISEASED]) {
|
|
if (c->_conditions[DISEASED] >= 4)
|
|
c->_conditions[DISEASED] -= 3;
|
|
else
|
|
c->_conditions[DISEASED] = 1;
|
|
|
|
sound.playFX(20);
|
|
c->addHitPoints(0);
|
|
intf.drawParty(true);
|
|
}
|
|
}
|
|
|
|
void Spells::suppressPoison() {
|
|
Interface &intf = *_vm->_interface;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
Character *c = SpellOnWho::show(_vm, MS_FirstAid);
|
|
if (!c)
|
|
return;
|
|
|
|
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() {
|
|
Map &map = *_vm->_map;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (map.mazeData()._mazeFlags & RESTRICTION_TELPORT) {
|
|
spellFailed();
|
|
} else {
|
|
switch (Teleport::show(_vm)) {
|
|
case 0:
|
|
spellFailed();
|
|
break;
|
|
case 1:
|
|
sound.playFX(51);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Spells::timeDistortion() {
|
|
Interface &intf = *_vm->_interface;
|
|
Map &map = *_vm->_map;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (map.mazeData()._mazeFlags & RESTRICTION_TIME_DISTORTION) {
|
|
spellFailed();
|
|
} else {
|
|
party.moveToRunLocation();
|
|
sound.playFX(51);
|
|
intf.draw3d(true);
|
|
}
|
|
}
|
|
|
|
void Spells::townPortal() {
|
|
Map &map = *_vm->_map;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (map.mazeData()._mazeFlags & RESTRICTION_TOWN_PORTAL) {
|
|
spellFailed();
|
|
return;
|
|
}
|
|
|
|
int townNumber = TownPortal::show(_vm);
|
|
if (!townNumber)
|
|
return;
|
|
|
|
sound.playFX(51);
|
|
map._loadDarkSide = map._sideTownPortal;
|
|
_vm->_files->_ccNum = map._sideTownPortal > 0;
|
|
map.load(Res.TOWN_MAP_NUMBERS[map._sideTownPortal][townNumber - 1]);
|
|
|
|
if (!_vm->_files->_ccNum) {
|
|
party.moveToRunLocation();
|
|
} else {
|
|
switch (townNumber) {
|
|
case 1:
|
|
party._mazePosition = Common::Point(14, 11);
|
|
party._mazeDirection = DIR_SOUTH;
|
|
break;
|
|
case 2:
|
|
party._mazePosition = Common::Point(5, 12);
|
|
party._mazeDirection = DIR_WEST;
|
|
break;
|
|
case 3:
|
|
party._mazePosition = Common::Point(2, 15);
|
|
party._mazeDirection = DIR_EAST;
|
|
break;
|
|
case 4:
|
|
party._mazePosition = Common::Point(8, 11);
|
|
party._mazeDirection = DIR_NORTH;
|
|
break;
|
|
case 5:
|
|
party._mazePosition = Common::Point(2, 6);
|
|
party._mazeDirection = DIR_NORTH;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Spells::toxicCloud() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 10;
|
|
combat._damageType = DT_POISON;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(17);
|
|
combat.rangedAttack(POW_SPRAY);
|
|
}
|
|
|
|
void Spells::turnUndead() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 0;
|
|
combat._damageType = DT_UNDEAD;
|
|
combat._rangeType = RT_GROUP;
|
|
sound.playFX(18);
|
|
combat.rangedAttack(POW_ENERGY_BLAST);
|
|
}
|
|
|
|
void Spells::walkOnWater() {
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
party._walkOnWaterActive = true;
|
|
sound.playFX(20);
|
|
}
|
|
|
|
void Spells::wizardEye() {
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
party._wizardEyeActive = true;
|
|
party._automapOn = false;
|
|
sound.playFX(20);
|
|
}
|
|
|
|
void Spells::frostbite2() {
|
|
Combat &combat = *_vm->_combat;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
combat._monsterDamage = 35;
|
|
combat._damageType = DT_COLD;
|
|
combat._rangeType = RT_SINGLE;
|
|
sound.playFX(15);
|
|
combat.rangedAttack(POW_FROST_WAVE);
|
|
}
|
|
|
|
} // End of namespace Xeen
|