[Scummvm-git-logs] scummvm master -> 2ab300cf355239f5e5f07e77edbc8a9644e01a2e
dreammaster
paulfgilbert at gmail.com
Wed Apr 29 01:47:32 UTC 2020
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
32c418e81d ULTIMA4: Refactored items methods into their own class
ac1bd28d22 ULTIMA4: Removal of outstanding using namespace
2ab300cf35 ULTIMA4: Refactored spell methods into their own class
Commit: 32c418e81d9c13dd96db5eafc745f8f430e5bfe8
https://github.com/scummvm/scummvm/commit/32c418e81d9c13dd96db5eafc745f8f430e5bfe8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-28T17:00:11-07:00
Commit Message:
ULTIMA4: Refactored items methods into their own class
Changed paths:
engines/ultima/ultima4/controllers/combat_controller.cpp
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/filesys/savegame.cpp
engines/ultima/ultima4/game/item.cpp
engines/ultima/ultima4/game/item.h
engines/ultima/ultima4/map/dungeon.cpp
engines/ultima/ultima4/map/mapmgr.cpp
engines/ultima/ultima4/ultima4.cpp
engines/ultima/ultima4/ultima4.h
diff --git a/engines/ultima/ultima4/controllers/combat_controller.cpp b/engines/ultima/ultima4/controllers/combat_controller.cpp
index 2662b6823a..53406464ad 100644
--- a/engines/ultima/ultima4/controllers/combat_controller.cpp
+++ b/engines/ultima/ultima4/controllers/combat_controller.cpp
@@ -998,7 +998,7 @@ bool CombatController::keyPressed(int key) {
#ifdef IOS_ULTIMA4
U4IOS::IOSConversationHelper::setIntroString("Use which item?");
#endif
- itemUse(gameGetInput().c_str());
+ g_items->itemUse(gameGetInput().c_str());
break;
case 'v':
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 0484a8c24f..02cbc5b7bb 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -985,14 +985,14 @@ bool Debugger::cmdSearch(int argc, const char **argv) {
} else {
print("Searching...");
- const ItemLocation *item = itemAtLocation(g_context->_location->_map, g_context->_location->_coords);
+ const ItemLocation *item = g_items->itemAtLocation(g_context->_location->_map, g_context->_location->_coords);
if (item) {
- if (item->_isItemInInventory && (*item->_isItemInInventory)(item->_data)) {
+ if (item->_isItemInInventory && (g_items->*(item->_isItemInInventory))(item->_data)) {
print("%cNothing Here!%c", FG_GREY, FG_WHITE);
} else {
if (item->_name)
print("You find...\n%s!", item->_name);
- (*item->_putItemInInventory)(item->_data);
+ (g_items->*(item->_putItemInInventory))(item->_data);
}
} else {
print("%cNothing Here!%c", FG_GREY, FG_WHITE);
@@ -1097,7 +1097,7 @@ bool Debugger::cmdUse(int argc, const char **argv) {
#ifdef IOS_ULTIMA4
U4IOS::IOSConversationHelper::setIntroString("Use which item?");
#endif
- itemUse(gameGetInput().c_str());
+ g_items->itemUse(gameGetInput().c_str());
return isDebuggerActive();
}
diff --git a/engines/ultima/ultima4/filesys/savegame.cpp b/engines/ultima/ultima4/filesys/savegame.cpp
index 34ffed8fce..8a56cae5cb 100644
--- a/engines/ultima/ultima4/filesys/savegame.cpp
+++ b/engines/ultima/ultima4/filesys/savegame.cpp
@@ -213,7 +213,7 @@ void SaveGame::load(Common::SeekableReadStream *stream) {
}
spellSetEffectCallback(&gameSpellEffect);
- itemSetDestroyAllCreaturesCallback(&gameDestroyAllCreatures);
+ g_items->setDestroyAllCreaturesCallback(&gameDestroyAllCreatures);
g_context->_stats->resetReagentsMenu();
diff --git a/engines/ultima/ultima4/game/item.cpp b/engines/ultima/ultima4/game/item.cpp
index 1db4c89d9e..4edefa2b7c 100644
--- a/engines/ultima/ultima4/game/item.cpp
+++ b/engines/ultima/ultima4/game/item.cpp
@@ -44,177 +44,156 @@
namespace Ultima {
namespace Ultima4 {
-using Common::String;
+Items *g_items;
-DestroyAllCreaturesCallback destroyAllCreaturesCallback;
-
-void itemSetDestroyAllCreaturesCallback(DestroyAllCreaturesCallback callback) {
- destroyAllCreaturesCallback = callback;
-}
-
-int needStoneNames = 0;
-byte stoneMask = 0;
-
-bool isRuneInInventory(int virt);
-void putRuneInInventory(int virt);
-bool isStoneInInventory(int virt);
-void putStoneInInventory(int virt);
-bool isItemInInventory(int item);
-bool isSkullInInventory(int item);
-void putItemInInventory(int item);
-void useBBC(int item);
-void useHorn(int item);
-void useWheel(int item);
-void useSkull(int item);
-void useStone(int item);
-void useKey(int item);
-bool isMysticInInventory(int mystic);
-void putMysticInInventory(int mystic);
-bool isWeaponInInventory(int weapon);
-void putWeaponInInventory(int weapon);
-void useTelescope(int notused);
-bool isReagentInInventory(int reag);
-void putReagentInInventory(int reag);
-bool isAbyssOpened(const Portal *p);
-void itemHandleStones(const Common::String &color);
-
-static const ItemLocation ITEMS[] = {
+const ItemLocation Items::ITEMS[N_ITEMS] = {
{
"Mandrake Root", nullptr, "mandrake1",
- &isReagentInInventory, &putReagentInInventory, nullptr, REAG_MANDRAKE, SC_NEWMOONS | SC_REAGENTDELAY
+ &Items::isReagentInInventory, &Items::putReagentInInventory, nullptr, REAG_MANDRAKE, SC_NEWMOONS | SC_REAGENTDELAY
},
{
"Mandrake Root", nullptr, "mandrake2",
- &isReagentInInventory, &putReagentInInventory, nullptr, REAG_MANDRAKE, SC_NEWMOONS | SC_REAGENTDELAY
+ &Items::isReagentInInventory, &Items::putReagentInInventory, nullptr, REAG_MANDRAKE, SC_NEWMOONS | SC_REAGENTDELAY
},
{
"Nightshade", nullptr, "nightshade1",
- &isReagentInInventory, &putReagentInInventory, nullptr, REAG_NIGHTSHADE, SC_NEWMOONS | SC_REAGENTDELAY
+ &Items::isReagentInInventory, &Items::putReagentInInventory, nullptr, REAG_NIGHTSHADE, SC_NEWMOONS | SC_REAGENTDELAY
},
{
"Nightshade", nullptr, "nightshade2",
- &isReagentInInventory, &putReagentInInventory, nullptr, REAG_NIGHTSHADE, SC_NEWMOONS | SC_REAGENTDELAY
+ &Items::isReagentInInventory, &Items::putReagentInInventory, nullptr, REAG_NIGHTSHADE, SC_NEWMOONS | SC_REAGENTDELAY
},
{
"the Bell of Courage", "bell", "bell",
- &isItemInInventory, &putItemInInventory, &useBBC, ITEM_BELL, 0
+ &Items::isItemInInventory, &Items::putItemInInventory, &Items::useBBC, ITEM_BELL, 0
},
{
"the Book of Truth", "book", "book",
- &isItemInInventory, &putItemInInventory, &useBBC, ITEM_BOOK, 0
+ &Items::isItemInInventory, &Items::putItemInInventory, &Items::useBBC, ITEM_BOOK, 0
},
{
"the Candle of Love", "candle", "candle",
- &isItemInInventory, &putItemInInventory, &useBBC, ITEM_CANDLE, 0
+ &Items::isItemInInventory, &Items::putItemInInventory, &Items::useBBC, ITEM_CANDLE, 0
},
{
"A Silver Horn", "horn", "horn",
- &isItemInInventory, &putItemInInventory, &useHorn, ITEM_HORN, 0
+ &Items::isItemInInventory, &Items::putItemInInventory, &Items::useHorn, ITEM_HORN, 0
},
{
"the Wheel from the H.M.S. Cape", "wheel", "wheel",
- &isItemInInventory, &putItemInInventory, &useWheel, ITEM_WHEEL, 0
+ &Items::isItemInInventory, &Items::putItemInInventory, &Items::useWheel, ITEM_WHEEL, 0
},
{
"the Skull of Modain the Wizard", "skull", "skull",
- &isSkullInInventory, &putItemInInventory, &useSkull, ITEM_SKULL, SC_NEWMOONS
+ &Items::isSkullInInventory, &Items::putItemInInventory, &Items::useSkull, ITEM_SKULL, SC_NEWMOONS
},
{
"the Red Stone", "red", "redstone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_RED, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_RED, 0
},
{
"the Orange Stone", "orange", "orangestone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_ORANGE, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_ORANGE, 0
},
{
"the Yellow Stone", "yellow", "yellowstone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_YELLOW, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_YELLOW, 0
},
{
"the Green Stone", "green", "greenstone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_GREEN, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_GREEN, 0
},
{
"the Blue Stone", "blue", "bluestone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_BLUE, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_BLUE, 0
},
{
"the Purple Stone", "purple", "purplestone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_PURPLE, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_PURPLE, 0
},
{
"the Black Stone", "black", "blackstone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_BLACK, SC_NEWMOONS
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_BLACK, SC_NEWMOONS
},
{
"the White Stone", "white", "whitestone",
- &isStoneInInventory, &putStoneInInventory, &useStone, STONE_WHITE, 0
+ &Items::isStoneInInventory, &Items::putStoneInInventory, &Items::useStone, STONE_WHITE, 0
},
/* handlers for using generic objects */
- { nullptr, "stone", nullptr, &isStoneInInventory, nullptr, &useStone, -1, 0 },
- { nullptr, "stones", nullptr, &isStoneInInventory, nullptr, &useStone, -1, 0 },
- { nullptr, "key", nullptr, &isItemInInventory, nullptr, &useKey, (ITEM_KEY_C | ITEM_KEY_L | ITEM_KEY_T), 0 },
- { nullptr, "keys", nullptr, &isItemInInventory, nullptr, &useKey, (ITEM_KEY_C | ITEM_KEY_L | ITEM_KEY_T), 0 },
+ { nullptr, "stone", nullptr, &Items::isStoneInInventory, nullptr, &Items::useStone, -1, 0 },
+ { nullptr, "stones", nullptr, &Items::isStoneInInventory, nullptr, &Items::useStone, -1, 0 },
+ { nullptr, "key", nullptr, &Items::isItemInInventory, nullptr, &Items::useKey, (ITEM_KEY_C | ITEM_KEY_L | ITEM_KEY_T), 0 },
+ { nullptr, "keys", nullptr, &Items::isItemInInventory, nullptr, &Items::useKey, (ITEM_KEY_C | ITEM_KEY_L | ITEM_KEY_T), 0 },
/* Lycaeum telescope */
- { nullptr, nullptr, "telescope", nullptr, &useTelescope, nullptr, 0, 0 },
+ { nullptr, nullptr, "telescope", nullptr, &Items::useTelescope, nullptr, 0, 0 },
{
"Mystic Armor", nullptr, "mysticarmor",
- &isMysticInInventory, &putMysticInInventory, nullptr, ARMR_MYSTICROBES, SC_FULLAVATAR
+ &Items::isMysticInInventory, &Items::putMysticInInventory, nullptr, ARMR_MYSTICROBES, SC_FULLAVATAR
},
{
"Mystic Swords", nullptr, "mysticswords",
- &isMysticInInventory, &putMysticInInventory, nullptr, WEAP_MYSTICSWORD, SC_FULLAVATAR
+ &Items::isMysticInInventory, &Items::putMysticInInventory, nullptr, WEAP_MYSTICSWORD, SC_FULLAVATAR
},
{
"the sulfury remains of an ancient Sosarian Laser Gun. It turns to ash in your fingers", nullptr, "lasergun", // lol, where'd that come from?
//Looks like someone was experimenting with "maps.xml". It effectively increments sulfur ash by one due to '16' being an invalid weapon index.
- &isWeaponInInventory, &putWeaponInInventory, nullptr, 16, 0
+ &Items::isWeaponInInventory, &Items::putWeaponInInventory, nullptr, 16, 0
},
{
"the rune of Honesty", nullptr, "honestyrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_HONESTY, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_HONESTY, 0
},
{
"the rune of Compassion", nullptr, "compassionrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_COMPASSION, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_COMPASSION, 0
},
{
"the rune of Valor", nullptr, "valorrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_VALOR, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_VALOR, 0
},
{
"the rune of Justice", nullptr, "justicerune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_JUSTICE, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_JUSTICE, 0
},
{
"the rune of Sacrifice", nullptr, "sacrificerune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_SACRIFICE, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_SACRIFICE, 0
},
{
"the rune of Honor", nullptr, "honorrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_HONOR, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_HONOR, 0
},
{
"the rune of Spirituality", nullptr, "spiritualityrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_SPIRITUALITY, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_SPIRITUALITY, 0
},
{
"the rune of Humility", nullptr, "humilityrune",
- &isRuneInInventory, &putRuneInInventory, nullptr, RUNE_HUMILITY, 0
+ &Items::isRuneInInventory, &Items::putRuneInInventory, nullptr, RUNE_HUMILITY, 0
}
};
-#define N_ITEMS (sizeof(ITEMS) / sizeof(ITEMS[0]))
+Items::Items() : destroyAllCreaturesCallback(nullptr),
+ needStoneNames(0), stoneMask(0) {
+ g_items = this;
+}
+
+Items::~Items() {
+ g_items = nullptr;
+}
+
+void Items::setDestroyAllCreaturesCallback(DestroyAllCreaturesCallback callback) {
+ destroyAllCreaturesCallback = callback;
+}
-bool isRuneInInventory(int virt) {
+bool Items::isRuneInInventory(int virt) {
return g_ultima->_saveGame->_runes & virt;
}
-void putRuneInInventory(int virt) {
+void Items::putRuneInInventory(int virt) {
g_context->_party->member(0)->awardXp(100);
g_context->_party->adjustKarma(KA_FOUND_ITEM);
g_ultima->_saveGame->_runes |= virt;
@@ -252,7 +231,7 @@ void putRuneInInventory(int virt) {
g_ultima->_saveGame->_lastReagent = g_ultima->_saveGame->_moves & 0xF0;
}
-bool isStoneInInventory(int virt) {
+bool Items::isStoneInInventory(int virt) {
/* generic test: does the party have any stones yet? */
if (virt == -1)
return (g_ultima->_saveGame->_stones > 0);
@@ -260,7 +239,7 @@ bool isStoneInInventory(int virt) {
else return g_ultima->_saveGame->_stones & virt;
}
-void putStoneInInventory(int virt) {
+void Items::putStoneInInventory(int virt) {
g_context->_party->member(0)->awardXp(200);
g_context->_party->adjustKarma(KA_FOUND_ITEM);
g_ultima->_saveGame->_stones |= virt;
@@ -298,15 +277,15 @@ void putStoneInInventory(int virt) {
g_ultima->_saveGame->_lastReagent = g_ultima->_saveGame->_moves & 0xF0;
}
-bool isItemInInventory(int item) {
+bool Items::isItemInInventory(int item) {
return g_ultima->_saveGame->_items & item;
}
-bool isSkullInInventory(int unused) {
+bool Items::isSkullInInventory(int unused) {
return (g_ultima->_saveGame->_items & (ITEM_SKULL | ITEM_SKULL_DESTROYED));
}
-void putItemInInventory(int item) {
+void Items::putItemInInventory(int item) {
g_context->_party->member(0)->awardXp(400);
g_context->_party->adjustKarma(KA_FOUND_ITEM);
g_ultima->_saveGame->_items |= item;
@@ -348,10 +327,7 @@ void putItemInInventory(int item) {
g_ultima->_saveGame->_lastReagent = g_ultima->_saveGame->_moves & 0xF0;
}
-/**
- * Use bell, book, or candle on the entrance to the Abyss
- */
-void useBBC(int item) {
+void Items::useBBC(int item) {
Coords abyssEntrance(0xe9, 0xe9);
/* on top of the Abyss entrance */
if (g_context->_location->_coords == abyssEntrance) {
@@ -384,28 +360,19 @@ void useBBC(int item) {
else g_screen->screenMessage("\nHmm...No effect!\n");
}
-/**
- * Uses the silver horn
- */
-void useHorn(int item) {
+void Items::useHorn(int item) {
g_screen->screenMessage("\nThe Horn sounds an eerie tone!\n");
g_context->_aura->set(Aura::HORN, 10);
}
-/**
- * Uses the wheel (if on board a ship)
- */
-void useWheel(int item) {
+void Items::useWheel(int item) {
if ((g_context->_transportContext == TRANSPORT_SHIP) && (g_ultima->_saveGame->_shipHull == 50)) {
g_screen->screenMessage("\nOnce mounted, the Wheel glows with a blue light!\n");
g_context->_party->setShipHull(99);
} else g_screen->screenMessage("\nHmm...No effect!\n");
}
-/**
- * Uses or destroys the skull of Mondain
- */
-void useSkull(int item) {
+void Items::useSkull(int item) {
/* FIXME: check to see if the abyss must be opened first
for the skull to be *able* to be destroyed */
@@ -443,10 +410,7 @@ void useSkull(int item) {
}
}
-/**
- * Handles using the virtue stones in dungeon altar rooms and on dungeon altars
- */
-void useStone(int item) {
+void Items::useStone(int item) {
MapCoords coords;
byte stone = static_cast<byte>(item);
@@ -613,11 +577,11 @@ void useStone(int item) {
// That doesn't match U4DOS; does it match another?
}
-void useKey(int item) {
+void Items::useKey(int item) {
g_screen->screenMessage("\nNo place to Use them!\n");
}
-bool isMysticInInventory(int mystic) {
+bool Items::isMysticInInventory(int mystic) {
/* FIXME: you could feasibly get more mystic weapons and armor if you
have 8 party members and equip them all with everything,
then search for Mystic Weapons/Armor again
@@ -637,7 +601,7 @@ bool isMysticInInventory(int mystic) {
return false;
}
-void putMysticInInventory(int mystic) {
+void Items::putMysticInInventory(int mystic) {
g_context->_party->member(0)->awardXp(400);
g_context->_party->adjustKarma(KA_FOUND_ITEM);
if (mystic == WEAP_MYSTICSWORD)
@@ -649,7 +613,7 @@ void putMysticInInventory(int mystic) {
g_ultima->_saveGame->_lastReagent = g_ultima->_saveGame->_moves & 0xF0;
}
-bool isWeaponInInventory(int weapon) {
+bool Items::isWeaponInInventory(int weapon) {
if (g_ultima->_saveGame->_weapons[weapon])
return true;
else {
@@ -661,11 +625,11 @@ bool isWeaponInInventory(int weapon) {
return false;
}
-void putWeaponInInventory(int weapon) {
+void Items::putWeaponInInventory(int weapon) {
g_ultima->_saveGame->_weapons[weapon]++;
}
-void useTelescope(int notused) {
+void Items::useTelescope(int notused) {
g_screen->screenMessage("You see a knob\non the telescope\nmarked A-P\nYou Select:");
#ifdef IOS_ULTIMA4
U4IOS::IOSConversationChoiceHelper telescopeHelper;
@@ -679,11 +643,11 @@ void useTelescope(int notused) {
gamePeerCity(choice, nullptr);
}
-bool isReagentInInventory(int reag) {
+bool Items::isReagentInInventory(int reag) {
return false;
}
-void putReagentInInventory(int reag) {
+void Items::putReagentInInventory(int reag) {
g_context->_party->adjustKarma(KA_FOUND_ITEM);
g_ultima->_saveGame->_reagents[reag] += xu4_random(8) + 2;
g_ultima->_saveGame->_lastReagent = g_ultima->_saveGame->_moves & 0xF0;
@@ -694,10 +658,7 @@ void putReagentInInventory(int reag) {
}
}
-/**
- * Returns true if the specified conditions are met to be able to get the item
- */
-bool itemConditionsMet(byte conditions) {
+bool Items::itemConditionsMet(byte conditions) {
int i;
if ((conditions & SC_NEWMOONS) &&
@@ -718,7 +679,7 @@ bool itemConditionsMet(byte conditions) {
return true;
}
-const ItemLocation *itemAtLocation(const Map *map, const Coords &coords) {
+const ItemLocation *Items::itemAtLocation(const Map *map, const Coords &coords) {
uint i;
for (i = 0; i < N_ITEMS; i++) {
if (!ITEMS[i]._locationLabel)
@@ -730,24 +691,24 @@ const ItemLocation *itemAtLocation(const Map *map, const Coords &coords) {
return nullptr;
}
-void itemUse(const Common::String &shortname) {
+void Items::itemUse(const Common::String &shortName) {
uint i;
const ItemLocation *item = nullptr;
for (i = 0; i < N_ITEMS; i++) {
if (ITEMS[i]._shortName &&
- scumm_stricmp(ITEMS[i]._shortName, shortname.c_str()) == 0) {
+ scumm_stricmp(ITEMS[i]._shortName, shortName.c_str()) == 0) {
item = &ITEMS[i];
/* item name found, see if we have that item in our inventory */
- if (!ITEMS[i]._isItemInInventory || (*ITEMS[i]._isItemInInventory)(ITEMS[i]._data)) {
+ if (!ITEMS[i]._isItemInInventory || (this->*(ITEMS[i]._isItemInInventory))(ITEMS[i]._data)) {
/* use the item, if we can! */
if (!item || !item->_useItem)
g_screen->screenMessage("\nNot a Usable item!\n");
else
- (*item->_useItem)(ITEMS[i]._data);
+ (this->*(item->_useItem))(ITEMS[i]._data);
} else
g_screen->screenMessage("\nNone owned!\n");
@@ -761,23 +722,7 @@ void itemUse(const Common::String &shortname) {
g_screen->screenMessage("\nNot a Usable item!\n");
}
-/**
- * Checks to see if the abyss was opened
- */
-bool isAbyssOpened(const Portal *p) {
- /* make sure the bell, book and candle have all been used */
- int items = g_ultima->_saveGame->_items;
- int isopened = (items & ITEM_BELL_USED) && (items & ITEM_BOOK_USED) && (items & ITEM_CANDLE_USED);
-
- if (!isopened)
- g_screen->screenMessage("Enter Can't!\n");
- return isopened;
-}
-
-/**
- * Handles naming of stones when used
- */
-void itemHandleStones(const Common::String &color) {
+void Items::itemHandleStones(const Common::String &color) {
bool found = false;
for (int i = 0; i < 8; i++) {
@@ -794,5 +739,15 @@ void itemHandleStones(const Common::String &color) {
}
}
+bool Items::isAbyssOpened(const Portal *p) {
+ /* make sure the bell, book and candle have all been used */
+ int items = g_ultima->_saveGame->_items;
+ int isopened = (items & ITEM_BELL_USED) && (items & ITEM_BOOK_USED) && (items & ITEM_CANDLE_USED);
+
+ if (!isopened)
+ g_screen->screenMessage("Enter Can't!\n");
+ return isopened;
+}
+
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/game/item.h b/engines/ultima/ultima4/game/item.h
index 6a23c3be64..ae0cb3665f 100644
--- a/engines/ultima/ultima4/game/item.h
+++ b/engines/ultima/ultima4/game/item.h
@@ -29,8 +29,9 @@
namespace Ultima {
namespace Ultima4 {
-class Map;
class Coords;
+class Map;
+struct Portal;
enum SearchCondition {
SC_NONE = 0x00,
@@ -39,31 +40,108 @@ enum SearchCondition {
SC_REAGENTDELAY = 0x04
};
+class Items;
+typedef bool (Items::*IsInInventoryProc)(int item);
+typedef void (Items::*InventoryActionProc)(int item);
+
+#include "common/pack-start.h" // START STRUCT PACKING
struct ItemLocation {
const char *_name;
const char *_shortName;
const char *_locationLabel;
- bool (*_isItemInInventory)(int item);
- void (*_putItemInInventory)(int item);
- void (*_useItem)(int item);
+ IsInInventoryProc _isItemInInventory;
+ InventoryActionProc _putItemInInventory;
+ InventoryActionProc _useItem;
int _data;
byte _conditions;
-};
+} PACKED_STRUCT;
+#include "common/pack-end.h" // END STRUCT PACKING
typedef void (*DestroyAllCreaturesCallback)();
+#define N_ITEMS 34
-void itemSetDestroyAllCreaturesCallback(DestroyAllCreaturesCallback callback);
+class Items {
+private:
-/**
- * Returns an item location record if a searchable object exists at
- * the given location. nullptr is returned if nothing is there.
- */
-const ItemLocation *itemAtLocation(const Map *map, const Coords &coords);
+ static const ItemLocation ITEMS[N_ITEMS];
+ DestroyAllCreaturesCallback destroyAllCreaturesCallback;
+ int needStoneNames;
+ byte stoneMask;
+private:
+ bool isRuneInInventory(int virt);
+ void putRuneInInventory(int virt);
+ bool isStoneInInventory(int virt);
+ void putStoneInInventory(int virt);
+ bool isItemInInventory(int item);
+ bool isSkullInInventory(int item);
+ void putItemInInventory(int item);
-/**
- * Uses the item indicated by 'shortname'
- */
-void itemUse(const Common::String &shortname);
+ /**
+ * Use bell, book, or candle on the entrance to the Abyss
+ */
+ void useBBC(int item);
+
+ /**
+ * Uses the silver horn
+ */
+ void useHorn(int item);
+
+ /**
+ * Uses the wheel (if on board a ship)
+ */
+ void useWheel(int item);
+
+ /**
+ * Uses or destroys the skull of Mondain
+ */
+ void useSkull(int item);
+
+ /**
+ * Handles using the virtue stones in dungeon altar rooms and on dungeon altars
+ */
+ void useStone(int item);
+ void useKey(int item);
+ bool isMysticInInventory(int mystic);
+ void putMysticInInventory(int mystic);
+ bool isWeaponInInventory(int weapon);
+ void putWeaponInInventory(int weapon);
+ void useTelescope(int notused);
+ bool isReagentInInventory(int reag);
+ void putReagentInInventory(int reag);
+
+ /**
+ * Handles naming of stones when used
+ */
+ void itemHandleStones(const Common::String &color);
+
+ /**
+ * Returns true if the specified conditions are met to be able to get the item
+ */
+ bool itemConditionsMet(byte conditions);
+public:
+ Items();
+ ~Items();
+
+ void setDestroyAllCreaturesCallback(DestroyAllCreaturesCallback callback);
+
+ /**
+ * Returns an item location record if a searchable object exists at
+ * the given location. nullptr is returned if nothing is there.
+ */
+ const ItemLocation *itemAtLocation(const Map *map, const Coords &coords);
+
+ /**
+ * Uses the item indicated by 'shortname'
+ */
+ void itemUse(const Common::String &shortName);
+
+ /**
+ * Checks to see if the abyss was opened
+ */
+ static bool isAbyssOpened(const Portal *p);
+};
+
+extern Items *g_items;
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/map/dungeon.cpp b/engines/ultima/ultima4/map/dungeon.cpp
index 771317e64f..c3bc45b839 100644
--- a/engines/ultima/ultima4/map/dungeon.cpp
+++ b/engines/ultima/ultima4/map/dungeon.cpp
@@ -122,14 +122,14 @@ void dungeonSearch(void) {
default: {
/* see if there is an item at the current location (stones on altars, etc.) */
- item = itemAtLocation(dungeon, g_context->_location->_coords);
+ item = g_items->itemAtLocation(dungeon, g_context->_location->_coords);
if (item) {
- if (item->_isItemInInventory && (*item->_isItemInInventory)(item->_data)) {
+ if (item->_isItemInInventory && (g_items->*(item->_isItemInInventory))(item->_data)) {
g_screen->screenMessage("Nothing Here!\n");
} else {
if (item->_name)
g_screen->screenMessage("You find...\n%s!\n", item->_name);
- (*item->_putItemInInventory)(item->_data);
+ (g_items->*(item->_putItemInInventory))(item->_data);
}
} else
g_screen->screenMessage("\nYou find Nothing!\n");
diff --git a/engines/ultima/ultima4/map/mapmgr.cpp b/engines/ultima/ultima4/map/mapmgr.cpp
index 50f7b5448d..ae48b93f37 100644
--- a/engines/ultima/ultima4/map/mapmgr.cpp
+++ b/engines/ultima/ultima4/map/mapmgr.cpp
@@ -28,6 +28,7 @@
#include "ultima/ultima4/map/map.h"
#include "ultima/ultima4/map/maploader.h"
#include "ultima/ultima4/map/mapmgr.h"
+#include "ultima/ultima4/game/item.h"
#include "ultima/ultima4/game/moongate.h"
#include "ultima/ultima4/game/person.h"
#include "ultima/ultima4/game/portal.h"
@@ -46,7 +47,6 @@ using Std::pair;
MapMgr *MapMgr::_instance = nullptr;
-extern bool isAbyssOpened(const Portal *p);
extern bool shrineCanEnter(const Portal *p);
MapMgr *MapMgr::getInstance() {
@@ -286,7 +286,7 @@ Portal *MapMgr::initPortalFromConf(const ConfigElement &portalConf) {
if (prop == "shrine")
portal->_portalConditionsMet = &shrineCanEnter;
else if (prop == "abyss")
- portal->_portalConditionsMet = &isAbyssOpened;
+ portal->_portalConditionsMet = &Items::isAbyssOpened;
else
error("unknown portalConditionsMet: %s", prop.c_str());
}
diff --git a/engines/ultima/ultima4/ultima4.cpp b/engines/ultima/ultima4/ultima4.cpp
index 76643f82aa..7eb04edb25 100644
--- a/engines/ultima/ultima4/ultima4.cpp
+++ b/engines/ultima/ultima4/ultima4.cpp
@@ -35,6 +35,7 @@
#include "ultima/ultima4/game/context.h"
#include "ultima/ultima4/game/death.h"
#include "ultima/ultima4/game/game.h"
+#include "ultima/ultima4/game/item.h"
#include "ultima/ultima4/game/moongate.h"
#include "ultima/ultima4/game/person.h"
#include "ultima/ultima4/game/weapon.h"
@@ -58,16 +59,17 @@ Ultima4Engine *g_ultima;
Ultima4Engine::Ultima4Engine(OSystem *syst, const Ultima::UltimaGameDescription *gameDesc) :
Shared::UltimaEngine(syst, gameDesc), _saveSlotToLoad(-1), _armors(nullptr),
_codex(nullptr), _config(nullptr), _context(nullptr), _death(nullptr),
- _dialogueLoaders(nullptr), _game(nullptr), _music(nullptr), _imageLoaders(nullptr),
- _mapLoaders(nullptr), _moongates(nullptr), _responseParts(nullptr), _saveGame(nullptr),
- _screen(nullptr), _shrines(nullptr), _tileMaps(nullptr), _tileRules(nullptr),
- _tileSets(nullptr), _weapons(nullptr) {
+ _dialogueLoaders(nullptr), _game(nullptr), _items(nullptr), _music(nullptr),
+ _imageLoaders(nullptr), _mapLoaders(nullptr), _moongates(nullptr),
+ _responseParts(nullptr), _saveGame(nullptr), _screen(nullptr), _shrines(nullptr),
+ _tileMaps(nullptr), _tileRules(nullptr), _tileSets(nullptr), _weapons(nullptr) {
g_ultima = this;
g_armors = nullptr;
g_codex = nullptr;
g_context = nullptr;
g_death = nullptr;
g_game = nullptr;
+ g_items = nullptr;
g_mapLoaders = nullptr;
g_moongates = nullptr;
g_responseParts = nullptr;
@@ -88,6 +90,7 @@ Ultima4Engine::~Ultima4Engine() {
delete _dialogueLoaders;
delete _game;
delete _imageLoaders;
+ delete _items;
delete _mapLoaders;
delete _moongates;
delete _music;
@@ -117,6 +120,7 @@ bool Ultima4Engine::initialize() {
_context = new Context();
_death = new Death();
_dialogueLoaders = new DialogueLoaders();
+ _items = new Items();
_mapLoaders = new MapLoaders();
_moongates = new Moongates();
_responseParts = new ResponseParts();
diff --git a/engines/ultima/ultima4/ultima4.h b/engines/ultima/ultima4/ultima4.h
index db9b63acc4..e5cbdbf51f 100644
--- a/engines/ultima/ultima4/ultima4.h
+++ b/engines/ultima/ultima4/ultima4.h
@@ -36,6 +36,7 @@ class Context;
class Death;
class DialogueLoaders;
class ImageLoaders;
+class Items;
class GameController;
class MapLoaders;
class Moongates;
@@ -73,6 +74,7 @@ public:
DialogueLoaders *_dialogueLoaders;
ImageLoaders *_imageLoaders;
GameController *_game;
+ Items *_items;
MapLoaders *_mapLoaders;
Moongates *_moongates;
Music *_music;
Commit: ac1bd28d22f68bddf20df47e19526a68c1bb9b88
https://github.com/scummvm/scummvm/commit/ac1bd28d22f68bddf20df47e19526a68c1bb9b88
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-28T17:02:38-07:00
Commit Message:
ULTIMA4: Removal of outstanding using namespace
Changed paths:
engines/ultima/ultima4/game/object.cpp
engines/ultima/ultima4/game/person.cpp
diff --git a/engines/ultima/ultima4/game/object.cpp b/engines/ultima/ultima4/game/object.cpp
index 6e112263b4..18223b6674 100644
--- a/engines/ultima/ultima4/game/object.cpp
+++ b/engines/ultima/ultima4/game/object.cpp
@@ -29,8 +29,6 @@
namespace Ultima {
namespace Ultima4 {
-using namespace Std;
-
bool Object::setDirection(Direction d) {
return _tile.setDirection(d);
}
diff --git a/engines/ultima/ultima4/game/person.cpp b/engines/ultima/ultima4/game/person.cpp
index 8d975d3796..8c2ac033fc 100644
--- a/engines/ultima/ultima4/game/person.cpp
+++ b/engines/ultima/ultima4/game/person.cpp
@@ -45,8 +45,6 @@
namespace Ultima {
namespace Ultima4 {
-using namespace Std;
-
int chars_needed(const char *s, int columnmax, int linesdesired, int *real_lines);
/**
@@ -355,8 +353,8 @@ Common::String Person::getIntro(Conversation *cnv) {
Common::String Person::processResponse(Conversation *cnv, Response *response) {
Common::String text;
- const vector<ResponsePart> &parts = response->getParts();
- for (vector<ResponsePart>::const_iterator i = parts.begin(); i != parts.end(); i++) {
+ const Std::vector<ResponsePart> &parts = response->getParts();
+ for (Std::vector<ResponsePart>::const_iterator i = parts.begin(); i != parts.end(); i++) {
// check for command triggers
if (i->isCommand())
@@ -441,7 +439,7 @@ Common::String Person::getResponse(Conversation *cnv, const char *inquiry) {
}
else if (settings._debug && scumm_strnicmp(inquiry, "dump", 4) == 0) {
- vector<Common::String> words = split(inquiry, " \t");
+ Std::vector<Common::String> words = split(inquiry, " \t");
if (words.size() <= 1)
reply = _dialogue->dump("");
else
Commit: 2ab300cf355239f5e5f07e77edbc8a9644e01a2e
https://github.com/scummvm/scummvm/commit/2ab300cf355239f5e5f07e77edbc8a9644e01a2e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2020-04-28T18:47:17-07:00
Commit Message:
ULTIMA4: Refactored spell methods into their own class
Changed paths:
engines/ultima/ultima4/core/debugger.cpp
engines/ultima/ultima4/core/debugger_actions.cpp
engines/ultima/ultima4/filesys/savegame.cpp
engines/ultima/ultima4/game/game.cpp
engines/ultima/ultima4/game/script.cpp
engines/ultima/ultima4/game/spell.cpp
engines/ultima/ultima4/game/spell.h
engines/ultima/ultima4/ultima4.cpp
engines/ultima/ultima4/ultima4.h
diff --git a/engines/ultima/ultima4/core/debugger.cpp b/engines/ultima/ultima4/core/debugger.cpp
index 02cbc5b7bb..12f28de3ff 100644
--- a/engines/ultima/ultima4/core/debugger.cpp
+++ b/engines/ultima/ultima4/core/debugger.cpp
@@ -326,18 +326,18 @@ bool Debugger::cmdCastSpell(int argc, const char **argv) {
if (spell == -1)
return isDebuggerActive();
- print("%s!", spellGetName(spell)); //Prints spell name at prompt
+ print("%s!", g_spells->spellGetName(spell)); //Prints spell name at prompt
g_context->_stats->setView(STATS_PARTY_OVERVIEW);
// if we can't really cast this spell, skip the extra parameters
- if (spellCheckPrerequisites(spell, player) != CASTERR_NOERROR) {
+ if (g_spells->spellCheckPrerequisites(spell, player) != CASTERR_NOERROR) {
gameCastSpell(spell, player, 0);
return isDebuggerActive();
}
// Get the final parameters for the spell
- switch (spellGetParamType(spell)) {
+ switch (g_spells->spellGetParamType(spell)) {
case Spell::PARAM_NONE:
gameCastSpell(spell, player, 0);
break;
@@ -432,7 +432,8 @@ bool Debugger::cmdCastSpell(int argc, const char **argv) {
* original Ultima IV (at least, in the Amiga version.)
*/
//c->saveGame->_mixtures[castSpell]--;
- g_context->_party->member(player)->adjustMp(-spellGetRequiredMP(spell));
+ g_context->_party->member(player)->adjustMp(
+ -g_spells->spellGetRequiredMP(spell));
}
break;
}
@@ -777,7 +778,7 @@ bool Debugger::cmdMixReagents(int argc, const char **argv) {
break;
int spell = choice - 'a';
- print("%s", spellGetName(spell));
+ print("%s", g_spells->spellGetName(spell));
// ensure the mixtures for the spell isn't already maxed out
if (g_ultima->_saveGame->_mixtures[spell] == 99) {
diff --git a/engines/ultima/ultima4/core/debugger_actions.cpp b/engines/ultima/ultima4/core/debugger_actions.cpp
index 59dd09289c..5e8a914270 100644
--- a/engines/ultima/ultima4/core/debugger_actions.cpp
+++ b/engines/ultima/ultima4/core/debugger_actions.cpp
@@ -233,7 +233,7 @@ bool DebuggerActions::mixReagentsForSpellU4(int spell) {
if (choice == '\n' || choice == '\r' || choice == ' ') {
g_screen->screenMessage("\n\nYou mix the Reagents, and...\n");
- if (spellMix(spell, &ingredients))
+ if (g_spells->spellMix(spell, &ingredients))
g_screen->screenMessage("Success!\n\n");
else
g_screen->screenMessage("It Fizzles!\n\n");
@@ -280,14 +280,14 @@ bool DebuggerActions::mixReagentsForSpellU5(int spell) {
bool DebuggerActions::gameSpellMixHowMany(int spell, int num, Ingredients *ingredients) {
int i;
- /* entered 0 mixtures, don't mix anything! */
+ // Entered 0 mixtures, don't mix anything!
if (num == 0) {
print("\nNone mixed!");
ingredients->revert();
return false;
}
- /* if they ask for more than will give them 99, only use what they need */
+ // If they ask for more than will give them 99, only use what they need
if (num > 99 - g_ultima->_saveGame->_mixtures[spell]) {
num = 99 - g_ultima->_saveGame->_mixtures[spell];
print("\n%cOnly need %d!%c", FG_GREY, num, FG_WHITE);
@@ -295,7 +295,7 @@ bool DebuggerActions::gameSpellMixHowMany(int spell, int num, Ingredients *ingre
print("\nMixing %d...", num);
- /* see if there's enough reagents to make number of mixtures requested */
+ // See if there's enough reagents to make number of mixtures requested
if (!ingredients->checkMultiple(num)) {
print("\n%cYou don't have enough reagents to mix %d spells!%c", FG_GREY, num, FG_WHITE);
ingredients->revert();
@@ -303,12 +303,12 @@ bool DebuggerActions::gameSpellMixHowMany(int spell, int num, Ingredients *ingre
}
print("\nYou mix the Reagents, and...");
- if (spellMix(spell, ingredients)) {
+ if (g_spells->spellMix(spell, ingredients)) {
print("Success!\n");
- /* mix the extra spells */
+ // Mix the extra spells
ingredients->multiply(num);
for (i = 0; i < num - 1; i++)
- spellMix(spell, ingredients);
+ g_spells->spellMix(spell, ingredients);
} else {
print("It Fizzles!\n");
}
@@ -341,8 +341,8 @@ void DebuggerActions::gameCastSpell(uint spell, int caster, int param) {
SpellCastError spellError;
Common::String msg;
- if (!spellCast(spell, caster, param, &spellError, true)) {
- msg = spellGetErrorMessage(spell, spellError);
+ if (!g_spells->spellCast(spell, caster, param, &spellError, true)) {
+ msg = g_spells->spellGetErrorMessage(spell, spellError);
if (!msg.empty())
g_screen->screenMessage("%s", msg.c_str());
}
diff --git a/engines/ultima/ultima4/filesys/savegame.cpp b/engines/ultima/ultima4/filesys/savegame.cpp
index 8a56cae5cb..7a0ed3db08 100644
--- a/engines/ultima/ultima4/filesys/savegame.cpp
+++ b/engines/ultima/ultima4/filesys/savegame.cpp
@@ -212,7 +212,7 @@ void SaveGame::load(Common::SeekableReadStream *stream) {
gameFixupObjects(g_context->_location->_prev->_map);
}
- spellSetEffectCallback(&gameSpellEffect);
+ g_spells->spellSetEffectCallback(&gameSpellEffect);
g_items->setDestroyAllCreaturesCallback(&gameDestroyAllCreatures);
g_context->_stats->resetReagentsMenu();
diff --git a/engines/ultima/ultima4/game/game.cpp b/engines/ultima/ultima4/game/game.cpp
index 721f8544b3..5711bedf11 100644
--- a/engines/ultima/ultima4/game/game.cpp
+++ b/engines/ultima/ultima4/game/game.cpp
@@ -761,7 +761,7 @@ void showMixturesSuper(int page = 0) {
for (int i = 0; i < 13; i++) {
char buf[4];
- const Spell *s = getSpell(i + 13 * page);
+ const Spell *s = g_spells->getSpell(i + 13 * page);
int line = i + 8;
g_screen->screenTextAt(2, line, "%s", s->_name);
@@ -835,7 +835,7 @@ void mixReagentsSuper() {
done = true;
} else {
spell -= 'a';
- const Spell *s = getSpell(spell);
+ const Spell *s = g_spells->getSpell(spell);
g_screen->screenMessage("%s\n", s->_name);
page = (spell >= 13);
showMixturesSuper(page);
diff --git a/engines/ultima/ultima4/game/script.cpp b/engines/ultima/ultima4/game/script.cpp
index da841fcfe6..04fcfe742c 100644
--- a/engines/ultima/ultima4/game/script.cpp
+++ b/engines/ultima/ultima4/game/script.cpp
@@ -44,8 +44,6 @@
namespace Ultima {
namespace Ultima4 {
-extern SpellEffectCallback spellEffectCallback;
-
/*
* Script::Variable class
*/
@@ -1211,7 +1209,7 @@ Script::ReturnCode Script::heal(Shared::XMLNode *script, Shared::XMLNode *curren
}
Script::ReturnCode Script::castSpell(Shared::XMLNode *script, Shared::XMLNode *current) {
- (*spellEffectCallback)('r', -1, SOUND_MAGIC);
+ g_spells->spellEffect('r', -1, SOUND_MAGIC);
if (_debug)
debug("<Spell effect>");
diff --git a/engines/ultima/ultima4/game/spell.cpp b/engines/ultima/ultima4/game/spell.cpp
index bd298611dd..bb33770012 100644
--- a/engines/ultima/ultima4/game/spell.cpp
+++ b/engines/ultima/ultima4/game/spell.cpp
@@ -45,39 +45,6 @@
namespace Ultima {
namespace Ultima4 {
-SpellEffectCallback spellEffectCallback = nullptr;
-
-CombatController *spellCombatController();
-void spellMagicAttack(const Common::String &tilename, Direction dir, int minDamage, int maxDamage);
-bool spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDamage);
-
-static int spellAwaken(int player);
-static int spellBlink(int dir);
-static int spellCure(int player);
-static int spellDispel(int dir);
-static int spellEField(int param);
-static int spellFireball(int dir);
-static int spellGate(int phase);
-static int spellHeal(int player);
-static int spellIceball(int dir);
-static int spellJinx(int unused);
-static int spellKill(int dir);
-static int spellLight(int unused);
-static int spellMMissle(int dir);
-static int spellNegate(int unused);
-static int spellOpen(int unused);
-static int spellProtect(int unused);
-static int spellRez(int player);
-static int spellQuick(int unused);
-static int spellSleep(int unused);
-static int spellTremor(int unused);
-static int spellUndead(int unused);
-static int spellView(int unsued);
-static int spellWinds(int fromdir);
-static int spellXit(int unused);
-static int spellYup(int unused);
-static int spellZdown(int unused);
-
/* masks for reagents */
#define ASH (1 << REAG_ASH)
#define GINSENG (1 << REAG_GINSENG)
@@ -92,7 +59,7 @@ static int spellZdown(int unused);
static const struct {
SpellCastError err;
const char *msg;
-} spellErrorMsgs[] = {
+} SPELL_ERROR_MSGS[] = {
{ CASTERR_NOMIX, "None Mixed!\n" },
{ CASTERR_MPTOOLOW, "Not Enough MP!\n" },
{ CASTERR_FAILED, "Failed!\n" },
@@ -102,55 +69,51 @@ static const struct {
{ CASTERR_WORLDMAPONLY, "Outdoors only!\nFailed!\n" }
};
-static const Spell spells[] = {
- { "Awaken", GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &spellAwaken, Spell::PARAM_PLAYER, 5 },
+const Spell Spells::SPELL_LIST[N_SPELLS] = {
+ { "Awaken", GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &Spells::spellAwaken, Spell::PARAM_PLAYER, 5 },
{
"Blink", SILK | MOSS, CTX_WORLDMAP, TRANSPORT_FOOT_OR_HORSE,
- &spellBlink, Spell::PARAM_DIR, 15
+ &Spells::spellBlink, Spell::PARAM_DIR, 15
},
- { "Cure", GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &spellCure, Spell::PARAM_PLAYER, 5 },
- { "Dispell", ASH | GARLIC | PEARL, CTX_ANY, TRANSPORT_ANY, &spellDispel, Spell::PARAM_DIR, 20 },
+ { "Cure", GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &Spells::spellCure, Spell::PARAM_PLAYER, 5 },
+ { "Dispell", ASH | GARLIC | PEARL, CTX_ANY, TRANSPORT_ANY, &Spells::spellDispel, Spell::PARAM_DIR, 20 },
{
"Energy Field", ASH | SILK | PEARL, (LocationContext)(CTX_COMBAT | CTX_DUNGEON),
- TRANSPORT_ANY, &spellEField, Spell::PARAM_TYPEDIR, 10
+ TRANSPORT_ANY, &Spells::spellEField, Spell::PARAM_TYPEDIR, 10
},
- { "Fireball", ASH | PEARL, CTX_COMBAT, TRANSPORT_ANY, &spellFireball, Spell::PARAM_DIR, 15 },
+ { "Fireball", ASH | PEARL, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellFireball, Spell::PARAM_DIR, 15 },
{
"Gate", ASH | PEARL | MANDRAKE, CTX_WORLDMAP, TRANSPORT_FOOT_OR_HORSE,
- &spellGate, Spell::PARAM_PHASE, 40
+ &Spells::spellGate, Spell::PARAM_PHASE, 40
},
- { "Heal", GINSENG | SILK, CTX_ANY, TRANSPORT_ANY, &spellHeal, Spell::PARAM_PLAYER, 10 },
- { "Iceball", PEARL | MANDRAKE, CTX_COMBAT, TRANSPORT_ANY, &spellIceball, Spell::PARAM_DIR, 20 },
+ { "Heal", GINSENG | SILK, CTX_ANY, TRANSPORT_ANY, &Spells::spellHeal, Spell::PARAM_PLAYER, 10 },
+ { "Iceball", PEARL | MANDRAKE, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellIceball, Spell::PARAM_DIR, 20 },
{
"Jinx", PEARL | NIGHTSHADE | MANDRAKE,
- CTX_ANY, TRANSPORT_ANY, &spellJinx, Spell::PARAM_NONE, 30
+ CTX_ANY, TRANSPORT_ANY, &Spells::spellJinx, Spell::PARAM_NONE, 30
},
- { "Kill", PEARL | NIGHTSHADE, CTX_COMBAT, TRANSPORT_ANY, &spellKill, Spell::PARAM_DIR, 25 },
- { "Light", ASH, CTX_DUNGEON, TRANSPORT_ANY, &spellLight, Spell::PARAM_NONE, 5 },
- { "Magic missile", ASH | PEARL, CTX_COMBAT, TRANSPORT_ANY, &spellMMissle, Spell::PARAM_DIR, 5 },
- { "Negate", ASH | GARLIC | MANDRAKE, CTX_ANY, TRANSPORT_ANY, &spellNegate, Spell::PARAM_NONE, 20 },
- { "Open", ASH | MOSS, CTX_ANY, TRANSPORT_ANY, &spellOpen, Spell::PARAM_NONE, 5 },
- { "Protection", ASH | GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &spellProtect, Spell::PARAM_NONE, 15 },
- { "Quickness", ASH | GINSENG | MOSS, CTX_ANY, TRANSPORT_ANY, &spellQuick, Spell::PARAM_NONE, 20 },
+ { "Kill", PEARL | NIGHTSHADE, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellKill, Spell::PARAM_DIR, 25 },
+ { "Light", ASH, CTX_DUNGEON, TRANSPORT_ANY, &Spells::spellLight, Spell::PARAM_NONE, 5 },
+ { "Magic missile", ASH | PEARL, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellMMissle, Spell::PARAM_DIR, 5 },
+ { "Negate", ASH | GARLIC | MANDRAKE, CTX_ANY, TRANSPORT_ANY, &Spells::spellNegate, Spell::PARAM_NONE, 20 },
+ { "Open", ASH | MOSS, CTX_ANY, TRANSPORT_ANY, &Spells::spellOpen, Spell::PARAM_NONE, 5 },
+ { "Protection", ASH | GINSENG | GARLIC, CTX_ANY, TRANSPORT_ANY, &Spells::spellProtect, Spell::PARAM_NONE, 15 },
+ { "Quickness", ASH | GINSENG | MOSS, CTX_ANY, TRANSPORT_ANY, &Spells::spellQuick, Spell::PARAM_NONE, 20 },
{
"Resurrect", ASH | GINSENG | GARLIC | SILK | MOSS | MANDRAKE,
- CTX_NON_COMBAT, TRANSPORT_ANY, &spellRez, Spell::PARAM_PLAYER, 45
+ CTX_NON_COMBAT, TRANSPORT_ANY, &Spells::spellRez, Spell::PARAM_PLAYER, 45
},
- { "Sleep", SILK | GINSENG, CTX_COMBAT, TRANSPORT_ANY, &spellSleep, Spell::PARAM_NONE, 15 },
- { "Tremor", ASH | MOSS | MANDRAKE, CTX_COMBAT, TRANSPORT_ANY, &spellTremor, Spell::PARAM_NONE, 30 },
- { "Undead", ASH | GARLIC, CTX_COMBAT, TRANSPORT_ANY, &spellUndead, Spell::PARAM_NONE, 15 },
- { "View", NIGHTSHADE | MANDRAKE, CTX_NON_COMBAT, TRANSPORT_ANY, &spellView, Spell::PARAM_NONE, 15 },
- { "Winds", ASH | MOSS, CTX_WORLDMAP, TRANSPORT_ANY, &spellWinds, Spell::PARAM_FROMDIR, 10 },
- { "X-it", ASH | SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &spellXit, Spell::PARAM_NONE, 15 },
- { "Y-up", SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &spellYup, Spell::PARAM_NONE, 10 },
- { "Z-down", SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &spellZdown, Spell::PARAM_NONE, 5 }
+ { "Sleep", SILK | GINSENG, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellSleep, Spell::PARAM_NONE, 15 },
+ { "Tremor", ASH | MOSS | MANDRAKE, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellTremor, Spell::PARAM_NONE, 30 },
+ { "Undead", ASH | GARLIC, CTX_COMBAT, TRANSPORT_ANY, &Spells::spellUndead, Spell::PARAM_NONE, 15 },
+ { "View", NIGHTSHADE | MANDRAKE, CTX_NON_COMBAT, TRANSPORT_ANY, &Spells::spellView, Spell::PARAM_NONE, 15 },
+ { "Winds", ASH | MOSS, CTX_WORLDMAP, TRANSPORT_ANY, &Spells::spellWinds, Spell::PARAM_FROMDIR, 10 },
+ { "X-it", ASH | SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &Spells::spellXit, Spell::PARAM_NONE, 15 },
+ { "Y-up", SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &Spells::spellYup, Spell::PARAM_NONE, 10 },
+ { "Z-down", SILK | MOSS, CTX_DUNGEON, TRANSPORT_ANY, &Spells::spellZdown, Spell::PARAM_NONE, 5 }
};
-#define N_SPELLS (sizeof(spells) / sizeof(spells[0]))
-
-void spellSetEffectCallback(SpellEffectCallback callback) {
- spellEffectCallback = callback;
-}
+/*-------------------------------------------------------------------*/
Ingredients::Ingredients() {
memset(_reagents, 0, sizeof(_reagents));
@@ -208,37 +171,53 @@ void Ingredients::multiply(int batches) {
}
}
-const char *spellGetName(uint spell) {
+/*-------------------------------------------------------------------*/
+
+Spells *g_spells;
+
+Spells::Spells() : spellEffectCallback(nullptr) {
+ g_spells = this;
+}
+
+Spells::~Spells() {
+ g_spells = nullptr;
+}
+
+void Spells::spellSetEffectCallback(SpellEffectCallback callback) {
+ spellEffectCallback = callback;
+}
+
+const char *Spells::spellGetName(uint spell) const {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
- return spells[spell]._name;
+ return SPELL_LIST[spell]._name;
}
-int spellGetRequiredMP(uint spell) {
+int Spells::spellGetRequiredMP(uint spell) const {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
- return spells[spell]._mp;
+ return SPELL_LIST[spell]._mp;
}
-LocationContext spellGetContext(uint spell) {
+LocationContext Spells::spellGetContext(uint spell) const {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
- return spells[spell]._context;
+ return SPELL_LIST[spell]._context;
}
-TransportContext spellGetTransportContext(uint spell) {
+TransportContext Spells::spellGetTransportContext(uint spell) const {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
- return spells[spell]._transportContext;
+ return SPELL_LIST[spell]._transportContext;
}
-Common::String spellGetErrorMessage(uint spell, SpellCastError error) {
+Common::String Spells::spellGetErrorMessage(uint spell, SpellCastError error) {
uint i;
SpellCastError err = error;
/* try to find a more specific error message */
if (err == CASTERR_WRONGCONTEXT) {
- switch (spells[spell]._context) {
+ switch (SPELL_LIST[spell]._context) {
case CTX_COMBAT:
err = CASTERR_COMBATONLY;
break;
@@ -254,19 +233,15 @@ Common::String spellGetErrorMessage(uint spell, SpellCastError error) {
}
/* find the message that we're looking for and return it! */
- for (i = 0; i < sizeof(spellErrorMsgs) / sizeof(spellErrorMsgs[0]); i++) {
- if (err == spellErrorMsgs[i].err)
- return Common::String(spellErrorMsgs[i].msg);
+ for (i = 0; i < sizeof(SPELL_ERROR_MSGS) / sizeof(SPELL_ERROR_MSGS[0]); i++) {
+ if (err == SPELL_ERROR_MSGS[i].err)
+ return Common::String(SPELL_ERROR_MSGS[i].msg);
}
return Common::String();
}
-/**
- * Mix reagents for a spell. Fails and returns false if the reagents
- * selected were not correct.
- */
-int spellMix(uint spell, const Ingredients *ingredients) {
+int Spells::spellMix(uint spell, const Ingredients *ingredients) {
int regmask, reg;
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
@@ -277,7 +252,7 @@ int spellMix(uint spell, const Ingredients *ingredients) {
regmask |= (1 << reg);
}
- if (regmask != spells[spell]._components)
+ if (regmask != SPELL_LIST[spell]._components)
return 0;
g_ultima->_saveGame->_mixtures[spell]++;
@@ -285,42 +260,33 @@ int spellMix(uint spell, const Ingredients *ingredients) {
return 1;
}
-Spell::Param spellGetParamType(uint spell) {
+Spell::Param Spells::spellGetParamType(uint spell) const {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
- return spells[spell]._paramType;
+ return SPELL_LIST[spell]._paramType;
}
-/**
- * Checks some basic prerequistes for casting a spell. Returns an
- * error if no mixture is available, the context is invalid, or the
- * character doesn't have enough magic points.
- */
-SpellCastError spellCheckPrerequisites(uint spell, int character) {
+SpellCastError Spells::spellCheckPrerequisites(uint spell, int character) {
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
ASSERT(character >= 0 && character < g_ultima->_saveGame->_members, "character out of range: %d", character);
if (g_ultima->_saveGame->_mixtures[spell] == 0)
return CASTERR_NOMIX;
- if ((g_context->_location->_context & spells[spell]._context) == 0)
+ if ((g_context->_location->_context & SPELL_LIST[spell]._context) == 0)
return CASTERR_WRONGCONTEXT;
- if ((g_context->_transportContext & spells[spell]._transportContext) == 0)
+ if ((g_context->_transportContext & SPELL_LIST[spell]._transportContext) == 0)
return CASTERR_FAILED;
- if (g_context->_party->member(character)->getMp() < spells[spell]._mp)
+ if (g_context->_party->member(character)->getMp() < SPELL_LIST[spell]._mp)
return CASTERR_MPTOOLOW;
return CASTERR_NOERROR;
}
-/**
- * Casts spell. Fails and returns false if the spell cannot be cast.
- * The error code is updated with the reason for failure.
- */
-bool spellCast(uint spell, int character, int param, SpellCastError *error, bool spellEffect) {
- int subject = (spells[spell]._paramType == Spell::PARAM_PLAYER) ? param : -1;
+bool Spells::spellCast(uint spell, int character, int param, SpellCastError *error, bool spellEffect) {
+ int subject = (SPELL_LIST[spell]._paramType == Spell::PARAM_PLAYER) ? param : -1;
PartyMember *p = g_context->_party->member(character);
ASSERT(spell < N_SPELLS, "invalid spell: %d", spell);
@@ -341,21 +307,20 @@ bool spellCast(uint spell, int character, int param, SpellCastError *error, bool
}
// subtract the mp needed for the spell
- p->adjustMp(-spells[spell]._mp);
+ p->adjustMp(-SPELL_LIST[spell]._mp);
if (spellEffect) {
int time;
/* recalculate spell speed - based on 5/sec */
float MP_OF_LARGEST_SPELL = 45;
- int spellMp = spells[spell]._mp;
+ int spellMp = SPELL_LIST[spell]._mp;
time = int(10000.0 / settings._spellEffectSpeed * spellMp / MP_OF_LARGEST_SPELL);
soundPlay(SOUND_PREMAGIC_MANA_JUMBLE, false, time);
EventHandler::wait_msecs(time);
-
- (*spellEffectCallback)(spell + 'a', subject, SOUND_MAGIC);
+ g_spells->spellEffect(spell + 'a', subject, SOUND_MAGIC);
}
- if (!(*spells[spell]._spellFunc)(param)) {
+ if (!(g_spells->*SPELL_LIST[spell]._spellFunc)(param)) {
*error = CASTERR_FAILED;
return false;
}
@@ -363,15 +328,12 @@ bool spellCast(uint spell, int character, int param, SpellCastError *error, bool
return true;
}
-CombatController *spellCombatController() {
+CombatController *Spells::spellCombatController() {
CombatController *cc = dynamic_cast<CombatController *>(eventHandler->getController());
return cc;
}
-/**
- * Makes a special magic ranged attack in the given direction
- */
-void spellMagicAttack(const Common::String &tilename, Direction dir, int minDamage, int maxDamage) {
+void Spells::spellMagicAttack(const Common::String &tilename, Direction dir, int minDamage, int maxDamage) {
CombatController *controller = spellCombatController();
PartyMemberVector *party = controller->getParty();
@@ -389,7 +351,7 @@ void spellMagicAttack(const Common::String &tilename, Direction dir, int minDama
}
}
-bool spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDamage) {
+bool Spells::spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDamage) {
bool objectHit = false;
// int attackdelay = MAX_BATTLE_SPEED - settings.battleSpeed;
CombatMap *cm = getCombatMap();
@@ -415,7 +377,7 @@ bool spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDama
return objectHit;
}
-static int spellAwaken(int player) {
+int Spells::spellAwaken(int player) {
ASSERT(player < 8, "player out of range: %d", player);
PartyMember *p = g_context->_party->member(player);
@@ -427,7 +389,7 @@ static int spellAwaken(int player) {
return 0;
}
-static int spellBlink(int dir) {
+int Spells::spellBlink(int dir) {
int i,
failed = 0,
distance,
@@ -476,14 +438,14 @@ static int spellBlink(int dir) {
return (failed ? 0 : 1);
}
-static int spellCure(int player) {
+int Spells::spellCure(int player) {
ASSERT(player < 8, "player out of range: %d", player);
GameController::flashTile(g_context->_party->member(player)->getCoords(), "wisp", 1);
return g_context->_party->member(player)->heal(HT_CURE);
}
-static int spellDispel(int dir) {
+int Spells::spellDispel(int dir) {
MapTile *tile;
MapCoords field;
@@ -541,7 +503,7 @@ static int spellDispel(int dir) {
return 1;
}
-static int spellEField(int param) {
+int Spells::spellEField(int param) {
MapTile fieldTile(0);
int fieldType;
int dir;
@@ -603,12 +565,12 @@ static int spellEField(int param) {
return 1;
}
-static int spellFireball(int dir) {
+int Spells::spellFireball(int dir) {
spellMagicAttack("hit_flash", (Direction)dir, 24, 128);
return 1;
}
-static int spellGate(int phase) {
+int Spells::spellGate(int phase) {
const Coords *moongate;
GameController::flashTile(g_context->_location->_coords, "moongate", 2);
@@ -620,7 +582,7 @@ static int spellGate(int phase) {
return 1;
}
-static int spellHeal(int player) {
+int Spells::spellHeal(int player) {
ASSERT(player < 8, "player out of range: %d", player);
GameController::flashTile(g_context->_party->member(player)->getCoords(), "wisp", 1);
@@ -628,58 +590,58 @@ static int spellHeal(int player) {
return 1;
}
-static int spellIceball(int dir) {
+int Spells::spellIceball(int dir) {
spellMagicAttack("magic_flash", (Direction)dir, 32, 224);
return 1;
}
-static int spellJinx(int unused) {
+int Spells::spellJinx(int unused) {
g_context->_aura->set(Aura::JINX, 10);
return 1;
}
-static int spellKill(int dir) {
+int Spells::spellKill(int dir) {
spellMagicAttack("whirlpool", (Direction)dir, -1, 232);
return 1;
}
-static int spellLight(int unused) {
+int Spells::spellLight(int unused) {
g_context->_party->lightTorch(100, false);
return 1;
}
-static int spellMMissle(int dir) {
+int Spells::spellMMissle(int dir) {
spellMagicAttack("miss_flash", (Direction)dir, 64, 16);
return 1;
}
-static int spellNegate(int unused) {
+int Spells::spellNegate(int unused) {
g_context->_aura->set(Aura::NEGATE, 10);
return 1;
}
-static int spellOpen(int unused) {
+int Spells::spellOpen(int unused) {
g_debugger->getChest();
return 1;
}
-static int spellProtect(int unused) {
+int Spells::spellProtect(int unused) {
g_context->_aura->set(Aura::PROTECTION, 10);
return 1;
}
-static int spellRez(int player) {
+int Spells::spellRez(int player) {
ASSERT(player < 8, "player out of range: %d", player);
return g_context->_party->member(player)->heal(HT_RESURRECT);
}
-static int spellQuick(int unused) {
+int Spells::spellQuick(int unused) {
g_context->_aura->set(Aura::QUICKNESS, 10);
return 1;
}
-static int spellSleep(int unused) {
+int Spells::spellSleep(int unused) {
CombatMap *cm = getCombatMap();
CreatureVector creatures = cm->getCreatures();
CreatureVector::iterator i;
@@ -702,7 +664,7 @@ static int spellSleep(int unused) {
return 1;
}
-static int spellTremor(int unused) {
+int Spells::spellTremor(int unused) {
CombatController *ct = spellCombatController();
CreatureVector creatures = ct->getMap()->getCreatures();
CreatureVector::iterator i;
@@ -740,7 +702,7 @@ static int spellTremor(int unused) {
return 1;
}
-static int spellUndead(int unused) {
+int Spells::spellUndead(int unused) {
CombatController *ct = spellCombatController();
CreatureVector creatures = ct->getMap()->getCreatures();
CreatureVector::iterator i;
@@ -754,17 +716,17 @@ static int spellUndead(int unused) {
return 1;
}
-static int spellView(int unsued) {
+int Spells::spellView(int unsued) {
peer(false);
return 1;
}
-static int spellWinds(int fromdir) {
+int Spells::spellWinds(int fromdir) {
g_context->_windDirection = fromdir;
return 1;
}
-static int spellXit(int unused) {
+int Spells::spellXit(int unused) {
if (!g_context->_location->_map->isWorldMap()) {
g_screen->screenMessage("Leaving...\n");
g_game->exitToParentMap();
@@ -774,7 +736,7 @@ static int spellXit(int unused) {
return 0;
}
-static int spellYup(int unused) {
+int Spells::spellYup(int unused) {
MapCoords coords = g_context->_location->_coords;
Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
@@ -803,7 +765,7 @@ static int spellYup(int unused) {
return 0;
}
-static int spellZdown(int unused) {
+int Spells::spellZdown(int unused) {
MapCoords coords = g_context->_location->_coords;
Dungeon *dungeon = dynamic_cast<Dungeon *>(g_context->_location->_map);
assert(dungeon);
@@ -828,8 +790,8 @@ static int spellZdown(int unused) {
return 0;
}
-const Spell *getSpell(int i) {
- return &spells[i];
+const Spell *Spells::getSpell(int i) const {
+ return &SPELL_LIST[i];
}
} // End of namespace Ultima4
diff --git a/engines/ultima/ultima4/game/spell.h b/engines/ultima/ultima4/game/spell.h
index 231e19ab26..6de614c9c3 100644
--- a/engines/ultima/ultima4/game/spell.h
+++ b/engines/ultima/ultima4/game/spell.h
@@ -44,7 +44,9 @@ enum SpellCastError {
CASTERR_WORLDMAPONLY /* e.g. spell must be cast on the world map */
};
-/* Field types for the Energy field spell */
+/**
+ * Field types for the Energy field spell
+ */
enum EnergyFieldType {
ENERGYFIELD_NONE,
ENERGYFIELD_FIRE,
@@ -70,44 +72,124 @@ private:
unsigned short _reagents[REAG_MAX];
};
+class Spells;
+typedef int (Spells::*SpellProc)(int);
+
struct Spell {
enum Param {
- PARAM_NONE, /* none */
- PARAM_PLAYER, /* number of a player required */
- PARAM_DIR, /* direction required */
- PARAM_TYPEDIR, /* type of field and direction required (energy field) */
- PARAM_PHASE, /* phase required (gate) */
- PARAM_FROMDIR /* direction from required (winds) */
+ PARAM_NONE, ///< None
+ PARAM_PLAYER, ///< number of a player required
+ PARAM_DIR, ///< direction required
+ PARAM_TYPEDIR, ///< type of field and direction required (energy field)
+ PARAM_PHASE, ///< phase required (gate)
+ PARAM_FROMDIR ///< direction from required (winds)
};
enum SpecialEffects {
- SFX_NONE, /* none */
- SFX_INVERT, /* invert the screen (moongates, most normal spells) */
- SFX_TREMOR /* tremor spell */
+ SFX_NONE, ///< none
+ SFX_INVERT, ///< invert the screen (moongates, most normal spells)
+ SFX_TREMOR ///< tremor spell
};
const char *_name;
int _components;
LocationContext _context;
TransportContext _transportContext;
- int (*_spellFunc)(int);
+ SpellProc _spellFunc;
Param _paramType;
int _mp;
};
typedef void (*SpellEffectCallback)(int spell, int player, Sound sound);
+#define N_SPELLS 26
+
+class Spells {
+private:
+ static const Spell SPELL_LIST[N_SPELLS];
+ SpellEffectCallback spellEffectCallback;
+private:
+ int spellAwaken(int player);
+ int spellBlink(int dir);
+ int spellCure(int player);
+ int spellDispel(int dir);
+ int spellEField(int param);
+ int spellFireball(int dir);
+ int spellGate(int phase);
+ int spellHeal(int player);
+ int spellIceball(int dir);
+ int spellJinx(int unused);
+ int spellKill(int dir);
+ int spellLight(int unused);
+ int spellMMissle(int dir);
+ int spellNegate(int unused);
+ int spellOpen(int unused);
+ int spellProtect(int unused);
+ int spellRez(int player);
+ int spellQuick(int unused);
+ int spellSleep(int unused);
+ int spellTremor(int unused);
+ int spellUndead(int unused);
+ int spellView(int unsued);
+ int spellWinds(int fromdir);
+ int spellXit(int unused);
+ int spellYup(int unused);
+ int spellZdown(int unused);
+private:
+ CombatController *spellCombatController();
+
+ /**
+ * Makes a special magic ranged attack in the given direction
+ */
+ void spellMagicAttack(const Common::String &tilename, Direction dir, int minDamage, int maxDamage);
+ bool spellMagicAttackAt(const Coords &coords, MapTile attackTile, int attackDamage);
+
+ LocationContext spellGetContext(uint spell) const;
+ TransportContext spellGetTransportContext(uint spell) const;
+public:
+ /**
+ * Constructor
+ */
+ Spells();
+
+ /**
+ * Destructor
+ */
+ ~Spells();
+
+ void spellSetEffectCallback(SpellEffectCallback callback);
+
+ void spellEffect(int spell, int player, Sound sound) {
+ (spellEffectCallback)(spell, player, sound);
+ }
+
+ /**
+ * Mix reagents for a spell. Fails and returns false if the reagents
+ * selected were not correct.
+ */
+ int spellMix(uint spell, const Ingredients *ingredients);
+
+ /**
+ * Casts spell. Fails and returns false if the spell cannot be cast.
+ * The error code is updated with the reason for failure.
+ */
+ bool spellCast(uint spell, int character, int param, SpellCastError *error, bool spellEffect);
+
+ Common::String spellGetErrorMessage(uint spell, SpellCastError error);
+
+ const char *spellGetName(uint spell) const;
+
+ /**
+ * Checks some basic prerequistes for casting a spell. Returns an
+ * error if no mixture is available, the context is invalid, or the
+ * character doesn't have enough magic points.
+ */
+ SpellCastError spellCheckPrerequisites(uint spell, int character);
+ Spell::Param spellGetParamType(uint spell) const;
+ int spellGetRequiredMP(uint spell) const;
+ const Spell *getSpell(int i) const;
+};
-void spellSetEffectCallback(SpellEffectCallback callback);
-const char *spellGetName(uint spell);
-int spellGetRequiredMP(uint spell);
-LocationContext spellGetContext(uint spell);
-TransportContext spellGetTransportContext(uint spell);
-Common::String spellGetErrorMessage(uint spell, SpellCastError error);
-int spellMix(uint spell, const Ingredients *ingredients);
-Spell::Param spellGetParamType(uint spell);
-SpellCastError spellCheckPrerequisites(uint spell, int character);
-bool spellCast(uint spell, int character, int param, SpellCastError *error, bool spellEffect);
-const Spell *getSpell(int i);
+extern Spells *g_spells;
} // End of namespace Ultima4
} // End of namespace Ultima
diff --git a/engines/ultima/ultima4/ultima4.cpp b/engines/ultima/ultima4/ultima4.cpp
index 7eb04edb25..e8cdcfa250 100644
--- a/engines/ultima/ultima4/ultima4.cpp
+++ b/engines/ultima/ultima4/ultima4.cpp
@@ -62,7 +62,8 @@ Ultima4Engine::Ultima4Engine(OSystem *syst, const Ultima::UltimaGameDescription
_dialogueLoaders(nullptr), _game(nullptr), _items(nullptr), _music(nullptr),
_imageLoaders(nullptr), _mapLoaders(nullptr), _moongates(nullptr),
_responseParts(nullptr), _saveGame(nullptr), _screen(nullptr), _shrines(nullptr),
- _tileMaps(nullptr), _tileRules(nullptr), _tileSets(nullptr), _weapons(nullptr) {
+ _spells(nullptr), _tileMaps(nullptr), _tileRules(nullptr), _tileSets(nullptr),
+ _weapons(nullptr) {
g_ultima = this;
g_armors = nullptr;
g_codex = nullptr;
@@ -75,6 +76,7 @@ Ultima4Engine::Ultima4Engine(OSystem *syst, const Ultima::UltimaGameDescription
g_responseParts = nullptr;
g_screen = nullptr;
g_shrines = nullptr;
+ g_spells = nullptr;
g_tileMaps = nullptr;
g_tileRules = nullptr;
g_tileSets = nullptr;
@@ -98,6 +100,7 @@ Ultima4Engine::~Ultima4Engine() {
delete _saveGame;
delete _screen;
delete _shrines;
+ delete _spells;
delete _tileMaps;
delete _tileRules;
delete _tileSets;
@@ -127,6 +130,7 @@ bool Ultima4Engine::initialize() {
_screen = new Screen();
_screen->init();
_shrines = new Shrines();
+ _spells = new Spells();
_tileRules = new TileRules();
_tileSets = new TileSets();
_tileMaps = new TileMaps();
diff --git a/engines/ultima/ultima4/ultima4.h b/engines/ultima/ultima4/ultima4.h
index e5cbdbf51f..4ba9a7180f 100644
--- a/engines/ultima/ultima4/ultima4.h
+++ b/engines/ultima/ultima4/ultima4.h
@@ -45,6 +45,7 @@ class ResponseParts;
struct SaveGame;
class Screen;
class Shrines;
+class Spells;
class TileMaps;
class TileRules;
class TileSets;
@@ -82,6 +83,7 @@ public:
SaveGame *_saveGame;
Screen *_screen;
Shrines *_shrines;
+ Spells *_spells;
TileMaps *_tileMaps;
TileRules *_tileRules;
TileSets *_tileSets;
More information about the Scummvm-git-logs
mailing list