mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 10:21:31 +00:00
ULTIMA4: Cast spell to keybinder
This commit is contained in:
parent
7bb3369c2c
commit
f2bd9f0f92
@ -50,6 +50,7 @@ Debugger::Debugger() : Shared::Debugger() {
|
||||
registerCmd("attack", WRAP_METHOD(Debugger, cmdAttack));
|
||||
registerCmd("board", WRAP_METHOD(Debugger, cmdBoard));
|
||||
registerCmd("cast", WRAP_METHOD(Debugger, cmdCastSpell));
|
||||
registerCmd("climb", WRAP_METHOD(Debugger, cmdClimb));
|
||||
registerCmd("enter", WRAP_METHOD(Debugger, cmdEnter));
|
||||
registerCmd("fire", WRAP_METHOD(Debugger, cmdFire));
|
||||
registerCmd("get", WRAP_METHOD(Debugger, cmdGet));
|
||||
@ -62,6 +63,7 @@ Debugger::Debugger() : Shared::Debugger() {
|
||||
registerCmd("order", WRAP_METHOD(Debugger, cmdNewOrder));
|
||||
registerCmd("pass", WRAP_METHOD(Debugger, cmdPass));
|
||||
registerCmd("peer", WRAP_METHOD(Debugger, cmdPeer));
|
||||
registerCmd("quitAndSave", WRAP_METHOD(Debugger, cmdQuitAndSave));
|
||||
|
||||
registerCmd("3d", WRAP_METHOD(Debugger, cmd3d));
|
||||
registerCmd("collisions", WRAP_METHOD(Debugger, cmdCollisions));
|
||||
@ -145,6 +147,14 @@ void Debugger::getChest(int player) {
|
||||
cmdGet(2, argv);
|
||||
}
|
||||
|
||||
void Debugger::castSpell(int player) {
|
||||
Common::String param = Common::String::format("%d", player);
|
||||
const char *argv[2] = { "cast", param.c_str() };
|
||||
|
||||
cmdCastSpell(2, argv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Debugger::cmdMove(int argc, const char **argv) {
|
||||
@ -247,7 +257,161 @@ bool Debugger::cmdBoard(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
bool Debugger::cmdCastSpell(int argc, const char **argv) {
|
||||
// TODO
|
||||
int player = -1;
|
||||
if (argc == 2)
|
||||
player = strToInt(argv[1]);
|
||||
|
||||
if (player == -1) {
|
||||
printN("Cast Spell!\nPlayer: ");
|
||||
player = gameGetPlayer(false, true);
|
||||
}
|
||||
if (player == -1)
|
||||
return isDebuggerActive();
|
||||
|
||||
// get the spell to cast
|
||||
g_context->_stats->setView(STATS_MIXTURES);
|
||||
printN("Spell: ");
|
||||
// ### Put the iPad thing too.
|
||||
#ifdef IOS
|
||||
U4IOS::IOSCastSpellHelper castSpellController;
|
||||
#endif
|
||||
int spell = AlphaActionController::get('z', "Spell: ");
|
||||
if (spell == -1)
|
||||
return isDebuggerActive();
|
||||
|
||||
screenMessage("%s!\n", 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) {
|
||||
gameCastSpell(spell, player, 0);
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
// Get the final parameters for the spell
|
||||
switch (spellGetParamType(spell)) {
|
||||
case Spell::PARAM_NONE:
|
||||
gameCastSpell(spell, player, 0);
|
||||
break;
|
||||
|
||||
case Spell::PARAM_PHASE: {
|
||||
screenMessage("To Phase: ");
|
||||
#ifdef IOS
|
||||
U4IOS::IOSConversationChoiceHelper choiceController;
|
||||
choiceController.fullSizeChoicePanel();
|
||||
choiceController.updateGateSpellChoices();
|
||||
#endif
|
||||
int choice = ReadChoiceController::get("12345678 \033\n");
|
||||
if (choice < '1' || choice > '8')
|
||||
print("None");
|
||||
else {
|
||||
print("");
|
||||
gameCastSpell(spell, player, choice - '1');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Spell::PARAM_PLAYER: {
|
||||
printN("Who: ");
|
||||
int subject = gameGetPlayer(true, false);
|
||||
if (subject != -1)
|
||||
gameCastSpell(spell, player, subject);
|
||||
break;
|
||||
}
|
||||
|
||||
case Spell::PARAM_DIR:
|
||||
if (g_context->_location->_context == CTX_DUNGEON)
|
||||
gameCastSpell(spell, player, g_ultima->_saveGame->_orientation);
|
||||
else {
|
||||
printN("Dir: ");
|
||||
Direction dir = gameGetDirection();
|
||||
if (dir != DIR_NONE)
|
||||
gameCastSpell(spell, player, (int)dir);
|
||||
}
|
||||
break;
|
||||
|
||||
case Spell::PARAM_TYPEDIR: {
|
||||
printN("Energy type? ");
|
||||
#ifdef IOS
|
||||
U4IOS::IOSConversationChoiceHelper choiceController;
|
||||
choiceController.fullSizeChoicePanel();
|
||||
choiceController.updateEnergyFieldSpellChoices();
|
||||
#endif
|
||||
EnergyFieldType fieldType = ENERGYFIELD_NONE;
|
||||
char key = ReadChoiceController::get("flps \033\n\r");
|
||||
switch (key) {
|
||||
case 'f':
|
||||
fieldType = ENERGYFIELD_FIRE;
|
||||
break;
|
||||
case 'l':
|
||||
fieldType = ENERGYFIELD_LIGHTNING;
|
||||
break;
|
||||
case 'p':
|
||||
fieldType = ENERGYFIELD_POISON;
|
||||
break;
|
||||
case 's':
|
||||
fieldType = ENERGYFIELD_SLEEP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldType != ENERGYFIELD_NONE) {
|
||||
print("");
|
||||
|
||||
Direction dir;
|
||||
if (g_context->_location->_context == CTX_DUNGEON)
|
||||
dir = (Direction)g_ultima->_saveGame->_orientation;
|
||||
else {
|
||||
printN("Dir: ");
|
||||
dir = gameGetDirection();
|
||||
}
|
||||
|
||||
if (dir != DIR_NONE) {
|
||||
|
||||
/* Need to pack both dir and fieldType into param */
|
||||
int param = fieldType << 4;
|
||||
param |= (int)dir;
|
||||
|
||||
gameCastSpell(spell, player, param);
|
||||
}
|
||||
} else {
|
||||
/* Invalid input here = spell failure */
|
||||
print("Failed!");
|
||||
|
||||
/*
|
||||
* Confirmed both mixture loss and mp loss in this situation in the
|
||||
* original Ultima IV (at least, in the Amiga version.)
|
||||
*/
|
||||
//c->saveGame->_mixtures[castSpell]--;
|
||||
g_context->_party->member(player)->adjustMp(-spellGetRequiredMP(spell));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Spell::PARAM_FROMDIR: {
|
||||
printN("From Dir: ");
|
||||
Direction dir = gameGetDirection();
|
||||
if (dir != DIR_NONE)
|
||||
gameCastSpell(spell, player, (int)dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
bool Debugger::cmdClimb(int argc, const char **argv) {
|
||||
if (!usePortalAt(g_context->_location, g_context->_location->_coords, ACTION_KLIMB)) {
|
||||
if (g_context->_transportContext == TRANSPORT_BALLOON) {
|
||||
g_ultima->_saveGame->_balloonState = 1;
|
||||
g_context->_opacity = 0;
|
||||
print("Klimb altitude");
|
||||
} else
|
||||
print("%cKlimb what?%c", FG_GREY, FG_WHITE);
|
||||
}
|
||||
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
@ -532,7 +696,7 @@ bool Debugger::cmdOpenDoor(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
print("%cNot Here!%c", FG_GREY, FG_WHITE);
|
||||
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
bool Debugger::cmdPass(int argc, const char **argv) {
|
||||
@ -552,6 +716,18 @@ bool Debugger::cmdPeer(int argc, const char **argv) {
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
bool Debugger::cmdQuitAndSave(int argc, const char **argv) {
|
||||
print("Quit & Save...\n%d moves", g_ultima->_saveGame->_moves);
|
||||
if (g_context->_location->_context & CTX_CAN_SAVE_GAME) {
|
||||
if (g_ultima->saveGameDialog())
|
||||
print("Press Alt-x to quit");
|
||||
} else {
|
||||
print("%cNot here!%c", FG_GREY, FG_WHITE);
|
||||
}
|
||||
|
||||
return isDebuggerActive();
|
||||
}
|
||||
|
||||
|
||||
bool Debugger::cmd3d(int argc, const char **argv) {
|
||||
if (g_context->_location->_context == CTX_DUNGEON) {
|
||||
|
@ -98,6 +98,11 @@ private:
|
||||
*/
|
||||
bool cmdCastSpell(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Climb
|
||||
*/
|
||||
bool cmdClimb(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Enter location
|
||||
*/
|
||||
@ -159,6 +164,11 @@ private:
|
||||
*/
|
||||
bool cmdPeer(int argc, const char **argv);
|
||||
|
||||
/**
|
||||
* Save and quit
|
||||
*/
|
||||
bool cmdQuitAndSave(int argc, const char **argv);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Collision detection on/off
|
||||
@ -297,6 +307,11 @@ public:
|
||||
* user. Otherwise, a non-negative player number is expected
|
||||
*/
|
||||
void getChest(int player = -2);
|
||||
|
||||
/**
|
||||
* Cast a spell
|
||||
*/
|
||||
void castSpell(int player);
|
||||
};
|
||||
|
||||
extern Debugger *g_debugger;
|
||||
|
@ -331,5 +331,16 @@ bool DebuggerActions::openAt(const Coords &coords) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DebuggerActions::gameCastSpell(unsigned int spell, int caster, int param) {
|
||||
SpellCastError spellError;
|
||||
Common::String msg;
|
||||
|
||||
if (!spellCast(spell, caster, param, &spellError, true)) {
|
||||
msg = spellGetErrorMessage(spell, spellError);
|
||||
if (!msg.empty())
|
||||
screenMessage("%s", msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima4
|
||||
} // End of namespace Ultima
|
||||
|
@ -108,6 +108,8 @@ public:
|
||||
* replaced by a temporary annotation of a floor tile for 4 turns.
|
||||
*/
|
||||
bool openAt(const Coords &coords);
|
||||
|
||||
void gameCastSpell(unsigned int spell, int caster, int param);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima4
|
||||
|
@ -84,9 +84,6 @@ void gameLostEighth(Virtue virtue);
|
||||
void gamePartyStarving(void);
|
||||
uint32 gameTimeSinceLastCommand(void);
|
||||
|
||||
/* spell functions */
|
||||
void gameCastSpell(unsigned int spell, int caster, int param);
|
||||
|
||||
void mixReagentsSuper();
|
||||
|
||||
/* conversation functions */
|
||||
@ -530,17 +527,6 @@ void gameSpellEffect(int spell, int player, Sound sound) {
|
||||
}
|
||||
}
|
||||
|
||||
void gameCastSpell(unsigned int spell, int caster, int param) {
|
||||
SpellCastError spellError;
|
||||
Common::String msg;
|
||||
|
||||
if (!spellCast(spell, caster, param, &spellError, true)) {
|
||||
msg = spellGetErrorMessage(spell, spellError);
|
||||
if (!msg.empty())
|
||||
screenMessage("%s", msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::keybinder(KeybindingAction action) {
|
||||
MetaEngine::executeAction(action);
|
||||
}
|
||||
@ -681,10 +667,6 @@ bool GameController::keyPressed(int key) {
|
||||
endTurn = false;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
castSpell();
|
||||
break;
|
||||
|
||||
case 'd': {
|
||||
// unload the map for the second level of Lord British's Castle. The reason
|
||||
// why is that Lord British's farewell is dependent on the number of party members.
|
||||
@ -708,32 +690,6 @@ bool GameController::keyPressed(int key) {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'k':
|
||||
if (!usePortalAt(g_context->_location, g_context->_location->_coords, ACTION_KLIMB)) {
|
||||
if (g_context->_transportContext == TRANSPORT_BALLOON) {
|
||||
g_ultima->_saveGame->_balloonState = 1;
|
||||
g_context->_opacity = 0;
|
||||
screenMessage("Klimb altitude\n");
|
||||
} else
|
||||
screenMessage("%cKlimb what?%c\n", FG_GREY, FG_WHITE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
peer();
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
screenMessage("Quit & Save...\n%d moves\n", g_ultima->_saveGame->_moves);
|
||||
if (g_context->_location->_context & CTX_CAN_SAVE_GAME) {
|
||||
if (g_ultima->saveGameDialog())
|
||||
screenMessage("Press Alt-x to quit\n");
|
||||
} else {
|
||||
screenMessage("%cNot here!%c\n", FG_GREY, FG_WHITE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
readyWeapon();
|
||||
break;
|
||||
@ -1101,140 +1057,6 @@ bool ZtatsController::keyPressed(int key) {
|
||||
}
|
||||
}
|
||||
|
||||
void castSpell(int player) {
|
||||
if (player == -1) {
|
||||
screenMessage("Cast Spell!\nPlayer: ");
|
||||
player = gameGetPlayer(false, true);
|
||||
}
|
||||
if (player == -1)
|
||||
return;
|
||||
|
||||
// get the spell to cast
|
||||
g_context->_stats->setView(STATS_MIXTURES);
|
||||
screenMessage("Spell: ");
|
||||
// ### Put the iPad thing too.
|
||||
#ifdef IOS
|
||||
U4IOS::IOSCastSpellHelper castSpellController;
|
||||
#endif
|
||||
int spell = AlphaActionController::get('z', "Spell: ");
|
||||
if (spell == -1)
|
||||
return;
|
||||
|
||||
screenMessage("%s!\n", 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) {
|
||||
gameCastSpell(spell, player, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the final parameters for the spell
|
||||
switch (spellGetParamType(spell)) {
|
||||
case Spell::PARAM_NONE:
|
||||
gameCastSpell(spell, player, 0);
|
||||
break;
|
||||
case Spell::PARAM_PHASE: {
|
||||
screenMessage("To Phase: ");
|
||||
#ifdef IOS
|
||||
U4IOS::IOSConversationChoiceHelper choiceController;
|
||||
choiceController.fullSizeChoicePanel();
|
||||
choiceController.updateGateSpellChoices();
|
||||
#endif
|
||||
int choice = ReadChoiceController::get("12345678 \033\n");
|
||||
if (choice < '1' || choice > '8')
|
||||
screenMessage("None\n");
|
||||
else {
|
||||
screenMessage("\n");
|
||||
gameCastSpell(spell, player, choice - '1');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Spell::PARAM_PLAYER: {
|
||||
screenMessage("Who: ");
|
||||
int subject = gameGetPlayer(true, false);
|
||||
if (subject != -1)
|
||||
gameCastSpell(spell, player, subject);
|
||||
break;
|
||||
}
|
||||
case Spell::PARAM_DIR:
|
||||
if (g_context->_location->_context == CTX_DUNGEON)
|
||||
gameCastSpell(spell, player, g_ultima->_saveGame->_orientation);
|
||||
else {
|
||||
screenMessage("Dir: ");
|
||||
Direction dir = gameGetDirection();
|
||||
if (dir != DIR_NONE)
|
||||
gameCastSpell(spell, player, (int) dir);
|
||||
}
|
||||
break;
|
||||
case Spell::PARAM_TYPEDIR: {
|
||||
screenMessage("Energy type? ");
|
||||
#ifdef IOS
|
||||
U4IOS::IOSConversationChoiceHelper choiceController;
|
||||
choiceController.fullSizeChoicePanel();
|
||||
choiceController.updateEnergyFieldSpellChoices();
|
||||
#endif
|
||||
EnergyFieldType fieldType = ENERGYFIELD_NONE;
|
||||
char key = ReadChoiceController::get("flps \033\n\r");
|
||||
switch (key) {
|
||||
case 'f':
|
||||
fieldType = ENERGYFIELD_FIRE;
|
||||
break;
|
||||
case 'l':
|
||||
fieldType = ENERGYFIELD_LIGHTNING;
|
||||
break;
|
||||
case 'p':
|
||||
fieldType = ENERGYFIELD_POISON;
|
||||
break;
|
||||
case 's':
|
||||
fieldType = ENERGYFIELD_SLEEP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fieldType != ENERGYFIELD_NONE) {
|
||||
screenMessage("\n");
|
||||
|
||||
Direction dir;
|
||||
if (g_context->_location->_context == CTX_DUNGEON)
|
||||
dir = (Direction)g_ultima->_saveGame->_orientation;
|
||||
else {
|
||||
screenMessage("Dir: ");
|
||||
dir = gameGetDirection();
|
||||
}
|
||||
|
||||
if (dir != DIR_NONE) {
|
||||
|
||||
/* Need to pack both dir and fieldType into param */
|
||||
int param = fieldType << 4;
|
||||
param |= (int) dir;
|
||||
|
||||
gameCastSpell(spell, player, param);
|
||||
}
|
||||
} else {
|
||||
/* Invalid input here = spell failure */
|
||||
screenMessage("Failed!\n");
|
||||
|
||||
/*
|
||||
* Confirmed both mixture loss and mp loss in this situation in the
|
||||
* original Ultima IV (at least, in the Amiga version.)
|
||||
*/
|
||||
//c->saveGame->_mixtures[castSpell]--;
|
||||
g_context->_party->member(player)->adjustMp(-spellGetRequiredMP(spell));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Spell::PARAM_FROMDIR: {
|
||||
screenMessage("From Dir: ");
|
||||
Direction dir = gameGetDirection();
|
||||
if (dir != DIR_NONE)
|
||||
gameCastSpell(spell, player, (int) dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool fireAt(const Coords &coords, bool originAvatar) {
|
||||
bool validObject = false;
|
||||
|
@ -235,7 +235,6 @@ void gameSetViewMode(ViewMode newMode);
|
||||
void gameUpdateScreen(void);
|
||||
|
||||
/* spell functions */
|
||||
void castSpell(int player = -1);
|
||||
void gameSpellEffect(int spell, int player, Sound sound);
|
||||
|
||||
/* action functions */
|
||||
|
@ -917,7 +917,7 @@ bool CombatController::keyPressed(int key) {
|
||||
|
||||
case 'c':
|
||||
screenMessage("Cast Spell!\n");
|
||||
castSpell(_focus);
|
||||
g_debugger->castSpell(_focus);
|
||||
break;
|
||||
|
||||
#ifdef IOS
|
||||
|
@ -46,6 +46,7 @@ static const KeybindingRecord KEYS[] = {
|
||||
{ KEYBIND_ATTACK, "ATTACK", "Attack", "attack", "a", nullptr },
|
||||
{ KEYBIND_BOARD, "BOARD", "Board", "board", "b", nullptr },
|
||||
{ KEYBIND_CAST, "CAST", "Cast", "cast", "c", nullptr },
|
||||
{ KEYBIND_CLIMB, "CLIMB", "Climb", "climb", "k", nullptr },
|
||||
{ KEYBIND_ENTER, "ENTER", "Enter", "enter", "e", nullptr },
|
||||
{ KEYBIND_FIRE, "FIRE", "Fire", "fire", "f", nullptr },
|
||||
{ KEYBIND_GET, "GET", "Get Chest", "get", "g", nullptr },
|
||||
@ -58,8 +59,9 @@ static const KeybindingRecord KEYS[] = {
|
||||
{ KEYBIND_OPEN_DOOR, "OPEN-DOOR", "Open Door", "open", "o", nullptr },
|
||||
{ KEYBIND_PASS, "PASS", "Pass", "pass", "SPACE", nullptr },
|
||||
{ KEYBIND_PEER, "PEER", "Peer", "peer", "p", nullptr },
|
||||
{ KEYBIND_QUIT_SAVE, "QUIT-SAVE", "Quit and Save", "quitAndSave", "q", nullptr },
|
||||
|
||||
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr, nullptr }
|
||||
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr, nullptr }
|
||||
};
|
||||
|
||||
static const KeybindingRecord CHEAT_KEYS[] = {
|
||||
|
@ -30,10 +30,11 @@ namespace Ultima4 {
|
||||
|
||||
enum KeybindingAction {
|
||||
KEYBIND_UP, KEYBIND_DOWN, KEYBIND_LEFT, KEYBIND_RIGHT,
|
||||
KEYBIND_ATTACK, KEYBIND_BOARD, KEYBIND_CAST, KEYBIND_ENTER,
|
||||
KEYBIND_FIRE, KEYBIND_GET, KEYBIND_HOLE_UP, KEYBIND_IGNITE,
|
||||
KEYBIND_JIMMY, KEYBIND_LOCATE, KEYBIND_MIX, KEYBIND_NEW_ORDER,
|
||||
KEYBIND_OPEN_DOOR, KEYBIND_PASS, KEYBIND_PEER,
|
||||
KEYBIND_ATTACK, KEYBIND_BOARD, KEYBIND_CAST, KEYBIND_CLIMB,
|
||||
KEYBIND_ENTER, KEYBIND_FIRE, KEYBIND_GET, KEYBIND_HOLE_UP,
|
||||
KEYBIND_IGNITE, KEYBIND_JIMMY, KEYBIND_LOCATE, KEYBIND_MIX,
|
||||
KEYBIND_NEW_ORDER, KEYBIND_OPEN_DOOR, KEYBIND_PASS,
|
||||
KEYBIND_PEER, KEYBIND_QUIT_SAVE,
|
||||
|
||||
KEYBIND_NONE
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user