Initial commit
This commit is contained in:
50
engines/mm/mm1/game/arenko.cpp
Normal file
50
engines/mm/mm1/game/arenko.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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/arenko.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void Arenko::giveGold() {
|
||||
g_globals->_treasure.setGold((getRandomNumber(8) + 8) * 256);
|
||||
g_maps->clearSpecial();
|
||||
g_events->addAction(KEYBIND_SEARCH);
|
||||
}
|
||||
|
||||
void Arenko::giveGems() {
|
||||
g_globals->_treasure.setGems(getRandomNumber(50) + 200);
|
||||
g_maps->clearSpecial();
|
||||
g_events->addAction(KEYBIND_SEARCH);
|
||||
}
|
||||
|
||||
void Arenko::giveItem() {
|
||||
g_globals->_treasure._items[2] = getRandomNumber(22) + 196;
|
||||
g_maps->clearSpecial();
|
||||
g_events->addAction(KEYBIND_SEARCH);
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
42
engines/mm/mm1/game/arenko.h
Normal file
42
engines/mm/mm1/game/arenko.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_ARENKO_H
|
||||
#define MM1_GAME_ARENKO_H
|
||||
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Arenko : public GameLogic {
|
||||
public:
|
||||
void giveGold();
|
||||
void giveGems();
|
||||
void giveItem();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
82
engines/mm/mm1/game/arrested.cpp
Normal file
82
engines/mm/mm1/game/arrested.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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/arrested.h"
|
||||
#include "mm/mm1/maps/map04.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void Arrested::attack() {
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
int monsterCount = getRandomNumber(5);
|
||||
g_events->close();
|
||||
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < monsterCount; ++i)
|
||||
enc.addMonster(6, 10);
|
||||
|
||||
enc._manual = true;
|
||||
enc._levelIndex = 64;
|
||||
enc._encounterType = Game::FORCE_SURPRISED;
|
||||
enc.execute();
|
||||
}
|
||||
|
||||
void Arrested::bribe() {
|
||||
if (getRandomNumber(10) == 10) {
|
||||
// Success
|
||||
g_events->close();
|
||||
} else {
|
||||
// 8 year sentence for attempted bribery
|
||||
surrender(8);
|
||||
}
|
||||
}
|
||||
|
||||
void Arrested::run() {
|
||||
g_events->close();
|
||||
g_globals->_currCharacter = &g_globals->_party[
|
||||
getRandomNumber(g_globals->_party.size()) - 1
|
||||
];
|
||||
g_globals->_currCharacter->_condition = ERADICATED;
|
||||
|
||||
static_cast<MM1::Maps::Map04 *>(g_maps->_currentMap)->special08();
|
||||
}
|
||||
|
||||
void Arrested::surrender(int numYears) {
|
||||
g_events->close();
|
||||
|
||||
// Characters are aged by their prision sentence, and their gold halved
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
|
||||
if ((int)c._age + numYears < 256)
|
||||
c._age += numYears;
|
||||
c._gold /= 2;
|
||||
}
|
||||
|
||||
(*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] = 0;
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
45
engines/mm/mm1/game/arrested.h
Normal file
45
engines/mm/mm1/game/arrested.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAMES_ARRESTED_H
|
||||
#define MM1_GAMES_ARRESTED_H
|
||||
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Arrested : public GameLogic {
|
||||
protected:
|
||||
void attack();
|
||||
void bribe();
|
||||
void run();
|
||||
void surrender(int numYears = 2);
|
||||
|
||||
Arrested() {}
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
1674
engines/mm/mm1/game/combat.cpp
Normal file
1674
engines/mm/mm1/game/combat.cpp
Normal file
File diff suppressed because it is too large
Load Diff
351
engines/mm/mm1/game/combat.h
Normal file
351
engines/mm/mm1/game/combat.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_COMBAT_H
|
||||
#define MM1_GAME_COMBAT_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/party.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
#include "mm/mm1/game/encounter.h"
|
||||
#include "mm/mm1/game/monster_touch.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Combat : public MonsterTouch {
|
||||
protected:
|
||||
Common::Array<Line> _message;
|
||||
int _monstersCount = 0;
|
||||
Monster *_monsterP;
|
||||
bool _treasureFlags[MAX_PARTY_SIZE];
|
||||
int _val1;
|
||||
int _roundNum;
|
||||
int _monsterIndex, _currentChar;
|
||||
bool _allowFight, _allowShoot, _allowCast, _allowAttack;
|
||||
byte _val6, _val7;
|
||||
int _partyIndex, _val9, _monsterShootingCtr;
|
||||
int _activeMonsterNum;
|
||||
int _destCharCtr;
|
||||
int _destAC;
|
||||
int _numberOfTimes;
|
||||
int _attackerLevel;
|
||||
int _handicapThreshold, _handicapParty;
|
||||
int _handicapMonsters, _handicapDelta;
|
||||
int _attackersCount;
|
||||
int _totalExperience;
|
||||
Common::String _monsterName;
|
||||
bool _monstersResistSpells;
|
||||
bool _monstersRegenerate;
|
||||
AttributePair _attackAttr1, _attackAttr2;
|
||||
int _timesHit;
|
||||
bool _isShooting;
|
||||
Common::String _attackMessage;
|
||||
enum Handicap {
|
||||
HANDICAP_EVEN = 0, HANDICAP_PARTY = 1,
|
||||
HANDICAP_MONSTER = 2
|
||||
};
|
||||
Handicap _handicap = HANDICAP_EVEN;
|
||||
enum Mode {
|
||||
SELECT_OPTION, FIGHT_WHICH, DEFEATED_MONSTERS,
|
||||
NEXT_ROUND, MONSTER_ADVANCES, MONSTERS_AFFECTED,
|
||||
MONSTER_FLEES, MONSTER_WANDERS, MONSTER_SPELL,
|
||||
CHAR_ATTACKS, MONSTER_ATTACK, INFILTRATION,
|
||||
WAITS_FOR_OPENING, SPELL_RESULT, NO_EFFECT
|
||||
};
|
||||
Mode _mode = SELECT_OPTION;
|
||||
|
||||
int _destMonsterNum = 0;
|
||||
int _monstersDestroyedCtr = 0;
|
||||
bool _turnUndeadUsed = false;
|
||||
bool _divineInterventionUsed = false;
|
||||
size_t _spellMonsterCount = 0;
|
||||
|
||||
int _monsterAttackStyle = -1;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Combat();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Combat();
|
||||
|
||||
/**
|
||||
* Sets the combat display mode
|
||||
*/
|
||||
virtual void setMode(Mode newMode) = 0;
|
||||
|
||||
/**
|
||||
* Does final cleanup when combat is done
|
||||
*/
|
||||
virtual void combatDone();
|
||||
|
||||
/**
|
||||
* Subtracts the damage from the character, making
|
||||
* them unconscious or die if needed
|
||||
*/
|
||||
Common::String subtractDamageFromChar() override;
|
||||
|
||||
/**
|
||||
* Clear all the combat variables
|
||||
*/
|
||||
void clear();
|
||||
|
||||
void loadMonsters();
|
||||
|
||||
/**
|
||||
* Sets the _monsterIndex to the index of
|
||||
* _monsterP in the monster list
|
||||
*/
|
||||
void monsterIndexOf();
|
||||
|
||||
/**
|
||||
* Sets _monsterP to point to a specified monster
|
||||
*/
|
||||
void monsterSetPtr(int monsterNum);
|
||||
|
||||
/**
|
||||
* Sets up the flags for whether each character
|
||||
* in the party can attack from their position.
|
||||
*/
|
||||
void setupCanAttacks();
|
||||
|
||||
/**
|
||||
* Chooses the starting character to
|
||||
*/
|
||||
void setupAttackersCount();
|
||||
|
||||
/**
|
||||
* Checks whether the third party member
|
||||
* is blocked by a left wall
|
||||
*/
|
||||
void checkLeftWall();
|
||||
|
||||
/**
|
||||
* Checks whether the fourth party member
|
||||
* is blocked by a right wall
|
||||
*/
|
||||
void checkRightWall();
|
||||
|
||||
/**
|
||||
* Sets up the handicap for the encounter
|
||||
*/
|
||||
void setupHandicap();
|
||||
|
||||
/*------- Inherited virtual methods ------*/
|
||||
|
||||
/**
|
||||
* Get the monster index
|
||||
*/
|
||||
int getMonsterIndex() const override {
|
||||
return _monsterIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a monster can cast certain spells
|
||||
*/
|
||||
bool canMonsterCast() const override;
|
||||
|
||||
/**
|
||||
* Dispels any effects on the party
|
||||
*/
|
||||
void dispelParty() override;
|
||||
|
||||
void removeMonster() override;
|
||||
|
||||
/*------- combat execution ------*/
|
||||
|
||||
/**
|
||||
* Main combat loop that selects the next party
|
||||
* member or monster to take their turn
|
||||
*/
|
||||
void combatLoop(bool checkMonstersFirst = false);
|
||||
|
||||
/**
|
||||
* Select treasure for a defeated monster
|
||||
*/
|
||||
void selectTreasure();
|
||||
void selectTreasure2(int index);
|
||||
|
||||
/**
|
||||
* Moves to the next round
|
||||
*/
|
||||
void nextRound();
|
||||
void nextRound2();
|
||||
void nextRound3();
|
||||
|
||||
/**
|
||||
* Update the _highestLevel to the remaining
|
||||
* active members of the party
|
||||
*/
|
||||
void updateHighestLevel();
|
||||
|
||||
/**
|
||||
* Calculate a monster action
|
||||
*/
|
||||
void monsterAction();
|
||||
|
||||
/**
|
||||
* Check if monster is mindless and wandering
|
||||
*/
|
||||
bool checkMonsterSpells();
|
||||
|
||||
/**
|
||||
* Check other monster actions
|
||||
*/
|
||||
void checkMonsterActions();
|
||||
|
||||
void defeatedMonsters();
|
||||
void setTreasure();
|
||||
void clearArrays();
|
||||
bool moveMonsters();
|
||||
void monsterAdvances(uint index);
|
||||
bool monsterChanges();
|
||||
void proc2();
|
||||
void checkParty();
|
||||
|
||||
/**
|
||||
* Attack a monster
|
||||
*/
|
||||
void fightMonster(int monsterNum);
|
||||
void shootMonster(int monsterNum);
|
||||
void attackMonsterPhysical();
|
||||
void attackMonsterShooting();
|
||||
void attackMonster(int monsterNum);
|
||||
|
||||
/**
|
||||
* Adds attack damage message for character hitting monster
|
||||
*/
|
||||
void addAttackDamage();
|
||||
|
||||
/**
|
||||
* Updates a monster's status
|
||||
*/
|
||||
void updateMonsterStatus();
|
||||
|
||||
/**
|
||||
* Handles a monster touch action, if any
|
||||
*/
|
||||
bool monsterTouch(Common::String &line);
|
||||
|
||||
/**
|
||||
* Handles monster atttack logic
|
||||
*/
|
||||
void monsterAttackRandom();
|
||||
void monsterAttackInner();
|
||||
|
||||
/**
|
||||
* Handles monster shooting a character
|
||||
*/
|
||||
void monsterAttackShooting();
|
||||
|
||||
/**
|
||||
* Selects monster to attack
|
||||
*/
|
||||
void selectMonsterTarget();
|
||||
|
||||
|
||||
/**
|
||||
* Attack option
|
||||
*/
|
||||
void attack();
|
||||
|
||||
/**
|
||||
* Block option
|
||||
*/
|
||||
void block();
|
||||
|
||||
/**
|
||||
* Cast option
|
||||
*/
|
||||
void cast();
|
||||
|
||||
/**
|
||||
* Exchange current character with another
|
||||
*/
|
||||
void exchangeWith(int charNum);
|
||||
|
||||
/**
|
||||
* Use option
|
||||
*/
|
||||
void use();
|
||||
|
||||
/**
|
||||
* Retreat option
|
||||
*/
|
||||
void retreat();
|
||||
|
||||
/**
|
||||
* Called to remove any dead monsters
|
||||
*/
|
||||
void removeDeadMonsters();
|
||||
|
||||
private:
|
||||
void spellFailed();
|
||||
void destroyMonster();
|
||||
bool monsterLevelThreshold() const;
|
||||
void iterateMonsters1Inner();
|
||||
void iterateMonsters2Inner();
|
||||
void characterDone();
|
||||
void summonLightning2();
|
||||
void fireball2();
|
||||
void levelAdjust();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Display a combat spell's result
|
||||
*/
|
||||
virtual void displaySpellResult(const InfoMessage &msg) = 0;
|
||||
|
||||
void iterateMonsters1();
|
||||
void iterateMonsters2();
|
||||
void resetDestMonster();
|
||||
|
||||
// Cleric spells that need access to internal fields
|
||||
void turnUndead();
|
||||
void summonLightning();
|
||||
void paralyze();
|
||||
bool divineIntervention();
|
||||
void holyWord();
|
||||
|
||||
// Wizard spells that need access to internal fields
|
||||
void identifyMonster();
|
||||
void fireball();
|
||||
void lightningBolt();
|
||||
void makeRoom();
|
||||
void slow();
|
||||
void weaken();
|
||||
bool web();
|
||||
bool acidRain();
|
||||
void fingerOfDeath();
|
||||
void disintegration();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
67
engines/mm/mm1/game/detect_magic.cpp
Normal file
67
engines/mm/mm1/game/detect_magic.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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/detect_magic.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void DetectMagic::getMagicStrings() {
|
||||
Inventory &inv = g_globals->_currCharacter->_backpack;
|
||||
for (uint i = 0; i < inv.size(); ++i) {
|
||||
int itemId = inv[i]._id;
|
||||
bool flag = false;
|
||||
if (itemId < 12)
|
||||
flag = false;
|
||||
else if (itemId < 61)
|
||||
flag = true;
|
||||
else if (itemId < 66)
|
||||
flag = false;
|
||||
else if (itemId < 86)
|
||||
flag = true;
|
||||
else if (itemId < 93)
|
||||
flag = false;
|
||||
else if (itemId < 121)
|
||||
flag = true;
|
||||
else if (itemId < 128)
|
||||
flag = false;
|
||||
else if (itemId < 156)
|
||||
flag = true;
|
||||
else if (itemId < 158)
|
||||
flag = false;
|
||||
else if (itemId < 255)
|
||||
flag = true;
|
||||
else
|
||||
flag = false;
|
||||
|
||||
if (flag) {
|
||||
_strings[i] = Common::String::format("Y (%d)", inv[i]._charges);
|
||||
} else {
|
||||
_strings[i] = "N";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
46
engines/mm/mm1/game/detect_magic.h
Normal file
46
engines/mm/mm1/game/detect_magic.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_DETECT_MAGIC_H
|
||||
#define MM1_GAME_DETECT_MAGIC_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class DetectMagic {
|
||||
protected:
|
||||
Common::String _strings[INVENTORY_COUNT];
|
||||
|
||||
/**
|
||||
* Gets the magic flags
|
||||
*/
|
||||
void getMagicStrings();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
53
engines/mm/mm1/game/duplication.cpp
Normal file
53
engines/mm/mm1/game/duplication.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/duplication.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
bool Duplication::duplicate(Character &c, Inventory &inv, int itemIndex) {
|
||||
if (c._backpack.full())
|
||||
// No space to duplicate
|
||||
return false;
|
||||
|
||||
if (getRandomNumber(100) == 100) {
|
||||
// OMG: The original seriously had this fringe
|
||||
// case that happens so rarely
|
||||
inv.removeAt(itemIndex); // Break item
|
||||
return false;
|
||||
|
||||
} else if (inv[itemIndex]._id >= 230) {
|
||||
// Item range that can't be duplicated
|
||||
return false;
|
||||
|
||||
} else {
|
||||
// Add a copy of the item
|
||||
c._backpack.add(inv[itemIndex]._id, inv[itemIndex]._charges);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
46
engines/mm/mm1/game/duplication.h
Normal file
46
engines/mm/mm1/game/duplication.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_DUPLICATION_H
|
||||
#define MM1_GAME_DUPLICATION_H
|
||||
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/items.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Duplication : public GameLogic {
|
||||
protected:
|
||||
/**
|
||||
* Charge a given item
|
||||
* @returns Returns true if the spell succeeded
|
||||
*/
|
||||
bool duplicate(Character &c, Inventory &inv, int itemIndex);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
186
engines/mm/mm1/game/encounter.cpp
Normal file
186
engines/mm/mm1/game/encounter.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* 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/encounter.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void Encounter::execute() {
|
||||
if (!g_globals->_encountersOn)
|
||||
return;
|
||||
|
||||
Maps::Map &map = *g_maps->_currentMap;
|
||||
int comp, maxRand, maxVal;
|
||||
const Monster *monsterP;
|
||||
_bribeFleeCtr = _bribeAlignmentCtr = 0;
|
||||
_alignmentsChanged = 0;
|
||||
|
||||
// In manual mode, the scripts have already set up
|
||||
// a list of monsters to use
|
||||
if (!_manual) {
|
||||
_monsterSummaries.clear();
|
||||
_levelIndex = 0;
|
||||
}
|
||||
|
||||
_totalLevels = _highestLevel = 0;
|
||||
_levelOffset = _monsterImgNum = _maxLevelForImg = _fleeThreshold = 0;
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
const Character &c = g_globals->_party[i];
|
||||
_highestLevel = MAX(_highestLevel, (int)c._level._current);
|
||||
|
||||
if (!(c._condition & (BAD_CONDITION | PARALYZED | UNCONSCIOUS)))
|
||||
_totalLevels = MIN(_totalLevels + c._level._current, 255);
|
||||
}
|
||||
|
||||
_totalLevels /= 2;
|
||||
_highestLevel /= 2;
|
||||
|
||||
bool firstLoop = !_manual;
|
||||
_manual = false;
|
||||
|
||||
while (firstLoop || _levelIndex < _totalLevels) {
|
||||
randomAdjust();
|
||||
firstLoop = false;
|
||||
|
||||
maxRand = _levelOffset + _highestLevel;
|
||||
if (maxRand >= 2) {
|
||||
int highestRand = map[Maps::MAP_33];
|
||||
maxRand = MIN(maxRand, highestRand);
|
||||
comp = getRandomNumber(maxRand);
|
||||
} else {
|
||||
comp = 1;
|
||||
}
|
||||
|
||||
maxVal = map[Maps::MAP_47];
|
||||
if (comp < maxVal) {
|
||||
comp = MIN(maxVal, 10);
|
||||
}
|
||||
|
||||
assert(_monsterSummaries.size() < MAX_COMBAT_MONSTERS);
|
||||
_monsterNum = getRandomNumber(16);
|
||||
_monsterSummaries.push_back(MonsterSummary(_monsterNum, comp));
|
||||
|
||||
_monsterLevel = comp;
|
||||
_levelIndex += comp;
|
||||
|
||||
if (_monsterSummaries.size() < MAX_COMBAT_MONSTERS) {
|
||||
if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS])
|
||||
goto exit_loop;
|
||||
|
||||
monsterP = getMonster();
|
||||
maxVal = getRandomNumber(monsterP->_count);
|
||||
|
||||
for (int i = 0; i < maxVal; ++i) {
|
||||
assert(!_monsterSummaries.empty());
|
||||
_monsterSummaries.push_back(_monsterSummaries.back());
|
||||
_levelIndex += _monsterSummaries.back()._level;
|
||||
|
||||
if (_monsterSummaries.size() >= MAX_COMBAT_MONSTERS)
|
||||
goto exit_loop;
|
||||
|
||||
if (_monsterSummaries.size() >= map[Maps::MAP_MAX_MONSTERS])
|
||||
goto exit_loop;
|
||||
}
|
||||
} else {
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
_monsterList.clear();
|
||||
|
||||
for (uint i = 0; i < _monsterSummaries.size(); ++i) {
|
||||
maxVal = (_monsterSummaries[i]._level - 1) * 16 +
|
||||
_monsterSummaries[i]._num;
|
||||
|
||||
if (_monsterSummaries[i]._level < 1 || _monsterSummaries[i]._level > 12
|
||||
|| maxVal >= 196) {
|
||||
_monsterSummaries[i]._level = 10;
|
||||
_monsterSummaries[i]._num = getRandomNumber(15);
|
||||
}
|
||||
|
||||
// Add monster details to list
|
||||
_monsterLevel = _monsterSummaries[i]._level;
|
||||
const Monster &srcMons = (*g_globals->_monsters)[_monsterSummaries[i]._num];
|
||||
_monsterList.push_back(srcMons);
|
||||
Monster &mons = _monsterList.back();
|
||||
mons._level = _monsterSummaries[i]._level;
|
||||
|
||||
if (_monsterLevel > _maxLevelForImg) {
|
||||
_maxLevelForImg = _monsterLevel;
|
||||
_fleeThreshold = mons._fleeThreshold;
|
||||
_monsterImgNum = mons._imgNum;
|
||||
}
|
||||
}
|
||||
|
||||
g_events->addView("Encounter");
|
||||
}
|
||||
|
||||
void Encounter::randomAdjust() {
|
||||
int rval = getRandomNumber(100);
|
||||
_levelOffset = 0;
|
||||
|
||||
if (rval < 51) {
|
||||
} else if (rval < 71)
|
||||
_levelOffset += 1;
|
||||
else if (rval < 86)
|
||||
_levelOffset += 2;
|
||||
else if (rval < 96)
|
||||
_levelOffset += 3;
|
||||
else
|
||||
_levelOffset += 4;
|
||||
}
|
||||
|
||||
const Monster *Encounter::getMonster() {
|
||||
assert(_monsterNum > 0 && _monsterLevel > 0);
|
||||
return &(*g_globals->_monsters)[_monsterNum + ((_monsterLevel - 1) * 16)];
|
||||
}
|
||||
|
||||
bool Encounter::checkSurroundParty() const {
|
||||
return getRandomNumber(100) > _fleeThreshold;
|
||||
}
|
||||
|
||||
void Encounter::changeCharAlignment(Alignment align) {
|
||||
if (g_globals->_currCharacter->_alignment != align) {
|
||||
g_globals->_currCharacter->_alignment = align;
|
||||
++_alignmentsChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void Encounter::clearMonsters() {
|
||||
_monsterSummaries.clear();
|
||||
}
|
||||
|
||||
void Encounter::addMonster(byte id, byte level) {
|
||||
_monsterSummaries.push_back(MonsterSummary(id, level));
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
96
engines/mm/mm1/game/encounter.h
Normal file
96
engines/mm/mm1/game/encounter.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_ENCOUNTER_H
|
||||
#define MM1_GAME_ENCOUNTER_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
#define MAX_COMBAT_MONSTERS 15
|
||||
|
||||
enum EncounterType {
|
||||
FORCE_SURPRISED = -1, NORMAL_SURPRISED = 0, NORMAL_ENCOUNTER = 1
|
||||
};
|
||||
|
||||
class Encounter : public GameLogic {
|
||||
private:
|
||||
int _levelOffset = 0;
|
||||
int _maxLevelForImg = 0;
|
||||
int _monsterLevel = 0;
|
||||
int _totalLevels = 0;
|
||||
int _monsterNum = 0;
|
||||
struct MonsterSummary {
|
||||
byte _num;
|
||||
byte _level;
|
||||
MonsterSummary() : _num(0), _level(0) {}
|
||||
MonsterSummary(byte num, byte level) : _num(num), _level(level) {}
|
||||
};
|
||||
Common::Array<MonsterSummary> _monsterSummaries;
|
||||
|
||||
void randomAdjust();
|
||||
const Monster *getMonster();
|
||||
public:
|
||||
Common::Array<Monster> _monsterList;
|
||||
int _bribeAlignmentCtr = 0, _bribeFleeCtr = 0;
|
||||
int _alignmentsChanged = 0;
|
||||
int _monsterImgNum = 0;
|
||||
int _highestLevel = 0;
|
||||
EncounterType _encounterType = NORMAL_SURPRISED;
|
||||
byte _fleeThreshold = 0;
|
||||
bool _manual = false;
|
||||
int _levelIndex = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Start an encounter
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Chooses whether an encounter can be fled
|
||||
*/
|
||||
bool checkSurroundParty() const;
|
||||
|
||||
void changeCharAlignment(Alignment align);
|
||||
|
||||
/**
|
||||
* Clears the monster list
|
||||
*/
|
||||
void clearMonsters();
|
||||
|
||||
/**
|
||||
* Adds a monster to the monster list
|
||||
*/
|
||||
void addMonster(byte id, byte level);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
259
engines/mm/mm1/game/equip_remove.cpp
Normal file
259
engines/mm/mm1/game/equip_remove.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
/* 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/equip_remove.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
bool EquipRemove::equipItem(int index, Common::Point &textPos, Common::String &equipError) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
uint itemId = c._backpack[index]._id;
|
||||
uint charges = c._backpack[index]._charges;
|
||||
|
||||
int classBit = 0;
|
||||
textPos.x = 0;
|
||||
|
||||
switch (c._class) {
|
||||
case KNIGHT:
|
||||
classBit = KNIGHT_BIT;
|
||||
break;
|
||||
case PALADIN:
|
||||
classBit = PALADIN_BIT;
|
||||
break;
|
||||
case ARCHER:
|
||||
classBit = ARCHER_BIT;
|
||||
break;
|
||||
case CLERIC:
|
||||
classBit = CLERIC_BIT;
|
||||
break;
|
||||
case SORCERER:
|
||||
classBit = SORCERER_BIT;
|
||||
break;
|
||||
case ROBBER:
|
||||
classBit = ROBBER_BIT;
|
||||
break;
|
||||
default:
|
||||
equipError = STRING["dialogs.character.wrong_class"];
|
||||
break;
|
||||
}
|
||||
|
||||
g_globals->_items.getItem(itemId);
|
||||
const Item &item = g_globals->_currItem;
|
||||
|
||||
if (equipError.empty() && (item._disablements & classBit))
|
||||
equipError = STRING["dialogs.character.wrong_class"];
|
||||
if (equipError.empty()) {
|
||||
int alignBit = 0;
|
||||
switch (c._alignment) {
|
||||
case GOOD:
|
||||
alignBit = GOOD_BIT;
|
||||
break;
|
||||
case NEUTRAL:
|
||||
alignBit = NEUTRAL_BIT;
|
||||
break;
|
||||
case EVIL:
|
||||
alignBit = EVIL_BIT;
|
||||
break;
|
||||
default:
|
||||
equipError = STRING["dialogs.character.wrong_alignment"];
|
||||
break;
|
||||
}
|
||||
|
||||
if ((item._disablements & alignBit) && alignBit != NEUTRAL_BIT)
|
||||
equipError = STRING["dialogs.character.wrong_alignment"];
|
||||
}
|
||||
|
||||
if (equipError.empty()) {
|
||||
if (item._constBonus_id == IS_EQUIPPABLE) {
|
||||
equipError = STRING["dialogs.character.not_equipped"];
|
||||
textPos.x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (equipError.empty()) {
|
||||
if (isWeapon(itemId)) {
|
||||
if (c._equipped.hasWeapon() || c._equipped.hasTwoHanded())
|
||||
equipError = STRING["dialogs.character.have_weapon"];
|
||||
} else if (isMissile(itemId)) {
|
||||
if (c._equipped.hasMissile()) {
|
||||
equipError = STRING["dialogs.character.have_missile"];
|
||||
textPos.x = 3;
|
||||
}
|
||||
} else if (isTwoHanded(itemId)) {
|
||||
if (c._equipped.hasShield()) {
|
||||
equipError = STRING["dialogs.character.cannot_with_shield"];
|
||||
textPos.x = 7;
|
||||
} else if (c._equipped.hasWeapon()) {
|
||||
equipError = STRING["dialogs.character.have_weapon"];
|
||||
|
||||
}
|
||||
} else if (isArmor(itemId)) {
|
||||
if (c._equipped.hasArmor()) {
|
||||
equipError = STRING["dialogs.character.have_armor"];
|
||||
textPos.x = 5;
|
||||
}
|
||||
} else if (isShield(itemId)) {
|
||||
if (c._equipped.hasTwoHanded()) {
|
||||
equipError = STRING["dialogs.character.cannot_two_handed"];
|
||||
textPos.x = 1;
|
||||
}
|
||||
} else if (itemId == 255) {
|
||||
equipError = STRING["dialogs.character.not_equipped"];
|
||||
textPos.x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (equipError.empty() && c._equipped.full()) {
|
||||
equipError = STRING["dialogs.character.full"];
|
||||
textPos.x = 14;
|
||||
}
|
||||
|
||||
if (equipError.empty()) {
|
||||
// All checks passed, can equip item
|
||||
c._backpack.removeAt(index);
|
||||
uint freeIndex = c._equipped.add(itemId, charges);
|
||||
|
||||
if (item._constBonus_id != NO_EQUIP_BONUS) {
|
||||
if (item._constBonus_id == IS_EQUIPPABLE) {
|
||||
equipError = STRING["dialogs.character.not_equipped"];
|
||||
textPos.x = 10;
|
||||
} else if (item._constBonus_id == EQUIP_CURSED) {
|
||||
c._equipped[freeIndex]._charges += item._constBonus_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!equipError.empty())
|
||||
return false;
|
||||
|
||||
//add const equip bonus to character parameters
|
||||
applyEquipBonus(item._constBonus_id, item._constBonus_value);
|
||||
|
||||
switch (getItemCategory(itemId)) {
|
||||
case ITEMCAT_WEAPON:
|
||||
case ITEMCAT_TWO_HANDED:
|
||||
c._physicalAttr._base = item._damage;
|
||||
c._physicalAttr._current = item._AC_Dmg;
|
||||
break;
|
||||
case ITEMCAT_MISSILE:
|
||||
c._missileAttr._base = item._damage;
|
||||
c._missileAttr._current = item._AC_Dmg;
|
||||
break;
|
||||
case ITEMCAT_ARMOR:
|
||||
case ITEMCAT_SHIELD:
|
||||
c._ac._base += item._AC_Dmg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
c.updateResistances();
|
||||
c.updateAttributes();
|
||||
c.updateAC();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EquipRemove::removeItem(int index, Common::Point &textPos, Common::String &removeError) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
uint itemId = c._equipped[index]._id;
|
||||
uint charges = c._equipped[index]._charges;
|
||||
|
||||
g_globals->_items.getItem(itemId);
|
||||
const Item &item = g_globals->_currItem;
|
||||
if (item._constBonus_id == EQUIP_CURSED) {
|
||||
removeError = STRING["dialogs.character.cursed"];
|
||||
textPos.x = 13;
|
||||
} else if (c._backpack.full()) {
|
||||
removeError = STRING["dialogs.character.full"];
|
||||
textPos.x = 14;
|
||||
}
|
||||
|
||||
if (!removeError.empty())
|
||||
return false;
|
||||
|
||||
// Shift item to backpack
|
||||
c._equipped.removeAt(index);
|
||||
c._backpack.add(itemId, charges);
|
||||
|
||||
if (item._constBonus_value) {
|
||||
// TODO: _equipMode is used as a character offset. Need to
|
||||
// find an example that calls it so I know what area of
|
||||
// the character updates are being done to
|
||||
//error("TODO: item flag in remove item");
|
||||
|
||||
//subtract const equip bonus from character parameters
|
||||
applyEquipBonus(item._constBonus_id, -item._constBonus_value);
|
||||
}
|
||||
|
||||
switch (getItemCategory(itemId)) {
|
||||
case ITEMCAT_WEAPON:
|
||||
case ITEMCAT_TWO_HANDED:
|
||||
c._physicalAttr.clear();
|
||||
break;
|
||||
case ITEMCAT_MISSILE:
|
||||
c._missileAttr.clear();
|
||||
break;
|
||||
case ITEMCAT_ARMOR:
|
||||
case ITEMCAT_SHIELD:
|
||||
c._ac._base = MAX((int)c._ac._base - (int)item._AC_Dmg, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EquipRemove::applyEquipBonus(int id, int value){
|
||||
if ((id<2)||(id>=0xff)) return;
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
// TODO: check strange cases (decimal id numbers): 16, 19
|
||||
switch (id) {
|
||||
//case 16: c.sex = NONE; break; //UNOBTAINIUM
|
||||
// case 19: c._luck._race = NONE; break; //JADE AMULET
|
||||
case 21: c._intelligence._base += value; break;
|
||||
case 23: c._might._base += value; break;
|
||||
case 25: c._personality._base += value; break;
|
||||
case 29: c._speed._base += value; break;
|
||||
case 31: c._accuracy._base += value; break;
|
||||
case 33: c._luck._base += value; break;
|
||||
case 37: c._age += value; break;
|
||||
case 60: c._ac._base += value; break;
|
||||
case 88: c._resistances._s._magic._base += value; break;
|
||||
case 90: c._resistances._s._fire._base += value; break;
|
||||
case 92: c._resistances._s._cold._base += value; break;
|
||||
case 94: c._resistances._s._electricity._base += value; break;
|
||||
case 96: c._resistances._s._acid._base += value; break;
|
||||
case 98: c._resistances._s._fear._base += value; break;
|
||||
case 100: c._resistances._s._poison._base += value; break;
|
||||
case 102: c._resistances._s._psychic._base += value; break; //resistance to sleep
|
||||
case 108: c._trapCtr += value; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
53
engines/mm/mm1/game/equip_remove.h
Normal file
53
engines/mm/mm1/game/equip_remove.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_EQUIP_REMOVE_H
|
||||
#define MM1_GAME_EQUIP_REMOVE_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
struct EquipRemove {
|
||||
/**
|
||||
* Equip an item
|
||||
*/
|
||||
bool equipItem(int index, Common::Point &textPos, Common::String &equipError);
|
||||
|
||||
/**
|
||||
* Remove an item
|
||||
*/
|
||||
bool removeItem(int index, Common::Point &textPos, Common::String &removeError);
|
||||
|
||||
/**
|
||||
* apply an equip bonus on a current character
|
||||
*/
|
||||
void applyEquipBonus(int id, int value);
|
||||
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
70
engines/mm/mm1/game/fly.cpp
Normal file
70
engines/mm/mm1/game/fly.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 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/fly.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
static const byte FLY_MAP_ID1[20] = {
|
||||
1, 0, 4, 5, 0x12,
|
||||
2, 3, 0x11, 5, 6,
|
||||
2, 1, 4, 6, 0x1A,
|
||||
3, 3, 4, 1, 0x1B
|
||||
};
|
||||
|
||||
static const byte FLY_MAP_ID2[20] = {
|
||||
0xF, 0xA, 3, 5, 1,
|
||||
5, 7, 0xA, 0xB, 7,
|
||||
0xB, 1, 9, 1, 0xB,
|
||||
1, 0xD, 0xF, 8, 1
|
||||
};
|
||||
|
||||
static const byte FLY_MAP_X[20] = {
|
||||
15, 8, 11, 0, 9,
|
||||
15, 3, 10, 4, 11,
|
||||
15, 3, 3, 7, 12,
|
||||
14, 11, 5, 7, 15
|
||||
};
|
||||
|
||||
static const byte FLY_MAP_Y[20] = {
|
||||
7, 10, 0, 8, 11,
|
||||
7, 2, 10, 0, 0,
|
||||
15, 3, 9, 0, 6,
|
||||
14, 15, 15, 7, 15
|
||||
};
|
||||
|
||||
void Fly::fly(int mapIndex) {
|
||||
if (mapIndex != -1) {
|
||||
Maps::Maps &maps = *g_maps;
|
||||
int id = FLY_MAP_ID1[mapIndex] | ((int)FLY_MAP_ID2[mapIndex] << 8);
|
||||
|
||||
maps._mapPos.x = FLY_MAP_X[mapIndex];
|
||||
maps._mapPos.y = FLY_MAP_Y[mapIndex];
|
||||
maps.changeMap(id, 2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
43
engines/mm/mm1/game/fly.h
Normal file
43
engines/mm/mm1/game/fly.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_FLY_H
|
||||
#define MM1_GAME_FLY_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Fly {
|
||||
protected:
|
||||
/**
|
||||
* Handles teleporting to the given map
|
||||
*/
|
||||
void fly(int mapIndex);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
39
engines/mm/mm1/game/game_logic.cpp
Normal file
39
engines/mm/mm1/game/game_logic.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 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/game_logic.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
int GameLogic::getRandomNumber(int minNumber, int maxNumber) {
|
||||
return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
|
||||
}
|
||||
|
||||
int GameLogic::getRandomNumber(int maxNumber) {
|
||||
return g_engine->getRandomNumber(maxNumber);
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
42
engines/mm/mm1/game/game_logic.h
Normal file
42
engines/mm/mm1/game/game_logic.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_GAME_LOGIC_H
|
||||
#define MM1_GAME_GAME_LOGIC_H
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class GameLogic {
|
||||
public:
|
||||
/**
|
||||
* Returns a random number
|
||||
*/
|
||||
static int getRandomNumber(int minNumber, int maxNumber);
|
||||
static int getRandomNumber(int maxNumber);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
67
engines/mm/mm1/game/leprechaun.cpp
Normal file
67
engines/mm/mm1/game/leprechaun.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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/leprechaun.h"
|
||||
#include "mm/mm1/maps/map00.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
#define TOWN_NUM 0x2fe
|
||||
#define LEPRECHAUN_MAP_ID1 0x2ff
|
||||
#define LEPRECHAUN_MAP_ID2 0x304
|
||||
#define LEPRECHAUN_MAP_X 0x309
|
||||
#define LEPRECHAUN_MAP_Y 0x30E
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void Leprechaun::teleportToTown(char townNum) {
|
||||
Maps::Maps &maps = *g_maps;
|
||||
Maps::Map00 &map = *static_cast<Maps::Map00 *>(g_maps->_currentMap);
|
||||
|
||||
map[TOWN_NUM] = townNum;
|
||||
|
||||
// Scan the party for someone with any gems
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
if (c._gems) {
|
||||
c._gems--;
|
||||
|
||||
int townIndex = map[TOWN_NUM] - Common::KEYCODE_1;
|
||||
maps._mapPos.x = map[LEPRECHAUN_MAP_X + townIndex];
|
||||
maps._mapPos.y = map[LEPRECHAUN_MAP_Y + townIndex];
|
||||
maps.changeMap(
|
||||
map[LEPRECHAUN_MAP_ID1 + townIndex] |
|
||||
(map[LEPRECHAUN_MAP_ID2 + townIndex] << 8),
|
||||
1);
|
||||
|
||||
g_events->redraw();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
maps._mapPos = Common::Point(8, 5);
|
||||
map.updateGame();
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
38
engines/mm/mm1/game/leprechaun.h
Normal file
38
engines/mm/mm1/game/leprechaun.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_LEPRECHAUN_H
|
||||
#define MM1_GAME_LEPRECHAUN_H
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class Leprechaun {
|
||||
public:
|
||||
void teleportToTown(char townNum);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
388
engines/mm/mm1/game/monster_touch.cpp
Normal file
388
engines/mm/mm1/game/monster_touch.cpp
Normal file
@@ -0,0 +1,388 @@
|
||||
/* 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/monster_touch.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
const MonsterTouchAction MonsterTouch::ACTIONS[25] = {
|
||||
&MonsterTouch::action00,
|
||||
&MonsterTouch::action01,
|
||||
&MonsterTouch::action02,
|
||||
&MonsterTouch::action03,
|
||||
&MonsterTouch::action04,
|
||||
&MonsterTouch::action05,
|
||||
&MonsterTouch::action06,
|
||||
&MonsterTouch::action07,
|
||||
&MonsterTouch::action08,
|
||||
&MonsterTouch::action09,
|
||||
&MonsterTouch::action10,
|
||||
&MonsterTouch::action11,
|
||||
&MonsterTouch::action12,
|
||||
&MonsterTouch::action13,
|
||||
&MonsterTouch::action14,
|
||||
&MonsterTouch::action15,
|
||||
&MonsterTouch::action16,
|
||||
&MonsterTouch::action17,
|
||||
&MonsterTouch::action18,
|
||||
&MonsterTouch::action19,
|
||||
&MonsterTouch::action20,
|
||||
&MonsterTouch::action21,
|
||||
&MonsterTouch::action22,
|
||||
&MonsterTouch::action23,
|
||||
&MonsterTouch::action24
|
||||
};
|
||||
|
||||
#define LINE(ACTION) line = Common::String::format(" %s%s", \
|
||||
STRING["monster_actions.and"].c_str(), STRING[ACTION].c_str())
|
||||
|
||||
bool MonsterTouch::monsterTouch(uint index, Common::String &line) {
|
||||
line = "";
|
||||
return (this->*ACTIONS[index])(line);
|
||||
}
|
||||
|
||||
bool MonsterTouch::canPerform(int level) const {
|
||||
return getRandomNumber(level) == level;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action00(Common::String &line) {
|
||||
if (canPerform(3)) {
|
||||
g_globals->_currCharacter->_food = 0;
|
||||
LINE("monster_actions.takes_food");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action01(Common::String &line) {
|
||||
if (canPerform(20)) {
|
||||
setCondition(DISEASED);
|
||||
LINE("monster_actions.inflicts_disease");
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action02(Common::String &line) {
|
||||
if (canPerform(20)) {
|
||||
return action07(line);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action03(Common::String &line) {
|
||||
if (canPerform(20)) {
|
||||
return action11(line);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action04(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(2) && c._gems != 0) {
|
||||
c._gems /= 2;
|
||||
LINE("monster_actions.steals_gems");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action05(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (c._endurance._current == 0 || --c._endurance._current == 0)
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
_damage += 3;
|
||||
|
||||
LINE("monster_actions.reduces_endurance");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action06(Common::String &line) {
|
||||
if (damageType7()) {
|
||||
setCondition(ASLEEP);
|
||||
LINE("monster_actions.induces_sleep");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action07(Common::String &line) {
|
||||
if (damageType5()) {
|
||||
setCondition(3);
|
||||
LINE("monster_actions.cures_paralysis");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action08(Common::String &line) {
|
||||
if (canPerform(4)) {
|
||||
setCondition(DISEASED);
|
||||
LINE("monster_actions.inflicts_disease");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action09(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(2) && c._gold != 0) {
|
||||
c._gold /= 2;
|
||||
LINE("monster_actions.steals_gold");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action10(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(2) && !c._backpack.empty()) {
|
||||
c._backpack.removeAt(c._backpack.size() - 1);
|
||||
LINE("monster_actions.steals_something");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action11(Common::String &line) {
|
||||
if (damageType6()) {
|
||||
setCondition(16);
|
||||
LINE("monster_actions.induces_poison");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action12(Common::String &line) {
|
||||
if (canPerform(3)) {
|
||||
setCondition(BLINDED);
|
||||
LINE("monster_actions.causes_blindness");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action13(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (c._level._current == 0 || --c._level._current == 0)
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
|
||||
_damage += 10;
|
||||
LINE("monster_actions.drains_lifeforce");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action14(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(3) && isCharAffected()) {
|
||||
setCondition(BAD_CONDITION | STONE);
|
||||
line = Common::String::format("%s %s",
|
||||
c._name,
|
||||
STRING["monster_actions.turned_to_stone"].c_str()
|
||||
);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action15(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (isCharAffected()) {
|
||||
int age = c._age + 10;
|
||||
c._age = age;
|
||||
|
||||
if (age > 255) {
|
||||
c._age = 200;
|
||||
setCondition(ERADICATED);
|
||||
}
|
||||
|
||||
LINE("monster_actions.causes_aging");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action16(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (c._level < 3) {
|
||||
c._level._current = 0;
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
|
||||
} else {
|
||||
c._level._current -= 2;
|
||||
}
|
||||
|
||||
_damage += 20;
|
||||
LINE("monster_actions.drains_lifeforce");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action17(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(3) && isCharAffected()) {
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
line = Common::String::format("%s %s",
|
||||
c._name,
|
||||
STRING["monster_actions.is_killed"].c_str()
|
||||
);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action18(Common::String &line) {
|
||||
if (canPerform(3) && isCharAffected()) {
|
||||
setCondition(UNCONSCIOUS);
|
||||
LINE("monster_actions.induces_unconsciousness");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action19(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (c._might._current < 4) {
|
||||
c._might._current = 0;
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
|
||||
} else {
|
||||
c._might._current -= 3;
|
||||
}
|
||||
|
||||
LINE("monster_actions.drains_might");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action20(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
AttributePair &attr = c.getAttribute(i);
|
||||
|
||||
if (attr._current < 3) {
|
||||
attr._current = 0;
|
||||
setCondition(BAD_CONDITION | DEAD);
|
||||
|
||||
} else {
|
||||
attr._current -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
LINE("monster_actions.drains_abilities");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action21(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(2)) {
|
||||
c._backpack.clear();
|
||||
LINE("monster_actions.steals_backpack");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action22(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (canPerform(2)) {
|
||||
c._gold = 0;
|
||||
c._gems = 0;
|
||||
|
||||
LINE("monster_actions.steals_gold_and_gems");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MonsterTouch::action23(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
setCondition(ERADICATED);
|
||||
line = Common::String::format("%s %s",
|
||||
c._name,
|
||||
STRING["monster_actions.is_eradicated"].c_str()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonsterTouch::action24(Common::String &line) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
c._sp._current = 0;
|
||||
LINE("monster_actions.drains_sp");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
76
engines/mm/mm1/game/monster_touch.h
Normal file
76
engines/mm/mm1/game/monster_touch.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_MONSTER_TOUCH_H
|
||||
#define MM1_GAME_MONSTER_TOUCH_H
|
||||
|
||||
#include "mm/mm1/game/spells_monsters.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class MonsterTouch;
|
||||
typedef bool (MonsterTouch::*MonsterTouchAction)(Common::String &line);
|
||||
|
||||
class MonsterTouch : public SpellsMonsters {
|
||||
private:
|
||||
static const MonsterTouchAction ACTIONS[25];
|
||||
|
||||
bool canPerform(int level) const;
|
||||
private:
|
||||
bool action00(Common::String &line);
|
||||
bool action01(Common::String &line);
|
||||
bool action02(Common::String &line);
|
||||
bool action03(Common::String &line);
|
||||
bool action04(Common::String &line);
|
||||
bool action05(Common::String &line);
|
||||
bool action06(Common::String &line);
|
||||
bool action07(Common::String &line);
|
||||
bool action08(Common::String &line);
|
||||
bool action09(Common::String &line);
|
||||
bool action10(Common::String &line);
|
||||
bool action11(Common::String &line);
|
||||
bool action12(Common::String &line);
|
||||
bool action13(Common::String &line);
|
||||
bool action14(Common::String &line);
|
||||
bool action15(Common::String &line);
|
||||
bool action16(Common::String &line);
|
||||
bool action17(Common::String &line);
|
||||
bool action18(Common::String &line);
|
||||
bool action19(Common::String &line);
|
||||
bool action20(Common::String &line);
|
||||
bool action21(Common::String &line);
|
||||
bool action22(Common::String &line);
|
||||
bool action23(Common::String &line);
|
||||
bool action24(Common::String &line);
|
||||
|
||||
public:
|
||||
virtual ~MonsterTouch() {}
|
||||
|
||||
bool monsterTouch(uint index, Common::String &line);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
48
engines/mm/mm1/game/recharge_item.cpp
Normal file
48
engines/mm/mm1/game/recharge_item.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* 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/recharge_item.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
bool RechargeItem::charge(Inventory &inv, int itemIndex) {
|
||||
const Item &item = *g_globals->_items.getItem(inv[itemIndex]._id);
|
||||
|
||||
if (getRandomNumber(100) == 100) {
|
||||
// OMG: The original seriously had this fringe
|
||||
// case that happens so rarely
|
||||
inv.removeAt(itemIndex); // Break item
|
||||
return false;
|
||||
|
||||
} else {
|
||||
inv[itemIndex]._charges = MIN(inv[itemIndex]._charges + getRandomNumber(4),
|
||||
(int)item._maxCharges);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
46
engines/mm/mm1/game/recharge_item.h
Normal file
46
engines/mm/mm1/game/recharge_item.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_RECHARGE_ITEM_H
|
||||
#define MM1_GAME_RECHARGE_ITEM_H
|
||||
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/items.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class RechargeItem : public GameLogic {
|
||||
protected:
|
||||
/**
|
||||
* Charge a given item
|
||||
* @returns Returns true if the spell succeeded
|
||||
*/
|
||||
bool charge(Inventory &inv, int itemIndex);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
72
engines/mm/mm1/game/rest.cpp
Normal file
72
engines/mm/mm1/game/rest.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 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/events.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
#include "mm/mm1/game/rest.h"
|
||||
#include "mm/mm1/game/encounter.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
void Rest::check() {
|
||||
int dangerRate = g_maps->_currentMap->dataByte(44);
|
||||
if (!dangerRate ||
|
||||
g_engine->getRandomNumber(dangerRate) != dangerRate) {
|
||||
// Rest allowed
|
||||
execute();
|
||||
} else {
|
||||
// Choose a random character, and make everyone
|
||||
// but them be asleep
|
||||
uint awakeIndex = g_engine->getRandomNumber(
|
||||
g_globals->_party.size() - 1);
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
if (!(c._condition & BAD_CONDITION) && i != awakeIndex)
|
||||
c._condition |= ASLEEP;
|
||||
}
|
||||
|
||||
// Start an encounter
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
}
|
||||
|
||||
void Rest::execute() {
|
||||
// Reset active spells
|
||||
Common::fill(&g_globals->_activeSpells._arr[0],
|
||||
&g_globals->_activeSpells._arr[ACTIVE_SPELLS_COUNT], 0);
|
||||
|
||||
// Rest the characters of the party
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
c.rest();
|
||||
}
|
||||
|
||||
g_events->send(InfoMessage(
|
||||
STRING["dialogs.game.rest.rest_complete"]
|
||||
));
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
46
engines/mm/mm1/game/rest.h
Normal file
46
engines/mm/mm1/game/rest.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_REST_H
|
||||
#define MM1_GAME_REST_H
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
struct Rest {
|
||||
/**
|
||||
* Checks the current map to see whether the
|
||||
* party is able to rest, or an encounter is triggered
|
||||
*/
|
||||
static void check();
|
||||
|
||||
/**
|
||||
* Handles the rest
|
||||
*/
|
||||
static void execute();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
192
engines/mm/mm1/game/spell_casting.cpp
Normal file
192
engines/mm/mm1/game/spell_casting.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/* 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/spell_casting.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/views/combat.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
static const int8 SPELLS_SP_GEMS[47 * 2] = {
|
||||
0, 0, 0, 0, 0, -1, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 0, 0, 0, 2, 0, 2, 2,
|
||||
0, 0, 0, 3, 3,
|
||||
4, 4, 4, 4, 4,
|
||||
10, 5, 5, 5, 5,
|
||||
|
||||
0, 0, -1, 0, 0, 0, 0, 0,
|
||||
0, 0, 1, 0, 0, 0, 0, 0,
|
||||
-1, 0, 1, -1, 0, 0, 1, 0,
|
||||
0, 0, 2, 0, 0, 2, 2, 2,
|
||||
0, 0, 3, 3, 3,
|
||||
4, 4, 4, 4, 4,
|
||||
5, 100, 5, 5, 5
|
||||
};
|
||||
|
||||
static const byte SPELL_FLAGS[47 * 2] = {
|
||||
1, 1, 9, 4, 2, 4, 0, 1,
|
||||
4, 5, 9, 0, 0, 0, 9, 9,
|
||||
2, 4, 4, 2, 9, 9, 2, 2,
|
||||
6, 6, 0, 0, 6, 25, 5, 2,
|
||||
17, 0, 1, 4, 4,
|
||||
17, 4, 6, 4, 2,
|
||||
1, 1, 0, 6, 25,
|
||||
|
||||
1, 2, 9, 9, 0, 2, 2, 9,
|
||||
9, 9, 9, 2, 2, 5, 5, 9,
|
||||
9, 18, 1, 9, 1, 1, 1, 9,
|
||||
9, 9, 9, 9, 2, 0, 1, 1,
|
||||
17, 0, 9, 2, 2,
|
||||
1, 9, 2, 0, 2,
|
||||
2, 2, 17, 1, 1
|
||||
};
|
||||
|
||||
enum SpellFlag {
|
||||
SF_COMBAT_ONLY = 1,
|
||||
SF_NONCOMBAT_ONLY = 2,
|
||||
SF_CAST_ON = 4,
|
||||
SF_OUTDOORS_ONLY = 0x10
|
||||
};
|
||||
|
||||
int SpellCasting::getSpellIndex(const Character *chr, int lvl, int num) {
|
||||
int lvlNum;
|
||||
int setNum = chr->_class == ARCHER || chr->_class == SORCERER ? 1 : 0;
|
||||
int spellNum = num - 1;
|
||||
for (lvlNum = 2; lvlNum <= MIN(lvl, 5); ++lvlNum)
|
||||
spellNum += 8;
|
||||
for (lvlNum = 5; lvlNum < lvl; ++lvlNum)
|
||||
spellNum += 5;
|
||||
|
||||
int spellIndex = setNum * 47 + spellNum;
|
||||
return spellIndex;
|
||||
}
|
||||
|
||||
void SpellCasting::getSpellLevelNum(int spellIndex, int &lvl, int &num) {
|
||||
int idx = spellIndex % 47;
|
||||
|
||||
for (lvl = 1; lvl < 8; ++lvl) {
|
||||
int numSpells = (lvl >= 5) ? 5 : 8;
|
||||
if (idx < numSpells) {
|
||||
num = idx + 1;
|
||||
return;
|
||||
}
|
||||
idx -= numSpells;
|
||||
}
|
||||
|
||||
num = -1;
|
||||
}
|
||||
|
||||
|
||||
void SpellCasting::setSpell(const Character *chr, int lvl, int num) {
|
||||
_spellState = SS_OK;
|
||||
|
||||
// Figure the offset in the spell list
|
||||
int spellIndex = getSpellIndex(chr, lvl, num);
|
||||
|
||||
// The required SP matches the spell level
|
||||
int requiredSp = lvl;
|
||||
|
||||
if (SPELLS_SP_GEMS[spellIndex] < 0)
|
||||
// required SP increases with character's level
|
||||
requiredSp = chr->_level;
|
||||
|
||||
if (SPELLS_SP_GEMS[spellIndex] < 0 && chr->_sp._current < chr->_level._current)
|
||||
_spellState = SS_NOT_ENOUGH_SP;
|
||||
else if (requiredSp > chr->_sp._current)
|
||||
_spellState = SS_NOT_ENOUGH_SP;
|
||||
|
||||
int requiredGems = ABS(SPELLS_SP_GEMS[spellIndex]);
|
||||
if (_spellState == SS_OK)
|
||||
setSpell(spellIndex, requiredSp, requiredGems);
|
||||
|
||||
// Supporting debugger command that enables all spells
|
||||
if (g_globals->_allSpells && _spellState != SS_COMBAT_ONLY &&
|
||||
_spellState != SS_NONCOMBAT_ONLY && _spellState != SS_OUTDOORS_ONLY) {
|
||||
_requiredSp = _requiredGems = 0;
|
||||
_spellState = SS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void SpellCasting::setSpell(int spellIndex, int requiredSp, int requiredGems) {
|
||||
_spellIndex = spellIndex;
|
||||
_requiredSp = requiredSp;
|
||||
_requiredGems = requiredGems;
|
||||
_spellState = SS_OK;
|
||||
|
||||
Maps::Map &map = *g_maps->_currentMap;
|
||||
|
||||
if (!isInCombat() && SPELL_FLAGS[spellIndex] & SF_COMBAT_ONLY)
|
||||
_spellState = SS_COMBAT_ONLY;
|
||||
else if (isInCombat() && SPELL_FLAGS[spellIndex] & SF_NONCOMBAT_ONLY)
|
||||
_spellState = SS_NONCOMBAT_ONLY;
|
||||
else if ((SPELL_FLAGS[spellIndex] & SF_OUTDOORS_ONLY) &&
|
||||
!(map[Maps::MAP_ID] & 0x80))
|
||||
_spellState = SS_OUTDOORS_ONLY;
|
||||
}
|
||||
|
||||
bool SpellCasting::hasCharTarget() const {
|
||||
return (SPELL_FLAGS[_spellIndex] & SF_CAST_ON) != 0;
|
||||
}
|
||||
|
||||
bool SpellCasting::isMagicAllowed() const {
|
||||
return !(g_maps->_currentState & Maps::SFLAG_SPELLS_DISALLOWED);
|
||||
}
|
||||
|
||||
Common::String SpellCasting::getSpellError() const {
|
||||
Common::String msg;
|
||||
switch (_spellState) {
|
||||
case SS_NOT_ENOUGH_SP:
|
||||
msg = STRING["dialogs.misc.not_enough_sp"];
|
||||
break;
|
||||
case SS_NOT_ENOUGH_GEMS:
|
||||
msg = STRING["dialogs.misc.not_enough_gems"];
|
||||
break;
|
||||
case SS_COMBAT_ONLY:
|
||||
msg = STRING["spells.combat_only"];
|
||||
break;
|
||||
case SS_NONCOMBAT_ONLY:
|
||||
msg = STRING["spells.noncombat_only"];
|
||||
break;
|
||||
case SS_OUTDOORS_ONLY:
|
||||
msg = STRING["spells.outdoors_only"];
|
||||
break;
|
||||
default:
|
||||
msg = STRING["spells.done"];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isInCombat())
|
||||
msg = Common::String::format("*** %s ***", msg.c_str());
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool SpellCasting::isInCombat() const {
|
||||
return g_events->isPresent("Combat");
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
107
engines/mm/mm1/game/spell_casting.h
Normal file
107
engines/mm/mm1/game/spell_casting.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_SPELL_CASTING_H
|
||||
#define MM1_GAME_SPELL_CASTING_H
|
||||
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
enum SpellState {
|
||||
SS_OK, SS_NOT_ENOUGH_SP, SS_NOT_ENOUGH_GEMS,
|
||||
SS_COMBAT_ONLY, SS_NONCOMBAT_ONLY, SS_DOESNT_WORK,
|
||||
SS_OUTDOORS_ONLY
|
||||
};
|
||||
|
||||
/**
|
||||
* Support class for handling spell casting logic
|
||||
*/
|
||||
class SpellCasting {
|
||||
protected:
|
||||
int _spellIndex = 0;
|
||||
int _requiredSp = 0, _requiredGems = 0;
|
||||
SpellState _spellState = SS_OK;
|
||||
|
||||
/**
|
||||
* Returns true if combat is in progress
|
||||
*/
|
||||
bool isInCombat() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets the current spell
|
||||
*/
|
||||
void setSpell(const Character *chr, int lvl, int num);
|
||||
|
||||
/**
|
||||
* Get the index in the spell array for a given spell
|
||||
*/
|
||||
static int getSpellIndex(const Character *chr, int lvl, int num);
|
||||
|
||||
/**
|
||||
* Get the spell level and number from spell index
|
||||
*/
|
||||
static void getSpellLevelNum(int spellIndex, int &lvl, int &num);
|
||||
|
||||
/**
|
||||
* Sets a spell directly by index
|
||||
*/
|
||||
void setSpell(int spellIndex, int requiredSp, int requiredGems);
|
||||
|
||||
/**
|
||||
* Returns true if the spell requires a target
|
||||
*/
|
||||
bool hasCharTarget() const;
|
||||
|
||||
/**
|
||||
* Returns true if a spell can be cast, with the exception
|
||||
* of magic not being allowed at the current location.
|
||||
*/
|
||||
bool canCast() const {
|
||||
return _spellState == SS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if magic is allowed at the current location
|
||||
*/
|
||||
bool isMagicAllowed() const;
|
||||
|
||||
/**
|
||||
* Returns the spell error
|
||||
*/
|
||||
SpellState getSpellState() const {
|
||||
return _spellState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message
|
||||
*/
|
||||
Common::String getSpellError() const;
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
699
engines/mm/mm1/game/spells_monsters.cpp
Normal file
699
engines/mm/mm1/game/spells_monsters.cpp
Normal file
@@ -0,0 +1,699 @@
|
||||
/* 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_monsters.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
const SpellMonstersSpell SpellsMonsters::SPELLS[MONSTER_SPELLS_COUNT] = {
|
||||
&SpellsMonsters::spell01_curse,
|
||||
&SpellsMonsters::spell02_energyBlast,
|
||||
&SpellsMonsters::spell03_fire,
|
||||
&SpellsMonsters::spell04_blindness,
|
||||
&SpellsMonsters::spell05_sprayPoison,
|
||||
&SpellsMonsters::spell06_sprayAcid,
|
||||
&SpellsMonsters::spell07_sleep,
|
||||
&SpellsMonsters::spell08_paralyze,
|
||||
&SpellsMonsters::spell09_dispel,
|
||||
&SpellsMonsters::spell10_lightningBolt,
|
||||
&SpellsMonsters::spell11_strangeGas,
|
||||
&SpellsMonsters::spell12_explode,
|
||||
&SpellsMonsters::spell13_fireball,
|
||||
&SpellsMonsters::spell14_fireBreath,
|
||||
&SpellsMonsters::spell15_gazes,
|
||||
&SpellsMonsters::spell16_acidArrow,
|
||||
&SpellsMonsters::spell17_elements,
|
||||
&SpellsMonsters::spell18_coldBeam,
|
||||
&SpellsMonsters::spell19_dancingSword,
|
||||
&SpellsMonsters::spell20_magicDrain,
|
||||
&SpellsMonsters::spell21_fingerOfDeath,
|
||||
&SpellsMonsters::spell22_sunRay,
|
||||
&SpellsMonsters::spell23_disintegration,
|
||||
&SpellsMonsters::spell24_commandsEnergy,
|
||||
&SpellsMonsters::spell25_poison,
|
||||
&SpellsMonsters::spell26_lightning,
|
||||
&SpellsMonsters::spell27_frost,
|
||||
&SpellsMonsters::spell28_spikes,
|
||||
&SpellsMonsters::spell29_acid,
|
||||
&SpellsMonsters::spell30_fire,
|
||||
&SpellsMonsters::spell31_energy,
|
||||
&SpellsMonsters::spell32_swarm
|
||||
};
|
||||
|
||||
SpellsMonsters::SpellsMonsters() {
|
||||
}
|
||||
|
||||
void SpellsMonsters::castMonsterSpell(const Common::String &monsterName, int spellNum) {
|
||||
g_globals->_spellsState._mmVal1 = 0;
|
||||
g_globals->_spellsState._resistanceIndex = 0;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_MAGIC;
|
||||
g_globals->_spellsState._damage = 0;
|
||||
|
||||
// All spell messages start with the monster who casts it
|
||||
_lines.clear();
|
||||
_lines.push_back(Line(monsterName));
|
||||
|
||||
(this->*SPELLS[spellNum - 1])();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell01_curse() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.a_curse"]);
|
||||
g_globals->_activeSpells._s.cursed = MIN(255,
|
||||
(int)g_globals->_activeSpells._s.cursed + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell02_energyBlast() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.energy_blast"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
g_globals->_spellsState._damage = getRandomNumber(16) + 4;
|
||||
damageRandomChar();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell03_fire() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.fire"].c_str()));
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_FIRE;
|
||||
|
||||
int count = _remainingMonsters[getMonsterIndex()]->_level;
|
||||
g_globals->_spellsState._damage += count * 6;
|
||||
|
||||
damageRandomChar();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell04_blindness() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.blindness"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = 2;
|
||||
|
||||
handlePartyEffects();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell05_sprayPoison() {
|
||||
add(STRING["monster_spells.sprays_poison"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_POISON;
|
||||
g_globals->_spellsState._damage = POISONED;
|
||||
handlePartyEffects();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell06_sprayAcid() {
|
||||
add(STRING["monster_spells.sprays_acid"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ACID;
|
||||
g_globals->_spellsState._damage = getRandomNumber((int)POISONED);
|
||||
add(':');
|
||||
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell07_sleep() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.sleep"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_PSYCHIC;
|
||||
g_globals->_spellsState._damage = ASLEEP;
|
||||
handlePartyEffects();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell08_paralyze() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.paralyze"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_FEAR;
|
||||
g_globals->_spellsState._damage = PARALYZED;
|
||||
|
||||
if (_remainingMonsters[getMonsterIndex()]->_level >= 5) {
|
||||
handlePartyEffects();
|
||||
} else {
|
||||
chooseCharacter();
|
||||
writeConditionEffect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell09_dispel() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.dispel"]);
|
||||
dispelParty();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell10_lightningBolt() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.lightning_bolt"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ELECTRICITY;
|
||||
g_globals->_spellsState._damage = getRandomNumber(37) + 5;
|
||||
damageRandomChar();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell11_strangeGas() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.strange_gas"].c_str()));
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_POISON;
|
||||
g_globals->_spellsState._damage = BAD_CONDITION | STONE;
|
||||
|
||||
handlePartyEffects();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell12_explode() {
|
||||
add(STRING["monster_spells.explode"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_POISON;
|
||||
g_globals->_spellsState._damage = getRandomNumber(
|
||||
_remainingMonsters[getMonsterIndex()]->_level);
|
||||
_remainingMonsters[getMonsterIndex()]->_level = 0;
|
||||
_remainingMonsters[getMonsterIndex()]->_status = MONFLAG_DEAD;
|
||||
removeMonster();
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell13_fireball() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.fireball"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_FIRE;
|
||||
|
||||
// This whole condition choice makes no sense
|
||||
g_globals->_spellsState._damage += 6 *
|
||||
_remainingMonsters[getMonsterIndex()]->_level;
|
||||
g_globals->_spellsState._damage = getRandomNumber(g_globals->_spellsState._damage) + 4;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell14_fireBreath() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.fire"].c_str()));
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_FIRE;
|
||||
|
||||
// This whole condition choice makes no sense
|
||||
g_globals->_spellsState._damage += 8 *
|
||||
_remainingMonsters[getMonsterIndex()]->_level;
|
||||
g_globals->_spellsState._damage = getRandomNumber(g_globals->_spellsState._damage);
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell15_gazes() {
|
||||
add(STRING["monster_spells.gazes"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = BAD_CONDITION | STONE;
|
||||
|
||||
chooseCharacter();
|
||||
writeConditionEffect();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell16_acidArrow() {
|
||||
add(STRING["monster_spells.acid_arrow"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ACID;
|
||||
g_globals->_spellsState._damage = getRandomNumber(31) + 9;
|
||||
|
||||
damageRandomChar();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell17_elements() {
|
||||
add(STRING["monster_spells.call_elements"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = getRandomNumber(21) + 39;
|
||||
|
||||
damageRandomChar();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell18_coldBeam() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.cold_beam"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_COLD;
|
||||
g_globals->_spellsState._damage = getRandomNumber(41) + 9;
|
||||
|
||||
damageRandomChar();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell19_dancingSword() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.dancing_sword"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
g_globals->_spellsState._damage = getRandomNumber(14) + 16;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell20_magicDrain() {
|
||||
add(STRING["monster_spells.magic_drain"]);
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
g_globals->_currCharacter = &c;
|
||||
c._sp._current = 0;
|
||||
}
|
||||
|
||||
dispelParty();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell21_fingerOfDeath() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.finger_of_death"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = BAD_CONDITION | DEAD;
|
||||
|
||||
chooseCharacter();
|
||||
writeConditionEffect();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell22_sunRay() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.sun_ray"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = getRandomNumber(51) + 49;
|
||||
|
||||
damageRandomChar();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell23_disintegration() {
|
||||
if (casts()) {
|
||||
add(STRING["monster_spells.disintegration"]);
|
||||
++g_globals->_spellsState._mmVal1;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = ERADICATED;
|
||||
|
||||
chooseCharacter();
|
||||
writeConditionEffect();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell24_commandsEnergy() {
|
||||
add(STRING["monster_spells.commands_energy"]);
|
||||
g_globals->_spellsState._damage = SILENCED | PARALYZED | UNCONSCIOUS;
|
||||
damageRandomChar();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell25_poison() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.poison"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_POISON;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell26_lightning() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.lightning"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ELECTRICITY;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell27_frost() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.frost"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_COLD;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell28_spikes() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.spikes"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ELECTRICITY;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell29_acid() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.acid"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_ACID;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell30_fire() {
|
||||
add(Common::String::format("%s %s",
|
||||
STRING["monster_spells.breathes"].c_str(),
|
||||
STRING["monster_spells.fire"].c_str()));
|
||||
g_globals->_spellsState._resistanceTypeOrTargetCount = RESISTANCE_FIRE;
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell31_energy() {
|
||||
add(STRING["monster_spells.energy"]);
|
||||
g_globals->_spellsState._damage = _remainingMonsters[getMonsterIndex()]->_hp;
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::spell32_swarm() {
|
||||
add(STRING["monster_spells.swarm"]);
|
||||
++g_globals->_spellsState._resistanceIndex;
|
||||
g_globals->_spellsState._damage = getRandomNumber(12);
|
||||
|
||||
add(':');
|
||||
handlePartyDamage();
|
||||
}
|
||||
|
||||
bool SpellsMonsters::casts() {
|
||||
if (canMonsterCast()) {
|
||||
add(STRING["monster_spells.casts"]);
|
||||
return true;
|
||||
} else {
|
||||
add(STRING["monster_spells.fails_to_cast"]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::addCharName() {
|
||||
add(g_globals->_currCharacter->_name);
|
||||
}
|
||||
|
||||
void SpellsMonsters::damageRandomChar() {
|
||||
chooseCharacter();
|
||||
handleDamage();
|
||||
}
|
||||
|
||||
void SpellsMonsters::chooseCharacter() {
|
||||
add(':');
|
||||
|
||||
// Choose a random character
|
||||
g_globals->_currCharacter = &g_globals->_party[
|
||||
getRandomNumber(g_globals->_party.size()) - 1
|
||||
];
|
||||
|
||||
if (g_globals->_currCharacter->_condition & (BAD_CONDITION | UNCONSCIOUS)) {
|
||||
// Can't use character, so sequently scan party
|
||||
// to find a character that can be used
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
g_globals->_currCharacter = &g_globals->_party[i];
|
||||
if (g_globals->_currCharacter->_condition & (BAD_CONDITION | UNCONSCIOUS))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellsMonsters::isCharAffected() const {
|
||||
int val = g_globals->_currCharacter->_resistances._s._magic._current +
|
||||
g_globals->_activeSpells._s.magic;
|
||||
return randomThreshold(val);
|
||||
}
|
||||
|
||||
void SpellsMonsters::handleDamage() {
|
||||
g_globals->_spellsState._mmVal5 = 1;
|
||||
_damage = g_globals->_spellsState._damage;
|
||||
|
||||
if (charAffected()) {
|
||||
if (isEffective()) {
|
||||
if (testElementalResistance()) {
|
||||
if (g_globals->_activeSpells._s.power_shield)
|
||||
_damage = 1;
|
||||
|
||||
writeDamage();
|
||||
Common::String str = subtractDamageFromChar();
|
||||
if (!str.empty())
|
||||
_lines.push_back(Line(0, _lines.back().y + 1, str));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellsMonsters::charAffected() {
|
||||
_lines.push_back(Line(0, 2, ""));
|
||||
addCharName();
|
||||
add(' ');
|
||||
|
||||
if (g_globals->_spellsState._mmVal1 && !isCharAffected()) {
|
||||
_lines.back()._text += STRING["monster_spells.not_affected"];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpellsMonsters::isEffective() {
|
||||
if (g_globals->_spellsState._resistanceIndex) {
|
||||
proc9();
|
||||
|
||||
if (g_globals->_spellsState._mmVal7) {
|
||||
if (g_globals->_spellsState._mmVal5) {
|
||||
_damage >>= 1;
|
||||
} else {
|
||||
_lines.back()._text += STRING["monster_spells.not_affected"];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpellsMonsters::testElementalResistance() {
|
||||
bool result = false;
|
||||
|
||||
switch (g_globals->_spellsState._resistanceTypeOrTargetCount) {
|
||||
case RESISTANCE_FIRE:
|
||||
result = damageType1(); break;
|
||||
case RESISTANCE_COLD:
|
||||
result = damageType2(); break;
|
||||
case RESISTANCE_ELECTRICITY:
|
||||
result = damageType3(); break;
|
||||
case RESISTANCE_ACID:
|
||||
result = damageType4(); break;
|
||||
case RESISTANCE_FEAR:
|
||||
result = damageType5(); break;
|
||||
case RESISTANCE_POISON:
|
||||
result = damageType6(); break;
|
||||
case RESISTANCE_PSYCHIC:
|
||||
result = damageType7(); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
if (g_globals->_spellsState._mmVal5) {
|
||||
_damage >>= 2;
|
||||
} else {
|
||||
add(STRING["monster_spells.not_affected"]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpellsMonsters::writeDamage() {
|
||||
add(STRING["monster_spells.takes"]);
|
||||
add(Common::String::format("%d ", _damage));
|
||||
add(STRING[_damage > 1 ? "monster_spells.points" : "monster_spells.point"]);
|
||||
add(' ');
|
||||
|
||||
if (_lines.back()._text.size() >= 30)
|
||||
add('!');
|
||||
else
|
||||
add(STRING["monster_spells.of_damage"]);
|
||||
}
|
||||
|
||||
void SpellsMonsters::proc9() {
|
||||
const Character &c = *g_globals->_currCharacter;
|
||||
int val = c._level._current * 4 + c._luck._current;
|
||||
if (c._class == PALADIN)
|
||||
val += 20;
|
||||
|
||||
int randVal = getRandomNumber(100);
|
||||
g_globals->_spellsState._mmVal7 = randVal < 99 && randVal <= val ? 1 : 0;
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType1() {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._fire +
|
||||
g_globals->_activeSpells._s.fire;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType2() {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._cold +
|
||||
g_globals->_activeSpells._s.cold;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType3() {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._electricity +
|
||||
g_globals->_activeSpells._s.electricity;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType4() {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._acid +
|
||||
g_globals->_activeSpells._s.acid;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType5() {
|
||||
if (g_globals->_activeSpells._s.psychic_protection) {
|
||||
return false;
|
||||
} else {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._fear +
|
||||
g_globals->_activeSpells._s.fear;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType6() {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._poison +
|
||||
g_globals->_activeSpells._s.poison;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
|
||||
bool SpellsMonsters::damageType7() {
|
||||
if (g_globals->_activeSpells._s.psychic_protection) {
|
||||
return false;
|
||||
} else {
|
||||
int threshold = g_globals->_currCharacter->_resistances._s._psychic;
|
||||
return randomThreshold(threshold);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::writeConditionEffect() {
|
||||
g_globals->_spellsState._mmVal5 = 0;
|
||||
int effectNum;
|
||||
|
||||
if (!charAffected() || !isEffective() || !testElementalResistance())
|
||||
return;
|
||||
|
||||
if (g_globals->_spellsState._damage == 0) {
|
||||
effectNum = 10;
|
||||
} else if (g_globals->_spellsState._damage & BAD_CONDITION) {
|
||||
if (!(g_globals->_spellsState._damage & (BAD_CONDITION | DEAD)))
|
||||
effectNum = 7;
|
||||
else if (!(g_globals->_spellsState._damage & (BAD_CONDITION | STONE)))
|
||||
effectNum = 8;
|
||||
else if (g_globals->_spellsState._damage == ERADICATED)
|
||||
effectNum = 9;
|
||||
else
|
||||
effectNum = 10;
|
||||
} else {
|
||||
effectNum = 0;
|
||||
|
||||
for (byte bitset = g_globals->_spellsState._damage; bitset & 1;
|
||||
++effectNum, bitset >>= 1) {
|
||||
}
|
||||
}
|
||||
|
||||
add(STRING[Common::String::format("spells.char_effects.%d",
|
||||
effectNum)]);
|
||||
add('!');
|
||||
}
|
||||
|
||||
void SpellsMonsters::setCondition(byte newCondition) {
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
|
||||
if (!(c._condition & BAD_CONDITION)) {
|
||||
c._condition |= newCondition;
|
||||
} else if (newCondition & BAD_CONDITION) {
|
||||
c._condition = newCondition;
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::handlePartyEffects() {
|
||||
add(':');
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
g_globals->_currCharacter = &g_globals->_party[i];
|
||||
writeConditionEffect();
|
||||
}
|
||||
}
|
||||
|
||||
void SpellsMonsters::handlePartyDamage() {
|
||||
Character *tmp = g_globals->_currCharacter;
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
g_globals->_currCharacter = &g_globals->_party[i];
|
||||
handleDamage();
|
||||
}
|
||||
|
||||
g_globals->_currCharacter = tmp;
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
213
engines/mm/mm1/game/spells_monsters.h
Normal file
213
engines/mm/mm1/game/spells_monsters.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_SPELLS_MONSTERS
|
||||
#define MM1_GAME_SPELLS_MONSTERS
|
||||
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/messages.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
#define MAX_COMBAT_MONSTERS 15
|
||||
#define MONSTER_SPELLS_COUNT 32
|
||||
|
||||
class SpellsMonsters;
|
||||
typedef void (SpellsMonsters::*SpellMonstersSpell)();
|
||||
|
||||
class SpellsMonsters : public GameLogic {
|
||||
private:
|
||||
static const SpellMonstersSpell SPELLS[MONSTER_SPELLS_COUNT];
|
||||
|
||||
void spell01_curse();
|
||||
void spell02_energyBlast();
|
||||
void spell03_fire();
|
||||
void spell04_blindness();
|
||||
void spell05_sprayPoison();
|
||||
void spell06_sprayAcid();
|
||||
void spell07_sleep();
|
||||
void spell08_paralyze();
|
||||
void spell09_dispel();
|
||||
void spell10_lightningBolt();
|
||||
void spell11_strangeGas();
|
||||
void spell12_explode();
|
||||
void spell13_fireball();
|
||||
void spell14_fireBreath();
|
||||
void spell15_gazes();
|
||||
void spell16_acidArrow();
|
||||
void spell17_elements();
|
||||
void spell18_coldBeam();
|
||||
void spell19_dancingSword();
|
||||
void spell20_magicDrain();
|
||||
void spell21_fingerOfDeath();
|
||||
void spell22_sunRay();
|
||||
void spell23_disintegration();
|
||||
void spell24_commandsEnergy();
|
||||
void spell25_poison();
|
||||
void spell26_lightning();
|
||||
void spell27_frost();
|
||||
void spell28_spikes();
|
||||
void spell29_acid();
|
||||
void spell30_fire();
|
||||
void spell31_energy();
|
||||
void spell32_swarm();
|
||||
|
||||
/**
|
||||
* Called to determine whether the spell can be cast
|
||||
*/
|
||||
bool casts();
|
||||
|
||||
/**
|
||||
* Selects a random character and applies the damage to them
|
||||
*/
|
||||
void damageRandomChar();
|
||||
|
||||
/**
|
||||
* Randomly chooses a character in the party
|
||||
*/
|
||||
void chooseCharacter();
|
||||
|
||||
/**
|
||||
* Checks whether the character is affected by the spell,
|
||||
* and if so writes out the damage and whether the
|
||||
* character is knocked unconscious or dies
|
||||
*/
|
||||
void handleDamage();
|
||||
|
||||
/**
|
||||
* Checks if character is affected by spell,
|
||||
* and adds to the message if not
|
||||
*/
|
||||
bool charAffected();
|
||||
|
||||
/**
|
||||
* Checks random range
|
||||
*/
|
||||
bool randomThreshold(int threshold) const {
|
||||
int v = getRandomNumber(120);
|
||||
return v < 3 || v >= threshold;
|
||||
}
|
||||
|
||||
bool isEffective();
|
||||
|
||||
/**
|
||||
* Writes out how much damage the character suffers
|
||||
*/
|
||||
void writeDamage();
|
||||
|
||||
bool testElementalResistance();
|
||||
|
||||
/**
|
||||
* Adds different spell effects to the lines
|
||||
*/
|
||||
void writeConditionEffect();
|
||||
|
||||
/**
|
||||
* Adds text for condition effects on the party
|
||||
*/
|
||||
void handlePartyEffects();
|
||||
|
||||
protected:
|
||||
Common::Array<Monster *> _remainingMonsters;
|
||||
LineArray _lines;
|
||||
int _damage = 0, _displayedDamage = 0;
|
||||
|
||||
virtual bool canMonsterCast() const = 0;
|
||||
virtual int getMonsterIndex() const = 0;
|
||||
virtual void dispelParty() = 0;
|
||||
virtual void removeMonster() = 0;
|
||||
|
||||
/**
|
||||
* Subtracts the damage from the character, making
|
||||
* them unconscious or die if needed
|
||||
*/
|
||||
virtual Common::String subtractDamageFromChar() = 0;
|
||||
|
||||
/**
|
||||
* Adds text for damage effects on the party
|
||||
*/
|
||||
void handlePartyDamage();
|
||||
|
||||
/**
|
||||
* Sets the condition to apply
|
||||
*/
|
||||
void setCondition(byte newCondition);
|
||||
|
||||
/**
|
||||
* Returns true if character is affected so spell
|
||||
*/
|
||||
bool isCharAffected() const;
|
||||
|
||||
/**
|
||||
* Test whether character resists different damage types
|
||||
*/
|
||||
bool damageType1();
|
||||
bool damageType2();
|
||||
bool damageType3();
|
||||
bool damageType4();
|
||||
bool damageType5();
|
||||
bool damageType6();
|
||||
bool damageType7();
|
||||
|
||||
void proc9();
|
||||
|
||||
/**
|
||||
* Adds text to the current line
|
||||
*/
|
||||
void add(const Common::String &msg) {
|
||||
_lines.back()._text += msg;
|
||||
}
|
||||
void add(char c) {
|
||||
_lines.back()._text += c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds current character's name
|
||||
*/
|
||||
void addCharName();
|
||||
|
||||
public:
|
||||
SpellsMonsters();
|
||||
virtual ~SpellsMonsters() {}
|
||||
|
||||
/**
|
||||
* Monster casts a spell
|
||||
*/
|
||||
void castMonsterSpell(const Common::String &monsterName, int spellNum);
|
||||
|
||||
/**
|
||||
* Gets a spell message
|
||||
*/
|
||||
const LineArray &getMonsterSpellMessage() const {
|
||||
return _lines;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
1002
engines/mm/mm1/game/spells_party.cpp
Normal file
1002
engines/mm/mm1/game/spells_party.cpp
Normal file
File diff suppressed because it is too large
Load Diff
188
engines/mm/mm1/game/spells_party.h
Normal file
188
engines/mm/mm1/game/spells_party.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_SPELLS_H
|
||||
#define MM1_GAME_SPELLS_H
|
||||
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
#include "mm/mm1/messages.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
#define CATEGORY_SPELLS_COUNT 47
|
||||
#define SPELLS_COUNT (CATEGORY_SPELLS_COUNT * 2)
|
||||
|
||||
enum SpellResult {
|
||||
SR_SUCCESS_DONE, SR_SUCCESS_SILENT, SR_FAILED
|
||||
};
|
||||
|
||||
extern byte FLY_MAP_ID1[20];
|
||||
extern byte FLY_MAP_ID2[20];
|
||||
extern byte FLY_MAP_X[20];
|
||||
extern byte FLY_MAP_Y[20];
|
||||
|
||||
class SpellsParty : public GameLogic {
|
||||
typedef SpellResult(*SpellFn)();
|
||||
private:
|
||||
static Character *_destChar;
|
||||
private:
|
||||
/**
|
||||
* Returns true if in combat
|
||||
*/
|
||||
static bool isInCombat();
|
||||
|
||||
/**
|
||||
* Restores an amount of Hp
|
||||
*/
|
||||
static void restoreHp(Character &c, uint16 hp);
|
||||
static void restoreHp(uint16 hp);
|
||||
|
||||
/**
|
||||
* Increases light duration
|
||||
*/
|
||||
static void addLight(int amount);
|
||||
|
||||
/**
|
||||
* Display a message
|
||||
*/
|
||||
static void display(const InfoMessage &msg);
|
||||
|
||||
private:
|
||||
static SpellResult cleric11_awaken();
|
||||
static SpellResult cleric12_bless();
|
||||
static SpellResult cleric13_blind();
|
||||
static SpellResult cleric14_firstAid();
|
||||
static SpellResult cleric15_light();
|
||||
static SpellResult cleric16_powerCure();
|
||||
static SpellResult cleric17_protectionFromFear();
|
||||
static SpellResult cleric18_turnUndead();
|
||||
static SpellResult cleric21_cureWounds();
|
||||
static SpellResult cleric22_heroism();
|
||||
static SpellResult cleric23_pain();
|
||||
static SpellResult cleric24_protectionFromCold();
|
||||
static SpellResult cleric25_protectionFromIce();
|
||||
static SpellResult cleric26_protectionFromPoison();
|
||||
static SpellResult cleric27_silence();
|
||||
static SpellResult cleric28_suggestion();
|
||||
static SpellResult cleric31_createFood();
|
||||
static SpellResult cleric32_cureBlindness();
|
||||
static SpellResult cleric33_cureParalysis();
|
||||
static SpellResult cleric34_lastingLight();
|
||||
static SpellResult cleric35_produceFlame();
|
||||
static SpellResult cleric36_produceFrost();
|
||||
static SpellResult cleric37_removeQuest();
|
||||
static SpellResult cleric38_walkOnWater();
|
||||
static SpellResult cleric41_cureDisease();
|
||||
static SpellResult cleric42_neutralizePoison();
|
||||
static SpellResult cleric43_protectionFromAcid();
|
||||
static SpellResult cleric44_protectionFromElectricity();
|
||||
static SpellResult cleric45_restoreAlignment();
|
||||
static SpellResult cleric46_summonLightning();
|
||||
static SpellResult cleric47_superHeroism();
|
||||
static SpellResult cleric48_surface();
|
||||
static SpellResult cleric51_deadlySwarm();
|
||||
static SpellResult cleric52_dispelMagic();
|
||||
static SpellResult cleric53_paralyze();
|
||||
static SpellResult cleric54_removeCondition();
|
||||
static SpellResult cleric55_restoreEnergy();
|
||||
static SpellResult cleric61_moonRay();
|
||||
static SpellResult cleric62_raiseDead();
|
||||
static SpellResult cleric63_rejuvinate();
|
||||
static SpellResult cleric64_stoneToFlesh();
|
||||
static SpellResult cleric65_townPortal();
|
||||
static SpellResult cleric71_divineIntervention();
|
||||
static SpellResult cleric72_holyWord();
|
||||
static SpellResult cleric73_protectionFromElements();
|
||||
static SpellResult cleric74_resurrection();
|
||||
static SpellResult cleric75_sunRay();
|
||||
|
||||
static SpellResult wizard11_awaken() {
|
||||
return cleric11_awaken();
|
||||
}
|
||||
static SpellResult wizard12_detectMagic();
|
||||
static SpellResult wizard13_energyBlast();
|
||||
static SpellResult wizard14_flameArrow();
|
||||
static SpellResult wizard15_leatherSkin();
|
||||
static SpellResult wizard16_light() {
|
||||
return cleric15_light();
|
||||
}
|
||||
static SpellResult wizard17_location();
|
||||
static SpellResult wizard18_sleep();
|
||||
static SpellResult wizard21_electricArrow();
|
||||
static SpellResult wizard22_hypnotize() {
|
||||
return cleric28_suggestion();
|
||||
}
|
||||
static SpellResult wizard23_identifyMonster();
|
||||
static SpellResult wizard24_jump();
|
||||
static SpellResult wizard25_levitate();
|
||||
static SpellResult wizard26_power();
|
||||
static SpellResult wizard27_quickness();
|
||||
static SpellResult wizard28_scare();
|
||||
static SpellResult wizard31_fireball();
|
||||
static SpellResult wizard32_fly();
|
||||
static SpellResult wizard33_invisibility();
|
||||
static SpellResult wizard34_lightningBolt();
|
||||
static SpellResult wizard35_makeRoom();
|
||||
static SpellResult wizard36_slow();
|
||||
static SpellResult wizard37_weaken();
|
||||
static SpellResult wizard38_web();
|
||||
static SpellResult wizard41_acidArrow();
|
||||
static SpellResult wizard42_coldBeam();
|
||||
static SpellResult wizard43_feebleMind();
|
||||
static SpellResult wizard44_freeze();
|
||||
static SpellResult wizard45_guardDog();
|
||||
static SpellResult wizard46_psychicProtection();
|
||||
static SpellResult wizard47_shield();
|
||||
static SpellResult wizard48_timeDistortion();
|
||||
static SpellResult wizard51_acidRain();
|
||||
static SpellResult wizard52_dispelMagic() {
|
||||
return cleric52_dispelMagic();
|
||||
}
|
||||
static SpellResult wizard53_fingerOfDeath();
|
||||
static SpellResult wizard54_shelter();
|
||||
static SpellResult wizard55_teleport();
|
||||
static SpellResult wizard61_dancingSword();
|
||||
static SpellResult wizard62_disintegration();
|
||||
static SpellResult wizard63_etherialize();
|
||||
static SpellResult wizard64_protectionFromMagic();
|
||||
static SpellResult wizard65_rechargeItem();
|
||||
static SpellResult wizard71_astralSpell();
|
||||
static SpellResult wizard72_duplication();
|
||||
static SpellResult wizard73_meteorShower();
|
||||
static SpellResult wizard74_powerShield();
|
||||
static SpellResult wizard75_prismaticLight();
|
||||
|
||||
static SpellFn SPELLS[SPELLS_COUNT];
|
||||
public:
|
||||
/**
|
||||
* Casts a spell
|
||||
*/
|
||||
static SpellResult cast(uint spell, Character *destChar);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
146
engines/mm/mm1/game/use_item.cpp
Normal file
146
engines/mm/mm1/game/use_item.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/* 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/use_item.h"
|
||||
#include "mm/mm1/game/equip_remove.h"
|
||||
#include "mm/mm1/game/combat.h"
|
||||
#include "mm/mm1/game/spells_party.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
|
||||
Common::String UseItem::combatUseItem(Inventory &inv, Inventory::Entry &invEntry,
|
||||
bool isEquipped) {
|
||||
Common::String msg;
|
||||
Item *item = g_globals->_items.getItem(invEntry._id);
|
||||
|
||||
if (!item->_tempBonus_id) {
|
||||
msg = STRING["dialogs.character.use_combat.no_special_power"];
|
||||
|
||||
} else if (item->_constBonus_id == IS_EQUIPPABLE || isEquipped) {
|
||||
if (invEntry._charges) {
|
||||
g_globals->_combatEffectCtr++;
|
||||
inv.removeCharge(&invEntry);
|
||||
|
||||
if (item->_tempBonus_id == 0xff) {
|
||||
setSpell(item->_spellId, 0, 0);
|
||||
Game::SpellsParty::cast(_spellIndex, g_globals->_currCharacter);
|
||||
|
||||
} else {
|
||||
// TODO: find out area of Character _effectId is used as an offset for
|
||||
//error("TODO: _effectId used as a character offset to increase attribute?");
|
||||
//add temporary equip bonus to character parameters
|
||||
applyItemBonus(item->_tempBonus_id, item->_tempBonus_value);
|
||||
|
||||
if (g_globals->_combatEffectCtr)
|
||||
(isEquipped ? &g_globals->_currCharacter->_equipped :
|
||||
&g_globals->_currCharacter->_backpack)->removeCharge(&invEntry);
|
||||
|
||||
g_globals->_party.updateAC();
|
||||
msg = STRING["dialogs.character.use_combat.done"];
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
msg = STRING["dialogs.character.use_combat.no_charges_left"];
|
||||
}
|
||||
} else {
|
||||
msg = STRING["dialogs.character.use_combat.not_equipped"];
|
||||
}
|
||||
|
||||
g_events->send("Combat", GameMessage("DISABLE_ATTACKS"));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
Common::String UseItem::nonCombatUseItem(Inventory &inv, Inventory::Entry &invEntry,
|
||||
bool isEquipped) {
|
||||
Common::String msg;
|
||||
Item *item = g_globals->_items.getItem(invEntry._id);
|
||||
|
||||
if (!item->_tempBonus_id) {
|
||||
msg = STRING["dialogs.character.use_noncombat.no_special_power"];
|
||||
|
||||
} else if (item->_constBonus_id == IS_EQUIPPABLE || isEquipped) {
|
||||
if (invEntry._charges) {
|
||||
g_globals->_nonCombatEffectCtr++;
|
||||
inv.removeCharge(&invEntry);
|
||||
|
||||
if (item->_tempBonus_id== 0xff) {
|
||||
setSpell(item->_spellId, 0, 0);
|
||||
SpellResult result = Game::SpellsParty::cast(_spellIndex, g_globals->_currCharacter);
|
||||
switch (result) {
|
||||
case SR_SUCCESS_DONE:
|
||||
msg = STRING["spells.done"];
|
||||
break;
|
||||
case SR_FAILED:
|
||||
msg = STRING["spells.failed"];
|
||||
break;
|
||||
case SR_SUCCESS_SILENT:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Add temorary equip bonus to character parameters
|
||||
applyItemBonus (item->_tempBonus_id, item->_tempBonus_value);
|
||||
|
||||
if (g_globals->_nonCombatEffectCtr)
|
||||
(isEquipped ? &g_globals->_currCharacter->_equipped :
|
||||
&g_globals->_currCharacter->_backpack)->removeCharge(&invEntry);
|
||||
|
||||
g_globals->_party.updateAC();
|
||||
msg = STRING["spells.done"];
|
||||
}
|
||||
} else {
|
||||
msg = STRING["dialogs.character.use_noncombat.no_charges_left"];
|
||||
}
|
||||
} else {
|
||||
msg = STRING["dialogs.character.use_noncombat.not_equipped"];
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
void UseItem::applyItemBonus(int id, int value){
|
||||
if ((id<2)||(id>=0xff)) return;
|
||||
Character &c = *g_globals->_currCharacter;
|
||||
switch (id) {
|
||||
case 24: c._might._current += value; break;
|
||||
case 30: c._speed._current += value; break;
|
||||
case 32: c._accuracy._current += value; break;
|
||||
case 34: c._luck._current += value; break;
|
||||
case 36: c._level._current += value; break;
|
||||
case 37: c._age += value; break;
|
||||
case 43: c._sp._current += value; break;
|
||||
case 48: c._spellLevel._current += value; break;
|
||||
case 49: c._gems += value; break;
|
||||
case 58: c._gold += 255*value; break;
|
||||
case 62: c._food += value; break;
|
||||
case 89: c._resistances._s._magic._current += value; break;
|
||||
case 99: c._resistances._s._fear._current += value; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
54
engines/mm/mm1/game/use_item.h
Normal file
54
engines/mm/mm1/game/use_item.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_USE_ITEM_H
|
||||
#define MM1_GAME_USE_ITEM_H
|
||||
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/game/spell_casting.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class UseItem : public MM1::Game::SpellCasting {
|
||||
public:
|
||||
/**
|
||||
* Using an item during combat
|
||||
*/
|
||||
Common::String combatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped);
|
||||
|
||||
/**
|
||||
* Using an item outside of combat
|
||||
*/
|
||||
Common::String nonCombatUseItem(Inventory &inv, Inventory::Entry &invEntry, bool isEquipped);
|
||||
|
||||
/**
|
||||
* Apply item to a character parameter
|
||||
*/
|
||||
void applyItemBonus(int id, int value);
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
250
engines/mm/mm1/game/view_base.cpp
Normal file
250
engines/mm/mm1/game/view_base.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/* 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 "common/util.h"
|
||||
#include "mm/mm1/game/view_base.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
ViewBase::ViewBase(UIElement *owner) : Views::TextView("View", owner) {
|
||||
}
|
||||
|
||||
void ViewBase::update() {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
Maps::Map &map = *maps._currentMap;
|
||||
|
||||
maps._mapOffset = maps._mapPos.y * MAP_W + maps._mapPos.x;
|
||||
maps._currentWalls = map._walls[maps._mapOffset];
|
||||
maps._currentState = map._states[maps._mapOffset];
|
||||
_isDark = false;
|
||||
|
||||
if (maps._currentState & Maps::CELL_DARK) {
|
||||
if (g_globals->_activeSpells._s.light) {
|
||||
g_globals->_activeSpells._s.light--;
|
||||
} else {
|
||||
goto darkness;
|
||||
}
|
||||
}
|
||||
|
||||
if ((map[Maps::MAP_FLAGS] & 1) && !g_globals->_activeSpells._s.light) {
|
||||
darkness:
|
||||
_isDark = true;
|
||||
}
|
||||
|
||||
// Refresh the view immediately, so things like the minimap will
|
||||
// update before special actions run
|
||||
g_events->redraw();
|
||||
g_events->drawElements();
|
||||
|
||||
// Encounter checks
|
||||
g_globals->_encounters._encounterType = NORMAL_SURPRISED;
|
||||
if (maps._currentState & Maps::CELL_SPECIAL) {
|
||||
map.visitedSpecial();
|
||||
draw();
|
||||
|
||||
map.special();
|
||||
return;
|
||||
|
||||
} else if (_stepRandom) {
|
||||
g_globals->_encounters._encounterType = NORMAL_ENCOUNTER;
|
||||
_stepRandom = false;
|
||||
g_globals->_encounters.execute();
|
||||
} else {
|
||||
g_globals->_party.checkPartyDead();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewBase::msgAction(const ActionMessage &msg) {
|
||||
switch (msg._action) {
|
||||
case KEYBIND_FORWARDS:
|
||||
case KEYBIND_STRAFE_LEFT:
|
||||
case KEYBIND_STRAFE_RIGHT:
|
||||
forward(msg._action);
|
||||
break;
|
||||
case KEYBIND_BACKWARDS:
|
||||
backwards();
|
||||
break;
|
||||
case KEYBIND_TURN_LEFT:
|
||||
turnLeft();
|
||||
break;
|
||||
case KEYBIND_TURN_RIGHT:
|
||||
turnRight();
|
||||
break;
|
||||
default:
|
||||
return TextView::msgAction(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewBase::msgFocus(const FocusMessage &msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewBase::msgGame(const GameMessage &msg) {
|
||||
if (msg._name == "DISPLAY") {
|
||||
replaceView("Game");
|
||||
return true;
|
||||
} else if (msg._name == "UPDATE") {
|
||||
replaceView("Game");
|
||||
update();
|
||||
return true;
|
||||
} else if (msg._name == "LOCATION") {
|
||||
_descriptionLine = STRING[Common::String::format(
|
||||
"dialogs.location.titles.%d", msg._value)];
|
||||
draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
return TextView::msgGame(msg);
|
||||
}
|
||||
|
||||
bool ViewBase::msgHeader(const HeaderMessage &msg) {
|
||||
_descriptionLine = msg._name;
|
||||
draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewBase::turnLeft() {
|
||||
g_globals->_maps.turnLeft();
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewBase::turnRight() {
|
||||
g_globals->_maps.turnRight();
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewBase::forward(KeybindingAction action) {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
Maps::Map &map = *g_globals->_maps._currentMap;
|
||||
|
||||
// Figure out direction mask
|
||||
byte mask = maps._forwardMask;
|
||||
if (action == KEYBIND_STRAFE_LEFT) {
|
||||
mask = maps._leftMask;
|
||||
} else if (action == KEYBIND_STRAFE_RIGHT) {
|
||||
mask = maps._rightMask;
|
||||
}
|
||||
|
||||
// Get the delta X/Y from the direction
|
||||
Common::Point delta = g_maps->getMoveDelta(mask);
|
||||
|
||||
// Check for obstructions
|
||||
if (!g_globals->_intangible) {
|
||||
if (maps._currentWalls & mask) {
|
||||
if (maps._currentState & 0x55 & mask) {
|
||||
obstructed(mask);
|
||||
redraw();
|
||||
return;
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (!(maps._currentWalls & mask & 0x55))
|
||||
offset = 1;
|
||||
else if (maps._currentWalls & mask & 0xaa)
|
||||
offset = 2;
|
||||
else
|
||||
offset = 0;
|
||||
|
||||
if (map.dataByte(Maps::MAP_30 + offset) == 4 &&
|
||||
!g_globals->_activeSpells._s.walk_on_water) {
|
||||
Sound::sound(SOUND_1);
|
||||
_dialogMessage = STRING["movement.obstructed.cant_swim"];
|
||||
redraw();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (maps._currentState & 0x55 & mask) {
|
||||
barrier();
|
||||
redraw();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_globals->_treasure.clear();
|
||||
|
||||
int maxVal = map[Maps::MAP_29];
|
||||
if (g_engine->getRandomNumber(maxVal) == maxVal)
|
||||
_stepRandom = true;
|
||||
|
||||
g_globals->_maps.step(delta);
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewBase::backwards() {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
Maps::Map &map = *g_globals->_maps._currentMap;
|
||||
Common::Point delta = g_maps->getMoveDelta(maps._backwardsMask);
|
||||
|
||||
if (!g_globals->_intangible) {
|
||||
if (maps._currentWalls & maps._backwardsMask) {
|
||||
Sound::sound(SOUND_1);
|
||||
g_globals->_party.checkPartyDead();
|
||||
return;
|
||||
}
|
||||
if (maps._currentState & 0x55 & maps._backwardsMask) {
|
||||
Sound::sound(SOUND_1);
|
||||
g_globals->_party.checkPartyDead();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_globals->_treasure.clear();
|
||||
|
||||
int maxVal = map[Maps::MAP_29];
|
||||
if (g_engine->getRandomNumber(maxVal) == maxVal)
|
||||
_stepRandom = true;
|
||||
|
||||
g_globals->_maps.step(delta);
|
||||
update();
|
||||
}
|
||||
|
||||
void ViewBase::obstructed(byte mask) {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
Maps::Map &map = *maps._currentMap;
|
||||
Sound::sound(SOUND_1);
|
||||
|
||||
int index = 32;
|
||||
if (!(maps._currentWalls & mask & 0x55))
|
||||
index = 31;
|
||||
else if (!(maps._currentWalls & mask & 0xaa))
|
||||
index = 30;
|
||||
|
||||
_dialogMessage = STRING[Common::String::format(
|
||||
"movement.obstructed.%d", map.dataByte(index))];
|
||||
}
|
||||
|
||||
void ViewBase::barrier() {
|
||||
_dialogMessage = STRING["movement.obstructed.barrier"];
|
||||
Sound::sound(SOUND_1);
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
92
engines/mm/mm1/game/view_base.h
Normal file
92
engines/mm/mm1/game/view_base.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_VIEW_BASE_H
|
||||
#define MM1_GAME_VIEW_BASE_H
|
||||
|
||||
#include "mm/mm1/views/text_view.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
/**
|
||||
* This acts as the base class for the 3d view
|
||||
* of the surroundings. It contains the all
|
||||
* the gameplay logic except for actual drawing.
|
||||
*/
|
||||
class ViewBase : public Views::TextView {
|
||||
protected:
|
||||
bool _isDark = false;
|
||||
Common::String _dialogMessage;
|
||||
bool _stepRandom = false;
|
||||
Common::String _descriptionLine;
|
||||
private:
|
||||
/**
|
||||
* Turn left
|
||||
*/
|
||||
void turnLeft();
|
||||
|
||||
/**
|
||||
* Turn right
|
||||
*/
|
||||
void turnRight();
|
||||
|
||||
/**
|
||||
* Move forwards
|
||||
*/
|
||||
void forward(KeybindingAction action);
|
||||
|
||||
/**
|
||||
* Move backwards
|
||||
*/
|
||||
void backwards();
|
||||
|
||||
/**
|
||||
* Forward movement is obstructed
|
||||
*/
|
||||
void obstructed(byte mask);
|
||||
|
||||
/**
|
||||
* Barrier blocking forward movement
|
||||
*/
|
||||
void barrier();
|
||||
|
||||
public:
|
||||
ViewBase(UIElement *owner);
|
||||
virtual ~ViewBase() {}
|
||||
|
||||
bool msgFocus(const FocusMessage &msg) override;
|
||||
bool msgHeader(const HeaderMessage &msg) override;
|
||||
bool msgGame(const GameMessage &msg) override;
|
||||
bool msgAction(const ActionMessage &msg) override;
|
||||
|
||||
/**
|
||||
* Updates game state
|
||||
*/
|
||||
void update();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
97
engines/mm/mm1/game/wheel_spin.cpp
Normal file
97
engines/mm/mm1/game/wheel_spin.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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/wheel_spin.h"
|
||||
#include "mm/mm1/maps/map16.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
#define VAL2 84
|
||||
#define VAL3 85
|
||||
#define VAL4 87
|
||||
|
||||
void WheelSpin::spin() {
|
||||
Maps::Map16 &map = *static_cast<Maps::Map16 *>(g_maps->_currentMap);
|
||||
_results.clear();
|
||||
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
g_globals->_currCharacter = &c;
|
||||
map[VAL2] = i;
|
||||
|
||||
// Count set flags
|
||||
map[VAL4] = 0;
|
||||
byte v = c._flags[2];
|
||||
for (int j = 0; j < 4; ++j, v >>= 1) {
|
||||
if (v & 1)
|
||||
map[VAL4]++;
|
||||
}
|
||||
|
||||
Common::String line;
|
||||
|
||||
if (map[VAL4] == 0) {
|
||||
line = STRING["maps.map16.loser"];
|
||||
} else {
|
||||
c._flags[2] |= CHARFLAG2_80;
|
||||
int val;
|
||||
|
||||
switch (getRandomNumber(6)) {
|
||||
case 1:
|
||||
val = 2000 << map[VAL4];
|
||||
WRITE_LE_UINT16(&map[VAL3], val);
|
||||
c._exp += val;
|
||||
line = Common::String::format("+%d %s", val,
|
||||
STRING["maps.map16.exp"].c_str());
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = 500 << map[VAL4];
|
||||
WRITE_LE_UINT16(&map[VAL3], val);
|
||||
c._gold += val;
|
||||
line = Common::String::format("+%d %s", val,
|
||||
STRING["maps.map16.gold"].c_str());
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = 15 << map[VAL4];
|
||||
WRITE_LE_UINT16(&map[VAL3], val);
|
||||
c._gems += val;
|
||||
line = Common::String::format("+%d %s", val,
|
||||
STRING["maps.map16.gems"].c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
line = STRING["maps.map16.loser"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_results.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
47
engines/mm/mm1/game/wheel_spin.h
Normal file
47
engines/mm/mm1/game/wheel_spin.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MM1_GAME_WHEEL_SPIN_H
|
||||
#define MM1_GAME_WHEEL_SPIN_H
|
||||
|
||||
#include "common/str-array.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Game {
|
||||
|
||||
class WheelSpin : public GameLogic {
|
||||
protected:
|
||||
Common::StringArray _results;
|
||||
public:
|
||||
/**
|
||||
* Spins the wheel for the party, and loads _results with
|
||||
* the result for each character
|
||||
*/
|
||||
void spin();
|
||||
};
|
||||
|
||||
} // namespace Game
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user