Files
scummvm-cursorfix/engines/mm/mm1/game/spells_party.cpp
2026-02-02 04:50:13 +01:00

1003 lines
25 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "mm/mm1/game/spells_party.h"
#include "mm/mm1/game/rest.h"
#include "mm/mm1/data/locations.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
#include "mm/mm1/sound.h"
#include "mm/mm1/views/spells/detect_magic.h"
#include "mm/mm1/views/spells/fly.h"
#include "mm/mm1/views/spells/location.h"
#include "mm/mm1/views/spells/teleport.h"
namespace MM {
namespace MM1 {
namespace Game {
Character *SpellsParty::_destChar;
SpellsParty::SpellFn SpellsParty::SPELLS[SPELLS_COUNT] = {
// Cleric spells
cleric11_awaken,
cleric12_bless,
cleric13_blind,
cleric14_firstAid,
cleric15_light,
cleric16_powerCure,
cleric17_protectionFromFear,
cleric18_turnUndead,
cleric21_cureWounds,
cleric22_heroism,
cleric23_pain,
cleric24_protectionFromCold,
cleric25_protectionFromIce,
cleric26_protectionFromPoison,
cleric27_silence,
cleric28_suggestion,
cleric31_createFood,
cleric32_cureBlindness,
cleric33_cureParalysis,
cleric34_lastingLight,
cleric35_produceFlame,
cleric36_produceFrost,
cleric37_removeQuest,
cleric38_walkOnWater,
cleric41_cureDisease,
cleric42_neutralizePoison,
cleric43_protectionFromAcid,
cleric44_protectionFromElectricity,
cleric45_restoreAlignment,
cleric46_summonLightning,
cleric47_superHeroism,
cleric48_surface,
cleric51_deadlySwarm,
cleric52_dispelMagic,
cleric53_paralyze,
cleric54_removeCondition,
cleric55_restoreEnergy,
cleric61_moonRay,
cleric62_raiseDead,
cleric63_rejuvinate,
cleric64_stoneToFlesh,
cleric65_townPortal,
cleric71_divineIntervention,
cleric72_holyWord,
cleric73_protectionFromElements,
cleric74_resurrection,
cleric75_sunRay,
wizard11_awaken,
wizard12_detectMagic,
wizard13_energyBlast,
wizard14_flameArrow,
wizard15_leatherSkin,
wizard16_light,
wizard17_location,
wizard18_sleep,
wizard21_electricArrow,
wizard22_hypnotize,
wizard23_identifyMonster,
wizard24_jump,
wizard25_levitate,
wizard26_power,
wizard27_quickness,
wizard28_scare,
wizard31_fireball,
wizard32_fly,
wizard33_invisibility,
wizard34_lightningBolt,
wizard35_makeRoom,
wizard36_slow,
wizard37_weaken,
wizard38_web,
wizard41_acidArrow,
wizard42_coldBeam,
wizard43_feebleMind,
wizard44_freeze,
wizard45_guardDog,
wizard46_psychicProtection,
wizard47_shield,
wizard48_timeDistortion,
wizard51_acidRain,
wizard52_dispelMagic,
wizard53_fingerOfDeath,
wizard54_shelter,
wizard55_teleport,
wizard61_dancingSword,
wizard62_disintegration,
wizard63_etherialize,
wizard64_protectionFromMagic,
wizard65_rechargeItem,
wizard71_astralSpell,
wizard72_duplication,
wizard73_meteorShower,
wizard74_powerShield,
wizard75_prismaticLight
};
SpellResult SpellsParty::cast(uint spell, Character *destChar) {
assert(spell < SPELLS_COUNT);
_destChar = destChar;
return SPELLS[spell]();
}
bool SpellsParty::isInCombat() {
return g_events->isPresent("Combat");
}
SpellResult SpellsParty::cleric11_awaken() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
if (!(c._condition & BAD_CONDITION))
c._condition &= ~ASLEEP;
}
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric12_bless() {
g_globals->_activeSpells._s.bless++;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric13_blind() {
SpellsState &s = g_globals->_spellsState;
s._mmVal1++;
s._resistanceIndex = 7;
s._damage = BLINDED;
s._resistanceTypeOrTargetCount = static_cast<Resistance>((int)s._resistanceTypeOrTargetCount + 1);
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric14_firstAid() {
restoreHp(8);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric15_light() {
addLight(1);
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric16_powerCure() {
int totalHp = 0;
for (uint i = 0; i < g_globals->_currCharacter->_level._current; ++i)
totalHp += g_engine->getRandomNumber(10);
restoreHp(MIN(totalHp, 250));
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric17_protectionFromFear() {
g_globals->_activeSpells._s.fear =
MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric18_turnUndead() {
if (g_globals->_currCharacter->_alignment !=
g_globals->_currCharacter->_alignmentInitial)
// Cleric's current alignment differs from initial, so spell fails
return SR_FAILED;
g_globals->_combat->turnUndead();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric21_cureWounds() {
restoreHp(16);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric22_heroism() {
if (g_globals->_currCharacter->_alignment != _destChar->_alignment ||
_destChar->_level._current != _destChar->_level._base)
return SR_FAILED;
_destChar->_level._current = MIN(
(int)_destChar->_level._current + 2, 255);
restoreHp(6);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric23_pain() {
SpellsState &ss = g_globals->_spellsState;
ss._damage = getRandomNumber(6) + getRandomNumber(6);
ss._mmVal1++;
ss._resistanceTypeOrTargetCount++;
ss._resistanceIndex = 6;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric24_protectionFromCold() {
g_globals->_activeSpells._s.cold =
MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric25_protectionFromIce() {
g_globals->_activeSpells._s.fire =
MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric26_protectionFromPoison() {
g_globals->_activeSpells._s.poison =
MIN((int)g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric27_silence() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex = 7;
ss._damage = SILENCED;
ss._resistanceTypeOrTargetCount++;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric28_suggestion() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex = 6;
ss._damage = PARALYZED;
ss._resistanceTypeOrTargetCount++;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric31_createFood() {
if (_destChar->_food == MAX_FOOD) {
return SR_FAILED;
} else {
_destChar->_food = MIN(_destChar->_food + 6, MAX_FOOD);
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric32_cureBlindness() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
_destChar->_condition &= ~BLINDED;
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric33_cureParalysis() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
_destChar->_condition &= ~PARALYZED;
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric34_lastingLight() {
addLight(19);
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric35_produceFlame() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceTypeOrTargetCount++;
ss._resistanceIndex = 4;
ss._damage = getRandomNumber(6) +
getRandomNumber(6) + getRandomNumber(6);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric36_produceFrost() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex++;
ss._damage = getRandomNumber(6) +
getRandomNumber(6) + getRandomNumber(6);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric37_removeQuest() {
for (uint i = 0; i < g_globals->_party.size(); ++i)
g_globals->_party[i]._quest = 0;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric38_walkOnWater() {
g_globals->_activeSpells._s.walk_on_water = MIN(
(int)g_globals->_activeSpells._s.walk_on_water + 1, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric41_cureDisease() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
_destChar->_condition &= ~DISEASED;
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric42_neutralizePoison() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
_destChar->_condition &= ~POISONED;
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric43_protectionFromAcid() {
g_globals->_activeSpells._s.acid =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric44_protectionFromElectricity() {
g_globals->_activeSpells._s.electricity =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric45_restoreAlignment() {
_destChar->_alignment = _destChar->_alignmentInitial;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric46_summonLightning() {
g_globals->_combat->summonLightning();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric47_superHeroism() {
if (_destChar->_level._current != _destChar->_level._base)
return SR_FAILED;
_destChar->_level._current = MIN(
(int)_destChar->_level._current + 3, 255);
restoreHp(10);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric48_surface() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
if (map[Maps::MAP_FLAGS] & 4) {
return SR_FAILED;
} else {
maps._mapPos = Common::Point(map[Maps::MAP_SURFACE_X],
map[Maps::MAP_SURFACE_Y]);
maps.changeMap(map.dataWord(Maps::MAP_SURFACE_ID),
map[Maps::MAP_SURFACE_SECTION]);
return SR_SUCCESS_SILENT;
}
}
SpellResult SpellsParty::cleric51_deadlySwarm() {
SpellsState &ss = g_globals->_spellsState;
g_globals->_combat->resetDestMonster();
ss._mmVal1++;
ss._resistanceIndex = 0;
ss._damage = getRandomNumber(10) + getRandomNumber(10);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric52_dispelMagic() {
Maps::Map &map = *g_maps->_currentMap;
if (g_engine->getRandomNumber(100) >= map[Maps::MAP_DISPEL_THRESHOLD]) {
Common::fill(&g_globals->_activeSpells._arr[0],
&g_globals->_activeSpells._arr[18], 0);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
c.updateAttributes();
c.updateAC();
if (!(c._condition & BAD_CONDITION))
c._condition &= ~(BLINDED | SILENCED);
}
return SR_SUCCESS_DONE;
} else {
return SR_FAILED;
}
}
SpellResult SpellsParty::cleric53_paralyze() {
g_globals->_combat->paralyze();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric54_removeCondition() {
if (_destChar->_condition & BAD_CONDITION) {
return SR_FAILED;
} else {
_destChar->_condition = FINE;
if (!_destChar->_hpCurrent)
_destChar->_hpCurrent = 1;
restoreHp(1);
return SR_SUCCESS_DONE;
}
}
SpellResult SpellsParty::cleric55_restoreEnergy() {
if (_destChar->_level._current < _destChar->_level._base) {
_destChar->_level._current = MIN(
_destChar->_level._current + g_engine->getRandomNumber(5),
(int)_destChar->_level._base
);
return SR_SUCCESS_DONE;
} else {
return SR_FAILED;
}
}
SpellResult SpellsParty::cleric61_moonRay() {
SpellsState &ss = g_globals->_spellsState;
// Heal the party
int hp = getRandomNumber(10) + getRandomNumber(10) +
getRandomNumber(10);
for (uint i = 0; i < g_globals->_party.size(); ++i) {
Character &c = g_globals->_party[i];
restoreHp(c, hp);
}
// Damage the monsters
g_globals->_combat->resetDestMonster();
ss._damage = hp;
ss._mmVal1++;
ss._resistanceIndex = 5;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric62_raiseDead() {
if ((_destChar->_condition == ERADICATED) ||
(_destChar->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
return SR_FAILED;
int rnd = g_engine->getRandomNumber(100);
if (rnd == 100) {
// This is such a minute chance, why even have it?
Sound::sound(SOUND_3);
return SR_FAILED;
} else if (rnd > 90) {
return SR_FAILED;
}
if (_destChar->_condition == (BAD_CONDITION | DEAD | STONE))
_destChar->_condition = BAD_CONDITION | STONE;
else
_destChar->_condition = FINE;
_destChar->_hpCurrent = 1;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric63_rejuvinate() {
if (g_engine->getRandomNumber(100) < 75) {
_destChar->_age = MIN(_destChar->_age - g_engine->getRandomNumber(10),
200);
return SR_FAILED;
} else {
// Failed, increase the user's age
_destChar->_age = MIN(_destChar->_age + 10, 200);
return SR_FAILED;
}
}
SpellResult SpellsParty::cleric64_stoneToFlesh() {
if ((_destChar->_condition == ERADICATED) ||
(_destChar->_condition & (BAD_CONDITION | DEAD)) ==
(BAD_CONDITION | DEAD))
return SR_FAILED;
if (_destChar->_condition == (BAD_CONDITION | DEAD | STONE))
_destChar->_condition = BAD_CONDITION | DEAD;
else
_destChar->_condition = FINE;
_destChar->_hpCurrent = 1;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric65_townPortal() {
Sound::sound(SOUND_2);
InfoMessage msg(
STRING["spells.which_town"],
[](const Common::KeyState &keyState) {
switch (keyState.keycode) {
case Common::KEYCODE_ESCAPE:
g_events->focusedView()->close();
break;
case Common::KEYCODE_1:
case Common::KEYCODE_2:
case Common::KEYCODE_3:
case Common::KEYCODE_4:
case Common::KEYCODE_5:
{
Maps::Maps &maps = *g_maps;
int townIndex = keyState.keycode - Common::KEYCODE_1;
maps._mapPos.x = TownData::TOWN_MAP_X[townIndex];
maps._mapPos.y = TownData::TOWN_MAP_Y[townIndex];
maps.changeMap(
TownData::TOWN_MAP_ID1[townIndex] |
(TownData::TOWN_MAP_ID1[townIndex] << 8),
1);
g_events->close();
return;
}
default:
break;
}
}
);
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric71_divineIntervention() {
return g_globals->_combat->divineIntervention() ?
SR_SUCCESS_DONE : SR_FAILED;
}
SpellResult SpellsParty::cleric72_holyWord() {
Character &c = *g_globals->_currCharacter;
if (c._alignment != c._alignmentInitial)
return SR_FAILED;
g_globals->_combat->holyWord();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::cleric73_protectionFromElements() {
int amount = g_globals->_currCharacter->_level._current + 25;
for (int i = 0; i < 6; ++i)
g_globals->_activeSpells._arr[i] = amount;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric74_resurrection() {
if (_destChar->_condition == ERADICATED)
return SR_FAILED;
if (_destChar->_age < 10 || _destChar->_age > 200)
_destChar->_age = 200;
if (g_engine->getRandomNumber(100) > 75)
return SR_FAILED;
_destChar->_endurance._base = MAX((int)_destChar->_endurance._base - 1, 1);
_destChar->_condition = FINE;
restoreHp(1);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::cleric75_sunRay() {
SpellsState &ss = g_globals->_spellsState;
ss._damage = getRandomNumber(51) + 49;
ss._mmVal1++;
ss._resistanceIndex++;
ss._resistanceTypeOrTargetCount = RESISTANCE_FIRE;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard12_detectMagic() {
g_events->replaceView("DetectMagic");
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard13_energyBlast() {
SpellsState &ss = g_globals->_spellsState;
int damage = 0;
for (int i = 0; i < g_globals->_currCharacter->_level._current; ++i)
damage += getRandomNumber(4);
ss._damage = MIN(damage, 255);
ss._resistanceIndex = 5;
ss._resistanceTypeOrTargetCount++;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard14_flameArrow() {
SpellsState &ss = g_globals->_spellsState;
ss._damage = getRandomNumber(6);
ss._mmVal1++;
ss._resistanceIndex = 1;
ss._resistanceTypeOrTargetCount++;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard15_leatherSkin() {
g_globals->_activeSpells._s.leather_skin = g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard17_location() {
g_events->replaceView("Location");
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard18_sleep() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex = 8;
ss._resistanceTypeOrTargetCount = RESISTANCE_FEAR;
ss._damage = 16;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard21_electricArrow() {
SpellsState &ss = g_globals->_spellsState;
ss._damage = getRandomNumber(6) + getRandomNumber(6);
ss._mmVal1++;
ss._resistanceTypeOrTargetCount++;
ss._resistanceIndex = 2;
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard23_identifyMonster() {
g_globals->_combat->identifyMonster();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard24_jump() {
Maps::Maps &maps = *g_maps;
Maps::Map &map = *maps._currentMap;
if ((maps._currentWalls & maps._forwardMask) != 0)
return SR_FAILED;
if ((map._states[maps._mapOffset] & maps._forwardMask & 0x55) != 0)
return SR_FAILED;
if ((map._walls[maps._mapOffset + maps._forwardOffset] &
maps._forwardMask) != 0)
return SR_FAILED;
if ((map._states[maps._mapOffset + maps._forwardOffset]
& maps._forwardMask & 0x55) != 0)
return SR_FAILED;
// The delta will be two steps in the facing direction.
// Ensure that that doesn't end up outside the map bounds
Common::Point delta = maps.getMoveDelta(maps._forwardMask);
delta.x *= 2;
delta.y *= 2;
Common::Point newPos = maps._mapPos + delta;
if (newPos.x < 0 || newPos.y < 0 ||
newPos.x >= MAP_W || newPos.y >= MAP_H)
return SR_FAILED;
// Move the two steps
g_maps->step(delta);
g_events->send("Game", GameMessage("UPDATE"));
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard25_levitate() {
g_globals->_activeSpells._s.levitate =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard26_power() {
g_globals->_currCharacter->_might._current += getRandomNumber(4);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard27_quickness() {
g_globals->_currCharacter->_speed._current += getRandomNumber(4);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard28_scare() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex = 7;
ss._resistanceTypeOrTargetCount++;
ss._damage = 1;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard31_fireball() {
g_globals->_combat->fireball();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard32_fly() {
g_events->addView("Fly");
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard33_invisibility() {
g_globals->_activeSpells._s.invisbility++;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard34_lightningBolt() {
g_globals->_combat->lightningBolt();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard35_makeRoom() {
g_globals->_combat->makeRoom();
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard36_slow() {
g_globals->_combat->slow();
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard37_weaken() {
g_globals->_combat->weaken();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard38_web() {
return g_globals->_combat->web() ? SR_SUCCESS_SILENT : SR_FAILED;
}
SpellResult SpellsParty::wizard41_acidArrow() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceTypeOrTargetCount++;
ss._resistanceIndex = 3;
ss._damage += getRandomNumber(10) +
getRandomNumber(10) + getRandomNumber(10);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard42_coldBeam() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceTypeOrTargetCount++;
ss._resistanceIndex = 4;
ss._damage = getRandomNumber(10) + getRandomNumber(10) +
getRandomNumber(10) + getRandomNumber(10);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard43_feebleMind() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1++;
ss._resistanceIndex = 0;
ss._resistanceTypeOrTargetCount++;
ss._damage = 8;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard44_freeze() {
SpellsState &ss = g_globals->_spellsState;
ss._mmVal1 = 0;
ss._resistanceIndex = 6;
ss._resistanceTypeOrTargetCount++;
ss._damage = 128;
g_globals->_combat->iterateMonsters1();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard45_guardDog() {
g_globals->_activeSpells._s.guard_dog =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard46_psychicProtection() {
g_globals->_activeSpells._s.psychic_protection =
g_globals->_currCharacter->_level._current;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard47_shield() {
g_globals->_activeSpells._s.shield++;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard48_timeDistortion() {
Maps::Map &map = *g_maps->_currentMap;
if (getRandomNumber(100) < map[Maps::MAP_DISPEL_THRESHOLD])
return SR_FAILED;
// End combat by closing the combat view
g_events->focusedView()->close();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard51_acidRain() {
return g_globals->_combat->acidRain() ? SR_SUCCESS_SILENT : SR_FAILED;
}
SpellResult SpellsParty::wizard53_fingerOfDeath() {
g_globals->_combat->fingerOfDeath();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard54_shelter() {
if (g_maps->_currentState & 8)
return SR_FAILED;
Game::Rest::execute();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard55_teleport() {
g_events->replaceView("Teleport");
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard61_dancingSword() {
SpellsState &ss = g_globals->_spellsState;
g_globals->_combat->resetDestMonster();
ss._mmVal1 = 0;
ss._resistanceIndex = 0;
ss._damage = getRandomNumber(30);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard62_disintegration() {
g_globals->_combat->disintegration();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard63_etherialize() {
g_events->draw();
g_maps->_currentState = 0;
g_maps->step(Common::Point(1, 0));
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard64_protectionFromMagic() {
g_globals->_activeSpells._s.magic =
MIN(g_globals->_currCharacter->_level._current + 20, 255);
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard65_rechargeItem() {
g_events->replaceView("RechargeItem");
return SR_FAILED;
}
SpellResult SpellsParty::wizard71_astralSpell() {
Maps::Maps &maps = *g_maps;
maps._mapPos.x = 7;
maps._mapPos.y = 0;
maps.changeMap(0xb1a, 3);
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard72_duplication() {
g_events->replaceView("Duplication");
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard73_meteorShower() {
SpellsState &ss = g_globals->_spellsState;
g_globals->_combat->resetDestMonster();
ss._mmVal1++;
ss._resistanceIndex = 5;
ss._damage = MIN((int)getRandomNumber(120) +
(int)g_globals->_currCharacter->_level._current, 120);
g_globals->_combat->iterateMonsters2();
return SR_SUCCESS_SILENT;
}
SpellResult SpellsParty::wizard74_powerShield() {
g_globals->_activeSpells._s.power_shield++;
return SR_SUCCESS_DONE;
}
SpellResult SpellsParty::wizard75_prismaticLight() {
SpellsState &ss = g_globals->_spellsState;
g_globals->_combat->resetDestMonster();
if (getRandomNumber(100) < 20)
return SR_FAILED;
if (ss._mmVal1 < 50) {
uint count = getRandomNumber(4);
ss._damage <<= count;
g_globals->_combat->iterateMonsters2();
} else {
uint count = getRandomNumber(8);
ss._damage <<= count;
g_globals->_combat->iterateMonsters1();
}
return SR_SUCCESS_SILENT;
}
void SpellsParty::restoreHp(uint16 hp) {
restoreHp(*_destChar, hp);
}
void SpellsParty::restoreHp(Character &c, uint16 hp) {
c._hpCurrent = MIN((int)(c._hpCurrent + hp), (int)c._hpMax);
if (!(c._condition & BAD_CONDITION))
c._condition &= ~UNCONSCIOUS;
}
void SpellsParty::addLight(int amount) {
g_globals->_activeSpells._s.light = MIN((int)g_globals->_activeSpells._s.light + amount, 255);
g_events->send("Game", GameMessage("UPDATE"));
}
void SpellsParty::display(const InfoMessage &msg) {
g_globals->_combat->displaySpellResult(msg);
}
} // namespace Game
} // namespace MM1
} // namespace MM