Initial commit
This commit is contained in:
5
engines/mm/POTFILES
Normal file
5
engines/mm/POTFILES
Normal file
@@ -0,0 +1,5 @@
|
||||
engines/mm/detection.cpp
|
||||
engines/mm/metaengine.cpp
|
||||
engines/mm/mm1/metaengine.cpp
|
||||
engines/mm/mm1/mm1.cpp
|
||||
engines/mm/xeen/saves.cpp
|
||||
5
engines/mm/configure.engine
Normal file
5
engines/mm/configure.engine
Normal file
@@ -0,0 +1,5 @@
|
||||
# This file is included from the main "configure" script
|
||||
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
|
||||
add_engine mm "Might and Magic" yes "mm1 xeen" "" "midi"
|
||||
add_engine mm1 "Might and Magic 1" yes
|
||||
add_engine xeen "Might and Magic Xeen" yes
|
||||
7
engines/mm/credits.pl
Normal file
7
engines/mm/credits.pl
Normal file
@@ -0,0 +1,7 @@
|
||||
begin_section("MM (Xeen)");
|
||||
add_person("Paul Gilbert", "dreammaster", "");
|
||||
add_person("Benoit Pierre", "benoit-pierre", "");
|
||||
add_person("", "TheDrakeRaider", "(M&M1 Gfx Mod)");
|
||||
add_person("David Goldsmith", "WizardStan", "(Xeen analysis)");
|
||||
add_person("Matt Taylor", "", "(Xeen analysis)");
|
||||
end_section();
|
||||
72
engines/mm/detection.cpp
Normal file
72
engines/mm/detection.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 "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "common/translation.h"
|
||||
#include "mm/detection.h"
|
||||
#include "mm/mm.h"
|
||||
|
||||
static const PlainGameDescriptor MIGHT_AND_MAGIC_GAMES[] = {
|
||||
{ "mm1", "Might and Magic: Book One - Secret of the Inner Sanctum"},
|
||||
{ "mm1_enh", "Might and Magic: Book One - Secret of the Inner Sanctum - Enhanced"},
|
||||
{ "cloudsofxeen", "Might and Magic IV: Clouds of Xeen" },
|
||||
{ "darksideofxeen", "Might and Magic V: Darkside of Xeen" },
|
||||
{ "worldofxeen", "Might and Magic: World of Xeen" },
|
||||
{ "swordsofxeen", "Might and Magic: Swords of Xeen" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const DebugChannelDef DEBUG_FLAT_LIST[] = {
|
||||
{ MM::kDebugPath, "Path", "Pathfinding debug level" },
|
||||
{ MM::kDebugScripts, "scripts", "Game scripts" },
|
||||
{ MM::kDebugGraphics, "graphics", "Graphics handling" },
|
||||
{ MM::kDebugSound, "sound", "Sound processing" },
|
||||
DEBUG_CHANNEL_END
|
||||
};
|
||||
|
||||
#include "mm/detection_tables.h"
|
||||
|
||||
class MMMetaEngineDetection : public AdvancedMetaEngineDetection<MM::MightAndMagicGameDescription> {
|
||||
public:
|
||||
MMMetaEngineDetection() : AdvancedMetaEngineDetection(MM::GAME_DESCRIPTIONS,
|
||||
MIGHT_AND_MAGIC_GAMES) {
|
||||
_maxScanDepth = 3;
|
||||
}
|
||||
|
||||
const char *getName() const override {
|
||||
return "mm";
|
||||
}
|
||||
|
||||
const char *getEngineName() const override {
|
||||
return "Might & Magic";
|
||||
}
|
||||
|
||||
const char *getOriginalCopyright() const override {
|
||||
return "Might And Magic games (C) 1986-1993 New World Computing, Inc.";
|
||||
}
|
||||
|
||||
const DebugChannelDef *getDebugChannels() const override {
|
||||
return DEBUG_FLAT_LIST;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_PLUGIN_STATIC(MM_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, MMMetaEngineDetection);
|
||||
60
engines/mm/detection.h
Normal file
60
engines/mm/detection.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 MM_DETECTION_H
|
||||
#define MM_DETECTION_H
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace MM {
|
||||
|
||||
enum {
|
||||
GType_MightAndMagic1,
|
||||
GType_Clouds,
|
||||
GType_DarkSide,
|
||||
GType_WorldOfXeen,
|
||||
GType_Swords
|
||||
};
|
||||
|
||||
enum GameFeature {
|
||||
GF_NONE = 0,
|
||||
GF_ENHANCED = 1,
|
||||
GF_GFX_PACK = 2
|
||||
};
|
||||
|
||||
struct MightAndMagicGameDescription {
|
||||
AD_GAME_DESCRIPTION_HELPERS(desc);
|
||||
|
||||
ADGameDescription desc;
|
||||
|
||||
int gameID;
|
||||
uint32 features;
|
||||
};
|
||||
|
||||
#define GAMEOPTION_SHOW_ITEM_COSTS GUIO_GAMEOPTIONS1
|
||||
#define GAMEOPTION_DURABLE_ARMOR GUIO_GAMEOPTIONS2
|
||||
#define GAMEOPTION_SHOW_HP_SP_BARS GUIO_GAMEOPTIONS3
|
||||
#define GAMEOPTION_COPY_PROTECTION GUIO_GAMEOPTIONS4
|
||||
#define GAMEOPTION_TTS GUIO_GAMEOPTIONS5
|
||||
|
||||
} // namespace MM
|
||||
|
||||
#endif // MM_DETECTION_H
|
||||
411
engines/mm/detection_tables.h
Normal file
411
engines/mm/detection_tables.h
Normal file
@@ -0,0 +1,411 @@
|
||||
/* 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 "engines/advancedDetector.h"
|
||||
#include "engines/mm/detection.h"
|
||||
|
||||
namespace MM {
|
||||
|
||||
#define GUIO_XEEN GUIO5(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR, GAMEOPTION_SHOW_HP_SP_BARS, GAMEOPTION_COPY_PROTECTION, GAMEOPTION_TTS)
|
||||
|
||||
static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
|
||||
{
|
||||
// Might and Magic 1
|
||||
{
|
||||
"mm1",
|
||||
nullptr,
|
||||
AD_ENTRY1s("wallpix.dta", "86a7ef03fd5bf434d83012b07fa92680", 123059),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GAMEOPTION_TTS)
|
||||
},
|
||||
GType_MightAndMagic1,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Might and Magic 1 (Enhanced)
|
||||
{
|
||||
"mm1_enh",
|
||||
nullptr,
|
||||
AD_ENTRY1s("wallpix.dta", "86a7ef03fd5bf434d83012b07fa92680", 123059),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GAMEOPTION_TTS)
|
||||
},
|
||||
GType_MightAndMagic1,
|
||||
GF_ENHANCED
|
||||
},
|
||||
|
||||
{
|
||||
// Might and Magic 1 (Gfx Pack)
|
||||
// This isn't directly supported, because using it would allow playing
|
||||
// the game without actually having the original game files
|
||||
{
|
||||
"mm1",
|
||||
nullptr,
|
||||
AD_ENTRY1s("wallpix.dta", "64af4dad1f86aedf307e8184a9f12ba9", 164220),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GAMEOPTION_TTS)
|
||||
},
|
||||
GType_MightAndMagic1,
|
||||
GF_GFX_PACK
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen
|
||||
{
|
||||
"worldofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY2s("xeen.cc", "0cffbab533d9afe140e69ec93096f43e", 13435646,
|
||||
"dark.cc", "df194483ecea6abc0511637d712ced7c", 11217676),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen (Monster Spawn Mod v1.0), Bugreport #12714
|
||||
{
|
||||
"worldofxeen",
|
||||
"Monster Spawn Mod v1.0",
|
||||
AD_ENTRY2s("xeen.cc", "37767811a52fb54a8f2be3b45acc91a9", 13536623,
|
||||
"dark.cc", "a4dcb0731ad3818fdd908f17230ee773", 11222393),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen (Bestseller Games Magazine #6 + #8 German)
|
||||
{
|
||||
"worldofxeen",
|
||||
nullptr,
|
||||
{
|
||||
{"xeen.cc", 0, "f4e4b3ddc43bd102dbe1637f480f1fa1", 13214150},
|
||||
{"dark.cc", 0, "84a86bbbc5f2fe96c0b0325485ed8203", 11173657},
|
||||
{"intro.cc", 0, "e47a7ab0223cf32b2d87eed91d024c35", 8899953},
|
||||
AD_LISTEND
|
||||
},
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen (GOG German)
|
||||
{
|
||||
"worldofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY2s("xeen.cc", "f4e4b3ddc43bd102dbe1637f480f1fa1", 13214150,
|
||||
"dark.cc", "84a86bbbc5f2fe96c0b0325485ed8203", 11168312),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen (2 CD talkie version)
|
||||
{
|
||||
"worldofxeen",
|
||||
"CD",
|
||||
AD_ENTRY2s("xeen.cc", "964078c53f649937ce9a1a3596ce3d9f", 13438429,
|
||||
"dark.cc", "7f755ce39ea614fa6adb016f8bfc6e43", 11288403),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen French- French untested
|
||||
// https://bugs.scummvm.org/ticket/12559
|
||||
{
|
||||
"worldofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY2s("xeen.cc", "b9bb33bbd3783e7930ddedb189d7ba54", 13203565,
|
||||
"dark.cc", "437618b6b5e76f174719dcb529edbfbb", 11152923),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen, Spanish fan-translation
|
||||
// https://bugs.scummvm.org/ticket/14976
|
||||
{
|
||||
"worldofxeen",
|
||||
"CD",
|
||||
AD_ENTRY2s("xeen.cc", "8ca98eba894b104e82963b0f4952e795", 13445166,
|
||||
"dark.cc", "9f319d7457e822f2484fa1daa26b2687", 11331280),
|
||||
Common::ES_ESP,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_CD,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// World of Xeen (DOS non-interactive demo)
|
||||
{
|
||||
"worldofxeen",
|
||||
"Non-Interactive Demo",
|
||||
AD_ENTRY1s("demo.cc", "bcd6775323833dc8dd2d930c3b98da03", 4556916),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE | ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
GType_WorldOfXeen,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen
|
||||
{
|
||||
"cloudsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("xeen.cc", "0cffbab533d9afe140e69ec93096f43e", 13435646),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen (GOG, Bestseller Games Magazine #6 German)
|
||||
{
|
||||
"cloudsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("xeen.cc", "f4e4b3ddc43bd102dbe1637f480f1fa1", 13214150),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen, Russian fan-translation
|
||||
{
|
||||
"cloudsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("xeen.cc", "1dead179f65bbb1ba11dd51d69768489", 13417817),
|
||||
Common::RU_RUS,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen (Chinese)
|
||||
{
|
||||
"cloudsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("xeen.cc", "1fea0587fe139b13f4effa2b5791bd80", 13859999),
|
||||
Common::ZH_TWN,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen- French untested
|
||||
// https://bugs.scummvm.org/ticket/12557
|
||||
{
|
||||
"cloudsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("xeen.cc", "b9bb33bbd3783e7930ddedb189d7ba54", 13203565),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Clouds of Xeen (DOS non-interactive demo)
|
||||
{
|
||||
"cloudsofxeen",
|
||||
"Non-Interactive Demo",
|
||||
AD_ENTRY1s("logobak.raw", "68425e43f4b0c74f5ff448d1f3c9855c", 64000),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE | ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
GType_Clouds,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen
|
||||
{
|
||||
"darksideofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("dark.cc", "df194483ecea6abc0511637d712ced7c", 11217676),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen (GOG German)
|
||||
{
|
||||
"darksideofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("dark.cc", "84a86bbbc5f2fe96c0b0325485ed8203", 11168312),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen (Bestseller Games Magazine #8 German)
|
||||
{
|
||||
"darksideofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY2s("dark.cc", "84a86bbbc5f2fe96c0b0325485ed8203", 11173657,
|
||||
"intro.cc", "e47a7ab0223cf32b2d87eed91d024c35", 8899953),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen (Chinese)
|
||||
{
|
||||
"darksideofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("dark.cc", "4dcbcdb0be885afebc2ab6c9e60c434e", 11137412),
|
||||
Common::ZH_TWN,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen- French untested
|
||||
// https://bugs.scummvm.org/ticket/12558
|
||||
{
|
||||
"darksideofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("dark.cc", "437618b6b5e76f174719dcb529edbfbb", 11152923),
|
||||
Common::FR_FRA,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Darkside of Xeen (DOS non-interactive demo)
|
||||
{
|
||||
"darksideofxeen",
|
||||
"Non-Interactive Demo",
|
||||
AD_ENTRY1s("demo.cc", "2c320db380a479652a27a604c7c357b6", 5017135),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_UNSTABLE | ADGF_DEMO,
|
||||
GUIO0()
|
||||
},
|
||||
GType_DarkSide,
|
||||
0
|
||||
},
|
||||
|
||||
{
|
||||
// Swords of Xeen
|
||||
{
|
||||
"swordsofxeen",
|
||||
nullptr,
|
||||
AD_ENTRY1s("swrd.cc", "0d51c3457070cc7d1a596da9241924a5", 13026924),
|
||||
Common::EN_ANY,
|
||||
Common::kPlatformDOS,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO_XEEN
|
||||
},
|
||||
GType_Swords,
|
||||
0
|
||||
},
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0, 0 }
|
||||
};
|
||||
|
||||
} // End of namespace MM
|
||||
213
engines/mm/metaengine.cpp
Normal file
213
engines/mm/metaengine.cpp
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/keymapper/action.h"
|
||||
#include "backends/keymapper/keymap.h"
|
||||
#include "backends/keymapper/standard-actions.h"
|
||||
#include "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "mm/detection.h"
|
||||
#ifdef ENABLE_MM1
|
||||
#include "mm/mm1/mm1.h"
|
||||
#endif
|
||||
#ifdef ENABLE_XEEN
|
||||
#include "mm/xeen/xeen.h"
|
||||
#include "mm/xeen/metaengine.h"
|
||||
#include "mm/xeen/worldofxeen/worldofxeen.h"
|
||||
#include "mm/xeen/swordsofxeen/swordsofxeen.h"
|
||||
#endif
|
||||
|
||||
static const ADExtraGuiOptionsMap optionsList[] = {
|
||||
{
|
||||
GAMEOPTION_COPY_PROTECTION,
|
||||
{
|
||||
_s("Enable copy protection"),
|
||||
_s("Enable any copy protection that would otherwise be bypassed by default."),
|
||||
"copy_protection",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
},
|
||||
},
|
||||
{
|
||||
GAMEOPTION_SHOW_ITEM_COSTS,
|
||||
{
|
||||
_s("Show item costs in standard inventory mode"),
|
||||
_s("Shows item costs in standard inventory mode, allowing the value of items to be compared"),
|
||||
"ShowItemCosts",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_DURABLE_ARMOR,
|
||||
{
|
||||
_s("More durable armor"),
|
||||
_s("Armor won't break until character is at -80HP, rather than merely -10HP"),
|
||||
"DurableArmor",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
{
|
||||
GAMEOPTION_SHOW_HP_SP_BARS,
|
||||
{
|
||||
_s("Hitpoint bars"),
|
||||
_s("Replace a colored gem with bars for hit points and spell points."),
|
||||
"ShowHpSpBars",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
#ifdef USE_TTS
|
||||
{
|
||||
GAMEOPTION_TTS,
|
||||
{
|
||||
_s("Enable Text to Speech"),
|
||||
_s("Use TTS to read text in the game (if TTS is available)"),
|
||||
"tts_enabled",
|
||||
false,
|
||||
0,
|
||||
0
|
||||
}
|
||||
},
|
||||
#endif
|
||||
AD_EXTRA_GUI_OPTIONS_TERMINATOR
|
||||
};
|
||||
|
||||
class MMMetaEngine : public AdvancedMetaEngine<MM::MightAndMagicGameDescription> {
|
||||
private:
|
||||
/**
|
||||
* Gets the game Id given a target string
|
||||
*/
|
||||
static Common::String getGameId(const Common::String &target);
|
||||
|
||||
/**
|
||||
* Returns true if the game is a Xeen game
|
||||
*/
|
||||
static bool isXeenGame(const Common::String &target);
|
||||
public:
|
||||
const char *getName() const override {
|
||||
return "mm";
|
||||
}
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const override;
|
||||
Common::Error createInstance(OSystem *syst, Engine **engine, const MM::MightAndMagicGameDescription *desc) const override;
|
||||
SaveStateList listSaves(const char *target) const override;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
|
||||
Common::KeymapArray initKeymaps(const char *target) const override;
|
||||
|
||||
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
|
||||
return optionsList;
|
||||
}
|
||||
};
|
||||
|
||||
bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return checkExtendedSaves(f) ||
|
||||
(f == kSupportsLoadingDuringStartup);
|
||||
}
|
||||
|
||||
Common::Error MMMetaEngine::createInstance(OSystem *syst, Engine **engine, const MM::MightAndMagicGameDescription *gd) const {
|
||||
switch (gd->gameID) {
|
||||
#ifdef ENABLE_MM1
|
||||
case MM::GType_MightAndMagic1:
|
||||
*engine = new MM::MM1::MM1Engine(syst, gd);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_XEEN
|
||||
case MM::GType_Clouds:
|
||||
case MM::GType_DarkSide:
|
||||
case MM::GType_WorldOfXeen:
|
||||
*engine = new MM::Xeen::WorldOfXeen::WorldOfXeenEngine(syst, gd);
|
||||
break;
|
||||
case MM::GType_Swords:
|
||||
*engine = new MM::Xeen::SwordsOfXeen::SwordsOfXeenEngine(syst, gd);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return Common::kUnsupportedGameidError;
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
SaveStateList MMMetaEngine::listSaves(const char *target) const {
|
||||
#ifdef ENABLE_XEEN
|
||||
if (isXeenGame(target))
|
||||
// Fallback original code for Xeen
|
||||
return MM::Xeen::XeenMetaEngine::listSaves(this, target);
|
||||
#endif
|
||||
return AdvancedMetaEngine::listSaves(target);
|
||||
}
|
||||
|
||||
SaveStateDescriptor MMMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
#ifdef ENABLE_XEEN
|
||||
if (isXeenGame(target))
|
||||
// Fallback original code for Xeen
|
||||
return MM::Xeen::XeenMetaEngine::querySaveMetaInfos(this, target, slot);
|
||||
#endif
|
||||
|
||||
return AdvancedMetaEngine::querySaveMetaInfos(target, slot);
|
||||
}
|
||||
|
||||
Common::KeymapArray MMMetaEngine::initKeymaps(const char *target) const {
|
||||
#ifdef ENABLE_MM1
|
||||
const Common::String gameId = getGameId(target);
|
||||
if (gameId == "mm1" || gameId == "mm1_enh")
|
||||
return MM::MM1::MetaEngine::initKeymaps();
|
||||
#endif
|
||||
|
||||
return Common::KeymapArray();
|
||||
}
|
||||
|
||||
Common::String MMMetaEngine::getGameId(const Common::String &target) {
|
||||
// Store a copy of the active domain
|
||||
Common::String currDomain = ConfMan.getActiveDomainName();
|
||||
|
||||
// Switch to the given target domain and get it's game Id
|
||||
ConfMan.setActiveDomain(target);
|
||||
Common::String gameId = ConfMan.get("gameid");
|
||||
|
||||
// Switch back to the original domain and return the game Id
|
||||
ConfMan.setActiveDomain(currDomain);
|
||||
return gameId;
|
||||
}
|
||||
|
||||
bool MMMetaEngine::isXeenGame(const Common::String &target) {
|
||||
Common::String gameId = getGameId(target);
|
||||
if (gameId == "mm1" || gameId == "mm1_enh")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(MM)
|
||||
REGISTER_PLUGIN_DYNAMIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(MM, PLUGIN_TYPE_ENGINE, MMMetaEngine);
|
||||
#endif
|
||||
60
engines/mm/mm.cpp
Normal file
60
engines/mm/mm.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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/mm.h"
|
||||
|
||||
namespace MM {
|
||||
|
||||
MMEngine *g_engine;
|
||||
|
||||
MMEngine::MMEngine(OSystem *syst, const MM::MightAndMagicGameDescription *gameDesc) :
|
||||
Engine(syst), _gameDescription(gameDesc), _randomSource("MightAndMagic") {
|
||||
g_engine = this;
|
||||
}
|
||||
|
||||
bool MMEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsReturnToLauncher) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
uint32 MMEngine::getGameID() const {
|
||||
return _gameDescription->gameID;
|
||||
}
|
||||
|
||||
uint32 MMEngine::getFeatures() const {
|
||||
return _gameDescription->desc.flags;
|
||||
}
|
||||
|
||||
Common::Language MMEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
Common::Platform MMEngine::getPlatform() const {
|
||||
return _gameDescription->desc.platform;
|
||||
}
|
||||
|
||||
bool MMEngine::getIsCD() const {
|
||||
return getFeatures() & ADGF_CD;
|
||||
}
|
||||
|
||||
} // namespace MM
|
||||
87
engines/mm/mm.h
Normal file
87
engines/mm/mm.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 MM_MM_H
|
||||
#define MM_MM_H
|
||||
|
||||
#include "common/random.h"
|
||||
#include "mm/detection.h"
|
||||
|
||||
namespace MM {
|
||||
|
||||
enum MightAndMagicDebugChannels {
|
||||
kDebugPath = 1,
|
||||
kDebugScripts,
|
||||
kDebugGraphics,
|
||||
kDebugSound,
|
||||
};
|
||||
|
||||
class MMEngine : public Engine {
|
||||
protected:
|
||||
const MightAndMagicGameDescription *_gameDescription;
|
||||
Common::RandomSource _randomSource;
|
||||
public:
|
||||
MMEngine(OSystem *syst, const MM::MightAndMagicGameDescription *gameDesc);
|
||||
~MMEngine() override {}
|
||||
|
||||
/**
|
||||
* Checks for feature flag
|
||||
*/
|
||||
bool hasFeature(EngineFeature f) const override;
|
||||
|
||||
/**
|
||||
* Returns the features
|
||||
*/
|
||||
uint32 getFeatures() const;
|
||||
|
||||
/**
|
||||
* Returns the game language
|
||||
*/
|
||||
Common::Language getLanguage() const;
|
||||
|
||||
/**
|
||||
* Returns the game's platform
|
||||
*/
|
||||
Common::Platform getPlatform() const;
|
||||
|
||||
/**
|
||||
* Gets the game Id
|
||||
*/
|
||||
uint32 getGameID() const;
|
||||
|
||||
/**
|
||||
* Returns true if the game is the CD version
|
||||
*/
|
||||
bool getIsCD() const;
|
||||
|
||||
/**
|
||||
* Get a random number
|
||||
*/
|
||||
uint getRandomNumber(int max) {
|
||||
return _randomSource.getRandomNumber(max);
|
||||
}
|
||||
};
|
||||
|
||||
extern MMEngine *g_engine;
|
||||
|
||||
} // namespace MM
|
||||
|
||||
#endif // MM_MM_H
|
||||
493
engines/mm/mm1/console.cpp
Normal file
493
engines/mm/mm1/console.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
/* 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/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "mm/shared/utils/strings.h"
|
||||
#include "mm/mm1/console.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/game/spells_party.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
Console::Console() : GUI::Debugger() {
|
||||
registerCmd("dump_map", WRAP_METHOD(Console, cmdDumpMap));
|
||||
registerCmd("dump_monsters", WRAP_METHOD(Console, cmdDumpMonsters));
|
||||
registerCmd("dump_items", WRAP_METHOD(Console, cmdDumpItems));
|
||||
registerCmd("dump_roster", WRAP_METHOD(Console, cmdDumpRoster));
|
||||
registerCmd("map_string", WRAP_METHOD(Console, cmdMapString));
|
||||
registerCmd("map", WRAP_METHOD(Console, cmdMap));
|
||||
registerCmd("pos", WRAP_METHOD(Console, cmdPos));
|
||||
registerCmd("intangible", WRAP_METHOD(Console, cmdIntangible));
|
||||
registerCmd("cast", WRAP_METHOD(Console, cmdCast));
|
||||
registerCmd("spells", WRAP_METHOD(Console, cmdSpellsAll));
|
||||
registerCmd("encounter", WRAP_METHOD(Console, cmdEncounter));
|
||||
registerCmd("encounters", WRAP_METHOD(Console, cmdEncounters));
|
||||
registerCmd("specials", WRAP_METHOD(Console, cmdSpecials));
|
||||
registerCmd("special", WRAP_METHOD(Console, cmdSpecial));
|
||||
registerCmd("view", WRAP_METHOD(Console, cmdView));
|
||||
}
|
||||
|
||||
bool Console::cmdDumpMap(int argc, const char **argv) {
|
||||
Common::File f;
|
||||
Common::OutSaveFile *dest;
|
||||
|
||||
if (argc != 2) {
|
||||
debugPrintf("%s <roomNum>\n", argv[0]);
|
||||
} else {
|
||||
int mapId = strToInt(argv[1]);
|
||||
Maps::Map *map = g_globals->_maps.getMap(mapId);
|
||||
|
||||
// Dump the map data
|
||||
if (f.open("mazedata.dta")) {
|
||||
dest = g_system->getSavefileManager()->openForSaving(
|
||||
Common::String::format("map%.2d-maze.bin", mapId), false);
|
||||
assert(dest);
|
||||
byte buffer[512];
|
||||
|
||||
f.seek(mapId * 512);
|
||||
f.read(buffer, 512);
|
||||
dest->write(buffer, 512);
|
||||
|
||||
dest->finalize();
|
||||
delete dest;
|
||||
f.close();
|
||||
}
|
||||
|
||||
if (f.open(Common::Path(Common::String::format("%s.ovr", map->getName().c_str())))) {
|
||||
int magicId = f.readUint16LE();
|
||||
int codePtr = f.readUint16LE();
|
||||
int codeSize = f.readUint16LE();
|
||||
int dataPtr = f.readUint16LE();
|
||||
int dataSize = f.readUint16LE();
|
||||
int extrasSize = f.readUint16LE();
|
||||
int startPtr = f.readUint16LE();
|
||||
|
||||
assert(magicId == 0xf2);
|
||||
assert(startPtr >= codePtr &&
|
||||
startPtr < (codePtr + codeSize));
|
||||
|
||||
dest = g_system->getSavefileManager()->openForSaving(
|
||||
Common::String::format("map%.2d-code.bin", mapId), false);
|
||||
byte *code = new byte[codeSize];
|
||||
f.read(code, codeSize);
|
||||
|
||||
for (int i = 0; i < (codePtr % 16); ++i)
|
||||
dest->writeByte(0);
|
||||
dest->write(code, codeSize);
|
||||
dest->flush();
|
||||
delete dest;
|
||||
delete[] code;
|
||||
|
||||
dest = g_system->getSavefileManager()->openForSaving(
|
||||
Common::String::format("map%.2d-data.bin", mapId), false);
|
||||
byte *data = new byte[dataSize];
|
||||
f.read(data, dataSize);
|
||||
dest->write(data, dataSize);
|
||||
dest->flush();
|
||||
delete dest;
|
||||
delete[] data;
|
||||
|
||||
f.close();
|
||||
|
||||
debugPrintf("data: ptr=%xh, size=%xh\n", dataPtr, dataSize);
|
||||
debugPrintf("code: ptr=%xh, size=%xh start=%xh\n",
|
||||
codePtr, codeSize, startPtr);
|
||||
debugPrintf("Extras size=%xh\n", extrasSize);
|
||||
}
|
||||
|
||||
debugPrintf("Done.\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdDumpMonsters(int argc, const char **argv) {
|
||||
Common::File f;
|
||||
Common::DumpFile df;
|
||||
if (f.open("mm.exe")) {
|
||||
if (df.open("monsters.txt")) {
|
||||
f.seek(0x1b312);
|
||||
|
||||
for (int i = 0; i < 195; ++i) {
|
||||
Common::String line = "\"";
|
||||
for (int j = 0; j < 15; ++j)
|
||||
line += f.readByte();
|
||||
line += '"';
|
||||
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
line += ", ";
|
||||
int val = (j == 7) ? f.readUint16LE() : f.readByte();
|
||||
line += Common::String::format("%d", val);
|
||||
}
|
||||
|
||||
df.writeString(line);
|
||||
df.writeByte('\n');
|
||||
}
|
||||
|
||||
df.close();
|
||||
f.close();
|
||||
debugPrintf("Done\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
debugPrintf("Could not create\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdDumpItems(int argc, const char **argv) {
|
||||
Common::File f;
|
||||
Common::DumpFile df;
|
||||
Common::String line;
|
||||
|
||||
if (f.open("mm.exe")) {
|
||||
if (df.open("items.txt")) {
|
||||
f.seek(0x19b2a);
|
||||
|
||||
for (int i = 0; i < 255; ++i) {
|
||||
if (i == 85) {
|
||||
// Add the blank unused item line
|
||||
line = "\" \", 0, 0, 0, 0, 0, 0, 0, 0, 0";
|
||||
df.writeString(line);
|
||||
df.writeByte('\n');
|
||||
}
|
||||
|
||||
line = "\"";
|
||||
for (int j = 0; j < 14; ++j)
|
||||
line += f.readByte();
|
||||
line += '"';
|
||||
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
line += ", ";
|
||||
line += Common::String::format("%d",
|
||||
(j == 6) ? f.readUint16BE() : f.readByte());
|
||||
}
|
||||
|
||||
df.writeString(line);
|
||||
df.writeByte('\n');
|
||||
}
|
||||
|
||||
df.close();
|
||||
f.close();
|
||||
debugPrintf("Done\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
debugPrintf("Could not create\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdDumpRoster(int argc, const char **argv) {
|
||||
g_globals->_roster.saveOriginal();
|
||||
debugPrintf("Dumped roster\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdMapString(int argc, const char **argv) {
|
||||
Common::File f;
|
||||
|
||||
if (argc != 3) {
|
||||
debugPrintf("%s <map Id> <offset>\n", argv[0]);
|
||||
} else {
|
||||
int mapId = strToInt(argv[1]);
|
||||
Maps::Map *map = g_globals->_maps.getMap(mapId);
|
||||
int offset = strToInt(Common::String::format(
|
||||
"%sh", argv[2]).c_str());
|
||||
|
||||
if (!f.open(Common::Path(Common::String::format("%s.ovr", map->getName().c_str()))))
|
||||
error("Failed to open map");
|
||||
|
||||
f.readUint16LE();
|
||||
f.readUint16LE();
|
||||
int codeSize = f.readUint16LE();
|
||||
int dataPtr = f.readUint16LE();
|
||||
f.readUint16LE();
|
||||
f.readUint16LE();
|
||||
f.readUint16LE();
|
||||
|
||||
f.skip(codeSize);
|
||||
f.skip(offset - dataPtr);
|
||||
|
||||
// Read the string
|
||||
Common::String s;
|
||||
char c;
|
||||
|
||||
while ((c = f.readByte()) != '\0') {
|
||||
if (c == '\r') {
|
||||
s += "\\n";
|
||||
debugPrintf("%s\n", s.c_str());
|
||||
s = "";
|
||||
} else {
|
||||
s += c;
|
||||
|
||||
if (s.size() == 40) {
|
||||
debugPrintf("%s\n", s.c_str());
|
||||
s = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
debugPrintf("%s\n", s.c_str());
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdMap(int argc, const char **argv) {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
|
||||
if (argc < 2) {
|
||||
debugPrintf("map <mapId section> | <mapNum [ xp, yp ]>\n");
|
||||
return true;
|
||||
|
||||
} else if (argc == 3) {
|
||||
int mapId = strToInt(argv[1]);
|
||||
int section = strToInt(argv[2]);
|
||||
maps.changeMap(mapId, section);
|
||||
|
||||
} else {
|
||||
int mapNum = strToInt(argv[1]);
|
||||
Maps::Map &map = *maps.getMap(mapNum);
|
||||
int x = g_maps->_mapPos.x, y = g_maps->_mapPos.y;
|
||||
|
||||
if (argc == 4) {
|
||||
x = strToInt(argv[2]);
|
||||
y = strToInt(argv[3]);
|
||||
}
|
||||
|
||||
maps._mapPos.x = x;
|
||||
maps._mapPos.y = y;
|
||||
maps.changeMap(map.getId(), map.getDefaultSection());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Console::cmdPos(int argc, const char **argv) {
|
||||
if (argc < 3) {
|
||||
debugPrintf("pos xp, yp\n");
|
||||
return true;
|
||||
} else {
|
||||
Maps::Maps &maps = g_globals->_maps;
|
||||
maps._mapPos.x = strToInt(argv[1]);
|
||||
maps._mapPos.y = strToInt(argv[2]);
|
||||
g_events->send("Game", GameMessage("UPDATE"));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::cmdIntangible(int argc, const char **argv) {
|
||||
g_globals->_intangible = (argc < 2) || strcmp(argv[1], "off");
|
||||
debugPrintf("Intangibility is %s\n", g_globals->_intangible ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdCast(int argc, const char **argv) {
|
||||
if (argc != 3) {
|
||||
debugPrintf("%s <level> <number>\n", argv[0]);
|
||||
return true;
|
||||
} else {
|
||||
Character *c = g_globals->_currCharacter;
|
||||
if (!c || (c->_class != CLERIC && c->_class != SORCERER
|
||||
&& c->_class != ARCHER)) {
|
||||
uint i;
|
||||
for (i = 0; i < g_globals->_party.size(); ++i) {
|
||||
if (g_globals->_party[i]._class == SORCERER) {
|
||||
c = &g_globals->_party[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == g_globals->_party.size()) {
|
||||
debugPrintf("Could not find sorcerer in party\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int spellIndex = getSpellIndex(c, strToInt(argv[1]), strToInt(argv[2]));
|
||||
setSpell(spellIndex, 0, 0);
|
||||
Game::SpellsParty::cast(_spellIndex, c);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::cmdSpellsAll(int argc, const char **argv) {
|
||||
g_globals->_allSpells = (argc == 2) && !strcmp(argv[1], "on");
|
||||
debugPrintf("All spells is %s\n",
|
||||
g_globals->_allSpells ? "enabled" : "disabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdEncounter(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
debugPrintf("encounter <monster-num> [<level>, <# monsters>, <encounter type>]\n");
|
||||
return true;
|
||||
|
||||
} else {
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
int monsterNum = strToInt(argv[1]);
|
||||
if (monsterNum < 1 || monsterNum > MONSTERS_COUNT) {
|
||||
debugPrintf("monster-num must be between 1 and %d\n", MONSTERS_COUNT);
|
||||
return true;
|
||||
}
|
||||
int level = (argc == 3) ? strToInt(argv[2]) : 1;
|
||||
if (level < 1 || level >= 15)
|
||||
level = 1;
|
||||
|
||||
int count = (argc > 3) ? strToInt(argv[3]) : 1;
|
||||
int encType = (argc > 4) ? strToInt(argv[2]) :
|
||||
Game::NORMAL_ENCOUNTER;
|
||||
if (encType != -1 || encType == 0 || encType == 1)
|
||||
enc._encounterType = (Game::EncounterType)encType;
|
||||
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < count; ++i)
|
||||
enc.addMonster(monsterNum, level);
|
||||
|
||||
enc._manual = true;
|
||||
enc._levelIndex = 80;
|
||||
|
||||
bool monstersOn = g_globals->_encountersOn;
|
||||
g_globals->_encountersOn = true;
|
||||
enc.execute();
|
||||
g_globals->_encountersOn = monstersOn;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Console::cmdEncounters(int argc, const char **argv) {
|
||||
if (argc == 1) {
|
||||
g_globals->_encountersOn = !g_globals->_encountersOn;
|
||||
} else {
|
||||
g_globals->_encountersOn = !scumm_stricmp(argv[1], "on");
|
||||
}
|
||||
|
||||
debugPrintf("Encounters are %s\n",
|
||||
g_globals->_encountersOn ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdSpecials(int argc, const char **argv) {
|
||||
int count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
|
||||
|
||||
// List specials that have code attached
|
||||
for (int i = 0; i < count; ++i) {
|
||||
int mapOffset = g_maps->_currentMap->dataByte(51 + i);
|
||||
int x = mapOffset % MAP_W;
|
||||
int y = mapOffset / MAP_W;
|
||||
Common::String line = Common::String::format(
|
||||
"Special #%.2d - %d, %d (", i, x, y);
|
||||
|
||||
int dirMask = g_maps->_currentMap->dataByte(51 + i);
|
||||
if (dirMask & Maps::DIRMASK_N)
|
||||
line += "N,";
|
||||
if (dirMask & Maps::DIRMASK_S)
|
||||
line += "S,";
|
||||
if (dirMask & Maps::DIRMASK_E)
|
||||
line += "E,";
|
||||
if (dirMask & Maps::DIRMASK_W)
|
||||
line += "W,";
|
||||
|
||||
line.deleteLastChar();
|
||||
line += ')';
|
||||
debugPrintf("%s\n", line.c_str());
|
||||
}
|
||||
|
||||
// Iterate through the map to find special cells that are codeless
|
||||
int mapOffset = 0, i;
|
||||
for (int mapPos = 0; mapPos < (MAP_W * MAP_H); ++mapPos) {
|
||||
bool isSpecial = (g_maps->_currentMap->_states[mapPos]
|
||||
& Maps::CELL_SPECIAL) != 0;
|
||||
if (!isSpecial)
|
||||
continue;
|
||||
|
||||
int x = mapPos % MAP_W;
|
||||
int y = mapPos / MAP_W;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
mapOffset = g_maps->_currentMap->dataByte(51 + i);
|
||||
if (mapOffset == mapPos)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add row for special if there's no code handling
|
||||
if (i == count) {
|
||||
Common::String line = Common::String::format(
|
||||
"Special #-- - %d, %d", x, y);
|
||||
debugPrintf("%s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Console::cmdSpecial(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("special <num> to execute special in the current map\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
Maps::Maps &maps = *g_maps;
|
||||
Maps::Map &map = *g_maps->_currentMap;
|
||||
uint count = g_maps->_currentMap->dataByte(Maps::MAP_SPECIAL_COUNT);
|
||||
uint specialNum = strToInt(argv[1]);
|
||||
|
||||
if (specialNum > count) {
|
||||
debugPrintf("Invalid special number\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set new position
|
||||
maps._mapOffset = map[51 + specialNum];
|
||||
maps._mapPos.x = maps._mapOffset % 16;
|
||||
maps._mapPos.y = maps._mapOffset / 16;
|
||||
|
||||
// Rotate to find a direction that will trigger the special
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (maps._forwardMask & map[51 + count + specialNum])
|
||||
break;
|
||||
maps.turnLeft();
|
||||
}
|
||||
|
||||
// Execute the specials handler for the map
|
||||
map.special();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Console::cmdView(int argc, const char **argv) {
|
||||
if (argc != 2) {
|
||||
debugPrintf("view <view name>\n");
|
||||
return true;
|
||||
} else {
|
||||
g_events->addView(argv[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
116
engines/mm/mm1/console.h
Normal file
116
engines/mm/mm1/console.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/* 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 MM_MM1_CONSOLE_H
|
||||
#define MM_MM1_CONSOLE_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
#include "mm/mm1/game/spell_casting.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class Console : public GUI::Debugger, public MM1::Game::SpellCasting {
|
||||
protected:
|
||||
/**
|
||||
* Used to dump a map's code and data
|
||||
*/
|
||||
bool cmdDumpMap(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Dumps the monster list
|
||||
*/
|
||||
bool cmdDumpMonsters(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Dumps the item list
|
||||
*/
|
||||
bool cmdDumpItems(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Prints a string from within a map's data segment
|
||||
*/
|
||||
bool cmdMapString(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Toggles intangible mode, allowing walking through walls
|
||||
*/
|
||||
bool cmdIntangible(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Jumps to a given map, and optionally a given position
|
||||
*/
|
||||
bool cmdMap(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Changes the party's position in the current map
|
||||
*/
|
||||
bool cmdPos(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Casts a spell
|
||||
*/
|
||||
bool cmdCast(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Enables/disables casting any spell
|
||||
*/
|
||||
bool cmdSpellsAll(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Trigger an encounter
|
||||
*/
|
||||
bool cmdEncounter(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Turns encounters on or off
|
||||
*/
|
||||
bool cmdEncounters(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* List the special cells in the current map
|
||||
*/
|
||||
bool cmdSpecials(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Trigger a special in the current map
|
||||
*/
|
||||
bool cmdSpecial(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Add a specific view
|
||||
*/
|
||||
bool cmdView(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Dump the roster in the original roster.dat format
|
||||
*/
|
||||
bool cmdDumpRoster(int argc, const char **argv);
|
||||
|
||||
public:
|
||||
Console();
|
||||
~Console() override {}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
36
engines/mm/mm1/data/active_spells.cpp
Normal file
36
engines/mm/mm1/data/active_spells.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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/data/active_spells.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
void ActiveSpells::clear() {
|
||||
Common::fill(&_arr[0], &_arr[ACTIVE_SPELLS_COUNT], 0);
|
||||
}
|
||||
|
||||
void ActiveSpells::synchronize(Common::Serializer &s) {
|
||||
s.syncBytes(_arr, ACTIVE_SPELLS_COUNT);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
73
engines/mm/mm1/data/active_spells.h
Normal file
73
engines/mm/mm1/data/active_spells.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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_DATA_ACTIVE_SPELLS_H
|
||||
#define MM1_DATA_ACTIVE_SPELLS_H
|
||||
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define ACTIVE_SPELLS_COUNT 18
|
||||
|
||||
struct ActiveSpellsStruct {
|
||||
byte fear;
|
||||
byte cold;
|
||||
byte fire;
|
||||
byte poison;
|
||||
byte acid;
|
||||
byte electricity;
|
||||
byte magic;
|
||||
byte light;
|
||||
byte leather_skin;
|
||||
byte levitate;
|
||||
byte walk_on_water;
|
||||
byte guard_dog;
|
||||
byte psychic_protection;
|
||||
byte bless;
|
||||
byte invisbility;
|
||||
byte shield;
|
||||
byte power_shield;
|
||||
byte cursed;
|
||||
};
|
||||
|
||||
union ActiveSpells {
|
||||
ActiveSpellsStruct _s;
|
||||
byte _arr[ACTIVE_SPELLS_COUNT];
|
||||
|
||||
ActiveSpells() { clear(); }
|
||||
|
||||
/**
|
||||
* Clear the spells
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Synchronize spell data to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
754
engines/mm/mm1/data/character.cpp
Normal file
754
engines/mm/mm1/data/character.cpp
Normal file
@@ -0,0 +1,754 @@
|
||||
/* 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/algorithm.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/shared/utils/strings.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
static const int CLASS_HP_PER_LEVEL[6] = {
|
||||
12, 10, 10, 8, 6, 8
|
||||
};
|
||||
|
||||
Resistances::Resistances() {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
_arr[i].clear();
|
||||
}
|
||||
|
||||
void Resistances::synchronize(Common::Serializer &s) {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
_arr[i].synchronize(s);
|
||||
}
|
||||
|
||||
size_t Resistances::getPerformanceTotal() const {
|
||||
size_t total = 0;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
total += _arr[i].getPerformanceTotal();
|
||||
return total;
|
||||
}
|
||||
|
||||
void Inventory::clear() {
|
||||
_items.clear();
|
||||
_items.resize(INVENTORY_COUNT);
|
||||
}
|
||||
|
||||
void Inventory::synchronize(Common::Serializer &s, bool ids) {
|
||||
for (int i = 0; i < INVENTORY_COUNT; ++i)
|
||||
s.syncAsByte(ids ? _items[i]._id : _items[i]._charges);
|
||||
}
|
||||
|
||||
bool Inventory::empty() const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (_items[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Inventory::full() const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (!_items[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint Inventory::size() const {
|
||||
for (int i = INVENTORY_COUNT - 1; i >= 0; --i) {
|
||||
if (_items[i])
|
||||
return i + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint Inventory::add(byte id, byte charges) {
|
||||
uint idx = getFreeSlot();
|
||||
_items[idx]._id = id;
|
||||
_items[idx]._charges = charges;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
int Inventory::getFreeSlot() const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (!_items[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
error("Inventory is full");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Inventory::removeAt(uint idx) {
|
||||
_items.remove_at(idx);
|
||||
_items.push_back(Entry());
|
||||
}
|
||||
|
||||
void Inventory::remove(Entry *e) {
|
||||
int index = indexOf(e);
|
||||
assert(index >= 0);
|
||||
removeAt(index);
|
||||
}
|
||||
|
||||
int Inventory::indexOf(Entry *e) const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (e == &_items[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Inventory::indexOf(byte itemId) const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (_items[i]._id == itemId)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Inventory::hasCategory(CategoryFn fn) const {
|
||||
for (uint i = 0; i < INVENTORY_COUNT; ++i) {
|
||||
if (fn(_items[i]._id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Inventory::removeCharge(Entry *e) {
|
||||
if (e->_charges) {
|
||||
if (--e->_charges == 0)
|
||||
remove(e);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Inventory::getPerformanceTotal() const {
|
||||
size_t total = 0;
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
total += (size_t)(*this)[i]._id + (size_t)(*this)[i]._charges;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Character::Character() : PrimaryAttributes() {
|
||||
Common::fill(&_flags[0], &_flags[14], 0);
|
||||
}
|
||||
|
||||
void Character::synchronize(Common::Serializer &s, int portraitNum) {
|
||||
char name[16];
|
||||
if (s.isSaving()) {
|
||||
// Save the name in uppercase to match original
|
||||
Common::strlcpy(name, uppercase(_name).c_str(), 16);
|
||||
s.syncBytes((byte *)name, 16);
|
||||
} else {
|
||||
s.syncBytes((byte *)name, 16);
|
||||
name[15] = '\0';
|
||||
|
||||
if (g_engine->isEnhanced())
|
||||
Common::strlcpy(_name, camelCase(name).c_str(), 16);
|
||||
else
|
||||
Common::strlcpy(_name, uppercase(name).c_str(), 16);
|
||||
}
|
||||
|
||||
s.syncAsByte(_sex);
|
||||
s.syncAsByte(_alignmentInitial);
|
||||
s.syncAsByte(_alignment);
|
||||
s.syncAsByte(_race);
|
||||
s.syncAsByte(_class);
|
||||
|
||||
_intelligence.synchronize(s);
|
||||
_might.synchronize(s);
|
||||
_personality.synchronize(s);
|
||||
_endurance.synchronize(s);
|
||||
_speed.synchronize(s);
|
||||
_accuracy.synchronize(s);
|
||||
_luck.synchronize(s);
|
||||
_level.synchronize(s);
|
||||
s.syncAsByte(_age);
|
||||
s.syncAsByte(_ageDayCtr);
|
||||
|
||||
s.syncAsUint32LE(_exp);
|
||||
s.syncAsUint16LE(_sp._current);
|
||||
s.syncAsUint16LE(_sp._base);
|
||||
_spellLevel.synchronize(s);
|
||||
|
||||
s.syncAsUint16LE(_gems);
|
||||
s.syncAsUint16LE(_hpCurrent);
|
||||
s.syncAsUint16LE(_hp);
|
||||
s.syncAsUint16LE(_hpMax);
|
||||
|
||||
// Gold field is annoying by being 3 bytes
|
||||
uint goldLo = _gold & 0xffff;
|
||||
uint goldHi = _gold >> 16;
|
||||
s.syncAsUint16LE(goldLo);
|
||||
s.syncAsByte(goldHi);
|
||||
if (s.isLoading())
|
||||
_gold = goldLo | (goldHi << 16);
|
||||
|
||||
_ac.synchronize(s);
|
||||
s.syncAsByte(_food);
|
||||
s.syncAsByte(_condition);
|
||||
|
||||
_equipped.synchronize(s, true);
|
||||
_backpack.synchronize(s, true);
|
||||
_equipped.synchronize(s, false);
|
||||
_backpack.synchronize(s, false);
|
||||
|
||||
_resistances.synchronize(s);
|
||||
_physicalAttr.synchronize(s);
|
||||
_missileAttr.synchronize(s);
|
||||
|
||||
s.syncAsByte(_trapCtr);
|
||||
s.syncAsByte(_quest);
|
||||
s.syncAsByte(_worthiness);
|
||||
s.syncAsByte(_alignmentCtr);
|
||||
s.syncBytes(_flags, 14);
|
||||
|
||||
s.syncAsByte(_portrait);
|
||||
if (s.isLoading()) {
|
||||
if (portraitNum != -1)
|
||||
_portrait = portraitNum;
|
||||
if (_portrait >= NUM_PORTRAITS)
|
||||
// Ensure portrait number is valid
|
||||
_portrait = 0;
|
||||
}
|
||||
|
||||
if (s.isLoading())
|
||||
loadFaceSprites();
|
||||
}
|
||||
|
||||
void Character::loadFaceSprites() {
|
||||
if (_portrait != 0xff && g_engine->isEnhanced()) {
|
||||
Common::Path cname(Common::String::format("char%02d.fac",
|
||||
_portrait * 2 + (_sex == MALE ? 0 : 1) + 1));
|
||||
_faceSprites.load(cname);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::clear() {
|
||||
Common::fill(_name, _name + 16, 0);
|
||||
_sex = (Sex)0;
|
||||
_alignmentInitial = (Alignment)0;
|
||||
_alignment = (Alignment)0;
|
||||
_race = (Race)0;
|
||||
_class = (CharacterClass)0;
|
||||
_intelligence = _might = _personality = _endurance = 0;
|
||||
_speed = _accuracy = _luck = 0;
|
||||
_level = 1;
|
||||
_age = _ageDayCtr = 0;
|
||||
_exp = 0;
|
||||
_sp = 0;
|
||||
_spellLevel = 0;
|
||||
_gems = 0;
|
||||
_hpCurrent = _hp = _hpMax = 0;
|
||||
_gold = 0;
|
||||
_ac = 0;
|
||||
_food = 0;
|
||||
_condition = 0;
|
||||
_quest = 0;
|
||||
_equipped.clear();
|
||||
_backpack.clear();
|
||||
|
||||
_alignmentInitial = GOOD;
|
||||
_alignment = GOOD;
|
||||
_resistances._s._magic.clear();
|
||||
_resistances._s._fear.clear();
|
||||
_resistances._s._poison.clear();
|
||||
_resistances._s._psychic.clear();
|
||||
_trapCtr = _alignmentCtr = 0;
|
||||
|
||||
Common::fill(&_flags[0], &_flags[8], 0);
|
||||
}
|
||||
|
||||
|
||||
void Character::gatherGold() {
|
||||
uint total = 0;
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
total += g_globals->_party[i]._gold;
|
||||
g_globals->_party[i]._gold = 0;
|
||||
}
|
||||
|
||||
_gold = total;
|
||||
}
|
||||
|
||||
Character::TradeResult Character::trade(int whoTo, int itemIndex) {
|
||||
Character &dest = g_globals->_party[whoTo];
|
||||
if (&dest == this)
|
||||
return TRADE_SUCCESS;
|
||||
|
||||
if (dest._backpack.full())
|
||||
return TRADE_FULL;
|
||||
if (!_backpack[itemIndex])
|
||||
return TRADE_NO_ITEM;
|
||||
|
||||
Inventory::Entry e = _backpack[itemIndex];
|
||||
_backpack.removeAt(itemIndex);
|
||||
dest._backpack.add(e._id, e._charges);
|
||||
|
||||
return TRADE_SUCCESS;
|
||||
}
|
||||
|
||||
Character::LevelIncrease Character::increaseLevel() {
|
||||
++_level;
|
||||
++_age;
|
||||
if (_age > 220)
|
||||
_age = 220;
|
||||
_trapCtr += 2;
|
||||
|
||||
int classNum = _class == NONE ? ROBBER : _class;
|
||||
int newHP = g_engine->getRandomNumber(CLASS_HP_PER_LEVEL[classNum - 1]);
|
||||
|
||||
if (_endurance._base >= 40)
|
||||
newHP += 10;
|
||||
else if (_endurance._base >= 35)
|
||||
newHP += 9;
|
||||
else if (_endurance._base >= 30)
|
||||
newHP += 8;
|
||||
else if (_endurance._base >= 27)
|
||||
newHP += 7;
|
||||
else if (_endurance._base >= 24)
|
||||
newHP += 6;
|
||||
else if (_endurance._base >= 21)
|
||||
newHP += 5;
|
||||
else if (_endurance._base >= 19)
|
||||
newHP += 4;
|
||||
else if (_endurance._base >= 17)
|
||||
newHP += 3;
|
||||
else if (_endurance._base >= 15)
|
||||
newHP += 2;
|
||||
else if (_endurance._base >= 13)
|
||||
newHP += 1;
|
||||
else if (_endurance._base >= 9)
|
||||
newHP += 0;
|
||||
else if (_endurance._base >= 7)
|
||||
newHP = MAX(newHP - 1, 1);
|
||||
else if (_endurance._base >= 5)
|
||||
newHP = MAX(newHP - 2, 1);
|
||||
else
|
||||
newHP = MAX(newHP - 3, 1);
|
||||
|
||||
_hpCurrent += newHP;
|
||||
_hp = _hpMax = _hpCurrent;
|
||||
|
||||
int gainedSpells = 0;
|
||||
if (classNum < ARCHER) {
|
||||
if (_level._base < 7)
|
||||
gainedSpells = 0;
|
||||
else if (_level._base == 7)
|
||||
gainedSpells = 1;
|
||||
else if (_level._base == 9)
|
||||
gainedSpells = 2;
|
||||
else if (_level._base == 11)
|
||||
gainedSpells = 3;
|
||||
else if (_level._base == 13)
|
||||
gainedSpells = 4;
|
||||
} else if (classNum < SORCERER) {
|
||||
if (_level._base == 3)
|
||||
gainedSpells = 2;
|
||||
else if (_level._base == 5)
|
||||
gainedSpells = 3;
|
||||
else if (_level._base == 7)
|
||||
gainedSpells = 4;
|
||||
else if (_level._base == 9)
|
||||
gainedSpells = 5;
|
||||
else if (_level._base == 11)
|
||||
gainedSpells = 6;
|
||||
else if (_level._base == 13)
|
||||
gainedSpells = 7;
|
||||
}
|
||||
|
||||
LevelIncrease result;
|
||||
result._numHP = newHP;
|
||||
result._numSpells = gainedSpells;
|
||||
return result;
|
||||
}
|
||||
|
||||
Character::BuyResult Character::buyItem(byte itemId) {
|
||||
// Check if backpack is full
|
||||
if (_backpack.full())
|
||||
return BUY_BACKPACK_FULL;
|
||||
|
||||
// Check character has enough gold
|
||||
g_globals->_items.getItem(itemId);
|
||||
Item &item = g_globals->_currItem;
|
||||
if (_gold < item._cost)
|
||||
return BUY_NOT_ENOUGH_GOLD;
|
||||
|
||||
// Add the item
|
||||
_gold -= item._cost;
|
||||
_backpack.add(itemId, item._maxCharges);
|
||||
|
||||
return BUY_SUCCESS;
|
||||
}
|
||||
|
||||
void Character::updateAttributes() {
|
||||
_intelligence.reset();
|
||||
_might.reset();
|
||||
_personality.reset();
|
||||
_endurance.reset();
|
||||
_speed.reset();
|
||||
_personality.reset();
|
||||
_endurance.reset();
|
||||
_speed.reset();
|
||||
_accuracy.reset();
|
||||
_luck.reset();
|
||||
_level.reset();
|
||||
_spellLevel.reset();
|
||||
}
|
||||
|
||||
void Character::updateAC() {
|
||||
int ac = _ac._base;
|
||||
|
||||
if (_speed >= 40)
|
||||
ac += 9;
|
||||
else if (_speed >= 35)
|
||||
ac += 8;
|
||||
else if (_speed >= 30)
|
||||
ac += 7;
|
||||
else if (_speed >= 25)
|
||||
ac += 6;
|
||||
else if (_speed >= 21)
|
||||
ac += 5;
|
||||
else if (_speed >= 19)
|
||||
ac += 4;
|
||||
else if (_speed >= 17)
|
||||
ac += 3;
|
||||
else if (_speed >= 15)
|
||||
ac += 2;
|
||||
else if (_speed >= 13)
|
||||
ac += 1;
|
||||
else if (_speed >= 9)
|
||||
ac += 0;
|
||||
else if (_speed >= 7)
|
||||
ac = MAX(ac - 1, 0);
|
||||
else if (_speed >= 5)
|
||||
ac = MAX(ac - 2, 0);
|
||||
else
|
||||
ac = MAX(ac - 3, 0);
|
||||
|
||||
_ac._current = ac;
|
||||
}
|
||||
|
||||
void Character::updateSP() {
|
||||
int intelligence = _intelligence._current;
|
||||
int personality = _personality._current;
|
||||
int level = _level._current;
|
||||
int index = 3;
|
||||
AttributePair newSP;
|
||||
|
||||
// Spell points only relevant for spell casters
|
||||
if (_spellLevel._current) {
|
||||
int threshold = -1;
|
||||
if (_class == CLERIC)
|
||||
threshold = personality;
|
||||
else if (_class == SORCERER)
|
||||
threshold = intelligence;
|
||||
else if (level < 7)
|
||||
threshold = -1;
|
||||
else {
|
||||
level -= 6;
|
||||
threshold = (_class == PALADIN) ?
|
||||
personality : intelligence;
|
||||
}
|
||||
|
||||
if (threshold >= 40)
|
||||
index += 10;
|
||||
else if (threshold >= 35)
|
||||
index += 9;
|
||||
else if (threshold >= 30)
|
||||
index += 8;
|
||||
else if (threshold >= 27)
|
||||
index += 7;
|
||||
else if (threshold >= 24)
|
||||
index += 6;
|
||||
else if (threshold >= 21)
|
||||
index += 5;
|
||||
else if (threshold >= 19)
|
||||
index += 4;
|
||||
else if (threshold >= 17)
|
||||
index += 3;
|
||||
else if (threshold >= 15)
|
||||
index += 2;
|
||||
else if (threshold >= 13)
|
||||
index += 1;
|
||||
else if (threshold < 5)
|
||||
index -= 3;
|
||||
else if (threshold < 7)
|
||||
index -= 2;
|
||||
else if (threshold < 9)
|
||||
index -= 1;
|
||||
|
||||
// Calculate the SP
|
||||
newSP._base += index * level;
|
||||
newSP._current = newSP._base;
|
||||
}
|
||||
|
||||
// Set the character's new SP
|
||||
_sp = newSP;
|
||||
}
|
||||
|
||||
void Character::updateResistances() {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
_resistances._arr[i]._current = _resistances._arr[i]._base;
|
||||
}
|
||||
|
||||
Common::String Character::getConditionString() const {
|
||||
Common::String result;
|
||||
int cond = _condition;
|
||||
|
||||
if (cond == 0) {
|
||||
result += STRING["stats.conditions.good"];
|
||||
} else if (cond == ERADICATED) {
|
||||
result += STRING["stats.conditions.eradicated"];
|
||||
} else {
|
||||
if (cond & BAD_CONDITION) {
|
||||
// Fatal conditions
|
||||
if (cond & DEAD)
|
||||
result += STRING["stats.conditions.dead"] + ",";
|
||||
if (cond & STONE)
|
||||
result += STRING["stats.conditions.stone"] + ",";
|
||||
} else {
|
||||
if (cond & UNCONSCIOUS)
|
||||
result += STRING["stats.conditions.unconscious"] + ",";
|
||||
if (cond & PARALYZED)
|
||||
result += STRING["stats.conditions.paralyzed"] + ",";
|
||||
if (cond & POISONED)
|
||||
result += STRING["stats.conditions.poisoned"] + ",";
|
||||
if (cond & DISEASED)
|
||||
result += STRING["stats.conditions.diseased"] + ",";
|
||||
if (cond & SILENCED)
|
||||
result += STRING["stats.conditions.silenced"] + ",";
|
||||
if (cond & BLINDED)
|
||||
result += STRING["stats.conditions.blinded"] + ",";
|
||||
if (cond & ASLEEP)
|
||||
result += STRING["stats.conditions.asleep"] + ",";
|
||||
}
|
||||
|
||||
result.deleteLastChar();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Character::rest() {
|
||||
// Characters with a bad condition like
|
||||
// being stoned can't rest
|
||||
if (_condition & BAD_CONDITION)
|
||||
return;
|
||||
|
||||
updateSP();
|
||||
updateAttributes();
|
||||
updateAC();
|
||||
updateResistances();
|
||||
|
||||
_condition &= ~(ASLEEP | BLINDED | SILENCED |
|
||||
PARALYZED | UNCONSCIOUS);
|
||||
|
||||
if (_hpCurrent == 0)
|
||||
_hpCurrent = 1;
|
||||
|
||||
// Increment the day counter. When it overflows,
|
||||
// it's time to increment the character's age by a year
|
||||
if (_ageDayCtr++ > 255) {
|
||||
_ageDayCtr = 0;
|
||||
if (_age < 255)
|
||||
++_age;
|
||||
}
|
||||
|
||||
if ((g_engine->getRandomNumber(70) + 80) < _age) {
|
||||
// Older characters have a chance of falling unconscious
|
||||
_condition = UNCONSCIOUS | BAD_CONDITION;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fun fact: in the original if any of the attributes reach zero,
|
||||
// then it jumps to an instruction that jumps to itself, freezing the game.
|
||||
// For ScummVM, I just limit the minimum to 1 instead
|
||||
if (_age >= 60) {
|
||||
_might._current = MAX(_might._current - 1, 1);
|
||||
_endurance._current = MAX(_endurance._current - 1, 1);
|
||||
_speed._current = MAX(_speed._current - 1, 1);
|
||||
}
|
||||
if (_age >= 70) {
|
||||
_might._current = MAX(_might._current - 1, 1);
|
||||
_endurance._current = MAX(_endurance._current - 1, 1);
|
||||
_speed._current = MAX(_speed._current - 1, 1);
|
||||
}
|
||||
|
||||
if (_age >= 80) {
|
||||
_might._current = MAX((int)_might._current - 2, 1);
|
||||
}
|
||||
|
||||
if (_food > 0) {
|
||||
--_food;
|
||||
|
||||
if (_condition & POISONED) {
|
||||
_hpMax /= 2;
|
||||
} else {
|
||||
_hpMax = _hp;
|
||||
}
|
||||
|
||||
if (!(_condition & DISEASED)) {
|
||||
_hpCurrent = _hpMax;
|
||||
_sp._current = _sp._base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Character::hasItem(byte itemId) const {
|
||||
return _backpack.indexOf(itemId) != -1 ||
|
||||
_equipped.indexOf(itemId) != -1;
|
||||
}
|
||||
|
||||
#define PERF16(x) ((x & 0xff) + ((x >> 8) & 0xff))
|
||||
#define PERF32(x) ((x & 0xff) + ((x >> 8) & 0xff) + \
|
||||
((x >> 16) & 0xff) + ((x >> 24) & 0xff))
|
||||
|
||||
size_t Character::getPerformanceTotal() const {
|
||||
size_t totalFlags = 0;
|
||||
for (int i = 0; i < 14; ++i)
|
||||
totalFlags += _flags[i];
|
||||
|
||||
return (int)_sex
|
||||
+ _alignmentInitial
|
||||
+ _alignment
|
||||
+ _race
|
||||
+ _class
|
||||
+ _intelligence.getPerformanceTotal()
|
||||
+ _might.getPerformanceTotal()
|
||||
+ _personality.getPerformanceTotal()
|
||||
+ _endurance.getPerformanceTotal()
|
||||
+ _speed.getPerformanceTotal()
|
||||
+ _accuracy.getPerformanceTotal()
|
||||
+ _luck.getPerformanceTotal()
|
||||
+ _level.getPerformanceTotal()
|
||||
+ (int)_age + (int)_ageDayCtr
|
||||
+ PERF32(_exp)
|
||||
+ _sp.getPerformanceTotal()
|
||||
+ _spellLevel.getPerformanceTotal()
|
||||
+ PERF16(_gems)
|
||||
+ PERF16(_hpCurrent)
|
||||
+ PERF16(_hp)
|
||||
+ PERF16(_hpMax)
|
||||
+ PERF32(_gold)
|
||||
+ _ac
|
||||
+ _food
|
||||
+ _condition
|
||||
+ _equipped.getPerformanceTotal()
|
||||
+ _backpack.getPerformanceTotal()
|
||||
+ _resistances.getPerformanceTotal()
|
||||
+ _physicalAttr.getPerformanceTotal()
|
||||
+ _missileAttr.getPerformanceTotal()
|
||||
+ _trapCtr
|
||||
+ _quest
|
||||
+ _worthiness
|
||||
+ _alignmentCtr
|
||||
+ totalFlags;
|
||||
}
|
||||
|
||||
byte Character::statColor(int amount, int threshold) const {
|
||||
if (amount < 1)
|
||||
return 6;
|
||||
else if (amount > threshold)
|
||||
return 2;
|
||||
else if (amount == threshold)
|
||||
return 15;
|
||||
else if (amount >= (threshold / 4))
|
||||
return 9;
|
||||
else
|
||||
return 32;
|
||||
}
|
||||
|
||||
byte Character::conditionColor() const {
|
||||
if (_condition == ERADICATED)
|
||||
return 32;
|
||||
else if (_condition == FINE)
|
||||
return 15;
|
||||
else if (_condition & BAD_CONDITION)
|
||||
return 6;
|
||||
else
|
||||
return 9;
|
||||
}
|
||||
|
||||
ConditionEnum Character::worstCondition() const {
|
||||
if (_condition == ERADICATED) {
|
||||
return C_ERADICATED;
|
||||
} else if (_condition & BAD_CONDITION) {
|
||||
if (_condition & DEAD)
|
||||
return C_DEAD;
|
||||
if (_condition & STONE)
|
||||
return C_STONE;
|
||||
if (_condition & UNCONSCIOUS)
|
||||
return C_UNCONSCIOUS;
|
||||
} else {
|
||||
if (_condition & PARALYZED)
|
||||
return C_PARALYZED;
|
||||
if (_condition & POISONED)
|
||||
return C_POISONED;
|
||||
if (_condition & DISEASED)
|
||||
return C_DISEASED;
|
||||
if (_condition & SILENCED)
|
||||
return C_SILENCED;
|
||||
if (_condition & BLINDED)
|
||||
return C_BLINDED;
|
||||
if (_condition & ASLEEP)
|
||||
return C_ASLEEP;
|
||||
}
|
||||
|
||||
return C_GOOD;
|
||||
}
|
||||
|
||||
Common::String Character::getConditionString(ConditionEnum cond) {
|
||||
switch (cond) {
|
||||
case C_ERADICATED: return STRING["stats.conditions.eradicated"];
|
||||
case C_DEAD: return STRING["stats.conditions.dead"];
|
||||
case C_STONE: return STRING["stats.conditions.stone"];
|
||||
case C_UNCONSCIOUS: return STRING["stats.conditions.unconscious"];
|
||||
case C_PARALYZED: return STRING["stats.conditions.paralyzed"];
|
||||
case C_POISONED: return STRING["stats.conditions.poisoned"];
|
||||
case C_DISEASED: return STRING["stats.conditions.diseased"];
|
||||
case C_SILENCED: return STRING["stats.conditions.silenced"];
|
||||
case C_BLINDED: return STRING["stats.conditions.blinded"];
|
||||
case C_ASLEEP: return STRING["stats.conditions.asleep"];
|
||||
default: return STRING["stats.conditions.good"];
|
||||
}
|
||||
}
|
||||
|
||||
int Character::spellNumber() const {
|
||||
return g_events->isInCombat() ? _combatSpell : _nonCombatSpell;
|
||||
}
|
||||
|
||||
void Character::setSpellNumber(int spellNum) {
|
||||
if (g_events->isInCombat())
|
||||
_combatSpell = spellNum;
|
||||
else
|
||||
_nonCombatSpell = spellNum;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
609
engines/mm/mm1/data/character.h
Normal file
609
engines/mm/mm1/data/character.h
Normal file
@@ -0,0 +1,609 @@
|
||||
/* 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_DATA_CHAR_H
|
||||
#define MM1_DATA_CHAR_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/items.h"
|
||||
#include "mm/shared/xeen/sprites.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define INVENTORY_COUNT 6
|
||||
#define MAX_LEVEL 200
|
||||
#define NUM_PORTRAITS 12
|
||||
|
||||
enum CharacterClass {
|
||||
KNIGHT = 1, PALADIN = 2, ARCHER = 3, CLERIC = 4,
|
||||
SORCERER = 5, ROBBER = 6, NONE = 0
|
||||
};
|
||||
|
||||
enum Race {
|
||||
HUMAN = 1, ELF = 2, DWARF = 3, GNOME = 4, HALF_ORC = 5
|
||||
};
|
||||
|
||||
enum Alignment {
|
||||
GOOD = 1, NEUTRAL = 2, EVIL = 3
|
||||
};
|
||||
|
||||
enum Sex {
|
||||
MALE = 1, FEMALE = 2, YES_PLEASE = 3
|
||||
};
|
||||
|
||||
enum Condition {
|
||||
FINE = 0, BAD_CONDITION = 0x80, ERADICATED = 0xff,
|
||||
DEAD = 0x40, STONE = 0x20,
|
||||
UNCONSCIOUS = 0x40, PARALYZED = 0x20, POISONED = 0x10,
|
||||
DISEASED = 8, SILENCED = 4, BLINDED = 2, ASLEEP = 1
|
||||
};
|
||||
|
||||
enum ConditionEnum {
|
||||
HEART_BROKEN = 1,
|
||||
C_BLINDED = 2, // WEAK condition in Xeen
|
||||
C_POISONED = 3,
|
||||
C_DISEASED = 4,
|
||||
C_ASLEEP = 8,
|
||||
DEPRESSED = 9,
|
||||
C_SILENCED = 10, // CONFUSED condition in Xeen
|
||||
C_PARALYZED = 11,
|
||||
C_UNCONSCIOUS = 12,
|
||||
C_DEAD = 13,
|
||||
C_STONE = 14,
|
||||
C_ERADICATED = 15,
|
||||
C_GOOD = 16
|
||||
};
|
||||
|
||||
enum Resistance {
|
||||
RESISTANCE_MAGIC = 0, RESISTANCE_FIRE = 1, RESISTANCE_COLD = 2,
|
||||
RESISTANCE_ELECTRICITY = 3, RESISTANCE_ACID = 4,
|
||||
RESISTANCE_FEAR = 5, RESISTANCE_POISON = 6,
|
||||
RESISTANCE_PSYCHIC = 7, RESISTANCE_15 = 15
|
||||
};
|
||||
|
||||
enum CharFlags0 {
|
||||
CHARFLAG0_COURIER1 = 1,
|
||||
CHARFLAG0_COURIER2 = 2,
|
||||
CHARFLAG0_COURIER3 = 4,
|
||||
CHARFLAG0_ZOM_CLUE = 8,
|
||||
CHARFLAG0_ZAM_CLUE = 0x10,
|
||||
CHARFLAG0_FOUND_CHEST = 0x20,
|
||||
CHARFLAG0_40 = 0x40,
|
||||
CHARFLAG0_DOG_STATUE = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags1 {
|
||||
CHARFLAG1_1 = 1,
|
||||
CHARFLAG1_2 = 2,
|
||||
CHARFLAG1_4 = 4,
|
||||
CHARFLAG1_8 = 8,
|
||||
CHARFLAG1_10 = 0x10,
|
||||
CHARFLAG1_20 = 0x20,
|
||||
CHARFLAG1_40 = 0x40,
|
||||
CHARFLAG1_WORTHY = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags2 {
|
||||
CHARFLAG2_1 = 1,
|
||||
CHARFLAG2_2 = 2,
|
||||
CHARFLAG2_4 = 4,
|
||||
CHARFLAG2_8 = 8,
|
||||
CHARFLAG2_10 = 0x10,
|
||||
CHARFLAG2_20 = 0x20,
|
||||
CHARFLAG2_40 = 0x40,
|
||||
CHARFLAG2_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags4 {
|
||||
CHARFLAG4_ASSIGNED = 8,
|
||||
CHARFLAG4_SIGN = 7,
|
||||
CHARFLAG4_COLOR = 0xf,
|
||||
CHARFLAG4_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags5 {
|
||||
CHARFLAG5_1 = 1,
|
||||
CHARFLAG5_2 = 2,
|
||||
CHARFLAG5_4 = 4,
|
||||
CHARFLAG5_8 = 8,
|
||||
CHARFLAG5_10 = 0x10,
|
||||
CHARFLAG5_20 = 0x20,
|
||||
CHARFLAG5_40 = 0x40,
|
||||
CHARFLAG5_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags6 {
|
||||
CHARFLAG6_1 = 1,
|
||||
CHARFLAG6_2 = 2,
|
||||
CHARFLAG6_4 = 4,
|
||||
CHARFLAG6_8 = 8,
|
||||
CHARFLAG6_10 = 0x10,
|
||||
CHARFLAG6_20 = 0x20,
|
||||
CHARFLAG6_40 = 0x40,
|
||||
CHARFLAG6_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags7 {
|
||||
CHARFLAG7_1 = 1,
|
||||
CHARFLAG7_2 = 2,
|
||||
CHARFLAG7_4 = 4,
|
||||
CHARFLAG7_8 = 8,
|
||||
CHARFLAG7_10 = 0x10,
|
||||
CHARFLAG7_20 = 0x20,
|
||||
CHARFLAG7_40 = 0x40,
|
||||
CHARFLAG7_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags8 {
|
||||
CHARFLAG8_1 = 1,
|
||||
CHARFLAG8_2 = 2,
|
||||
CHARFLAG8_4 = 4,
|
||||
CHARFLAG8_8 = 8,
|
||||
CHARFLAG8_10 = 0x10,
|
||||
CHARFLAG8_20 = 0x20,
|
||||
CHARFLAG8_40 = 0x40,
|
||||
CHARFLAG8_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags9 {
|
||||
CHARFLAG9_1 = 1,
|
||||
CHARFLAG9_2 = 2,
|
||||
CHARFLAG9_4 = 4,
|
||||
CHARFLAG9_8 = 8,
|
||||
CHARFLAG9_10 = 0x10,
|
||||
CHARFLAG9_20 = 0x20,
|
||||
CHARFLAG9_40 = 0x40,
|
||||
CHARFLAG9_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags10 {
|
||||
CHARFLAG10_1 = 1,
|
||||
CHARFLAG10_2 = 2,
|
||||
CHARFLAG10_4 = 4,
|
||||
CHARFLAG10_8 = 8,
|
||||
CHARFLAG10_10 = 0x10,
|
||||
CHARFLAG10_20 = 0x20,
|
||||
CHARFLAG10_40 = 0x40,
|
||||
CHARFLAG10_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags11 {
|
||||
CHARFLAG11_GOT_ENDURANCE = 1,
|
||||
CHARFLAG11_PERSONALITY = 2,
|
||||
CHARFLAG11_GOT_INTELLIGENCE = 4,
|
||||
CHARFLAG11_GOT_MIGHT = 8,
|
||||
CHARFLAG11_GOT_ACCURACY = 0x10,
|
||||
CHARFLAG11_GOT_SPEED = 0x20,
|
||||
CHARFLAG11_GOT_LUCK = 0x40,
|
||||
CHARFLAG11_CLERICS = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags12 {
|
||||
CHARFLAG12_1 = 1,
|
||||
CHARFLAG12_2 = 2,
|
||||
CHARFLAG12_4 = 4,
|
||||
CHARFLAG12_8 = 8,
|
||||
CHARFLAG12_10 = 0x10,
|
||||
CHARFLAG12_20 = 0x20,
|
||||
CHARFLAG12_40 = 0x40,
|
||||
CHARFLAG12_80 = 0x80
|
||||
};
|
||||
|
||||
enum CharFlags13 {
|
||||
CHARFLAG13_1 = 1,
|
||||
CHARFLAG13_2 = 2,
|
||||
CHARFLAG13_4 = 4,
|
||||
CHARFLAG13_8 = 8,
|
||||
CHARFLAG13_10 = 0x10,
|
||||
CHARFLAG13_20 = 0x20,
|
||||
CHARFLAG13_ALAMAR = 0x40,
|
||||
CHARFLAG13_80 = 0x80
|
||||
};
|
||||
|
||||
class Inventory {
|
||||
public:
|
||||
struct Entry {
|
||||
byte _id = 0;
|
||||
byte _charges = 0;
|
||||
operator bool() const { return _id != 0; }
|
||||
// bool operator!() const { return !_id; }
|
||||
// operator byte() const { return _id; }
|
||||
};
|
||||
private:
|
||||
Common::Array<Entry> _items;
|
||||
|
||||
/**
|
||||
* Used to test if the inventory has a category of item
|
||||
*/
|
||||
typedef bool (*CategoryFn)(byte id);
|
||||
bool hasCategory(CategoryFn fn) const;
|
||||
|
||||
/**
|
||||
* Returns the index of a free slot
|
||||
*/
|
||||
int getFreeSlot() const;
|
||||
|
||||
public:
|
||||
Inventory() {
|
||||
clear();
|
||||
}
|
||||
Entry &operator[](uint idx) {
|
||||
assert(idx < INVENTORY_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
const Entry &operator[](uint idx) const {
|
||||
assert(idx < INVENTORY_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves or loads the inventory data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, bool ids);
|
||||
|
||||
/**
|
||||
* Clears the inventory
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Returns true if the inventory is empty
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* Returns true if the inventory is full
|
||||
*/
|
||||
bool full() const;
|
||||
|
||||
/**
|
||||
* Returns the size of the backpack that's filled in
|
||||
*/
|
||||
uint size() const;
|
||||
|
||||
/**
|
||||
* Adds an item to the inventory
|
||||
*/
|
||||
uint add(byte id, byte charges);
|
||||
|
||||
/**
|
||||
* Removes an index from the inventory
|
||||
*/
|
||||
void removeAt(uint idx);
|
||||
|
||||
/**
|
||||
* Remove an entry from the inventory
|
||||
*/
|
||||
void remove(Entry *e);
|
||||
|
||||
/**
|
||||
* Returns the index of a given entry
|
||||
*/
|
||||
int indexOf(Entry *e) const;
|
||||
|
||||
/**
|
||||
* Returns the index of an entry with a given id
|
||||
*/
|
||||
int indexOf(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Decreases the charge on a magic item, and removes
|
||||
* it if the charges have run out
|
||||
*/
|
||||
void removeCharge(Entry *e);
|
||||
|
||||
/**
|
||||
* The following methods return true if any of
|
||||
* the contained items are of the given category
|
||||
*/
|
||||
bool hasWeapon() const { return hasCategory(isWeapon); }
|
||||
bool hasMissile() const { return hasCategory(isMissile); }
|
||||
bool hasTwoHanded() const { return hasCategory(isTwoHanded); }
|
||||
bool hasArmor() const { return hasCategory(isArmor); }
|
||||
bool hasShield() const { return hasCategory(isShield); }
|
||||
|
||||
size_t getPerformanceTotal() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attribute pair representing it's base value and the
|
||||
* current temporary value
|
||||
*/
|
||||
struct AttributePair {
|
||||
uint8 _current = 0;
|
||||
uint8 _base = 0;
|
||||
|
||||
operator uint8() const { return _current; }
|
||||
AttributePair &operator=(byte v) {
|
||||
_base = _current = v;
|
||||
return *this;
|
||||
}
|
||||
AttributePair &operator++() {
|
||||
if (_base < 255)
|
||||
_current = ++_base;
|
||||
return *this;
|
||||
}
|
||||
AttributePair &operator--() {
|
||||
if (_base > 0)
|
||||
_current = --_base;
|
||||
return *this;
|
||||
}
|
||||
void clear() { _current = _base = 0; }
|
||||
void reset() { _current = _base; }
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_base);
|
||||
s.syncAsByte(_current);
|
||||
}
|
||||
|
||||
size_t getPerformanceTotal() const {
|
||||
return (size_t)_base + (size_t)_current;
|
||||
}
|
||||
};
|
||||
|
||||
struct AttributePair16 {
|
||||
uint16 _current = 0;
|
||||
uint16 _base = 0;
|
||||
|
||||
void clear() { _current = _base = 0; }
|
||||
AttributePair16 &operator=(byte v) {
|
||||
_base = _current = v;
|
||||
return *this;
|
||||
}
|
||||
operator uint16() const {
|
||||
return _current;
|
||||
}
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsUint16LE(_base);
|
||||
s.syncAsUint16LE(_current);
|
||||
}
|
||||
|
||||
size_t getPerformanceTotal() const {
|
||||
return (_base & 0xff) + (_base >> 8) +
|
||||
(_current & 0xff) + (_current >> 8);
|
||||
}
|
||||
};
|
||||
|
||||
struct ResistanceFields {
|
||||
AttributePair _magic;
|
||||
AttributePair _fire;
|
||||
AttributePair _cold;
|
||||
AttributePair _electricity;
|
||||
AttributePair _acid;
|
||||
AttributePair _fear;
|
||||
AttributePair _poison;
|
||||
AttributePair _psychic;
|
||||
};
|
||||
|
||||
union Resistances {
|
||||
ResistanceFields _s;
|
||||
AttributePair _arr[8];
|
||||
|
||||
Resistances();
|
||||
|
||||
/**
|
||||
* Handles save/loading resistances
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
size_t getPerformanceTotal() const;
|
||||
};
|
||||
|
||||
struct PrimaryAttributes {
|
||||
public:
|
||||
AttributePair _intelligence;
|
||||
AttributePair _might;
|
||||
AttributePair _personality;
|
||||
AttributePair _endurance;
|
||||
AttributePair _speed;
|
||||
AttributePair _accuracy;
|
||||
AttributePair _luck;
|
||||
AttributePair _level;
|
||||
|
||||
AttributePair &getAttribute(uint i) {
|
||||
return *_attributes[i];
|
||||
}
|
||||
private:
|
||||
AttributePair *_attributes[8] = {
|
||||
&_intelligence, &_might, &_personality, &_endurance,
|
||||
&_speed, &_accuracy, &_luck, &_level
|
||||
};
|
||||
};
|
||||
|
||||
struct Character : public PrimaryAttributes {
|
||||
char _name[16] = { 0 };
|
||||
Sex _sex = MALE;
|
||||
Alignment _alignmentInitial = GOOD;
|
||||
Alignment _alignment = GOOD;
|
||||
Race _race = HUMAN;
|
||||
CharacterClass _class = NONE;
|
||||
|
||||
byte _age = 0;
|
||||
int _ageDayCtr = 0;
|
||||
AttributePair16 _sp;
|
||||
AttributePair _spellLevel;
|
||||
AttributePair _ac;
|
||||
|
||||
uint32 _exp = 0;
|
||||
uint16 _gems = 0;
|
||||
uint16 _hpCurrent = 0, _hp = 0, _hpMax = 0;
|
||||
uint32 _gold = 0;
|
||||
uint8 _food = 0;
|
||||
uint8 _condition = 0;
|
||||
Inventory _equipped;
|
||||
Inventory _backpack;
|
||||
Resistances _resistances;
|
||||
|
||||
AttributePair _physicalAttr, _missileAttr;
|
||||
byte _trapCtr = 0;
|
||||
byte _quest = 0;
|
||||
byte _worthiness = 0;
|
||||
byte _alignmentCtr = 0;
|
||||
byte _flags[14];
|
||||
|
||||
byte _portrait = 0;
|
||||
Shared::Xeen::SpriteResource _faceSprites;
|
||||
|
||||
// Non persistent fields
|
||||
byte _numDrinks = 0;
|
||||
// Combat fields
|
||||
bool _checked = false;
|
||||
bool _canAttack = false;
|
||||
int _nonCombatSpell = -1;
|
||||
int _combatSpell = -1;
|
||||
|
||||
/**
|
||||
* Get the selected combat/noncombat spell number
|
||||
*/
|
||||
int spellNumber() const;
|
||||
|
||||
/**
|
||||
* Sets the selected spell
|
||||
*/
|
||||
void setSpellNumber(int spellNum);
|
||||
|
||||
Character();
|
||||
|
||||
/**
|
||||
* Handles save/loading a character
|
||||
* @param portraitNum Override for portrait to use for
|
||||
* a character being loaded from the game defaults
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, int portraitNum = -1);
|
||||
|
||||
/**
|
||||
* Equality test
|
||||
*/
|
||||
bool operator==(const Character &rhs) const {
|
||||
return !strcmp(_name, rhs._name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clearing the character
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Gathers the party gold into the character
|
||||
*/
|
||||
void gatherGold();
|
||||
|
||||
/**
|
||||
* Trade an item to another
|
||||
*/
|
||||
enum TradeResult { TRADE_SUCCESS, TRADE_NO_ITEM, TRADE_FULL };
|
||||
TradeResult trade(int whoTo, int itemIndex);
|
||||
|
||||
/**
|
||||
* Increase the character's level by 1 at a trainer
|
||||
*/
|
||||
struct LevelIncrease {
|
||||
int _numHP;
|
||||
int _numSpells;
|
||||
};
|
||||
LevelIncrease increaseLevel();
|
||||
|
||||
/**
|
||||
* Buy an item
|
||||
*/
|
||||
enum BuyResult { BUY_SUCCESS, BUY_NOT_ENOUGH_GOLD, BUY_BACKPACK_FULL };
|
||||
BuyResult buyItem(byte itemId);
|
||||
|
||||
/**
|
||||
* Updates the current attribute levels to match
|
||||
* their base values
|
||||
*/
|
||||
void updateAttributes();
|
||||
|
||||
/**
|
||||
* Updates the character's AC
|
||||
*/
|
||||
void updateAC();
|
||||
|
||||
/**
|
||||
* Updates the character's SP
|
||||
*/
|
||||
void updateSP();
|
||||
|
||||
void updateResistances();
|
||||
|
||||
/**
|
||||
* Gets a character's condition string
|
||||
*/
|
||||
Common::String getConditionString() const;
|
||||
|
||||
/**
|
||||
* Rest the character
|
||||
*/
|
||||
void rest();
|
||||
|
||||
/**
|
||||
* Returns true if the character has a given item
|
||||
*/
|
||||
bool hasItem(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Gets the numeric value of every property a character
|
||||
* has and totals it up to give a stupid 'performance'
|
||||
* value for the party at the end of the game
|
||||
*/
|
||||
size_t getPerformanceTotal() const;
|
||||
|
||||
/**
|
||||
* Loads the face sprites for the character
|
||||
*/
|
||||
void loadFaceSprites();
|
||||
|
||||
/**
|
||||
* Returns the color to use in enhanced mode to
|
||||
* represent the color of a character attribute
|
||||
*/
|
||||
byte statColor(int amount, int threshold) const;
|
||||
|
||||
/**
|
||||
* Returns the condition color for display
|
||||
*/
|
||||
byte conditionColor() const;
|
||||
|
||||
/**
|
||||
* Returns the worst condition, if any, a character
|
||||
* currently has.
|
||||
*/
|
||||
ConditionEnum worstCondition() const;
|
||||
|
||||
/**
|
||||
* Returns a string for a given condition
|
||||
*/
|
||||
static Common::String getConditionString(ConditionEnum cond);
|
||||
|
||||
/**
|
||||
* Returns true if the character has a fatal condition
|
||||
*/
|
||||
bool hasBadCondition() const {
|
||||
return (_condition & BAD_CONDITION) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
33
engines/mm/mm1/data/game_state.cpp
Normal file
33
engines/mm/mm1/data/game_state.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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/algorithm.h"
|
||||
#include "mm/mm1/data/game_state.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
GameState::GameState() {
|
||||
Common::fill(&_activeSpells._arr[0], &_activeSpells._arr[ACTIVE_SPELLS_COUNT], 0);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
51
engines/mm/mm1/data/game_state.h
Normal file
51
engines/mm/mm1/data/game_state.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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_DATA_GAME_STATE_H
|
||||
#define MM1_DATA_GAME_STATE_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/party.h"
|
||||
#include "mm/mm1/data/active_spells.h"
|
||||
#include "mm/mm1/data/spells_state.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
/**
|
||||
* This acts as a container for everything in the game
|
||||
* that is persisted to savegames
|
||||
*/
|
||||
struct GameState {
|
||||
Party _party;
|
||||
ActiveSpells _activeSpells;
|
||||
SpellsState _spellsState;
|
||||
|
||||
GameState();
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
71
engines/mm/mm1/data/int_array.h
Normal file
71
engines/mm/mm1/data/int_array.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* 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_DATA_INT_ARRAY_H
|
||||
#define MM1_DATA_INT_ARRAY_H
|
||||
|
||||
#include "common/array.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class IntArray : public Common::Array<uint> {
|
||||
public:
|
||||
IntArray() : Common::Array<uint>() {}
|
||||
|
||||
int indexOf(uint val) const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
if ((*this)[i] == val)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the array contains the value
|
||||
*/
|
||||
bool contains(uint val) {
|
||||
return indexOf(val) != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a given item from the array
|
||||
*/
|
||||
void remove(uint val) {
|
||||
int idx = indexOf(val);
|
||||
if (idx != -1)
|
||||
remove_at(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the array
|
||||
*/
|
||||
void push_back(uint val) {
|
||||
assert(!contains(val));
|
||||
Common::Array<uint>::push_back(val);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
93
engines/mm/mm1/data/items.cpp
Normal file
93
engines/mm/mm1/data/items.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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/data/items.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
uint Item::getSellCost() const {
|
||||
uint cost = _cost;
|
||||
if (_maxCharges)
|
||||
cost /= 2;
|
||||
cost /= 2;
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
bool ItemsArray::load() {
|
||||
Common::File f;
|
||||
if (!f.open("items.txt"))
|
||||
return false;
|
||||
|
||||
resize(255);
|
||||
for (int lineNum = 0; lineNum < 255; ++lineNum) {
|
||||
Item &item = (*this)[lineNum];
|
||||
Common::String line = f.readLine();
|
||||
assert(line.size() > 20 && line[0] == '"' && line[15] == '"');
|
||||
|
||||
item._name = Common::String(line.c_str() + 1, line.c_str() + 15);
|
||||
line = Common::String(line.c_str() + 16);
|
||||
while (item._name.lastChar() == ' ')
|
||||
item._name.deleteLastChar();
|
||||
|
||||
item._disablements = getNextValue(line);
|
||||
item._constBonus_id = getNextValue(line);
|
||||
item._constBonus_value = getNextValue(line);
|
||||
item._tempBonus_id = getNextValue(line);
|
||||
|
||||
if (item._tempBonus_id != 0xff) {item._tempBonus_value = getNextValue(line);}
|
||||
else {item._spellId = getNextValue(line);}
|
||||
|
||||
item._maxCharges = getNextValue(line);
|
||||
item._cost = getNextValue(line);
|
||||
item._damage = getNextValue(line);
|
||||
item._AC_Dmg = getNextValue(line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Item *ItemsArray::getItem(byte index) const {
|
||||
assert(index > 0);
|
||||
g_globals->_currItem = (*this)[index - 1];
|
||||
|
||||
return &g_globals->_currItem;
|
||||
}
|
||||
|
||||
ItemCategory getItemCategory(byte itemId) {
|
||||
if (isWeapon(itemId))
|
||||
return ITEMCAT_WEAPON;
|
||||
if (isMissile(itemId))
|
||||
return ITEMCAT_MISSILE;
|
||||
if (isTwoHanded(itemId))
|
||||
return ITEMCAT_TWO_HANDED;
|
||||
if (isArmor(itemId))
|
||||
return ITEMCAT_ARMOR;
|
||||
if (isShield(itemId))
|
||||
return ITEMCAT_SHIELD;
|
||||
|
||||
return ITEMCAT_NONE;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
142
engines/mm/mm1/data/items.h
Normal file
142
engines/mm/mm1/data/items.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* 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_DATA_ITEMS_H
|
||||
#define MM1_DATA_ITEMS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stream.h"
|
||||
#include "mm/mm1/data/text_parser.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
enum ItemId {
|
||||
GARLIC_ID = 175,
|
||||
WOLFSBANE_ID = 176,
|
||||
BELLADONNA_ID = 177,
|
||||
VELLUM_SCROLL_ID = 231,
|
||||
RUBY_WHISTLE_ID = 232,
|
||||
KINGS_PASS_ID = 233,
|
||||
MERCHANTS_PASS_ID = 234,
|
||||
CRYSTAL_KEY_ID = 235,
|
||||
CORAL_KEY_ID = 236,
|
||||
BRONZE_KEY_ID = 237,
|
||||
SILVER_KEY_ID = 238,
|
||||
GOLD_KEY_ID = 239,
|
||||
DIAMOND_KEY_ID = 240,
|
||||
CACTUS_NECTAR_ID = 241,
|
||||
MAP_OF_DESERT_ID = 242,
|
||||
LASER_BLASTER_ID = 243,
|
||||
DRAGONS_TOOTH_ID = 244,
|
||||
WYVERN_EYE_ID = 245,
|
||||
MEDUSA_HEAD_ID = 246,
|
||||
RING_OF_OKRIM_ID = 247,
|
||||
B_QUEEN_IDOL_ID = 248,
|
||||
W_QUEEN_IDOL_ID = 249,
|
||||
PIRATES_MAP_A_ID = 250,
|
||||
PIRATES_MAP_B_ID = 251,
|
||||
THUNDRANIUM_ID = 252,
|
||||
KEY_CARD_ID = 253,
|
||||
EYE_OF_GOROS_ID = 254,
|
||||
USELESS_ITEM_ID = 255
|
||||
};
|
||||
|
||||
enum EnablementBit {
|
||||
KNIGHT_BIT = 0x20, PALADIN_BIT = 0x10, ARCHER_BIT = 8,
|
||||
CLERIC_BIT = 4, SORCERER_BIT = 2, ROBBER_BIT = 1,
|
||||
GOOD_BIT = 0x80, EVIL_BIT = 0x40,
|
||||
NEUTRAL_BIT = GOOD_BIT | EVIL_BIT
|
||||
};
|
||||
|
||||
enum ItemCategory {
|
||||
ITEMCAT_NONE, ITEMCAT_WEAPON, ITEMCAT_MISSILE,
|
||||
ITEMCAT_TWO_HANDED, ITEMCAT_ARMOR, ITEMCAT_SHIELD
|
||||
};
|
||||
|
||||
enum EquipMode {
|
||||
NO_EQUIP_BONUS = 0, IS_EQUIPPABLE = 1,
|
||||
EQUIP_CURSED = 0xff
|
||||
};
|
||||
|
||||
enum TransferKind {
|
||||
TK_GEMS = 1, TK_GOLD = 2, TK_FOOD = 3, TK_ITEM = 4
|
||||
};
|
||||
|
||||
|
||||
struct ItemData {
|
||||
byte _disablements = 0;
|
||||
byte _constBonus_id = 0; // id equals to character characteristic id, except special "EquipMode" values
|
||||
byte _constBonus_value = 0; // value to be added to character characteristic
|
||||
byte _tempBonus_id = 0; // id equals to character characteristic id, except 0xff
|
||||
byte _tempBonus_value = 0; // value to be added to character characteristic
|
||||
byte _spellId = 0;
|
||||
byte _maxCharges = 0; // for spells and tempBonus
|
||||
uint16 _cost = 0;
|
||||
byte _damage = 0;
|
||||
byte _AC_Dmg = 0; //it is AC for armor and additional damage for weapon
|
||||
};
|
||||
|
||||
struct Item : public ItemData {
|
||||
Common::String _name;
|
||||
|
||||
/**
|
||||
* Get the sell value
|
||||
*/
|
||||
uint getSellCost() const;
|
||||
};
|
||||
|
||||
struct ItemsArray : public Common::Array<Item>, public TextParser {
|
||||
ItemsArray() {}
|
||||
|
||||
/**
|
||||
* Loads the items array
|
||||
*/
|
||||
bool load();
|
||||
|
||||
/**
|
||||
* Gets an item
|
||||
*/
|
||||
Item *getItem(byte index) const;
|
||||
};
|
||||
|
||||
inline bool isWeapon(byte id) {
|
||||
return id >= 1 && id <= 60;
|
||||
}
|
||||
inline bool isMissile(byte id) {
|
||||
return id >= 61 && id <= 85;
|
||||
}
|
||||
inline bool isTwoHanded(byte id) {
|
||||
return id >= 86 && id <= 120;
|
||||
}
|
||||
inline bool isArmor(byte id) {
|
||||
return id >= 121 && id <= 155;
|
||||
}
|
||||
inline bool isShield(byte id) {
|
||||
return id >= 156 && id <= 170;
|
||||
}
|
||||
|
||||
extern ItemCategory getItemCategory(byte itemId);
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
33
engines/mm/mm1/data/locations.cpp
Normal file
33
engines/mm/mm1/data/locations.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* 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/data/locations.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
const byte TownData::TOWN_MAP_ID1[5] = { 4, 3, 3, 2, 0x1A };
|
||||
const byte TownData::TOWN_MAP_ID2[5] = { 6, 0xC, 2, 8, 0xB };
|
||||
const byte TownData::TOWN_MAP_X[5] = { 8, 1, 11, 12, 4 };
|
||||
const byte TownData::TOWN_MAP_Y[5] = { 5, 12, 13, 8, 6 };
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
106
engines/mm/mm1/data/locations.h
Normal file
106
engines/mm/mm1/data/locations.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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_DATA_LOCATIONS_H
|
||||
#define MM1_DATA_LOCATIONS_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
struct BlacksmithData {
|
||||
const byte BLACKSMITH_CLASS_USAGE[6] = { 0x20, 0x10, 8, 4, 2, 1 };
|
||||
};
|
||||
|
||||
struct BuyWeaponData {
|
||||
const byte WEAPONS_TOWN1[6] = { 2, 3, 5, 61, 62, 86 };
|
||||
const byte WEAPONS_TOWN2[6] = { 4, 6, 8, 63, 87, 88 };
|
||||
const byte WEAPONS_TOWN3[6] = { 9, 10, 62, 64, 89, 91 };
|
||||
const byte WEAPONS_TOWN4[6] = { 23, 67, 69, 93, 97, 99 };
|
||||
const byte WEAPONS_TOWN5[6] = { 7, 11, 64, 65, 90, 92 };
|
||||
const byte *WEAPONS[5] = {
|
||||
WEAPONS_TOWN1, WEAPONS_TOWN2, WEAPONS_TOWN3,
|
||||
WEAPONS_TOWN4, WEAPONS_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
struct BuyArmorData {
|
||||
const byte ARMOR_TOWN1[6] = { 156, 121, 122, 123, 124, 125 };
|
||||
const byte ARMOR_TOWN2[6] = { 156, 157, 121, 122, 123, 124 };
|
||||
const byte ARMOR_TOWN3[6] = { 157, 121, 124, 125, 126, 127 };
|
||||
const byte ARMOR_TOWN4[6] = { 160, 128, 131, 132, 133, 134 };
|
||||
const byte ARMOR_TOWN5[6] = { 157, 123, 124, 125, 126, 127 };
|
||||
const byte *ARMOR[5] = {
|
||||
ARMOR_TOWN1, ARMOR_TOWN2, ARMOR_TOWN3,
|
||||
ARMOR_TOWN4, ARMOR_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
struct BuyMiscData {
|
||||
const byte MISC_TOWN1[6] = { 172, 171, 175, 178, 185, 192 };
|
||||
const byte MISC_TOWN2[6] = { 172, 171, 174, 183, 188, 195 };
|
||||
const byte MISC_TOWN3[6] = { 173, 175, 176, 179, 184, 195 };
|
||||
const byte MISC_TOWN4[6] = { 180, 196, 211, 215, 219, 223 };
|
||||
const byte MISC_TOWN5[6] = { 171, 173, 177, 185, 186, 192 };
|
||||
const byte *MISC[5] = {
|
||||
MISC_TOWN1, MISC_TOWN2, MISC_TOWN3,
|
||||
MISC_TOWN4, MISC_TOWN5
|
||||
};
|
||||
};
|
||||
|
||||
#define MAX_FOOD 40
|
||||
|
||||
struct MarketData {
|
||||
const byte FOOD_COST[5] = { 5, 10, 20, 200, 50 };
|
||||
};
|
||||
|
||||
struct TempleData {
|
||||
const uint16 HEAL_COST1[5] = { 2000, 5000, 5000, 2000, 8000 };
|
||||
const uint16 HEAL_COST2[5] = { 200, 500, 500, 200, 1000 };
|
||||
const uint16 HEAL_COST3[5] = { 25, 50, 50, 25, 100 };
|
||||
const uint16 UNCURSE_COST[5] = { 500, 1000, 1000, 1012, 1500 };
|
||||
const uint16 ALIGNMENT_COST[5] = { 250, 200, 200, 200, 250 };
|
||||
const uint16 DONATE_COST[5] = { 100, 100, 100, 25, 200 };
|
||||
const byte ALIGNMENT_VALS[3] = { 8, 0x10, 0x18 };
|
||||
const byte DONATE_VALS[5] = { 1, 2, 4, 8, 0x10 };
|
||||
};
|
||||
|
||||
struct TrainingData {
|
||||
const int TRAINING_COSTS1[7] = {
|
||||
25, 50, 100, 200, 400, 800, 1500
|
||||
};
|
||||
const int TRAINING_COSTS2[7] = {
|
||||
40, 75, 150, 300, 600, 1200, 2500
|
||||
};
|
||||
};
|
||||
|
||||
struct TownData {
|
||||
static const byte TOWN_MAP_ID1[5];
|
||||
static const byte TOWN_MAP_ID2[5];
|
||||
static const byte TOWN_MAP_X[5];
|
||||
static const byte TOWN_MAP_Y[5];
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
106
engines/mm/mm1/data/monsters.cpp
Normal file
106
engines/mm/mm1/data/monsters.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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/file.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/gfx/dta.h"
|
||||
#include "mm/mm1/gfx/screen_decoder.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
static const uint16 PALETTE[76] = {
|
||||
0xf470, 0xf420, 0xfe20, 0xf630, 0xf420, 0xf620, 0xf460, 0xf6e0,
|
||||
0xf510, 0xfe40, 0xf420, 0xf410, 0xfd50, 0xfc90, 0xf430, 0xfc30,
|
||||
0xf770, 0xfc30, 0xf420, 0xf430, 0xf420, 0xf490, 0xf110, 0xf4e0,
|
||||
0xf430, 0xfd60, 0xf430, 0xfc20, 0xf2a0, 0xf470, 0xf4e0, 0xf250,
|
||||
0xf430, 0xf320, 0xfee0, 0xf420, 0xf220, 0xf420, 0xfdd0, 0xf420,
|
||||
0xf620, 0xfc20, 0xfc10, 0xf520, 0xf420, 0xf220, 0xf420, 0xfa50,
|
||||
0xfe20, 0xf620, 0xf470, 0xf420, 0xfe10, 0xf4e0, 0xfe40, 0xf140,
|
||||
0xf290, 0xf410, 0xf520, 0xf410, 0xfc10, 0xf120, 0xf420, 0xfe10,
|
||||
0xf520, 0xf4a0, 0xfe60, 0xfe60, 0xf620, 0xf620, 0xfce0, 0xf420,
|
||||
0xfc20, 0xfc20, 0xfd90, 0xf420
|
||||
};
|
||||
|
||||
Monsters::Monsters() : _monPix(MONPIX_DTA) {
|
||||
}
|
||||
|
||||
bool Monsters::load() {
|
||||
Common::File f;
|
||||
if (!f.open("monsters.txt"))
|
||||
return false;
|
||||
|
||||
for (int lineNum = 0; lineNum < MONSTERS_COUNT; ++lineNum) {
|
||||
Monster &mon = _monsters[lineNum];
|
||||
Common::String line = f.readLine();
|
||||
assert(line.size() > 20 && line[0] == '"' && line[16] == '"');
|
||||
|
||||
mon._name = Common::String(line.c_str() + 1, line.c_str() + 15);
|
||||
while (mon._name.hasSuffix(" "))
|
||||
mon._name.deleteLastChar();
|
||||
|
||||
line = Common::String(line.c_str() + 17);
|
||||
mon._count = getNextValue(line);
|
||||
mon._fleeThreshold = getNextValue(line);
|
||||
mon._defaultHP = getNextValue(line);
|
||||
mon._defaultAC = getNextValue(line);
|
||||
mon._maxDamage = getNextValue(line);
|
||||
mon._numberOfAttacks = getNextValue(line);
|
||||
mon._speed = getNextValue(line);
|
||||
mon._experience = getNextValue(line);
|
||||
mon._loot = getNextValue(line);
|
||||
mon._resistUndead = getNextValue(line);
|
||||
mon._resistances = getNextValue(line);
|
||||
mon._bonusOnTouch = getNextValue(line);
|
||||
mon._specialAbility = getNextValue(line);
|
||||
mon._specialThreshold = getNextValue(line);
|
||||
mon._counterFlags = getNextValue(line);
|
||||
mon._imgNum = getNextValue(line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface Monsters::getMonsterImage(int imgNum) {
|
||||
Common::SeekableReadStream *entry = _monPix.load(imgNum);
|
||||
entry->skip(2);
|
||||
|
||||
// Decode the image
|
||||
Graphics::ManagedSurface img;
|
||||
Gfx::ScreenDecoder decoder;
|
||||
|
||||
uint pal = PALETTE[imgNum];
|
||||
decoder._indexes[0] = pal & 0xf;
|
||||
decoder._indexes[1] = (pal >> 4) & 0xf;
|
||||
decoder._indexes[2] = (pal >> 8) & 0xf;
|
||||
decoder._indexes[3] = (pal >> 12) & 0xf;
|
||||
|
||||
if (!decoder.loadStream(*entry, 104, 96))
|
||||
error("Failed decoding monster image");
|
||||
|
||||
img.copyFrom(*decoder.getSurface());
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
140
engines/mm/mm1/data/monsters.h
Normal file
140
engines/mm/mm1/data/monsters.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* 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_DATA_MONSTERS_H
|
||||
#define MM1_DATA_MONSTERS_H
|
||||
|
||||
#include "mm/mm1/gfx/dta.h"
|
||||
#include "mm/mm1/data/text_parser.h"
|
||||
#include "common/str.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define MONSTERS_COUNT 195
|
||||
|
||||
enum MonsterStatus {
|
||||
MON_PARALYZED = 0, MON_WEBBED = 1, MON_HELD = 2,
|
||||
MON_ASLEEP = 3, MON_MINDLESS = 4, MON_SILENCED = 5,
|
||||
MON_BLINDED = 6, MON_AFRAID = 7, MON_DEAD = 8
|
||||
};
|
||||
enum MonsterStatusFlag {
|
||||
MONFLAG_AFRAID = 1, MONFLAG_BLIND = 2, MONFLAG_SILENCED = 4,
|
||||
MONFLAG_MINDLESS = 8, MONFLAG_ASLEEP = 0x10,
|
||||
MONFLAG_HELD = 0x20, MONFLAG_WEBBED = 0x40,
|
||||
MONFLAG_PARALYZED = 0x80, MONFLAG_DEAD = 0xff
|
||||
};
|
||||
|
||||
enum MonsterLoot {
|
||||
DROPS_GEMS = 0x1, // if 1 - a monster can drop gems
|
||||
GOLD_DROP = 0xfe>>1 // _loot>>1 - gold value that a monster drops
|
||||
};
|
||||
|
||||
enum MonsterResistUndead {
|
||||
MAGIC_RESISTANCE = 0x7f,
|
||||
IS_UNDEAD = 0x80
|
||||
};
|
||||
|
||||
enum MonsterBonusOnTouch {
|
||||
TOUCH_BONUS_VALUE = 0x7f,
|
||||
HAS_BONUS = 0x80
|
||||
};
|
||||
|
||||
enum MonsterResistances {
|
||||
MONRES_ASLEEP = 1, MONRES_FEAR = 2, MONRES_PARALYSIS = 4,
|
||||
MONRES_ENERGY = 8, MONRES_COLD = 0x10,
|
||||
MONRES_ELECTRICITY = 0x20, MONRES_FIRE = 0x40,
|
||||
MONRES_PHYSICAL_ATTACK = 0x80,
|
||||
};
|
||||
|
||||
enum MonsterSpecialAbility {
|
||||
HAS_RANGED_ATTACK = 0x80, // 1 if has ranged attack, 0 if has special attack
|
||||
ATTACK_VALUE = 0x7f // damage for ranged attack. Special attack id for special attack
|
||||
};
|
||||
|
||||
enum MonsterCounter {
|
||||
COUNTER_BITS = 0xf,
|
||||
COUNTER_THRESHOLD1 = 0x10, COUNTER_THRESHOLD2 = 0x20,
|
||||
COUNTER_REGENERATE = 0x40, COUNTER_ADVANCES = 0x80
|
||||
};
|
||||
|
||||
struct Monster {
|
||||
Common::String _name; // char _name[15];
|
||||
byte _count;
|
||||
byte _fleeThreshold;
|
||||
byte _defaultHP;
|
||||
byte _defaultAC;
|
||||
byte _maxDamage;
|
||||
byte _numberOfAttacks;
|
||||
byte _speed;
|
||||
uint16 _experience;
|
||||
byte _loot;
|
||||
byte _resistUndead;
|
||||
byte _resistances;
|
||||
byte _bonusOnTouch;
|
||||
byte _specialAbility;
|
||||
byte _specialThreshold; // % of luck of special attack
|
||||
byte _counterFlags;
|
||||
byte _imgNum;
|
||||
|
||||
// Runtime combat fields
|
||||
byte _level = 0;
|
||||
bool _checked = false;
|
||||
byte _status = 0;
|
||||
byte _hp = 0;
|
||||
byte _ac = 0;
|
||||
|
||||
Common::String getDisplayName() const {
|
||||
return _name;
|
||||
}
|
||||
};
|
||||
|
||||
class Monsters : public TextParser {
|
||||
private:
|
||||
Monster _monsters[MONSTERS_COUNT];
|
||||
Gfx::DTA _monPix;
|
||||
public:
|
||||
Monsters();
|
||||
|
||||
/**
|
||||
* Load the monster list
|
||||
*/
|
||||
bool load();
|
||||
|
||||
/**
|
||||
* Square brackets operator
|
||||
*/
|
||||
const Monster &operator[](uint i) {
|
||||
assert(i >= 1 && i <= MONSTERS_COUNT);
|
||||
return _monsters[i - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a monster image
|
||||
*/
|
||||
Graphics::ManagedSurface getMonsterImage(int imgNum);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
185
engines/mm/mm1/data/party.cpp
Normal file
185
engines/mm/mm1/data/party.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/* 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/data/party.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define SHARE_FIELD(FIELD) \
|
||||
for (uint i = 0; i < party.size(); ++i) \
|
||||
total += party[i].FIELD; \
|
||||
avg = total / party.size(); \
|
||||
party[0].FIELD = avg + (total % party.size()); \
|
||||
for (uint i = 1; i < party.size(); ++i) \
|
||||
party[i].FIELD = avg;
|
||||
|
||||
void Party::share(TransferKind shareType) {
|
||||
auto &party = g_globals->_party;
|
||||
int total = 0, avg;
|
||||
|
||||
switch (shareType) {
|
||||
case TK_GEMS:
|
||||
SHARE_FIELD(_gems);
|
||||
break;
|
||||
case TK_GOLD:
|
||||
SHARE_FIELD(_gold);
|
||||
break;
|
||||
case TK_FOOD:
|
||||
SHARE_FIELD(_food);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint Party::getPartyGold() const {
|
||||
uint total = 0;
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
total += (*this)[i]._gold;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void Party::clearPartyGold() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._gold = 0;
|
||||
}
|
||||
|
||||
void Party::clearPartyGems() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._gems = 0;
|
||||
}
|
||||
|
||||
void Party::clearPartyFood() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i]._food = 0;
|
||||
}
|
||||
|
||||
void Party::updateAC() {
|
||||
for (uint i = 0; i < size(); ++i)
|
||||
(*this)[i].updateAC();
|
||||
}
|
||||
|
||||
void Party::combatDone() {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
Character &c = (*this)[i];
|
||||
c.updateAttributes();
|
||||
c.updateResistances();
|
||||
|
||||
if (!(c._condition & BAD_CONDITION))
|
||||
c._condition &= ~(ASLEEP | SILENCED);
|
||||
}
|
||||
}
|
||||
|
||||
bool Party::hasItem(byte itemId) const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
if (c._equipped.indexOf(itemId) != -1 ||
|
||||
c._backpack.indexOf(itemId) != -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Party::isPartyDead() const {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
if (!(c._condition & (ASLEEP | PARALYZED | UNCONSCIOUS | BAD_CONDITION)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Party::checkPartyDead() const {
|
||||
if (isPartyDead()) {
|
||||
// At this point, there's no good characters.
|
||||
// So redirect to the death screen
|
||||
g_events->replaceView("Dead", true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Party::checkPartyIncapacitated() const {
|
||||
bool isActive = false;
|
||||
for (uint i = 0; i < size() && !isActive; ++i) {
|
||||
const Character &c = (*this)[i];
|
||||
isActive = !(c._condition & (BAD_CONDITION | UNCONSCIOUS));
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
return false;
|
||||
} else {
|
||||
g_events->replaceView("Dead", true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Party::synchronize(Common::Serializer &s) {
|
||||
int partySize = size();
|
||||
s.syncAsByte(partySize);
|
||||
if (s.isLoading())
|
||||
resize(partySize);
|
||||
|
||||
for (int i = 0; i < partySize; ++i) {
|
||||
// Sync the common properties
|
||||
Character &c = (*this)[i];
|
||||
c.synchronize(s);
|
||||
|
||||
// Sync extra properties
|
||||
s.syncAsSByte(c._combatSpell);
|
||||
s.syncAsSByte(c._nonCombatSpell);
|
||||
}
|
||||
|
||||
if (s.isLoading())
|
||||
g_globals->_currCharacter = &front();
|
||||
}
|
||||
|
||||
void Party::rearrange(const Common::Array<Character *> &party) {
|
||||
assert(party.size() == size());
|
||||
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
for (uint j = i; j < size(); ++j) {
|
||||
if (party[i] == &(*this)[j]) {
|
||||
if (j != i)
|
||||
insert_at(i, remove_at(j));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Party::indexOf(const Character *c) {
|
||||
for (uint i = 0; i < size(); ++i) {
|
||||
if (&(*this)[i] == c)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
110
engines/mm/mm1/data/party.h
Normal file
110
engines/mm/mm1/data/party.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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_DATA_PARTY_H
|
||||
#define MM1_DATA_PARTY_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define MAX_PARTY_SIZE 6
|
||||
|
||||
struct Party : public Common::Array<Character> {
|
||||
/**
|
||||
* Share food, gold, gems between entire party
|
||||
*/
|
||||
static void share(TransferKind shareType);
|
||||
|
||||
/**
|
||||
* Get the party gold combined
|
||||
*/
|
||||
uint getPartyGold() const;
|
||||
|
||||
/**
|
||||
* Reset entire party's gold to zero
|
||||
*/
|
||||
void clearPartyGold();
|
||||
|
||||
/**
|
||||
* Reset entire party's gems to zero
|
||||
*/
|
||||
void clearPartyGems();
|
||||
|
||||
/**
|
||||
* Reset entire party's food to zero
|
||||
*/
|
||||
void clearPartyFood();
|
||||
|
||||
/**
|
||||
* Update the entire party AC
|
||||
*/
|
||||
void updateAC();
|
||||
|
||||
/**
|
||||
* Called to update the party after combat is done
|
||||
*/
|
||||
void combatDone();
|
||||
|
||||
/**
|
||||
* Returns true if any of the party has an item
|
||||
*/
|
||||
bool hasItem(byte itemId) const;
|
||||
|
||||
/**
|
||||
* Returns true if the party is dead or out of action
|
||||
*/
|
||||
bool isPartyDead() const;
|
||||
|
||||
/**
|
||||
* Checks whether the party is dead or out of action,
|
||||
* and if so, switches to the death screen
|
||||
*/
|
||||
bool checkPartyDead() const;
|
||||
|
||||
/**
|
||||
* Checks whether the party is incapitated, and if so,
|
||||
* switches to the death screen
|
||||
*/
|
||||
bool checkPartyIncapacitated() const;
|
||||
|
||||
/**
|
||||
* Reorder the party based on a passed array of character pointers
|
||||
*/
|
||||
void rearrange(const Common::Array<Character *> &party);
|
||||
|
||||
/**
|
||||
* Synchronizes the party to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Return the index of a given character
|
||||
*/
|
||||
int indexOf(const Character *c);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
177
engines/mm/mm1/data/roster.cpp
Normal file
177
engines/mm/mm1/data/roster.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "mm/mm1/data/roster.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
static byte DEFAULT_PORTRAITS[6] = { 0, 11, 9, 7, 4, 3 };
|
||||
|
||||
void Roster::synchronize(Common::Serializer &s, bool isLoadingDefaults) {
|
||||
for (int i = 0; i < ROSTER_COUNT; ++i)
|
||||
_items[i].synchronize(s, s.isLoading() && isLoadingDefaults ?
|
||||
(i < 6 ? DEFAULT_PORTRAITS[i] : 0xff) : -1
|
||||
);
|
||||
|
||||
for (int i = 0; i < ROSTER_COUNT; ++i)
|
||||
s.syncAsByte(_towns[i]);
|
||||
}
|
||||
|
||||
void Roster::load() {
|
||||
Common::InSaveFile *sf = g_system->getSavefileManager()->openForLoading(
|
||||
rosterSaveName());
|
||||
|
||||
if (sf) {
|
||||
Common::Serializer s(sf, nullptr);
|
||||
synchronize(s, false);
|
||||
|
||||
while (!sf->eos()) {
|
||||
uint32 chunk = sf->readUint32BE();
|
||||
if (!sf->eos() && chunk == MKTAG('M', 'A', 'P', 'S')) {
|
||||
sf->skip(4); // Skip chunk size
|
||||
g_maps->synchronize(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sf = g_system->getSavefileManager()->openForLoading("roster.dta");
|
||||
|
||||
if (sf) {
|
||||
Common::Serializer s(sf, nullptr);
|
||||
synchronize(s, true);
|
||||
|
||||
} else {
|
||||
Common::File f;
|
||||
if (!f.open("roster.dta"))
|
||||
error("Could not open roster.dta");
|
||||
|
||||
Common::Serializer s(&f, nullptr);
|
||||
synchronize(s, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Roster::update(const IntArray &charNums) {
|
||||
int fallbackIndex = ROSTER_COUNT - 1;
|
||||
|
||||
for (int i = (int)g_globals->_party.size() - 1; i >= 0; --i) {
|
||||
const Character &c = g_globals->_party[i];
|
||||
|
||||
int destIndex;
|
||||
if (charNums.size() == g_globals->_party.size() &&
|
||||
charNums[i] < ROSTER_COUNT &&
|
||||
!strcmp(_items[charNums[i]]._name, c._name)) {
|
||||
// Started game from title screen and set up party,
|
||||
// so we known the correct roster index already
|
||||
destIndex = charNums[i];
|
||||
|
||||
} else {
|
||||
for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
|
||||
if (!strcmp(_items[destIndex]._name, c._name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (destIndex == ROSTER_COUNT) {
|
||||
// Couldn't find a matching name in roster to update
|
||||
for (destIndex = 0; destIndex < ROSTER_COUNT; ++destIndex) {
|
||||
if (!_towns[destIndex])
|
||||
break;
|
||||
}
|
||||
|
||||
if (destIndex == ROSTER_COUNT)
|
||||
// Replace entries at the end of the roster
|
||||
destIndex = fallbackIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the entry into the roster
|
||||
_items[destIndex] = c;
|
||||
_towns[destIndex] = (Maps::TownId)g_maps->_currentMap->dataByte(Maps::MAP_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void Roster::save() {
|
||||
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
|
||||
rosterSaveName());
|
||||
Common::Serializer s(nullptr, sf);
|
||||
synchronize(s, false);
|
||||
|
||||
// Get automap data to save
|
||||
Common::MemoryWriteStreamDynamic mapData(DisposeAfterUse::YES);
|
||||
Common::Serializer s2(nullptr, &mapData);
|
||||
g_maps->synchronize(s2);
|
||||
|
||||
// Write out the map data
|
||||
sf->writeUint32BE(MKTAG('M', 'A', 'P', 'S'));
|
||||
sf->writeUint32LE(mapData.size());
|
||||
sf->write(mapData.getData(), mapData.size());
|
||||
|
||||
sf->finalize();
|
||||
delete sf;
|
||||
}
|
||||
|
||||
void Roster::saveOriginal() {
|
||||
Common::OutSaveFile *sf = g_system->getSavefileManager()->openForSaving(
|
||||
"roster.dta", false);
|
||||
Common::Serializer s(nullptr, sf);
|
||||
synchronize(s, false);
|
||||
|
||||
sf->finalize();
|
||||
delete sf;
|
||||
}
|
||||
|
||||
Common::String Roster::rosterSaveName() const {
|
||||
return Common::String::format("%s-roster.dta",
|
||||
g_engine->getTargetName().c_str());
|
||||
}
|
||||
|
||||
void Roster::remove(Character *entry) {
|
||||
entry->clear();
|
||||
|
||||
size_t idx = entry - _items;
|
||||
_towns[idx] = Maps::NO_TOWN;
|
||||
}
|
||||
|
||||
bool Roster::empty() const {
|
||||
for (uint i = 0; i < ROSTER_COUNT; ++i) {
|
||||
if (_towns[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Roster::full() const {
|
||||
for (uint i = 0; i < ROSTER_COUNT; ++i) {
|
||||
if (!_towns[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
93
engines/mm/mm1/data/roster.h
Normal file
93
engines/mm/mm1/data/roster.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* 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_DATA_ROSTER_H
|
||||
#define MM1_DATA_ROSTER_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
#include "mm/mm1/data/int_array.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define ROSTER_COUNT 18
|
||||
|
||||
struct Roster {
|
||||
private:
|
||||
Common::String rosterSaveName() const;
|
||||
public:
|
||||
Character _items[ROSTER_COUNT];
|
||||
Maps::TownId _towns[ROSTER_COUNT] = { Maps::NO_TOWN };
|
||||
|
||||
Character &operator[](uint idx) {
|
||||
assert(idx < ROSTER_COUNT);
|
||||
return _items[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the contents of the roster
|
||||
* @param isLoadingDefaults True if we're loading the
|
||||
* default roster of the game
|
||||
*/
|
||||
void synchronize(Common::Serializer &s, bool isLoadingDefaults);
|
||||
|
||||
/**
|
||||
* Load the roster
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Updates the roster from the party
|
||||
*/
|
||||
void update(const IntArray &charNums);
|
||||
|
||||
/**
|
||||
* Save the roster
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Save the roster in the original format
|
||||
*/
|
||||
void saveOriginal();
|
||||
|
||||
/**
|
||||
* Deletes a character
|
||||
*/
|
||||
void remove(Character *entry);
|
||||
|
||||
/**
|
||||
* Returns true if the roster is empty
|
||||
*/
|
||||
bool empty() const;
|
||||
|
||||
/**
|
||||
* Returns true if the roster is full
|
||||
*/
|
||||
bool full() const;
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
61
engines/mm/mm1/data/spells_state.h
Normal file
61
engines/mm/mm1/data/spells_state.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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_DATA_SPELLS_H
|
||||
#define MM1_DATA_SPELLS_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "mm/mm1/data/character.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
struct SpellsState {
|
||||
byte _mmVal1 = 0;
|
||||
byte _resistanceIndex = 0;
|
||||
byte _mmVal5 = 0;
|
||||
byte _mmVal7 = 0;
|
||||
|
||||
// This can hold both a resistance type, or count of monsters to affect
|
||||
byte _resistanceTypeOrTargetCount = RESISTANCE_MAGIC;
|
||||
|
||||
// TODO: Is this variable different in different contexts?
|
||||
// In some places it's used to hold a new condition,
|
||||
// but others, like moonRay, uses it to hold Hp
|
||||
byte _damage = 0;
|
||||
|
||||
/**
|
||||
* Synchronize data to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_mmVal1);
|
||||
s.syncAsByte(_resistanceIndex);
|
||||
s.syncAsByte(_mmVal5);
|
||||
s.syncAsByte(_mmVal7);
|
||||
s.syncAsByte(_resistanceTypeOrTargetCount);
|
||||
s.syncAsByte(_damage);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
44
engines/mm/mm1/data/text_parser.cpp
Normal file
44
engines/mm/mm1/data/text_parser.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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/data/text_parser.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
uint TextParser::getNextValue(Common::String &line) {
|
||||
// Verify the next comma
|
||||
if (!line.hasPrefix(", "))
|
||||
return 0;
|
||||
line.deleteChar(0);
|
||||
line.deleteChar(0);
|
||||
|
||||
// Get the value
|
||||
int result = atoi(line.c_str());
|
||||
while (!line.empty() && Common::isDigit(line.firstChar()))
|
||||
line.deleteChar(0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
40
engines/mm/mm1/data/text_parser.h
Normal file
40
engines/mm/mm1/data/text_parser.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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_DATA_TEXT_PARSER_H
|
||||
#define MM1_DATA_TEXT_PARSER_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
/**
|
||||
* Get the next value from a read line
|
||||
*/
|
||||
struct TextParser {
|
||||
static uint getNextValue(Common::String &line);
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
141
engines/mm/mm1/data/trap.cpp
Normal file
141
engines/mm/mm1/data/trap.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* 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/data/trap.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
int8 TrapData::RESISTANCE_INDEXES[11] = {
|
||||
-1, -1, -1, -1, -1, -1,
|
||||
1, // Fire
|
||||
3, // Electricity
|
||||
4, // Acid
|
||||
2, // Cold
|
||||
0 // Magic
|
||||
};
|
||||
byte TrapData::CONDITIONS1[11] = {
|
||||
16, 32, 16, 16, 2, 1, 2, 32, 2, 2, 2
|
||||
};
|
||||
byte TrapData::CONDITIONS2[11] = {
|
||||
16, 16, 16, 32, 2, 16, 64, 64, 2, 32, 32
|
||||
};
|
||||
byte TrapData::CONDITIONS3[11] = {
|
||||
64, 64, 64, 64, 64, 192, 192, 192, 255, 64, 224
|
||||
};
|
||||
byte TrapData::DAMAGE_TYPE[7] = {
|
||||
3, 0, 2, 5, 4, 1, 6
|
||||
};
|
||||
|
||||
|
||||
void TrapData::trap() {
|
||||
_trapType = getRandomNumber(11) - 1;
|
||||
|
||||
int maxVal = 4;
|
||||
for (int i = (int)g_globals->_treasure._container - 1; i > 0; i -= 2) {
|
||||
maxVal <<= 1;
|
||||
}
|
||||
maxVal += getRandomNumber(maxVal);
|
||||
|
||||
_resistanceIndex = RESISTANCE_INDEXES[_trapType];
|
||||
|
||||
if (g_globals->_treasure._container < WOODEN_BOX)
|
||||
_condition = 0;
|
||||
else if (g_globals->_treasure._container < SILVER_BOX)
|
||||
_condition = CONDITIONS1[_trapType];
|
||||
else if (g_globals->_treasure._container < BLACK_BOX)
|
||||
_condition = CONDITIONS2[_trapType];
|
||||
else
|
||||
_condition = CONDITIONS3[_trapType];
|
||||
|
||||
int idx = _trapType;
|
||||
if (idx >= 7)
|
||||
idx -= 5;
|
||||
else if (_condition == POISONED)
|
||||
idx = 0;
|
||||
else if (_condition == PARALYZED)
|
||||
idx = 1;
|
||||
else
|
||||
idx = -1;
|
||||
|
||||
int val4 = 0;
|
||||
_reduced = 0;
|
||||
if (idx >= 0) {
|
||||
int spellCount = g_globals->_activeSpells._arr[DAMAGE_TYPE[idx]];
|
||||
if (spellCount > 0 && getRandomNumber(100) < spellCount) {
|
||||
_reduced = val4 = 1;
|
||||
maxVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i, _reduced = val4) {
|
||||
_hpInitial = maxVal;
|
||||
damageChar(i);
|
||||
}
|
||||
}
|
||||
|
||||
void TrapData::damageChar(uint partyIndex) {
|
||||
Character &c = g_globals->_party[partyIndex];
|
||||
if (&c != g_globals->_currCharacter)
|
||||
_hpInitial >>= 1;
|
||||
|
||||
if (_resistanceIndex != -1 &&
|
||||
c._resistances._arr[_resistanceIndex] != 0 &&
|
||||
getRandomNumber(100) < c._resistances._arr[_resistanceIndex]) {
|
||||
_hpInitial >>= 1;
|
||||
++_reduced;
|
||||
}
|
||||
|
||||
int luckLevel1 = c._luck + c._level;
|
||||
int luckLevel2 = getRandomNumber(luckLevel1 + 20);
|
||||
|
||||
if (getRandomNumber(luckLevel2) < luckLevel1) {
|
||||
_hpInitial >>= 1;
|
||||
++_reduced;
|
||||
}
|
||||
|
||||
if (c._condition & BAD_CONDITION) {
|
||||
c._hpCurrent = 0;
|
||||
|
||||
} else if (c._condition & UNCONSCIOUS) {
|
||||
c._condition = BAD_CONDITION | DEAD;
|
||||
c._hpCurrent = 0;
|
||||
|
||||
} else {
|
||||
c._hpCurrent = MAX((int)c._hpCurrent - _hpInitial, 0);
|
||||
|
||||
if (c._hpCurrent == 0) {
|
||||
c._condition |= UNCONSCIOUS;
|
||||
|
||||
} else if (!_reduced && _condition &&
|
||||
getRandomNumber(luckLevel1 + 20) >= luckLevel1) {
|
||||
if (_condition >= UNCONSCIOUS)
|
||||
c._hpCurrent = 0;
|
||||
|
||||
if (!(c._condition & BAD_CONDITION))
|
||||
c._condition = _condition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
59
engines/mm/mm1/data/trap.h
Normal file
59
engines/mm/mm1/data/trap.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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_DATA_TRAP_H
|
||||
#define MM1_DATA_TRAP_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class TrapData : public Game::GameLogic {
|
||||
private:
|
||||
/**
|
||||
* Damages a party member from the trap
|
||||
*/
|
||||
void damageChar(uint partyIndex);
|
||||
|
||||
protected:
|
||||
static int8 RESISTANCE_INDEXES[11];
|
||||
static byte CONDITIONS1[11];
|
||||
static byte CONDITIONS2[11];
|
||||
static byte CONDITIONS3[11];
|
||||
static byte DAMAGE_TYPE[7];
|
||||
|
||||
int _trapType = 0;
|
||||
int _hpInitial = 0;
|
||||
int _reduced = 0;
|
||||
int _resistanceIndex = 0;
|
||||
byte _condition = 0;
|
||||
|
||||
virtual void trap();
|
||||
public:
|
||||
virtual ~TrapData() {}
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
80
engines/mm/mm1/data/treasure.cpp
Normal file
80
engines/mm/mm1/data/treasure.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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/algorithm.h"
|
||||
#include "mm/mm1/data/treasure.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define TREASURE_COUNT 6
|
||||
#define ARRAY_COUNT (TREASURE_COUNT + 3)
|
||||
|
||||
void Treasure::clear() {
|
||||
Common::fill(&_data[0], &_data[ARRAY_COUNT], 0);
|
||||
}
|
||||
|
||||
void Treasure::clear0() {
|
||||
Common::fill(&_data[1], &_data[ARRAY_COUNT], 0);
|
||||
}
|
||||
|
||||
byte &Treasure::operator[](uint i) {
|
||||
assert(i < ARRAY_COUNT);
|
||||
return _data[i];
|
||||
}
|
||||
|
||||
bool Treasure::present() const {
|
||||
// Checks for items, treasure, and/or gems
|
||||
for (int i = 0; i < TREASURE_COUNT; ++i) {
|
||||
if (_data[i + 3])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Treasure::hasItems() const {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (_items[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
byte Treasure::removeItem() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (_items[i]) {
|
||||
byte result = _items[i];
|
||||
_items[i] = 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Treasure::synchronize(Common::Serializer &s) {
|
||||
s.syncBytes(_data, 9);
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
114
engines/mm/mm1/data/treasure.h
Normal file
114
engines/mm/mm1/data/treasure.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/* 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_DATA_TREASURE_H
|
||||
#define MM1_DATA_TREASURE_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
enum ContainerType {
|
||||
CLOTH_SACK = 0, LEATHER_SACK = 1, WOODEN_BOX = 2,
|
||||
WOODEN_CHEST = 3, IRON_BOX = 4, IRON_CHEST = 5,
|
||||
SILVER_BOX = 6, SILVER_CHEST = 7, GOLD_BOX = 8,
|
||||
GOLD_CHEST = 9, BLACK_BOX = 10
|
||||
};
|
||||
|
||||
class Treasure {
|
||||
private:
|
||||
byte _data[9];
|
||||
public:
|
||||
byte &_trapType = _data[1];
|
||||
byte &_container = _data[2];
|
||||
byte *const _items = &_data[3];
|
||||
|
||||
Treasure() {
|
||||
clear();
|
||||
}
|
||||
|
||||
byte &operator[](uint i);
|
||||
|
||||
/**
|
||||
* Clears the treasure list
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Clears everything except byte 0
|
||||
*/
|
||||
void clear0();
|
||||
|
||||
/**
|
||||
* Returns true if any treasure has been assigned
|
||||
*/
|
||||
bool present() const;
|
||||
|
||||
/**
|
||||
* Returns true if any items are present
|
||||
*/
|
||||
bool hasItems() const;
|
||||
|
||||
/**
|
||||
* Synchronize savegame data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
|
||||
/**
|
||||
* Return the gold value for the treasure
|
||||
*/
|
||||
uint16 getGold() const {
|
||||
return READ_LE_UINT16(&_data[6]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gold value for the treasure
|
||||
*/
|
||||
void setGold(uint16 amount) {
|
||||
WRITE_LE_UINT16(&_data[6], amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the gems amount
|
||||
*/
|
||||
byte getGems() const {
|
||||
return _data[8];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gems amount
|
||||
*/
|
||||
void setGems(byte amount) {
|
||||
_data[8] = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any item, and remove it from the treasure
|
||||
*/
|
||||
byte removeItem();
|
||||
};
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
366
engines/mm/mm1/events.cpp
Normal file
366
engines/mm/mm1/events.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
/* 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/system.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
#include "mm/mm1/gfx/gfx.h"
|
||||
#include "mm/mm1/views/dialogs.h"
|
||||
#include "mm/mm1/views_enh/dialogs.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
Events *g_events;
|
||||
|
||||
Events::Events(bool enhancedMode) : UIElement("Root", nullptr),
|
||||
_enhancedMode(enhancedMode) {
|
||||
g_events = this;
|
||||
}
|
||||
|
||||
Events::~Events() {
|
||||
g_events = nullptr;
|
||||
}
|
||||
|
||||
void Events::runGame() {
|
||||
ViewsBase *allViews = _enhancedMode ?
|
||||
(ViewsBase *)new ViewsEnh::Dialogs() :
|
||||
(ViewsBase *)new Views::Dialogs();
|
||||
uint currTime, nextFrameTime = 0;
|
||||
_screen = new Graphics::Screen();
|
||||
|
||||
// Run the game
|
||||
int saveSlot = ConfMan.getInt("save_slot");
|
||||
if (saveSlot == -1 ||
|
||||
g_engine->loadGameState(saveSlot).getCode() != Common::kNoError) {
|
||||
addView("Title");
|
||||
}
|
||||
|
||||
Common::Event e;
|
||||
bool quitFlag = false;
|
||||
while (!quitFlag) {
|
||||
while (g_system->getEventManager()->pollEvent(e)) {
|
||||
if (e.type == Common::EVENT_QUIT ||
|
||||
e.type == Common::EVENT_RETURN_TO_LAUNCHER) {
|
||||
quitFlag = true;
|
||||
break;
|
||||
} else {
|
||||
processEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
g_system->delayMillis(10);
|
||||
if ((currTime = g_system->getMillis()) >= nextFrameTime) {
|
||||
nextFrameTime = currTime + FRAME_DELAY;
|
||||
tick();
|
||||
drawElements();
|
||||
_screen->update();
|
||||
}
|
||||
|
||||
quitFlag |= shouldQuit();
|
||||
}
|
||||
|
||||
delete _screen;
|
||||
delete allViews;
|
||||
}
|
||||
|
||||
void Events::processEvent(Common::Event &ev) {
|
||||
switch (ev.type) {
|
||||
case Common::EVENT_KEYDOWN:
|
||||
if (ev.kbd.keycode < Common::KEYCODE_NUMLOCK)
|
||||
msgKeypress(KeypressMessage(ev.kbd));
|
||||
break;
|
||||
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
|
||||
msgAction(ActionMessage((KeybindingAction)ev.customType));
|
||||
break;
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
case Common::EVENT_RBUTTONDOWN:
|
||||
//case Common::EVENT_MBUTTONDOWN:
|
||||
msgMouseDown(MouseDownMessage(ev.type, ev.mouse));
|
||||
break;
|
||||
case Common::EVENT_LBUTTONUP:
|
||||
case Common::EVENT_RBUTTONUP:
|
||||
//case Common::EVENT_MBUTTONUP:
|
||||
msgMouseUp(MouseUpMessage(ev.type, ev.mouse));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Events::replaceView(UIElement *ui, bool replaceAllViews) {
|
||||
assert(ui);
|
||||
UIElement *priorView = focusedView();
|
||||
|
||||
if (replaceAllViews) {
|
||||
clearViews();
|
||||
|
||||
} else if (!_views.empty()) {
|
||||
priorView->msgUnfocus(UnfocusMessage());
|
||||
_views.pop();
|
||||
}
|
||||
|
||||
_views.push(ui);
|
||||
ui->redraw();
|
||||
ui->msgFocus(FocusMessage(priorView));
|
||||
}
|
||||
|
||||
void Events::replaceView(const Common::String &name, bool replaceAllViews) {
|
||||
replaceView(findView(name));
|
||||
}
|
||||
|
||||
void Events::addView(UIElement *ui) {
|
||||
assert(ui);
|
||||
UIElement *priorView = focusedView();
|
||||
|
||||
if (!_views.empty())
|
||||
priorView->msgUnfocus(UnfocusMessage());
|
||||
|
||||
_views.push(ui);
|
||||
ui->redraw();
|
||||
ui->msgFocus(FocusMessage(priorView));
|
||||
}
|
||||
|
||||
void Events::addView(const Common::String &name) {
|
||||
addView(findView(name));
|
||||
}
|
||||
|
||||
void Events::popView() {
|
||||
UIElement *priorView = focusedView();
|
||||
priorView->msgUnfocus(UnfocusMessage());
|
||||
_views.pop();
|
||||
|
||||
for (int i = 0; i < (int)_views.size() - 1; ++i) {
|
||||
_views[i]->redraw();
|
||||
_views[i]->draw();
|
||||
}
|
||||
|
||||
if (!_views.empty()) {
|
||||
UIElement *view = focusedView();
|
||||
view->msgFocus(FocusMessage(priorView));
|
||||
view->redraw();
|
||||
view->draw();
|
||||
}
|
||||
}
|
||||
|
||||
void Events::redrawViews() {
|
||||
for (uint i = 0; i < _views.size(); ++i) {
|
||||
_views[i]->redraw();
|
||||
_views[i]->draw();
|
||||
}
|
||||
}
|
||||
|
||||
bool Events::isPresent(const Common::String &name) const {
|
||||
for (uint i = 0; i < _views.size(); ++i) {
|
||||
if (_views[i]->_name == name)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Events::clearViews() {
|
||||
if (!_views.empty())
|
||||
focusedView()->msgUnfocus(UnfocusMessage());
|
||||
|
||||
_views.clear();
|
||||
}
|
||||
|
||||
void Events::addKeypress(const Common::KeyCode kc) {
|
||||
Common::KeyState ks;
|
||||
ks.keycode = kc;
|
||||
if (kc >= Common::KEYCODE_SPACE && kc <= Common::KEYCODE_TILDE)
|
||||
ks.ascii = kc;
|
||||
|
||||
focusedView()->msgKeypress(KeypressMessage(ks));
|
||||
}
|
||||
|
||||
void Events::addAction(KeybindingAction action) {
|
||||
focusedView()->msgAction(ActionMessage(action));
|
||||
}
|
||||
|
||||
bool Events::isKeypressPending() const {
|
||||
// TODO: Currently the engine doesn't cache keypresses, but rather
|
||||
// processes them immediately after each is pulled from the
|
||||
// SDL event queue. So for this to work, we'd need to rework
|
||||
// the event handler code
|
||||
return false;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Bounds::Bounds(Common::Rect &innerBounds) :
|
||||
_bounds(0, 0, 320, 200),
|
||||
_innerBounds(innerBounds),
|
||||
left(_bounds.left), top(_bounds.top),
|
||||
right(_bounds.right), bottom(_bounds.bottom) {
|
||||
}
|
||||
|
||||
Bounds &Bounds::operator=(const Common::Rect &r) {
|
||||
_bounds = r;
|
||||
_innerBounds = r;
|
||||
_innerBounds.grow(-_borderSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Bounds::setBorderSize(size_t borderSize) {
|
||||
_borderSize = borderSize;
|
||||
_innerBounds = *this;
|
||||
_innerBounds.grow(-_borderSize);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
UIElement::UIElement(const Common::String &name, UIElement *uiParent) :
|
||||
_name(name), _parent(uiParent),
|
||||
_bounds(_innerBounds) {
|
||||
if (_parent)
|
||||
_parent->_children.push_back(this);
|
||||
}
|
||||
|
||||
void UIElement::redraw() {
|
||||
_needsRedraw = true;
|
||||
|
||||
for (size_t i = 0; i < _children.size(); ++i)
|
||||
_children[i]->redraw();
|
||||
}
|
||||
|
||||
void UIElement::drawElements() {
|
||||
if (_needsRedraw) {
|
||||
draw();
|
||||
_needsRedraw = false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _children.size(); ++i)
|
||||
_children[i]->drawElements();
|
||||
}
|
||||
|
||||
UIElement *UIElement::findViewGlobally(const Common::String &name) {
|
||||
return g_events->findView(name);
|
||||
}
|
||||
|
||||
void UIElement::focus() {
|
||||
g_engine->replaceView(this);
|
||||
}
|
||||
|
||||
void UIElement::close() {
|
||||
assert(g_engine->focusedView() == this);
|
||||
g_engine->popView();
|
||||
}
|
||||
|
||||
bool UIElement::isFocused() const {
|
||||
return g_events->focusedView() == this;
|
||||
}
|
||||
|
||||
void UIElement::clearSurface() {
|
||||
Graphics::ManagedSurface s = getSurface();
|
||||
s.fillRect(Common::Rect(s.w, s.h), 0);
|
||||
}
|
||||
|
||||
void UIElement::draw() {
|
||||
for (size_t i = 0; i < _children.size(); ++i) {
|
||||
_children[i]->draw();
|
||||
}
|
||||
}
|
||||
|
||||
bool UIElement::tick() {
|
||||
if (_timeoutCtr && --_timeoutCtr == 0) {
|
||||
timeout();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _children.size(); ++i) {
|
||||
if (_children[i]->tick())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UIElement *UIElement::findView(const Common::String &name) {
|
||||
if (_name.equalsIgnoreCase(name))
|
||||
return this;
|
||||
|
||||
UIElement *result;
|
||||
for (size_t i = 0; i < _children.size(); ++i) {
|
||||
if ((result = _children[i]->findView(name)) != nullptr)
|
||||
return result;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UIElement::replaceView(UIElement *ui, bool replaceAllViews) {
|
||||
g_events->replaceView(ui, replaceAllViews);
|
||||
}
|
||||
|
||||
void UIElement::replaceView(const Common::String &name, bool replaceAllViews) {
|
||||
g_events->replaceView(name, replaceAllViews);
|
||||
}
|
||||
|
||||
void UIElement::addView(UIElement *ui) {
|
||||
g_events->addView(ui);
|
||||
}
|
||||
|
||||
void UIElement::addView(const Common::String &name) {
|
||||
g_events->addView(name);
|
||||
}
|
||||
|
||||
void UIElement::addView() {
|
||||
g_events->addView(this);
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface UIElement::getSurface() const {
|
||||
return Graphics::ManagedSurface(*g_events->getScreen(), _bounds);
|
||||
}
|
||||
|
||||
int UIElement::getRandomNumber(int minNumber, int maxNumber) {
|
||||
return g_engine->getRandomNumber(maxNumber - minNumber + 1) + minNumber;
|
||||
}
|
||||
|
||||
int UIElement::getRandomNumber(int maxNumber) {
|
||||
return g_engine->getRandomNumber(maxNumber);
|
||||
}
|
||||
|
||||
void UIElement::delaySeconds(uint seconds) {
|
||||
_timeoutCtr = seconds * FRAME_RATE;
|
||||
}
|
||||
|
||||
void UIElement::delayFrames(uint frames) {
|
||||
_timeoutCtr = frames;
|
||||
}
|
||||
|
||||
bool UIElement::endDelay() {
|
||||
if (_timeoutCtr) {
|
||||
_timeoutCtr = 0;
|
||||
timeout();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void UIElement::timeout() {
|
||||
redraw();
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
407
engines/mm/mm1/events.h
Normal file
407
engines/mm/mm1/events.h
Normal file
@@ -0,0 +1,407 @@
|
||||
/* 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_EVENTS_H
|
||||
#define MM1_EVENTS_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/stack.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "mm/mm1/messages.h"
|
||||
#include "mm/mm1/utils/mouse.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
#define FRAME_RATE 20
|
||||
#define FRAME_DELAY (1000 / FRAME_RATE)
|
||||
|
||||
class Events;
|
||||
|
||||
/**
|
||||
* Implements a thunk layer around an element's
|
||||
* bounds, allowing access to it as if it were
|
||||
* a simple Common::Rect, but any changes to it
|
||||
* will also be applied to a linked inner bounds
|
||||
*/
|
||||
struct Bounds {
|
||||
private:
|
||||
Common::Rect _bounds;
|
||||
Common::Rect &_innerBounds;
|
||||
int _borderSize = 0;
|
||||
public:
|
||||
const int16 &left;
|
||||
const int16 ⊤
|
||||
const int16 &right;
|
||||
const int16 ⊥
|
||||
public:
|
||||
Bounds(Common::Rect &innerBounds);
|
||||
operator const Common::Rect &() const { return _bounds; }
|
||||
Bounds &operator=(const Common::Rect &r);
|
||||
void setBorderSize(size_t borderSize);
|
||||
size_t borderSize() const { return _borderSize; }
|
||||
int16 width() const { return _bounds.width(); }
|
||||
int16 height() const { return _bounds.height(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* User interface element
|
||||
*/
|
||||
class UIElement {
|
||||
friend class Events;
|
||||
private:
|
||||
int _timeoutCtr = 0;
|
||||
protected:
|
||||
UIElement *_parent;
|
||||
Common::Array<UIElement *> _children;
|
||||
Common::Rect _innerBounds;
|
||||
Bounds _bounds;
|
||||
bool _needsRedraw = true;
|
||||
Common::String _name;
|
||||
protected:
|
||||
Common::Rect getLineBounds(int line1, int line2) const {
|
||||
return Common::Rect(0, line1 * 8, 320, (line2 + 1) * 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a delay countdown in seconds
|
||||
*/
|
||||
void delaySeconds(uint seconds);
|
||||
|
||||
/**
|
||||
* Set a delay countdown in frames
|
||||
*/
|
||||
void delayFrames(uint frames);
|
||||
|
||||
/**
|
||||
* Returns true if a delay is active
|
||||
*/
|
||||
bool isDelayActive() const {
|
||||
return _timeoutCtr != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels any active delay
|
||||
*/
|
||||
void cancelDelay() {
|
||||
_timeoutCtr = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends an active delay and calls timeout
|
||||
*/
|
||||
bool endDelay();
|
||||
|
||||
/**
|
||||
* Called when an active timeout countdown expired
|
||||
*/
|
||||
virtual void timeout();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Outer method for doing drawing
|
||||
*
|
||||
*/
|
||||
void drawElements();
|
||||
|
||||
/**
|
||||
* Finds a view globally
|
||||
*/
|
||||
static UIElement *findViewGlobally(const Common::String &name);
|
||||
public:
|
||||
UIElement(const Common::String &name, UIElement *uiParent);
|
||||
virtual ~UIElement() {}
|
||||
|
||||
/**
|
||||
* Returns true if the elements needs to be redrawn
|
||||
*/
|
||||
bool needsRedraw() const { return _needsRedraw; }
|
||||
|
||||
/**
|
||||
* Sets that the element needs to be redrawn
|
||||
*/
|
||||
void redraw();
|
||||
|
||||
/**
|
||||
* Focuses the element as the current view
|
||||
*/
|
||||
void focus();
|
||||
|
||||
/**
|
||||
* Closes the current view. The view must have been added
|
||||
* via addView, so there's a remaining view afterwards
|
||||
*/
|
||||
virtual void close();
|
||||
|
||||
/*
|
||||
* Returns true if the view is focused
|
||||
*/
|
||||
bool isFocused() const;
|
||||
|
||||
/**
|
||||
* Sets the focus to a new view
|
||||
*/
|
||||
void replaceView(UIElement *ui, bool replaceAllViews = false);
|
||||
void replaceView(const Common::String &name, bool replaceAllViews = false);
|
||||
|
||||
/**
|
||||
* Adds a focused view to the view stack without replacing current one
|
||||
*/
|
||||
void addView(UIElement *ui);
|
||||
void addView(const Common::String &name);
|
||||
void addView();
|
||||
void open() { addView(); }
|
||||
|
||||
/**
|
||||
* Returns a random number
|
||||
*/
|
||||
int getRandomNumber(int minNumber, int maxNumber);
|
||||
int getRandomNumber(int maxNumber);
|
||||
|
||||
/**
|
||||
* Gets the element's name
|
||||
*/
|
||||
Common::String getName() const { return _name; }
|
||||
|
||||
/**
|
||||
* Sets the element's bounds
|
||||
*/
|
||||
virtual void setBounds(const Common::Rect &r) {
|
||||
_bounds = r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element's bounds
|
||||
*/
|
||||
Common::Rect getBounds() const {
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a surface for drawing the element
|
||||
*/
|
||||
Graphics::ManagedSurface getSurface() const;
|
||||
|
||||
/**
|
||||
* Clear the surface
|
||||
*/
|
||||
virtual void clearSurface();
|
||||
|
||||
/**
|
||||
* Draws the element
|
||||
*/
|
||||
virtual void draw();
|
||||
|
||||
/**
|
||||
* Called for game frame ticks
|
||||
*/
|
||||
virtual bool tick();
|
||||
|
||||
/**
|
||||
* Find a view by name
|
||||
*/
|
||||
virtual UIElement *findView(const Common::String &name);
|
||||
|
||||
/**
|
||||
* Handles events
|
||||
*/
|
||||
#define MESSAGE(NAME) \
|
||||
protected: \
|
||||
virtual bool msg##NAME(const NAME##Message &e) { \
|
||||
for (Common::Array<UIElement *>::iterator it = _children.begin(); \
|
||||
it != _children.end(); ++it) { \
|
||||
if ((*it)->msg##NAME(e)) return true; \
|
||||
} \
|
||||
return false; \
|
||||
} \
|
||||
public: \
|
||||
bool send(const Common::String &viewName, const NAME##Message &msg) { \
|
||||
UIElement *view = UIElement::findViewGlobally(viewName); \
|
||||
assert(view); \
|
||||
return view->msg##NAME(msg); \
|
||||
} \
|
||||
bool send(const NAME##Message &msg) { \
|
||||
return send("Root", msg); \
|
||||
} \
|
||||
|
||||
MESSAGE(Focus);
|
||||
MESSAGE(Unfocus);
|
||||
MESSAGE(Keypress);
|
||||
MESSAGE(MouseDown);
|
||||
MESSAGE(MouseUp);
|
||||
MESSAGE(Action);
|
||||
MESSAGE(Game);
|
||||
MESSAGE(Header);
|
||||
MESSAGE(Info);
|
||||
MESSAGE(DrawGraphic);
|
||||
#undef MESSAGE
|
||||
};
|
||||
|
||||
class ViewsBase {
|
||||
public:
|
||||
ViewsBase() {}
|
||||
virtual ~ViewsBase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Main events and view manager
|
||||
*/
|
||||
class Events : public UIElement, public Mouse {
|
||||
private:
|
||||
Graphics::Screen *_screen = nullptr;
|
||||
Common::Stack<UIElement *> _views;
|
||||
bool _enhancedMode;
|
||||
protected:
|
||||
/**
|
||||
* Process an event
|
||||
*/
|
||||
void processEvent(Common::Event &ev);
|
||||
|
||||
/**
|
||||
* Returns true if the game should quit
|
||||
*/
|
||||
virtual bool shouldQuit() const = 0;
|
||||
|
||||
/**
|
||||
* Overrides events we want to only go to the focused view
|
||||
*/
|
||||
#define MESSAGE(NAME) \
|
||||
bool msg##NAME(const NAME##Message &e) override { \
|
||||
return !_views.empty() ? focusedView()->msg##NAME(e) : false; \
|
||||
}
|
||||
MESSAGE(Action);
|
||||
MESSAGE(Focus);
|
||||
MESSAGE(Unfocus);
|
||||
MESSAGE(Keypress);
|
||||
MESSAGE(MouseDown);
|
||||
MESSAGE(MouseUp);
|
||||
MESSAGE(DrawGraphic);
|
||||
#undef MESSAGE
|
||||
public:
|
||||
Events(bool enhancedMode);
|
||||
virtual ~Events();
|
||||
|
||||
/**
|
||||
* Main game loop
|
||||
*/
|
||||
void runGame();
|
||||
|
||||
/**
|
||||
* Sets the focus to a new view
|
||||
*/
|
||||
void replaceView(UIElement *ui, bool replaceAllViews = false);
|
||||
void replaceView(const Common::String &name, bool replaceAllViews = false);
|
||||
|
||||
/**
|
||||
* Adds a focused view to the view stack without replacing current one
|
||||
*/
|
||||
void addView(UIElement *ui);
|
||||
void addView(const Common::String &name);
|
||||
|
||||
/**
|
||||
* Clears the view list
|
||||
*/
|
||||
void clearViews();
|
||||
|
||||
/**
|
||||
* Pops a view from the view stack
|
||||
*/
|
||||
void popView();
|
||||
|
||||
/**
|
||||
* Redraws the views in order. This is used in rare cases
|
||||
* where a view draws outside it's defined area, and needs
|
||||
* to restore whether the background was before
|
||||
*/
|
||||
void redrawViews();
|
||||
|
||||
/**
|
||||
* Returns the currently focused view, if any
|
||||
*/
|
||||
UIElement *focusedView() const {
|
||||
return _views.empty() ? nullptr : _views.top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view prior to the current view, if any
|
||||
*/
|
||||
UIElement *priorView() const {
|
||||
return _views.size() < 2 ? nullptr :
|
||||
_views[_views.size() - 2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a view of a given name is present
|
||||
* at all in the visible view stack
|
||||
*/
|
||||
bool isPresent(const Common::String &name) const;
|
||||
|
||||
/**
|
||||
* Returns true if combat is active
|
||||
*/
|
||||
bool isInCombat() const {
|
||||
return isPresent("Combat");
|
||||
}
|
||||
|
||||
Graphics::Screen *getScreen() const {
|
||||
return _screen;
|
||||
}
|
||||
|
||||
void drawElements() {
|
||||
if (!_views.empty())
|
||||
focusedView()->drawElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a keypress to the event queue
|
||||
*/
|
||||
void addKeypress(const Common::KeyCode kc);
|
||||
|
||||
/**
|
||||
* Add a action to the event queue
|
||||
*/
|
||||
void addAction(KeybindingAction action);
|
||||
|
||||
/**
|
||||
* Checks whether a keypress is pending
|
||||
*/
|
||||
bool isKeypressPending() const;
|
||||
|
||||
void draw() override {}
|
||||
|
||||
bool tick() override {
|
||||
return !_views.empty() ? focusedView()->tick() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling the close method for g_events closes the active window
|
||||
*/
|
||||
void close() override {
|
||||
focusedView()->close();
|
||||
}
|
||||
};
|
||||
|
||||
extern Events *g_events;
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
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
|
||||
47
engines/mm/mm1/gfx/bitmap_font.h
Normal file
47
engines/mm/mm1/gfx/bitmap_font.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mm/shared/utils/bitmap_font.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
/**
|
||||
* The Might and Magic 1 font only has uppercase. So we
|
||||
* override the base BitmapFont class to uppercase characters
|
||||
*/
|
||||
class BitmapFont : public ::MM::BitmapFont {
|
||||
public:
|
||||
void drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const override {
|
||||
chr = (chr & 0x80) | toupper(chr & 0x7f);
|
||||
MM::BitmapFont::drawChar(dst, chr, x, y, color);
|
||||
}
|
||||
|
||||
void drawChar(Graphics::ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override {
|
||||
chr = (chr & 0x80) | toupper(chr & 0x7f);
|
||||
MM::BitmapFont::drawChar(dst, chr, x, y, color);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
49
engines/mm/mm1/gfx/dta.cpp
Normal file
49
engines/mm/mm1/gfx/dta.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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/file.h"
|
||||
#include "mm/mm1/gfx/dta.h"
|
||||
#include "mm/mm1/gfx/screen_decoder.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
Common::SeekableReadStream *DTA::load(uint entryIndex) {
|
||||
Common::File f;
|
||||
|
||||
if (!f.open(_fname))
|
||||
error("Could not open - %s", _fname.toString().c_str());
|
||||
|
||||
uint indexSize = f.readUint16LE();
|
||||
assert(entryIndex < (indexSize / 4));
|
||||
f.seek(entryIndex * 4, SEEK_CUR);
|
||||
size_t entryOffset = f.readUint32LE();
|
||||
size_t nextOffset = (entryIndex == (indexSize / 4 - 1)) ?
|
||||
f.size() : f.readUint32LE();
|
||||
|
||||
f.seek(2 + indexSize + entryOffset);
|
||||
return f.readStream(nextOffset - entryOffset);
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
51
engines/mm/mm1/gfx/dta.h
Normal file
51
engines/mm/mm1/gfx/dta.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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_GFX_DTA_H
|
||||
#define MM1_GFX_DTA_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
#define WALLPIX_DTA (g_engine->isEnhanced() ? "gfx/wallpix.dta" : "wallpix.dta")
|
||||
#define MONPIX_DTA (g_engine->isEnhanced() ? "gfx/monpix.dta" : "monpix.dta")
|
||||
|
||||
class DTA {
|
||||
public:
|
||||
Common::Path _fname;
|
||||
public:
|
||||
DTA(const Common::Path &fname) : _fname(fname) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a read stream for an entry
|
||||
*/
|
||||
Common::SeekableReadStream *load(uint entryIndex);
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
86
engines/mm/mm1/gfx/gfx.cpp
Normal file
86
engines/mm/mm1/gfx/gfx.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/* 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/system.h"
|
||||
#include "common/debug.h"
|
||||
#include "graphics/paletteman.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "mm/mm1/gfx/gfx.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
byte EGA_INDEXES[EGA_PALETTE_COUNT];
|
||||
|
||||
static const uint32 EGA_PALETTE[16] = {
|
||||
0x000000, 0x0000aa, 0x00aa00, 0x00aaaa,
|
||||
0xaa0000, 0xaa00aa, 0xaa5500, 0xaaaaaa,
|
||||
0x555555, 0x5555ff, 0x55ff55, 0x55ffff,
|
||||
0xff5555, 0xff55ff, 0xffff55, 0xffffff
|
||||
};
|
||||
|
||||
|
||||
void GFX::setEgaPalette() {
|
||||
byte pal[16 * 3];
|
||||
byte *pDest = pal;
|
||||
|
||||
for (int i = 0; i < EGA_PALETTE_COUNT; ++i) {
|
||||
*pDest++ = (EGA_PALETTE[i] >> 16) & 0xff;
|
||||
*pDest++ = (EGA_PALETTE[i] >> 8) & 0xff;
|
||||
*pDest++ = EGA_PALETTE[i] & 0xff;
|
||||
EGA_INDEXES[i] = i;
|
||||
}
|
||||
|
||||
g_system->getPaletteManager()->setPalette(pal, 0, 16);
|
||||
|
||||
uint32 c = 0xffffffff;
|
||||
g_system->getPaletteManager()->setPalette((const byte *)&c, 255, 1);
|
||||
|
||||
// Set the EGA palette indexes to be themselves
|
||||
}
|
||||
|
||||
void GFX::findPalette(const byte palette[256 * 3]) {
|
||||
for (int col = 0; col < 16; ++col) {
|
||||
byte r = (EGA_PALETTE[col] >> 16) & 0xff;
|
||||
byte g = (EGA_PALETTE[col] >> 8) & 0xff;
|
||||
byte b = EGA_PALETTE[col] & 0xff;
|
||||
int closestDiff = 0x7fffffff;
|
||||
byte closest = 0;
|
||||
const byte *pal = &palette[0];
|
||||
|
||||
for (int i = 0; i < 256; ++i, pal += 3) {
|
||||
int diff = ABS((int)r - (int)pal[0]) +
|
||||
ABS((int)g - (int)pal[1]) +
|
||||
ABS((int)b - (int)pal[2]);
|
||||
if (diff < closestDiff) {
|
||||
closestDiff = diff;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
|
||||
EGA_INDEXES[col] = closest;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
53
engines/mm/mm1/gfx/gfx.h
Normal file
53
engines/mm/mm1/gfx/gfx.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_GFX_H
|
||||
#define MM1_GFX_H
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
#define SCREEN_W 320
|
||||
#define SCREEN_H 200
|
||||
#define EGA_PALETTE_COUNT 16
|
||||
|
||||
extern byte EGA_INDEXES[EGA_PALETTE_COUNT];
|
||||
|
||||
class GFX {
|
||||
public:
|
||||
/**
|
||||
* Sets the EGA palette
|
||||
*/
|
||||
static void setEgaPalette();
|
||||
|
||||
/**
|
||||
* Called after the Xeen palette has been loaded, to determine
|
||||
* which palette indexes most closely match the EGA colors
|
||||
*/
|
||||
static void findPalette(const byte palette[256 * 3]);
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
102
engines/mm/mm1/gfx/screen_decoder.cpp
Normal file
102
engines/mm/mm1/gfx/screen_decoder.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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/file.h"
|
||||
#include "common/system.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "mm/mm1/gfx/gfx.h"
|
||||
#include "mm/mm1/gfx/screen_decoder.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
#define IMAGE_SIZE 16000
|
||||
|
||||
ScreenDecoder::~ScreenDecoder() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ScreenDecoder::destroy() {
|
||||
_surface.free();
|
||||
}
|
||||
|
||||
bool ScreenDecoder::loadFile(const Common::Path &fname,
|
||||
int16 w, int16 h) {
|
||||
Common::File f;
|
||||
if (!f.open(fname))
|
||||
return false;
|
||||
|
||||
f.skip(2); // Skip size word
|
||||
return loadStream(f, w, h);
|
||||
}
|
||||
|
||||
bool ScreenDecoder::loadStream(Common::SeekableReadStream &stream,
|
||||
int16 w, int16 h) {
|
||||
byte bytes[IMAGE_SIZE];
|
||||
byte v;
|
||||
int len;
|
||||
const byte *srcP;
|
||||
byte *destP = &bytes[0];
|
||||
int index = 0;
|
||||
int imgSize = w * h / 4;
|
||||
|
||||
// Decompress the image bytes
|
||||
int x = 0;
|
||||
while (x < (w / 4) && !stream.eos()) {
|
||||
v = stream.readByte();
|
||||
if (v != 0x7B) {
|
||||
len = 1;
|
||||
} else {
|
||||
len = stream.readByte() + 1;
|
||||
v = stream.readByte();
|
||||
}
|
||||
|
||||
for (; len > 0; --len) {
|
||||
destP[index] = v;
|
||||
|
||||
index += (w / 4);
|
||||
if (index >= imgSize) {
|
||||
index = 0;
|
||||
++destP;
|
||||
++x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create surface from splitting up the pairs of bits
|
||||
_surface.free();
|
||||
_surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8());
|
||||
srcP = &bytes[0];
|
||||
destP = (byte *)_surface.getPixels();
|
||||
|
||||
for (int i = 0; i < w * h / 4; ++i, ++srcP) {
|
||||
v = *srcP;
|
||||
for (int j = 0; j < 4; ++j, v <<= 2)
|
||||
*destP++ = EGA_INDEXES[_indexes[v >> 6]];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
} // End of namespace Xeen
|
||||
} // End of namespace MM
|
||||
62
engines/mm/mm1/gfx/screen_decoder.h
Normal file
62
engines/mm/mm1/gfx/screen_decoder.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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_GFX_SCREEN_DECODER_H
|
||||
#define MM1_GFX_SCREEN_DECODER_H
|
||||
|
||||
#include "image/image_decoder.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
#include "graphics/palette.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
class ScreenDecoder : public Image::ImageDecoder {
|
||||
private:
|
||||
Graphics::Surface _surface;
|
||||
Graphics::Palette _palette;
|
||||
public:
|
||||
byte _indexes[4] = { 0 }; // EGA palete indexes used
|
||||
public:
|
||||
ScreenDecoder() : _palette(0) {}
|
||||
~ScreenDecoder() override;
|
||||
|
||||
void destroy() override;
|
||||
bool loadFile(const Common::Path &fname,
|
||||
int16 w = 320, int16 h = 200);
|
||||
bool loadStream(Common::SeekableReadStream &stream, int16 w, int16 h);
|
||||
bool loadStream(Common::SeekableReadStream &stream) override {
|
||||
return loadStream(stream, 320, 200);
|
||||
}
|
||||
|
||||
const Graphics::Surface *getSurface() const override {
|
||||
return &_surface;
|
||||
}
|
||||
const Graphics::Palette &getPalette() const override { return _palette; }
|
||||
void clear() { _surface.free(); }
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
69
engines/mm/mm1/gfx/symbols.cpp
Normal file
69
engines/mm/mm1/gfx/symbols.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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/file.h"
|
||||
#include "image/bmp.h"
|
||||
#include "image/png.h"
|
||||
#include "mm/mm1/gfx/symbols.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
void Symbols::load() {
|
||||
Common::File f;
|
||||
if (!f.open("symbols.bin"))
|
||||
error("Could not load symbols.bin");
|
||||
|
||||
for (uint i = 0; i < MAX_SYMBOLS; ++i) {
|
||||
const Common::String fname1 = Common::String::format("gfx//symbols.bin//image%.2d.bmp", i);
|
||||
const Common::String fname2 = Common::String::format("gfx//symbols.bin//image%.2d.bmp", i);
|
||||
|
||||
Common::File fOverride1, fOverride2;
|
||||
Image::BitmapDecoder bmpDecoder;
|
||||
Image::PNGDecoder pngDecoder;
|
||||
|
||||
if (fOverride1.open(fname1.c_str()) && bmpDecoder.loadStream(fOverride1)) {
|
||||
// Load the bitmap
|
||||
_data[i].copyFrom(*bmpDecoder.getSurface());
|
||||
f.skip(SYMBOL_WIDTH * SYMBOL_HEIGHT);
|
||||
} else if (fOverride2.open(fname2.c_str()) && pngDecoder.loadStream(fOverride2)) {
|
||||
// Load the png
|
||||
_data[i].copyFrom(*pngDecoder.getSurface());
|
||||
f.skip(SYMBOL_WIDTH * SYMBOL_HEIGHT);
|
||||
} else {
|
||||
// Fall back on the default
|
||||
_data[i].create(SYMBOL_WIDTH, SYMBOL_HEIGHT);
|
||||
f.read((byte *)_data[i].getPixels(), SYMBOL_WIDTH * SYMBOL_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
void Symbols::draw(Graphics::ManagedSurface &dest, const Common::Point &destPos, int symbolNum) {
|
||||
assert(symbolNum < MAX_SYMBOLS);
|
||||
dest.blitFrom(_data[symbolNum], destPos);
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
49
engines/mm/mm1/gfx/symbols.h
Normal file
49
engines/mm/mm1/gfx/symbols.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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_GFX_SYMBOLS_H
|
||||
#define MM1_GFX_SYMBOLS_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Gfx {
|
||||
|
||||
#define MAX_SYMBOLS 20
|
||||
#define SYMBOL_WIDTH 8
|
||||
#define SYMBOL_HEIGHT 8
|
||||
|
||||
class Symbols {
|
||||
private:
|
||||
Graphics::ManagedSurface _data[20];
|
||||
|
||||
public:
|
||||
void load();
|
||||
|
||||
void draw(Graphics::ManagedSurface &dest, const Common::Point &destPos, int symbolNum);
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
180
engines/mm/mm1/globals.cpp
Normal file
180
engines/mm/mm1/globals.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/* 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/engine_data.h"
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/fonts/ttf.h"
|
||||
#include "image/bmp.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/mm1.h"
|
||||
#include "mm/shared/utils/strings.h"
|
||||
#include "graphics/fontman.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
Globals *g_globals;
|
||||
|
||||
Globals::Globals() {
|
||||
g_globals = this;
|
||||
_treasure.clear();
|
||||
}
|
||||
|
||||
Globals::~Globals() {
|
||||
delete _monsters;
|
||||
g_globals = nullptr;
|
||||
}
|
||||
|
||||
void Globals::createBlankButton() {
|
||||
// Get the Escape glyph we'll use as a base
|
||||
Shared::Xeen::SpriteResource escSprite;
|
||||
escSprite.load("esc.icn");
|
||||
_blankButton.create(20, 20);
|
||||
_blankButton.clear(255);
|
||||
_blankButton.setTransparentColor(255);
|
||||
escSprite.draw(&_blankButton, 0, Common::Point(0, 0));
|
||||
_blankButton.fillRect(Common::Rect(2, 2, 18, 18), 0x9f);
|
||||
}
|
||||
|
||||
bool Globals::load(bool isEnhanced) {
|
||||
// Initialise engine data for the game
|
||||
Common::U32String errMsg;
|
||||
if (!Common::load_engine_data("mm.dat", "mm1", 1, 0, errMsg)) {
|
||||
GUIErrorMessage(errMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_strings.load("strings_en.yml"))
|
||||
return false;
|
||||
|
||||
if (!_font.load("font.bmp"))
|
||||
return false;
|
||||
|
||||
_monsters = new Monsters();
|
||||
if (!_monsters->load() || !_items.load())
|
||||
return false;
|
||||
|
||||
// Load roster
|
||||
_roster.load();
|
||||
|
||||
if (isEnhanced) {
|
||||
_mainIcons.load("main.icn");
|
||||
_confirmIcons.load("confirm.icn");
|
||||
_globalSprites.load("global.icn");
|
||||
_tileSprites.load("town.til");
|
||||
_escSprites.load("esc.icn");
|
||||
|
||||
createBlankButton();
|
||||
|
||||
{
|
||||
// Load the Xeen game screen background
|
||||
Common::File f;
|
||||
Image::BitmapDecoder decoder;
|
||||
if (f.open("gfx/back.bmp") && decoder.loadStream(f))
|
||||
_gameBackground.copyFrom(*decoder.getSurface());
|
||||
else if (f.open("back.raw")) {
|
||||
_gameBackground.create(320, 200);
|
||||
f.read(_gameBackground.getPixels(), 320 * 200);
|
||||
} else {
|
||||
error("Could not load background");
|
||||
}
|
||||
}
|
||||
|
||||
_symbols.load();
|
||||
|
||||
{
|
||||
Common::File f;
|
||||
if (!f.open("fnt"))
|
||||
error("Could not open font");
|
||||
_fontNormal.load(&f, 0, 0x1000);
|
||||
_fontReduced.load(&f, 0x800, 0x1080);
|
||||
f.close();
|
||||
}
|
||||
|
||||
{
|
||||
Common::File f;
|
||||
if (!f.open("text_colors.bin"))
|
||||
error("Could not open text colors");
|
||||
XeenFont::loadColors(&f);
|
||||
XeenFont::setColors(0);
|
||||
f.close();
|
||||
}
|
||||
|
||||
// Show the mouse cursor
|
||||
g_events->loadCursors();
|
||||
g_events->setCursor(0);
|
||||
g_events->showCursor();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::String Globals::operator[](const Common::String &name) const {
|
||||
bool isMapStr = name.hasPrefix("maps.map");
|
||||
|
||||
if (g_engine->isEnhanced()) {
|
||||
if (isMapStr) {
|
||||
// Map strings support having alternate versions in Enhanced version
|
||||
Common::String altName = Common::String::format("maps.emap%s",
|
||||
name.c_str() + 8);
|
||||
if (_strings.contains(altName))
|
||||
return _strings[altName];
|
||||
}
|
||||
|
||||
if (name.hasPrefix("dialogs.")) {
|
||||
Common::String altName = Common::String::format("enh%s", name.c_str());
|
||||
if (_strings.contains(altName))
|
||||
return _strings[altName];
|
||||
}
|
||||
}
|
||||
|
||||
assert(_strings.contains(name));
|
||||
Common::String result = _strings[name];
|
||||
|
||||
if (g_engine->isEnhanced() && name.hasPrefix("maps."))
|
||||
result = searchAndReplace(result, "\n", " ");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Globals::synchronize(Common::Serializer &s) {
|
||||
s.syncAsByte(_startingTown);
|
||||
s.syncAsByte(_minimapOn);
|
||||
|
||||
// Sync the state information
|
||||
_party.synchronize(s);
|
||||
_activeSpells.synchronize(s);
|
||||
_spellsState.synchronize(s);
|
||||
_treasure.synchronize(s);
|
||||
|
||||
// Sync map data and visited tiles
|
||||
_maps.synchronize(s);
|
||||
_maps.synchronizeCurrent(s);
|
||||
|
||||
if (s.isLoading()) {
|
||||
_currCharacter = nullptr;
|
||||
_heardRumor = false;
|
||||
_nonCombatEffectCtr = _combatEffectCtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
113
engines/mm/mm1/globals.h
Normal file
113
engines/mm/mm1/globals.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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_GLOBALS_H
|
||||
#define MM1_GLOBALS_H
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "graphics/font.h"
|
||||
#include "mm/shared/utils/strings_data.h"
|
||||
#include "mm/shared/utils/xeen_font.h"
|
||||
#include "mm/xeen/sprites.h"
|
||||
#include "mm/mm1/data/game_state.h"
|
||||
#include "mm/mm1/data/items.h"
|
||||
#include "mm/mm1/data/monsters.h"
|
||||
#include "mm/mm1/data/roster.h"
|
||||
#include "mm/mm1/data/treasure.h"
|
||||
#include "mm/mm1/gfx/bitmap_font.h"
|
||||
#include "mm/mm1/gfx/symbols.h"
|
||||
#include "mm/mm1/game/combat.h"
|
||||
#include "mm/mm1/game/encounter.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
|
||||
class Globals : public GameState {
|
||||
public:
|
||||
StringsData _strings;
|
||||
Roster _roster;
|
||||
Common::Array<Character *> _combatParty;
|
||||
Character *_currCharacter = nullptr;
|
||||
Item _currItem;
|
||||
ItemsArray _items;
|
||||
Maps::TownId _startingTown = Maps::SORPIGAL;
|
||||
Maps::Maps _maps;
|
||||
Gfx::BitmapFont _font;
|
||||
bool _heardRumor = false;
|
||||
Game::Encounter _encounters;
|
||||
Game::Combat *_combat = nullptr;
|
||||
Monsters *_monsters = nullptr;
|
||||
Treasure _treasure;
|
||||
byte _delay = 5;
|
||||
int _nonCombatEffectCtr = 0, _combatEffectCtr = 0;
|
||||
bool _minimapOn = false;
|
||||
|
||||
// Console flags
|
||||
bool _intangible = false;
|
||||
bool _encountersOn = true;
|
||||
bool _allSpells = false;
|
||||
|
||||
/**
|
||||
* Creates a blank button with no inner glyph
|
||||
*/
|
||||
void createBlankButton();
|
||||
|
||||
public:
|
||||
// Enhanced mode globals
|
||||
Shared::Xeen::SpriteResource _mainIcons;
|
||||
Shared::Xeen::SpriteResource _confirmIcons;
|
||||
Shared::Xeen::SpriteResource _globalSprites;
|
||||
Shared::Xeen::SpriteResource _tileSprites;
|
||||
Shared::Xeen::SpriteResource _escSprites;
|
||||
Graphics::ManagedSurface _blankButton;
|
||||
Graphics::ManagedSurface _gameBackground;
|
||||
Gfx::Symbols _symbols;
|
||||
XeenFont _fontNormal;
|
||||
XeenFont _fontReduced;
|
||||
public:
|
||||
Globals();
|
||||
virtual ~Globals();
|
||||
|
||||
/**
|
||||
* Loads data for the globals
|
||||
*/
|
||||
bool load(bool isEnhanced);
|
||||
|
||||
/**
|
||||
* Returns a string
|
||||
*/
|
||||
Common::String operator[](const Common::String &name) const;
|
||||
|
||||
/**
|
||||
* Saves global data to/from savegames
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
extern Globals *g_globals;
|
||||
|
||||
#define STRING (*g_globals)
|
||||
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
148
engines/mm/mm1/maps/map.cpp
Normal file
148
engines/mm/mm1/maps/map.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/* 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/file.h"
|
||||
#include "mm/mm1/maps/map.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/events.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
Map::Map(uint index, const Common::String &name, uint16 id,
|
||||
byte defaultSection, const char *desc) :
|
||||
_mapIndex(index), _name(name), _id(id), _defaultSection(defaultSection) {
|
||||
_description = desc ? Common::String(desc) : _name;
|
||||
_description.setChar(toupper(_description[0]), 0);
|
||||
if (_description.hasPrefix("Area")) {
|
||||
_description.setChar(toupper(_description[4]), 4);
|
||||
_description.insertChar(' ', 4);
|
||||
}
|
||||
|
||||
Common::fill((byte *)&_walls[0], (byte *)&_walls[MAP_SIZE], 0);
|
||||
Common::fill(&_states[0], (byte *)&_states[MAP_SIZE], 0);
|
||||
Common::fill(&_visited[0], &_visited[MAP_SIZE], 0);
|
||||
}
|
||||
|
||||
void Map::load() {
|
||||
loadMazeData();
|
||||
loadOverlay();
|
||||
|
||||
g_globals->_heardRumor = false;
|
||||
}
|
||||
|
||||
void Map::loadMazeData() {
|
||||
Common::File f;
|
||||
if (!f.open("mazedata.dta"))
|
||||
error("Could not open mazedata.dta");
|
||||
|
||||
f.seek(512 * _mapIndex);
|
||||
f.read((byte *)_walls, MAP_SIZE);
|
||||
f.read(_states, MAP_SIZE);
|
||||
f.close();
|
||||
}
|
||||
|
||||
void Map::loadOverlay() {
|
||||
Common::File f;
|
||||
if (!f.open(Common::Path(Common::String::format("%s.ovr", _name.c_str()))))
|
||||
error("Could not open %s.ovr overlay", _name.c_str());
|
||||
|
||||
int magicId = f.readUint16LE();
|
||||
int codePtr = f.readUint16LE();
|
||||
int codeSize = f.readUint16LE();
|
||||
f.readUint16LE(); // dataPtr
|
||||
int dataSize = f.readUint16LE();
|
||||
f.readUint16LE(); // extras size
|
||||
f.readUint16LE(); // code entry-point
|
||||
|
||||
if (magicId != 0xF2 || (codePtr != 0xF48F && codePtr != 0xF47C))
|
||||
error("Invalid map overlay header");
|
||||
|
||||
// Skip over code segment, since each map's
|
||||
// code is going to be reimplemented in C++
|
||||
f.skip(codeSize);
|
||||
|
||||
// Read in the data segment
|
||||
_data.resize(dataSize);
|
||||
f.read(&_data[0], dataSize);
|
||||
}
|
||||
|
||||
bool Map::checkPartyDead() {
|
||||
return g_globals->_party.checkPartyDead();
|
||||
}
|
||||
|
||||
uint16 Map::dataWord(uint16 ofs) const {
|
||||
return READ_LE_UINT16(&_data[ofs]);
|
||||
}
|
||||
|
||||
void Map::dataWord(uint16 ofs, uint16 val) {
|
||||
WRITE_LE_UINT16(&_data[ofs], val);
|
||||
}
|
||||
|
||||
void Map::reduceHP() {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i)
|
||||
g_globals->_party[i]._hpCurrent /= 2;
|
||||
}
|
||||
|
||||
void Map::updateGame() {
|
||||
g_events->send("Game", GameMessage("UPDATE"));
|
||||
}
|
||||
|
||||
void Map::redrawGame() {
|
||||
g_events->send("Game", GameMessage("REDRAW"));
|
||||
}
|
||||
|
||||
void Map::encounter(const byte *id1, const byte *id2) {
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
g_maps->clearSpecial();
|
||||
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < 14 && *id1; ++i, ++id1, ++id2)
|
||||
enc.addMonster(*id1, *id2);
|
||||
|
||||
enc._manual = true;
|
||||
enc._levelIndex = 64;
|
||||
enc.execute();
|
||||
}
|
||||
|
||||
void Map::unlockDoor() {
|
||||
g_maps->_currentState = _states[g_maps->_mapOffset] ^=
|
||||
g_maps->_forwardMask & 0x55;
|
||||
}
|
||||
|
||||
void Map::visitedSpecial() {
|
||||
if (!_visited[g_maps->_mapOffset])
|
||||
_visited[g_maps->_mapOffset] = VISITED_SPECIAL;
|
||||
}
|
||||
|
||||
void Map::visitedExit() {
|
||||
_visited[g_maps->_mapOffset] = VISITED_EXIT;
|
||||
}
|
||||
|
||||
void Map::visitedBusiness() {
|
||||
_visited[g_maps->_mapOffset] = VISITED_BUSINESS;
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
260
engines/mm/mm1/maps/map.h
Normal file
260
engines/mm/mm1/maps/map.h
Normal file
@@ -0,0 +1,260 @@
|
||||
/* 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_MAPS_MAP_H
|
||||
#define MM1_MAPS_MAP_H
|
||||
|
||||
#include "common/array.h"
|
||||
#include "common/str.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/game/game_logic.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
#define MAP_W 16
|
||||
#define MAP_H 16
|
||||
#define MAP_SIZE (MAP_W * MAP_H)
|
||||
|
||||
class Maps;
|
||||
|
||||
enum DataOffset {
|
||||
MAP_ID = 0,
|
||||
MAP_1 = 1,
|
||||
MAP_2 = 2,
|
||||
MAP_4 = 4,
|
||||
MAP_6 = 6,
|
||||
MAP_NORTH_EXIT_ID = 8,
|
||||
MAP_NORTH_EXIT_SECTION = 10,
|
||||
MAP_EAST_EXIT_ID = 11,
|
||||
MAP_EAST_EXIT_SECTION = 13,
|
||||
MAP_SOUTH_EXIT_ID = 14,
|
||||
MAP_SOUTH_EXIT_SECTION = 16,
|
||||
MAP_WEST_EXIT_ID = 17,
|
||||
MAP_WEST_EXIT_SECTION = 19,
|
||||
MAP_20 = 20,
|
||||
MAP_21 = 21,
|
||||
MAP_FLEE_THRESHOLD = 22,
|
||||
MAP_FLEE_X = 23,
|
||||
MAP_FLEE_Y = 24,
|
||||
MAP_SURRENDER_THRESHOLD = 25,
|
||||
MAP_SURRENDER_X = 26,
|
||||
MAP_SURRENDER_Y = 27,
|
||||
MAP_BRIBE_THRESHOLD = 28,
|
||||
MAP_29 = 29,
|
||||
MAP_30 = 30,
|
||||
MAP_31 = 31,
|
||||
MAP_32 = 32,
|
||||
MAP_33 = 33,
|
||||
MAP_MAX_MONSTERS = 34,
|
||||
MAP_SECTOR1 = 35,
|
||||
MAP_SECTOR2 = 36,
|
||||
MAP_TYPE = 37,
|
||||
MAP_DISPEL_THRESHOLD = 38,
|
||||
MAP_SURFACE_ID = 39,
|
||||
MAP_SURFACE_SECTION = 41,
|
||||
MAP_SURFACE_X = 42,
|
||||
MAP_SURFACE_Y = 43,
|
||||
MAP_44 = 44,
|
||||
MAP_45 = 45,
|
||||
MAP_FLAGS = 46,
|
||||
MAP_47 = 47,
|
||||
MAP_TRAP_THRESHOLD = 48,
|
||||
MAP_49 = 49,
|
||||
MAP_SPECIAL_COUNT = 50
|
||||
};
|
||||
|
||||
enum WallType {
|
||||
WALL_NONE = 0, WALL_NORMAL = 1, WALL_DOOR = 2,
|
||||
WALL_TORCH = 3
|
||||
};
|
||||
|
||||
enum CellState {
|
||||
CELL_SPECIAL = 0x80, CELL_DARK = 0x20
|
||||
};
|
||||
|
||||
class Maps;
|
||||
|
||||
class Map : public Game::GameLogic {
|
||||
protected:
|
||||
Common::String _name;
|
||||
Common::String _description;
|
||||
uint16 _id;
|
||||
uint _mapIndex;
|
||||
byte _defaultSection;
|
||||
Common::Array<byte> _data;
|
||||
private:
|
||||
/**
|
||||
* Loads the map's maze data
|
||||
*/
|
||||
void loadMazeData();
|
||||
|
||||
/**
|
||||
* Load the map's overlay file
|
||||
*/
|
||||
void loadOverlay();
|
||||
public:
|
||||
/**
|
||||
* Divides all the party's Hp in half
|
||||
*/
|
||||
static void reduceHP();
|
||||
|
||||
/**
|
||||
* Many special methods return a 160 key, but it
|
||||
* doesn't look like the game uses. My current
|
||||
* assumption is that this is just a convenient
|
||||
* 'do nothing' return value
|
||||
*/
|
||||
static void none160() {}
|
||||
|
||||
/**
|
||||
* Generates an encounter based on the passed id arrays
|
||||
*/
|
||||
void encounter(const byte *id1, const byte *id2);
|
||||
|
||||
public:
|
||||
byte _walls[MAP_SIZE];
|
||||
byte _states[MAP_SIZE];
|
||||
uint8 _visited[MAP_SIZE];
|
||||
public:
|
||||
Map(uint index, const Common::String &name, uint16 id,
|
||||
byte defaultSection, const char *desc = nullptr);
|
||||
virtual ~Map() {}
|
||||
|
||||
/**
|
||||
* Loads the map
|
||||
*/
|
||||
virtual void load();
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
virtual void special() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if mapping is allowed in enhanced mode.
|
||||
* This is to prevent places like the desert where the
|
||||
* players shouldn't be able to see where they are
|
||||
*/
|
||||
virtual bool mappingAllowed() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map name
|
||||
*/
|
||||
Common::String getName() const { return _name; }
|
||||
|
||||
/**
|
||||
* Gets the map description for the map display
|
||||
*/
|
||||
Common::String getDescription() const { return _description; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns the map Id
|
||||
*/
|
||||
uint16 getId() const { return _id; }
|
||||
|
||||
/**
|
||||
* Returns the map default section
|
||||
*/
|
||||
byte getDefaultSection() const {
|
||||
return _defaultSection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses the map data
|
||||
*/
|
||||
const byte &operator[](uint ofs) const {
|
||||
return _data[ofs];
|
||||
}
|
||||
byte &operator[](uint ofs) {
|
||||
return _data[ofs];
|
||||
}
|
||||
byte dataByte(uint ofs) const {
|
||||
return _data[ofs];
|
||||
}
|
||||
uint16 dataWord(uint16 ofs) const;
|
||||
void dataWord(uint16 ofs, uint16 val);
|
||||
|
||||
/**
|
||||
* Checks whether the party is dead or out of action,
|
||||
* and if so, switches to the death screen
|
||||
*/
|
||||
bool checkPartyDead();
|
||||
|
||||
/**
|
||||
* Send a message to a UI element
|
||||
*/
|
||||
template<class T>
|
||||
bool send(const T &msg) {
|
||||
return g_events->send(msg);
|
||||
}
|
||||
template<class T>
|
||||
bool send(const Common::String &name, const T &msg) {
|
||||
return g_events->send(name, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map's index
|
||||
*/
|
||||
uint getMapIndex() const {
|
||||
return _mapIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the game display
|
||||
*/
|
||||
static void updateGame();
|
||||
|
||||
/**
|
||||
* Redraw the game display
|
||||
*/
|
||||
static void redrawGame();
|
||||
|
||||
/**
|
||||
* Unlocks door
|
||||
*/
|
||||
void unlockDoor();
|
||||
|
||||
/**
|
||||
* Visited a special cell
|
||||
*/
|
||||
void visitedSpecial();
|
||||
|
||||
/**
|
||||
* Visited an exit cell
|
||||
*/
|
||||
void visitedExit();
|
||||
|
||||
/**
|
||||
* Visited a business cell
|
||||
*/
|
||||
void visitedBusiness();
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
235
engines/mm/mm1/maps/map00.cpp
Normal file
235
engines/mm/mm1/maps/map00.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/* 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/maps/map00.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
#define STATUE_VAL 0x412
|
||||
|
||||
void Map00::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 24; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[75 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cells on the map are encounters
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map00::special00() {
|
||||
inn();
|
||||
}
|
||||
|
||||
void Map00::special01() {
|
||||
Common::String line2;
|
||||
int x = 5;
|
||||
|
||||
switch (g_maps->_forwardMask) {
|
||||
case DIRMASK_E:
|
||||
line2 = STRING["maps.map00.market"];
|
||||
x = 6;
|
||||
break;
|
||||
case DIRMASK_W:
|
||||
line2 = STRING["maps.map00.blacksmith"];
|
||||
break;
|
||||
default:
|
||||
line2 = STRING["maps.map00.inn"];
|
||||
break;
|
||||
}
|
||||
|
||||
send(SoundMessage(
|
||||
2, 0, STRING["maps.sign"],
|
||||
x, 1, line2
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special02() {
|
||||
blacksmith();
|
||||
}
|
||||
|
||||
void Map00::special03() {
|
||||
market();
|
||||
}
|
||||
|
||||
void Map00::special04() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.passage_outside1"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(10, 10);
|
||||
g_maps->changeMap(0xa11, 2);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special05() {
|
||||
tavern();
|
||||
}
|
||||
|
||||
void Map00::special06() {
|
||||
temple();
|
||||
}
|
||||
|
||||
void Map00::special07() {
|
||||
training();
|
||||
}
|
||||
|
||||
void Map00::special08() {
|
||||
g_events->addView("Leprechaun");
|
||||
}
|
||||
|
||||
void Map00::special09() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.stairs_down"],
|
||||
[]() {
|
||||
g_maps->changeMap(0xa11, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special10() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 0;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special11() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 1;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special12() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 2;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special13() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 3;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special14() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 4;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special15() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 5;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special16() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 6;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special17() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[STATUE_VAL] = 7;
|
||||
searchStatue();
|
||||
}
|
||||
|
||||
void Map00::special18() {
|
||||
send(SoundMessage(
|
||||
2, 0, STRING["maps.sign"],
|
||||
6, 1, STRING["maps.map00.temple"]
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special19() {
|
||||
send(SoundMessage(
|
||||
2, 0, STRING["maps.sign"],
|
||||
6, 1, STRING["maps.map00.jail"]
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special20() {
|
||||
send(SoundMessage(
|
||||
2, 0, STRING["maps.sign"],
|
||||
6, 1, STRING["maps.map00.tavern"]
|
||||
));
|
||||
}
|
||||
void Map00::special21() {
|
||||
send(SoundMessage(
|
||||
2, 0, STRING["maps.sign"],
|
||||
6, 1, STRING["maps.map00.training"]
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::special22() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
map[MM1::Maps::MAP_47] = 3;
|
||||
map[MM1::Maps::MAP_33] = 6;
|
||||
g_maps->clearSpecial();
|
||||
}
|
||||
|
||||
void Map00::special23() {
|
||||
visitedExit();
|
||||
Common::String msg = STRING["maps.map00.trapdoor"];
|
||||
if (g_globals->_activeSpells._s.levitate)
|
||||
msg += STRING["maps.map00.levitate"];
|
||||
|
||||
send(SoundMessage(msg,
|
||||
[](const Common::KeyState &keyState) {
|
||||
g_events->focusedView()->close();
|
||||
if (!g_globals->_activeSpells._s.levitate)
|
||||
g_maps->changeMap(0xa11, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map00::searchStatue() {
|
||||
send(SoundMessage(
|
||||
STRING["maps.map00.statue"],
|
||||
[]() {
|
||||
Map &map = *g_maps->_currentMap;
|
||||
g_events->send("Statue", GameMessage("STATUE", map[STATUE_VAL]));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
100
engines/mm/mm1/maps/map00.h
Normal file
100
engines/mm/mm1/maps/map00.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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_MAPS_MAP00_H
|
||||
#define MM1_MAPS_MAP00_H
|
||||
|
||||
#include "mm/mm1/maps/map_town.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
class Map00 : public MapTown {
|
||||
typedef void (Map00:: *SpecialFn)();
|
||||
private:
|
||||
void searchStatue();
|
||||
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special08();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special12();
|
||||
void special13();
|
||||
void special14();
|
||||
void special15();
|
||||
void special16();
|
||||
void special17();
|
||||
void special18();
|
||||
void special19();
|
||||
void special20();
|
||||
void special21();
|
||||
void special22();
|
||||
void special23();
|
||||
|
||||
const SpecialFn SPECIAL_FN[24] = {
|
||||
&Map00::special00,
|
||||
&Map00::special01,
|
||||
&Map00::special02,
|
||||
&Map00::special03,
|
||||
&Map00::special04,
|
||||
&Map00::special05,
|
||||
&Map00::special06,
|
||||
&Map00::special07,
|
||||
&Map00::special08,
|
||||
&Map00::special09,
|
||||
&Map00::special10,
|
||||
&Map00::special11,
|
||||
&Map00::special12,
|
||||
&Map00::special13,
|
||||
&Map00::special14,
|
||||
&Map00::special15,
|
||||
&Map00::special16,
|
||||
&Map00::special17,
|
||||
&Map00::special18,
|
||||
&Map00::special19,
|
||||
&Map00::special20,
|
||||
&Map00::special21,
|
||||
&Map00::special22,
|
||||
&Map00::special23
|
||||
};
|
||||
public:
|
||||
Map00() : MapTown(0, "sorpigal", 0x604, 1) {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
virtual void special();
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
184
engines/mm/mm1/maps/map01.cpp
Normal file
184
engines/mm/mm1/maps/map01.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/* 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/maps/map01.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
void Map01::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 17; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[68 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cells on the map are encounters
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map01::special00() {
|
||||
inn();
|
||||
}
|
||||
|
||||
void Map01::special01() {
|
||||
Common::String line1 = STRING["maps.map01.zam1"];
|
||||
Common::String line2 = STRING["maps.map01.zam3"];
|
||||
|
||||
bool hasCourier = false;
|
||||
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
|
||||
hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
|
||||
}
|
||||
|
||||
if (hasCourier) {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
c._flags[0] |= CHARFLAG0_COURIER3 | CHARFLAG0_ZAM_CLUE;
|
||||
}
|
||||
|
||||
line2 = STRING["maps.map01.zam2"];
|
||||
}
|
||||
|
||||
send(InfoMessage(
|
||||
0, 1, line1,
|
||||
0, 3, line2
|
||||
));
|
||||
}
|
||||
|
||||
void Map01::special02() {
|
||||
blacksmith();
|
||||
}
|
||||
|
||||
void Map01::special03() {
|
||||
market();
|
||||
}
|
||||
|
||||
void Map01::special04() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.passage_outside2"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(3, 3);
|
||||
g_maps->changeMap(0x101, 2);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map01::special05() {
|
||||
tavern();
|
||||
}
|
||||
|
||||
void Map01::special06() {
|
||||
temple();
|
||||
}
|
||||
|
||||
void Map01::special07() {
|
||||
training();
|
||||
}
|
||||
|
||||
void Map01::special08() {
|
||||
// Paralyze all the men
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
if (c._sex == MALE && !(c._condition & BAD_CONDITION))
|
||||
c._condition = PARALYZED;
|
||||
}
|
||||
|
||||
redrawGame();
|
||||
|
||||
// Show the message and wait for a keypress
|
||||
send(SoundMessage(
|
||||
STRING["maps.map01.secret"],
|
||||
[](const Common::KeyState &) {
|
||||
g_events->close();
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
enc.clearMonsters();
|
||||
|
||||
uint count = g_events->getRandomNumber(4) + 4;
|
||||
enc.addMonster(6, 12);
|
||||
for (uint i = 0; i < count; ++i)
|
||||
enc.addMonster(4, 9);
|
||||
|
||||
enc._manual = true;
|
||||
enc._levelIndex = 80;
|
||||
enc.execute();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map01::special09() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.stairs_down"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(8, 0);
|
||||
g_maps->changeMap(0xc01, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map01::special10() {
|
||||
showSign(STRING["maps.map01.market"]);
|
||||
}
|
||||
|
||||
void Map01::special11() {
|
||||
showSign(STRING["maps.map01.blacksmith"]);
|
||||
}
|
||||
|
||||
void Map01::special12() {
|
||||
showSign(STRING["maps.map01.inn"]);
|
||||
}
|
||||
|
||||
void Map01::special13() {
|
||||
showSign(STRING["maps.map01.temple"]);
|
||||
}
|
||||
|
||||
void Map01::special14() {
|
||||
send(SoundMessage(
|
||||
0, 1, STRING["maps.map01.zam0"]
|
||||
));
|
||||
}
|
||||
|
||||
void Map01::special15() {
|
||||
showSign(STRING["maps.map01.tavern"]);
|
||||
}
|
||||
|
||||
void Map01::special16() {
|
||||
showSign(STRING["maps.map01.training"]);
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
84
engines/mm/mm1/maps/map01.h
Normal file
84
engines/mm/mm1/maps/map01.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* 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_MAPS_MAP01_H
|
||||
#define MM1_MAPS_MAP01_H
|
||||
|
||||
#include "mm/mm1/maps/map_town.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
class Map01 : public MapTown {
|
||||
typedef void (Map01:: *SpecialFn)();
|
||||
private:
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special08();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special12();
|
||||
void special13();
|
||||
void special14();
|
||||
void special15();
|
||||
void special16();
|
||||
|
||||
const SpecialFn SPECIAL_FN[17] = {
|
||||
&Map01::special00,
|
||||
&Map01::special01,
|
||||
&Map01::special02,
|
||||
&Map01::special03,
|
||||
&Map01::special04,
|
||||
&Map01::special05,
|
||||
&Map01::special06,
|
||||
&Map01::special07,
|
||||
&Map01::special08,
|
||||
&Map01::special09,
|
||||
&Map01::special10,
|
||||
&Map01::special11,
|
||||
&Map01::special12,
|
||||
&Map01::special13,
|
||||
&Map01::special14,
|
||||
&Map01::special15,
|
||||
&Map01::special16
|
||||
};
|
||||
public:
|
||||
Map01() : MapTown(1, "portsmit", 0xc03, 1, "Portsmith") {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
void special() override;
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
181
engines/mm/mm1/maps/map02.cpp
Normal file
181
engines/mm/mm1/maps/map02.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/* 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/maps/map02.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
static const byte PORTAL_DEST_X[4] = { 8, 15, 0, 5 };
|
||||
static const byte PORTAL_DEST_Y[4] = { 4, 0, 0, 14 };
|
||||
static const uint16 PORTAL_DEST_ID[4] = { 0xc03, 0xa00, 0xf01, 0x604 };
|
||||
static const byte PORTAL_DEST_SECTION[4] = { 3, 0, 1, 4 };
|
||||
|
||||
void Map02::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 22; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[73 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cells on the map are encounters
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map02::special00() {
|
||||
inn();
|
||||
}
|
||||
|
||||
void Map02::special01() {
|
||||
Common::String line1 = STRING["maps.map02.zom1"];
|
||||
Common::String line2 = STRING["maps.map02.zom3"];
|
||||
|
||||
bool hasCourier = false;
|
||||
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
|
||||
hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
|
||||
}
|
||||
|
||||
if (hasCourier) {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
c._flags[0] |= CHARFLAG0_COURIER3 | CHARFLAG0_ZOM_CLUE;
|
||||
}
|
||||
|
||||
line2 = STRING["maps.map02.zom2"];
|
||||
}
|
||||
|
||||
send(InfoMessage(
|
||||
0, 1, line1,
|
||||
0, 3, line2
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
void Map02::special02() {
|
||||
blacksmith();
|
||||
}
|
||||
|
||||
void Map02::special03() {
|
||||
market();
|
||||
}
|
||||
|
||||
void Map02::special04() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.passage_outside2"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(7, 7);
|
||||
g_maps->changeMap(0x801, 2);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map02::special05() {
|
||||
tavern();
|
||||
}
|
||||
|
||||
void Map02::special06() {
|
||||
temple();
|
||||
}
|
||||
|
||||
void Map02::special07() {
|
||||
training();
|
||||
}
|
||||
|
||||
void Map02::special08() {
|
||||
g_events->addView("Resistances");
|
||||
}
|
||||
|
||||
void Map02::special09() {
|
||||
showSign(STRING["maps.map02.docks"]);
|
||||
}
|
||||
|
||||
void Map02::special10() {
|
||||
showSign(STRING["maps.map02.market"]);
|
||||
}
|
||||
|
||||
void Map02::special11() {
|
||||
showSign(STRING["maps.map02.blacksmith"]);
|
||||
}
|
||||
|
||||
void Map02::special12() {
|
||||
showSign(STRING["maps.map02.inn"]);
|
||||
}
|
||||
|
||||
void Map02::special13() {
|
||||
send(SoundMessage(0, 1, STRING["maps.map02.zom0"]));
|
||||
}
|
||||
|
||||
void Map02::special14() {
|
||||
send(SoundMessage(
|
||||
STRING["maps.map02.pit"],
|
||||
[]() {
|
||||
g_maps->_mapPos.x++;
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map02::special15() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.map02.portal"],
|
||||
[]() {
|
||||
int index = g_maps->_mapPos.x - 9;
|
||||
g_maps->_mapPos.x = PORTAL_DEST_X[index];
|
||||
g_maps->_mapPos.y = PORTAL_DEST_Y[index];
|
||||
|
||||
uint16 id = PORTAL_DEST_ID[index];
|
||||
byte section = PORTAL_DEST_SECTION[index];
|
||||
g_maps->changeMap(id, section);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map02::special18() {
|
||||
showSign(STRING["maps.map02.temple"]);
|
||||
}
|
||||
|
||||
void Map02::special20() {
|
||||
showSign(STRING["maps.map02.tavern"]);
|
||||
}
|
||||
|
||||
void Map02::special21() {
|
||||
showSign(STRING["maps.map02.training"]);
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
91
engines/mm/mm1/maps/map02.h
Normal file
91
engines/mm/mm1/maps/map02.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* 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_MAPS_MAP02_H
|
||||
#define MM1_MAPS_MAP02_H
|
||||
|
||||
#include "mm/mm1/maps/map_town.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
class Map02 : public MapTown {
|
||||
typedef void (Map02:: *SpecialFn)();
|
||||
private:
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special08();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special12();
|
||||
void special13();
|
||||
void special14();
|
||||
void special15();
|
||||
void special18();
|
||||
void special20();
|
||||
void special21();
|
||||
|
||||
const SpecialFn SPECIAL_FN[22] = {
|
||||
&Map02::special00,
|
||||
&Map02::special01,
|
||||
&Map02::special02,
|
||||
&Map02::special03,
|
||||
&Map02::special04,
|
||||
&Map02::special05,
|
||||
&Map02::special06,
|
||||
&Map02::special07,
|
||||
&Map02::special08,
|
||||
&Map02::special09,
|
||||
&Map02::special10,
|
||||
&Map02::special11,
|
||||
&Map02::special12,
|
||||
&Map02::special13,
|
||||
&Map02::special14,
|
||||
&Map02::special15,
|
||||
&Map02::special15,
|
||||
&Map02::special15,
|
||||
&Map02::special18,
|
||||
&Map02::special15,
|
||||
&Map02::special20,
|
||||
&Map02::special21
|
||||
};
|
||||
public:
|
||||
Map02() : MapTown(2, "algary", 0x203, 1) {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
void special() override;
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
228
engines/mm/mm1/maps/map03.cpp
Normal file
228
engines/mm/mm1/maps/map03.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/* 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/maps/map03.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
static const byte MONSTER_ID1[8] = { 5, 10, 12, 2, 11, 16, 6, 12 };
|
||||
static const byte MONSTER_ID2[8] = { 2, 7, 7, 7, 5, 4, 3, 8 };
|
||||
|
||||
void Map03::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 29; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[80 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cells on the map are encounters
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map03::special00() {
|
||||
inn();
|
||||
}
|
||||
|
||||
void Map03::special01() {
|
||||
bool hasCourier = false;
|
||||
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
|
||||
hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER3) != 0;
|
||||
}
|
||||
|
||||
bool hasScroll = false;
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
if (c.hasItem(VELLUM_SCROLL_ID)) {
|
||||
hasScroll = true;
|
||||
c._gold += 1500;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCourier && hasScroll) {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
g_globals->_currCharacter = &c;
|
||||
c._exp += 2500;
|
||||
|
||||
int idx = c._equipped.indexOf(VELLUM_SCROLL_ID);
|
||||
if (idx != -1)
|
||||
c._equipped.removeAt(idx);
|
||||
idx = c._backpack.indexOf(VELLUM_SCROLL_ID);
|
||||
if (idx != -1)
|
||||
c._backpack.removeAt(idx);
|
||||
}
|
||||
|
||||
InfoMessage info1(
|
||||
0, 0, STRING["maps.map03.telgoran1"],
|
||||
0, 1, STRING["maps.map03.telgoran2"],
|
||||
[](const Common::KeyState &) {
|
||||
InfoMessage info2(
|
||||
0, 1, STRING["maps.map03.telgoran3"],
|
||||
[](const Common::KeyState &) {
|
||||
g_events->close();
|
||||
}
|
||||
);
|
||||
|
||||
info2._largeMessage = true;
|
||||
g_events->send(info2);
|
||||
}
|
||||
);
|
||||
info1._largeMessage = true;
|
||||
g_events->send(info1);
|
||||
|
||||
} else {
|
||||
send(InfoMessage(
|
||||
0, 0, STRING["maps.map03.telgoran1"],
|
||||
0, 1, STRING["maps.map03.telgoran4"]
|
||||
));
|
||||
}
|
||||
|
||||
none160();
|
||||
}
|
||||
|
||||
void Map03::special02() {
|
||||
blacksmith();
|
||||
}
|
||||
|
||||
void Map03::special03() {
|
||||
market();
|
||||
}
|
||||
|
||||
void Map03::special04() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.passage_outside1"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(9, 11);
|
||||
g_maps->changeMap(0x112, 2);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map03::special05() {
|
||||
tavern();
|
||||
}
|
||||
|
||||
void Map03::special06() {
|
||||
temple();
|
||||
}
|
||||
|
||||
void Map03::special07() {
|
||||
training();
|
||||
}
|
||||
|
||||
void Map03::special08() {
|
||||
g_globals->_treasure._container = GOLD_CHEST;
|
||||
g_globals->_treasure._items[2] = 200;
|
||||
g_globals->_treasure.setGems(200);
|
||||
g_events->addAction(KEYBIND_SEARCH);
|
||||
}
|
||||
|
||||
void Map03::special09() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.stairs_down"],
|
||||
[]() {
|
||||
g_maps->_mapPos = Common::Point(14, 0);
|
||||
g_maps->changeMap(5, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map03::special10() {
|
||||
showSign(STRING["maps.map03.market"]);
|
||||
}
|
||||
|
||||
void Map03::special11() {
|
||||
showSign(STRING["maps.map03.blacksmith"]);
|
||||
}
|
||||
|
||||
void Map03::special12() {
|
||||
showSign(STRING["maps.map03.inn"]);
|
||||
}
|
||||
|
||||
void Map03::special13() {
|
||||
_data[0x1d] = 80;
|
||||
_data[0x2e] = 3;
|
||||
_data[0x2f] = 3;
|
||||
}
|
||||
|
||||
void Map03::special14() {
|
||||
_data[0x1d] = 150;
|
||||
_data[0x2e] = 2;
|
||||
_data[0x2f] = 2;
|
||||
}
|
||||
|
||||
void Map03::special15() {
|
||||
assert(g_maps->_mapPos.x < 8);
|
||||
g_maps->clearSpecial();
|
||||
int monsterCount = (g_maps->_mapPos.x < 3) ? 1 :
|
||||
getRandomNumber(8);
|
||||
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
enc._levelIndex = 80;
|
||||
enc._manual = true;
|
||||
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < monsterCount; ++i)
|
||||
enc.addMonster(MONSTER_ID1[i], MONSTER_ID2[i]);
|
||||
|
||||
enc.execute();
|
||||
}
|
||||
|
||||
void Map03::special18() {
|
||||
showSign(STRING["maps.map03.temple"]);
|
||||
}
|
||||
|
||||
void Map03::special20() {
|
||||
showSign(STRING["maps.map03.tavern"]);
|
||||
}
|
||||
|
||||
void Map03::special21() {
|
||||
showSign(STRING["maps.map03.training"]);
|
||||
}
|
||||
|
||||
void Map03::special27() {
|
||||
showSign(STRING["maps.map03.forbidden_crypt"]);
|
||||
}
|
||||
|
||||
void Map03::special28() {
|
||||
showSign(STRING["maps.map03.eternal_rest"]);
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
100
engines/mm/mm1/maps/map03.h
Normal file
100
engines/mm/mm1/maps/map03.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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_MAPS_MAP03_H
|
||||
#define MM1_MAPS_MAP03_H
|
||||
|
||||
#include "mm/mm1/maps/map_town.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
class Map03 : public MapTown {
|
||||
typedef void (Map03:: *SpecialFn)();
|
||||
private:
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special08();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special12();
|
||||
void special13();
|
||||
void special14();
|
||||
void special15();
|
||||
void special18();
|
||||
void special20();
|
||||
void special21();
|
||||
void special27();
|
||||
void special28();
|
||||
|
||||
const SpecialFn SPECIAL_FN[29] = {
|
||||
&Map03::special00,
|
||||
&Map03::special01,
|
||||
&Map03::special02,
|
||||
&Map03::special03,
|
||||
&Map03::special04,
|
||||
&Map03::special05,
|
||||
&Map03::special06,
|
||||
&Map03::special07,
|
||||
&Map03::special08,
|
||||
&Map03::special09,
|
||||
&Map03::special10,
|
||||
&Map03::special11,
|
||||
&Map03::special12,
|
||||
&Map03::special13,
|
||||
&Map03::special14,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special18,
|
||||
&Map03::special15,
|
||||
&Map03::special20,
|
||||
&Map03::special21,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special15,
|
||||
&Map03::special27,
|
||||
&Map03::special28
|
||||
};
|
||||
public:
|
||||
Map03() : MapTown(3, "dusk", 0x802, 1) {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
void special() override;
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
200
engines/mm/mm1/maps/map04.cpp
Normal file
200
engines/mm/mm1/maps/map04.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/* 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/maps/map04.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
void Map04::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 22; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[73 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Stealable treasure
|
||||
send(SoundMessage(
|
||||
STRING["maps.map04.treasure"],
|
||||
[]() {
|
||||
g_maps->clearSpecial();
|
||||
if ((*g_maps->_currentMap)[MAP04_TREASURE_STOLEN] < 255)
|
||||
(*g_maps->_currentMap)[MAP04_TREASURE_STOLEN]++;
|
||||
g_globals->_treasure.setGold(600);
|
||||
g_globals->_treasure.setGems(10);
|
||||
g_events->addAction(KEYBIND_SEARCH);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map04::special00() {
|
||||
inn();
|
||||
}
|
||||
|
||||
void Map04::special01() {
|
||||
bool hasCourier = false;
|
||||
for (uint i = 0; i < g_globals->_party.size() && !hasCourier; ++i) {
|
||||
hasCourier = (g_globals->_party[i]._flags[0] & CHARFLAG0_COURIER1) != 0;
|
||||
}
|
||||
|
||||
bool hasScroll = g_globals->_party.hasItem(VELLUM_SCROLL_ID);
|
||||
|
||||
auto callback = [](const Common::KeyState &) {
|
||||
g_events->close();
|
||||
g_maps->_mapPos.y = 6;
|
||||
g_maps->_currentMap->updateGame();
|
||||
};
|
||||
|
||||
if (hasCourier && hasScroll) {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
g_globals->_currCharacter = &c;
|
||||
c._exp += 1000;
|
||||
c._flags[0] &= (c._flags[0] & CHARFLAG0_COURIER1) | CHARFLAG0_COURIER2;
|
||||
}
|
||||
|
||||
send(InfoMessage(
|
||||
0, 0, STRING["maps.map04.agar1"],
|
||||
0, 1, STRING["maps.map04.agar2"],
|
||||
callback
|
||||
));
|
||||
} else {
|
||||
send(InfoMessage(
|
||||
0, 0, STRING["maps.map04.agar1"],
|
||||
0, 1, STRING["maps.map04.agar3"],
|
||||
callback
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void Map04::special02() {
|
||||
blacksmith();
|
||||
}
|
||||
|
||||
void Map04::special03() {
|
||||
market();
|
||||
}
|
||||
|
||||
void Map04::special04() {
|
||||
visitedExit();
|
||||
if (_data[MAP04_PASSAGE_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
|
||||
send(SoundMessage(
|
||||
STRING["maps.passage_outside2"],
|
||||
[]() {
|
||||
g_maps->_mapPos.x = 13;
|
||||
g_maps->_mapPos.y = 1;
|
||||
g_maps->changeMap(0xa00, 2);
|
||||
}
|
||||
));
|
||||
} else {
|
||||
// Sucks to be you
|
||||
_data[MAP04_PASSAGE_OVERRIDE]++;
|
||||
g_events->addView("Arrested");
|
||||
}
|
||||
}
|
||||
|
||||
void Map04::special05() {
|
||||
tavern();
|
||||
}
|
||||
|
||||
void Map04::special06() {
|
||||
temple();
|
||||
}
|
||||
|
||||
void Map04::special07() {
|
||||
training();
|
||||
}
|
||||
|
||||
void Map04::special08() {
|
||||
g_maps->_mapPos.x = getRandomNumber(15);
|
||||
g_maps->_mapPos.y = getRandomNumber(15);
|
||||
redrawGame();
|
||||
|
||||
send(InfoMessage(0, 1, STRING["maps.poof"]));
|
||||
}
|
||||
|
||||
void Map04::special09() {
|
||||
visitedExit();
|
||||
if (_data[MAP04_STAIRS_OVERRIDE] || _data[MAP04_TREASURE_STOLEN] == 0) {
|
||||
send(SoundMessage(
|
||||
STRING["maps.stairs_down"],
|
||||
[]() {
|
||||
g_maps->_mapPos.x = 0;
|
||||
g_maps->_mapPos.y = 7;
|
||||
g_maps->changeMap(0x202, 1);
|
||||
}
|
||||
));
|
||||
} else {
|
||||
// Sucks to be you
|
||||
_data[MAP04_STAIRS_OVERRIDE]++;
|
||||
g_events->addView("Arrested");
|
||||
}
|
||||
}
|
||||
|
||||
void Map04::special10() {
|
||||
showSign(STRING["maps.map04.market"]);
|
||||
}
|
||||
|
||||
void Map04::special11() {
|
||||
showSign(STRING["maps.map04.blacksmith"]);
|
||||
}
|
||||
|
||||
void Map04::special12() {
|
||||
showSign(STRING["maps.map04.inn"]);
|
||||
}
|
||||
|
||||
void Map04::special13() {
|
||||
if (_data[MAP04_TREASURE_STOLEN]) {
|
||||
g_maps->clearSpecial();
|
||||
g_events->addView("Arrested");
|
||||
} else {
|
||||
none160();
|
||||
}
|
||||
}
|
||||
|
||||
void Map04::special18() {
|
||||
showSign(STRING["maps.map04.temple"]);
|
||||
}
|
||||
|
||||
void Map04::special20() {
|
||||
showSign(STRING["maps.map04.tavern"]);
|
||||
}
|
||||
|
||||
void Map04::special21() {
|
||||
showSign(STRING["maps.map04.training"]);
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
94
engines/mm/mm1/maps/map04.h
Normal file
94
engines/mm/mm1/maps/map04.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* 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_MAPS_MAP04_H
|
||||
#define MM1_MAPS_MAP04_H
|
||||
|
||||
#include "mm/mm1/maps/map_town.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
#define MAP04_PASSAGE_OVERRIDE 169
|
||||
#define MAP04_STAIRS_OVERRIDE 196
|
||||
#define MAP04_TREASURE_STOLEN 971
|
||||
|
||||
class Map04 : public MapTown {
|
||||
typedef void (Map04:: *SpecialFn)();
|
||||
private:
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special12();
|
||||
void special13();
|
||||
void special18();
|
||||
void special20();
|
||||
void special21();
|
||||
|
||||
const SpecialFn SPECIAL_FN[22] = {
|
||||
&Map04::special00,
|
||||
&Map04::special01,
|
||||
&Map04::special02,
|
||||
&Map04::special03,
|
||||
&Map04::special04,
|
||||
&Map04::special05,
|
||||
&Map04::special06,
|
||||
&Map04::special07,
|
||||
&Map04::special08,
|
||||
&Map04::special09,
|
||||
&Map04::special10,
|
||||
&Map04::special11,
|
||||
&Map04::special12,
|
||||
&Map04::special13,
|
||||
&Map04::special13,
|
||||
&Map04::special13,
|
||||
&Map04::special13,
|
||||
&Map04::special13,
|
||||
&Map04::special18,
|
||||
&Map04::special13,
|
||||
&Map04::special20,
|
||||
&Map04::special21
|
||||
};
|
||||
public:
|
||||
Map04() : MapTown(4, "erliquin", 0xb1a, 3) {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
void special() override;
|
||||
|
||||
void special08();
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
225
engines/mm/mm1/maps/map05.cpp
Normal file
225
engines/mm/mm1/maps/map05.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/* 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/maps/map05.h"
|
||||
#include "mm/mm1/maps/maps.h"
|
||||
#include "mm/mm1/events.h"
|
||||
#include "mm/mm1/globals.h"
|
||||
#include "mm/mm1/sound.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
#define MONSTER_ID 169
|
||||
#define VAL1 574
|
||||
#define VAL2 575
|
||||
|
||||
void Map05::special() {
|
||||
// Scan for special actions on the map cell
|
||||
for (uint i = 0; i < 21; ++i) {
|
||||
if (g_maps->_mapOffset == _data[51 + i]) {
|
||||
// Found a specially handled cell, but it
|
||||
// only triggers in designated direction(s)
|
||||
if (g_maps->_forwardMask & _data[72 + i]) {
|
||||
(this->*SPECIAL_FN[i])();
|
||||
} else {
|
||||
checkPartyDead();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cells on the map are encounters
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map05::special00() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.stairs_up"],
|
||||
[]() {
|
||||
g_maps->changeMap(0x604, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map05::special01() {
|
||||
encounter(1);
|
||||
}
|
||||
|
||||
void Map05::special02() {
|
||||
encounter(9);
|
||||
}
|
||||
|
||||
void Map05::special03() {
|
||||
encounter(14);
|
||||
}
|
||||
|
||||
void Map05::special04() {
|
||||
encounter(20);
|
||||
}
|
||||
|
||||
void Map05::special05() {
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
g_maps->clearSpecial();
|
||||
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < 10; ++i)
|
||||
enc.addMonster(14, 1);
|
||||
|
||||
enc._levelIndex = 80;
|
||||
enc._manual = true;
|
||||
enc.execute();
|
||||
}
|
||||
|
||||
void Map05::special06() {
|
||||
if (!g_globals->_party.hasItem(VELLUM_SCROLL_ID)) {
|
||||
send(SoundMessage(
|
||||
0, 1, STRING[!hasFlag() ? "maps.map05.man1" : "maps.map05.man2"],
|
||||
[]() {
|
||||
Map05 &map = *static_cast<Map05 *>(g_maps->_currentMap);
|
||||
if (map.addScroll()) {
|
||||
map.addFlag();
|
||||
g_events->send(InfoMessage(0, 1, STRING["maps.map05.man3"]));
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void Map05::special07() {
|
||||
visitedExit();
|
||||
send(SoundMessage(
|
||||
STRING["maps.map05.portal"],
|
||||
[]() {
|
||||
g_maps->_mapPos.x = 8;
|
||||
g_maps->_mapPos.y = 8;
|
||||
g_maps->changeMap(1, 1);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map05::special08() {
|
||||
send(SoundMessage(
|
||||
2, 1, STRING["maps.sign"],
|
||||
10, 2, STRING["maps.map05.arena"]
|
||||
));
|
||||
}
|
||||
|
||||
void Map05::special09() {
|
||||
send(SoundMessage(
|
||||
0, 1, STRING["maps.map05.arena_inside"],
|
||||
[]() {
|
||||
Map05 &map = *static_cast<Map05 *>(g_maps->_currentMap);
|
||||
map[MAP_47] = 2;
|
||||
map[MAP_33] = 6;
|
||||
map[MAP_MAX_MONSTERS] = 15;
|
||||
g_globals->_encounters._encounterType = Game::FORCE_SURPRISED;
|
||||
g_globals->_encounters.execute();
|
||||
},
|
||||
[]() {
|
||||
Map05 &map = *static_cast<Map05 *>(g_maps->_currentMap);
|
||||
map[MAP_47] = 1;
|
||||
map[MAP_33] = 4;
|
||||
map[MAP_MAX_MONSTERS] = 10;
|
||||
g_globals->_treasure.clear();
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
void Map05::special10() {
|
||||
showMessage(STRING["maps.map05.message2"]);
|
||||
}
|
||||
|
||||
void Map05::special11() {
|
||||
if (g_maps->_forwardMask == DIRMASK_S) {
|
||||
g_maps->clearSpecial();
|
||||
g_globals->_encounters.execute();
|
||||
} else {
|
||||
showMessage(STRING["maps.map05.message3"]);
|
||||
}
|
||||
}
|
||||
|
||||
void Map05::special14() {
|
||||
g_maps->clearSpecial();
|
||||
if (getRandomNumber(2) == 2)
|
||||
g_globals->_encounters.execute();
|
||||
}
|
||||
|
||||
void Map05::encounter(int monsterId) {
|
||||
Game::Encounter &enc = g_globals->_encounters;
|
||||
_data[MONSTER_ID] = monsterId;
|
||||
g_maps->clearSpecial();
|
||||
|
||||
int monsterCount = getRandomNumber(5);
|
||||
enc.clearMonsters();
|
||||
for (int i = 0; i < monsterCount; ++i)
|
||||
enc.addMonster(monsterId, 1);
|
||||
|
||||
enc._levelIndex = 80;
|
||||
enc._manual = true;
|
||||
enc.execute();
|
||||
}
|
||||
|
||||
void Map05::showMessage(const Common::String &msg) {
|
||||
send(SoundMessage(
|
||||
0, 1, STRING["maps.map05.message1"],
|
||||
0, 2, msg
|
||||
));
|
||||
}
|
||||
|
||||
bool Map05::addScroll() {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
if (!c._backpack.full()) {
|
||||
// Add item
|
||||
c._backpack.add(VELLUM_SCROLL_ID, 0);
|
||||
g_globals->_items.getItem(VELLUM_SCROLL_ID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
g_events->send(SoundMessage(8, 2, STRING["maps.map05.backpacks_full"]));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Map05::hasFlag() {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
const Character &c = g_globals->_party[i];
|
||||
if (c._flags[0] & CHARFLAG0_COURIER1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Map05::addFlag() {
|
||||
for (uint i = 0; i < g_globals->_party.size(); ++i) {
|
||||
Character &c = g_globals->_party[i];
|
||||
c._flags[0] |= CHARFLAG0_COURIER1;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
89
engines/mm/mm1/maps/map05.h
Normal file
89
engines/mm/mm1/maps/map05.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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_MAPS_MAP05_H
|
||||
#define MM1_MAPS_MAP05_H
|
||||
|
||||
#include "mm/mm1/maps/map.h"
|
||||
|
||||
namespace MM {
|
||||
namespace MM1 {
|
||||
namespace Maps {
|
||||
|
||||
class Map05 : public Map {
|
||||
typedef void (Map05:: *SpecialFn)();
|
||||
private:
|
||||
void special00();
|
||||
void special01();
|
||||
void special02();
|
||||
void special03();
|
||||
void special04();
|
||||
void special05();
|
||||
void special06();
|
||||
void special07();
|
||||
void special08();
|
||||
void special09();
|
||||
void special10();
|
||||
void special11();
|
||||
void special14();
|
||||
void encounter(int monsterId);
|
||||
void showMessage(const Common::String &msg);
|
||||
static bool addScroll();
|
||||
static bool hasFlag();
|
||||
static void addFlag();
|
||||
|
||||
const SpecialFn SPECIAL_FN[21] = {
|
||||
&Map05::special00,
|
||||
&Map05::special01,
|
||||
&Map05::special02,
|
||||
&Map05::special03,
|
||||
&Map05::special04,
|
||||
&Map05::special05,
|
||||
&Map05::special06,
|
||||
&Map05::special07,
|
||||
&Map05::special08,
|
||||
&Map05::special09,
|
||||
&Map05::special10,
|
||||
&Map05::special11,
|
||||
&Map05::special11,
|
||||
&Map05::special11,
|
||||
&Map05::special14,
|
||||
&Map05::special14,
|
||||
&Map05::special14,
|
||||
&Map05::special14,
|
||||
&Map05::special14,
|
||||
&Map05::special14,
|
||||
&Map05::special08
|
||||
};
|
||||
public:
|
||||
Map05() : Map(5, "cave1", 0xa11, 1) {}
|
||||
|
||||
/**
|
||||
* Handles all special stuff that happens on the map
|
||||
*/
|
||||
void special() override;
|
||||
};
|
||||
|
||||
} // namespace Maps
|
||||
} // namespace MM1
|
||||
} // namespace MM
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user