From 10f6bb920690a3d5eae7ee80926bdfdffdbcc4c0 Mon Sep 17 00:00:00 2001 From: dreammaster Date: Tue, 21 Jan 2020 07:12:18 +0000 Subject: [PATCH] ULTIMA1: Added direction selection for spell casting --- engines/ultima/shared/core/character.h | 5 +-- engines/ultima/shared/gfx/character_input.cpp | 14 ++----- engines/ultima/shared/maps/map_widget.cpp | 23 +++++++++++ engines/ultima/shared/maps/map_widget.h | 6 +++ engines/ultima/ultima1/actions/map_action.h | 12 ++++++ engines/ultima/ultima1/spells/blink.cpp | 1 + engines/ultima/ultima1/spells/create.cpp | 1 + engines/ultima/ultima1/spells/destroy.cpp | 1 + .../ultima1/spells/kill_magic_missile.cpp | 26 ++++++++++++ .../ultima1/spells/kill_magic_missile.h | 12 ++++++ engines/ultima/ultima1/spells/ladder_down.cpp | 1 + engines/ultima/ultima1/spells/ladder_up.cpp | 1 + engines/ultima/ultima1/spells/open_unlock.cpp | 1 + engines/ultima/ultima1/spells/prayer.cpp | 2 + engines/ultima/ultima1/spells/spell.cpp | 4 +- engines/ultima/ultima1/u1gfx/view_game.cpp | 40 +++++++++---------- 16 files changed, 115 insertions(+), 35 deletions(-) diff --git a/engines/ultima/shared/core/character.h b/engines/ultima/shared/core/character.h index 1953db41cf4..00aea66e567 100644 --- a/engines/ultima/shared/core/character.h +++ b/engines/ultima/shared/core/character.h @@ -26,6 +26,7 @@ #include "common/array.h" #include "common/str.h" #include "common/serializer.h" +#include "ultima/shared/core/named_item.h" namespace Ultima { namespace Shared { @@ -97,9 +98,7 @@ public: /** * Spell entry */ -class Spell : public Itemized { -public: - Common::String _name; +class Spell : public Itemized, public NamedItem { }; template diff --git a/engines/ultima/shared/gfx/character_input.cpp b/engines/ultima/shared/gfx/character_input.cpp index 37b3645bc23..b8d6c761c14 100644 --- a/engines/ultima/shared/gfx/character_input.cpp +++ b/engines/ultima/shared/gfx/character_input.cpp @@ -34,7 +34,7 @@ BEGIN_MESSAGE_MAP(CharacterInput, Popup) END_MESSAGE_MAP() void CharacterInput::show(const Point &pt, byte color, TreeItem *respondTo) { - Popup::show(_respondTo); + Popup::show(respondTo); _color = color; _bounds = Rect(pt.x, pt.y, pt.x + 8, pt.y + 8); @@ -43,16 +43,10 @@ void CharacterInput::show(const Point &pt, byte color, TreeItem *respondTo) { } bool CharacterInput::KeypressMsg(CKeypressMsg &msg) { - uint16 c = msg._keyState.ascii; + hide(); - if (msg._keyState.keycode == Common::KEYCODE_ESCAPE) { - CTextInputMsg inputMsg("", true); - inputMsg.execute(_respondTo); - } else if (c >= ' ' && c <= 0x7f) { - // Printable character - CTextInputMsg inputMsg(Common::String(c), false); - inputMsg.execute(_respondTo); - } + CCharacterInputMsg inputMsg(msg._keyState); + inputMsg.execute(_respondTo); return true; } diff --git a/engines/ultima/shared/maps/map_widget.cpp b/engines/ultima/shared/maps/map_widget.cpp index 3b924359e0c..b397ec8a586 100644 --- a/engines/ultima/shared/maps/map_widget.cpp +++ b/engines/ultima/shared/maps/map_widget.cpp @@ -32,6 +32,29 @@ namespace Maps { EMPTY_MESSAGE_MAP(MapWidget, MessageTarget); +Direction MapWidget::directionFromKey(Common::KeyCode keycode) { + switch (keycode) { + case Common::KEYCODE_LEFT: + case Common::KEYCODE_KP4: + return DIR_WEST; + + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_KP6: + return DIR_EAST; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + return DIR_NORTH; + + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + return DIR_SOUTH; + + default: + return DIR_NONE; + } +} + void MapWidget::synchronize(Common::Serializer &s) { s.syncAsUint16LE(_position.x); s.syncAsSint16LE(_position.y); diff --git a/engines/ultima/shared/maps/map_widget.h b/engines/ultima/shared/maps/map_widget.h index ce9b915a805..4729b0b8479 100644 --- a/engines/ultima/shared/maps/map_widget.h +++ b/engines/ultima/shared/maps/map_widget.h @@ -23,6 +23,7 @@ #ifndef ULTIMA_SHARED_MAPS_MAP_WIDGET_H #define ULTIMA_SHARED_MAPS_MAP_WIDGET_H +#include "common/events.h" #include "common/ptr.h" #include "common/serializer.h" #include "common/str.h" @@ -56,6 +57,11 @@ public: Point _position; // Position within the map Direction _direction; // Direction Common::String _name; // Name of widget +public: + /** + * Support method to get a direction from a keycode + */ + static Direction directionFromKey(Common::KeyCode keycode); public: CLASSDEF; diff --git a/engines/ultima/ultima1/actions/map_action.h b/engines/ultima/ultima1/actions/map_action.h index 7df92ec468a..591bcc30c55 100644 --- a/engines/ultima/ultima1/actions/map_action.h +++ b/engines/ultima/ultima1/actions/map_action.h @@ -28,6 +28,18 @@ namespace Ultima1 { namespace Actions { #define MAP_ACTION(NAME, ACTION_NUM, MAP_METHOD) \ + using Shared::C##NAME##Msg; \ + class NAME : public Action { DECLARE_MESSAGE_MAP; bool NAME##Msg(C##NAME##Msg &msg) { \ + addInfoMsg(getRes()->ACTION_NAMES[ACTION_NUM], false); \ + getMap()->MAP_METHOD(); \ + return true; } \ + public: \ + CLASSDEF; \ + NAME(TreeItem *parent) : Action(parent) {} \ + }; \ + BEGIN_MESSAGE_MAP(NAME, Action) ON_MESSAGE(NAME##Msg) END_MESSAGE_MAP() + +#define MAP_ACTION_END_TURN(NAME, ACTION_NUM, MAP_METHOD) \ using Shared::C##NAME##Msg; \ class NAME : public Action { DECLARE_MESSAGE_MAP; bool NAME##Msg(C##NAME##Msg &msg) { \ addInfoMsg(getRes()->ACTION_NAMES[ACTION_NUM], false); \ diff --git a/engines/ultima/ultima1/spells/blink.cpp b/engines/ultima/ultima1/spells/blink.cpp index 8ca663b0073..9d760fe37bd 100644 --- a/engines/ultima/ultima1/spells/blink.cpp +++ b/engines/ultima/ultima1/spells/blink.cpp @@ -46,6 +46,7 @@ void Blink::dungeonCast(Maps::MapDungeon *map) { // And teleport there addInfoMsg(_game->_res->TELEPORTED); map->setPosition(newPos); + _game->endOfTurn(); } } // End of namespace Spells diff --git a/engines/ultima/ultima1/spells/create.cpp b/engines/ultima/ultima1/spells/create.cpp index 32486c3b8b5..6eb5b2bd099 100644 --- a/engines/ultima/ultima1/spells/create.cpp +++ b/engines/ultima/ultima1/spells/create.cpp @@ -44,6 +44,7 @@ void Create::dungeonCast(Maps::MapDungeon *map) { // Create beams on the tile in front of the player map->setTileAt(newPos, Maps::DTILE_BEAMS); addInfoMsg(_game->_res->FIELD_CREATED); + _game->endOfTurn(); } else { // Failed Spell::dungeonCast(map); diff --git a/engines/ultima/ultima1/spells/destroy.cpp b/engines/ultima/ultima1/spells/destroy.cpp index e952c4dc876..064cdc69e21 100644 --- a/engines/ultima/ultima1/spells/destroy.cpp +++ b/engines/ultima/ultima1/spells/destroy.cpp @@ -44,6 +44,7 @@ void Destroy::dungeonCast(Maps::MapDungeon *map) { // Destroy the beams in front of the player map->setTileAt(newPos, Maps::DTILE_HALLWAY); addInfoMsg(_game->_res->FIELD_DESTROYED); + _game->endOfTurn(); } else { // Failed Spell::dungeonCast(map); diff --git a/engines/ultima/ultima1/spells/kill_magic_missile.cpp b/engines/ultima/ultima1/spells/kill_magic_missile.cpp index 079d2245fba..723952638ca 100644 --- a/engines/ultima/ultima1/spells/kill_magic_missile.cpp +++ b/engines/ultima/ultima1/spells/kill_magic_missile.cpp @@ -26,11 +26,36 @@ #include "ultima/ultima1/core/resources.h" #include "ultima/ultima1/maps/map_tile.h" #include "ultima/ultima1/widgets/dungeon_monster.h" +#include "ultima/shared/maps/map_widget.h" namespace Ultima { namespace Ultima1 { namespace Spells { +BEGIN_MESSAGE_MAP(KillMagicMIssile, Spell) + ON_MESSAGE(CharacterInputMsg) +END_MESSAGE_MAP() + +void KillMagicMIssile::cast(Maps::MapBase *map) { + // Prompt for a direction + addInfoMsg(": ", false); + Shared::CInfoGetKeypress keyMsg(this); + keyMsg.execute(_game); +} + +bool KillMagicMIssile::CharacterInputMsg(CCharacterInputMsg &msg) { + Shared::Maps::Direction dir = Shared::Maps::MapWidget::directionFromKey(msg._keyState.keycode); + + if (dir == Shared::Maps::DIR_NONE) { + addInfoMsg(_game->_res->NONE); + } else { + addInfoMsg(_game->_res->DIRECTION_NAMES[(int)dir - 1]); + } + + _game->endOfTurn(); + return true; +} + /*-------------------------------------------------------------------*/ Kill::Kill() : KillMagicMIssile(SPELL_KILL) { @@ -46,6 +71,7 @@ void Kill::dungeonCast(Maps::MapDungeon *map) { Widgets::DungeonMonster *monster = dynamic_cast(tile._widget); if (monster) { monster->attackMonster(5, 101, Widgets::ITS_OVER_9000); + _game->endOfTurn(); } else { // Failed KillMagicMIssile::dungeonCast(map); diff --git a/engines/ultima/ultima1/spells/kill_magic_missile.h b/engines/ultima/ultima1/spells/kill_magic_missile.h index 43cb053947d..470cc84a6d5 100644 --- a/engines/ultima/ultima1/spells/kill_magic_missile.h +++ b/engines/ultima/ultima1/spells/kill_magic_missile.h @@ -24,20 +24,32 @@ #define ULTIMA_ULTIMA1_U1DIALOGS_KILL_MAGIC_MISSILE_H #include "ultima/ultima1/spells/spell.h" +#include "ultima/shared/engine/messages.h" namespace Ultima { namespace Ultima1 { namespace Spells { +using Shared::CCharacterInputMsg; + /** * Common intermediate base class for both the Kill and Magic Missile spells */ class KillMagicMIssile : public Spell { + DECLARE_MESSAGE_MAP; + bool CharacterInputMsg(CCharacterInputMsg &msg); public: + CLASSDEF; + /** * Constructor */ KillMagicMIssile(SpellId spellId) : Spell(spellId) {} + + /** + * Cast the spell outside a dungeon + */ + virtual void cast(Maps::MapBase *map) override; }; /** diff --git a/engines/ultima/ultima1/spells/ladder_down.cpp b/engines/ultima/ultima1/spells/ladder_down.cpp index 8fa329ade19..29c6f4b3db9 100644 --- a/engines/ultima/ultima1/spells/ladder_down.cpp +++ b/engines/ultima/ultima1/spells/ladder_down.cpp @@ -40,6 +40,7 @@ void LadderDown::dungeonCast(Maps::MapDungeon *map) { if (map->getLevel() < 10 && !tile._isBeams && ((pt.x & 1) || (pt.y & 1))) { map->setTileAt(pt, Maps::DTILE_LADDER_DOWN); addInfoMsg(_game->_res->LADDER_CREATED); + _game->endOfTurn(); } else { // Failed Spell::dungeonCast(map); diff --git a/engines/ultima/ultima1/spells/ladder_up.cpp b/engines/ultima/ultima1/spells/ladder_up.cpp index ac766693c9e..b2568efc7d8 100644 --- a/engines/ultima/ultima1/spells/ladder_up.cpp +++ b/engines/ultima/ultima1/spells/ladder_up.cpp @@ -40,6 +40,7 @@ void LadderUp::dungeonCast(Maps::MapDungeon *map) { if (!tile._isBeams && ((pt.x & 1) || (pt.y & 1))) { map->setTileAt(pt, Maps::DTILE_LADDER_UP); addInfoMsg(_game->_res->LADDER_CREATED); + _game->endOfTurn(); } else { // Failed Spell::dungeonCast(map); diff --git a/engines/ultima/ultima1/spells/open_unlock.cpp b/engines/ultima/ultima1/spells/open_unlock.cpp index 0f41c94d678..f5b4ec80e6c 100644 --- a/engines/ultima/ultima1/spells/open_unlock.cpp +++ b/engines/ultima/ultima1/spells/open_unlock.cpp @@ -38,6 +38,7 @@ void OpenUnlock::dungeonCast(Maps::MapDungeon *map) { if (item) { addInfoMsg(item->_name, false); openItem(map, item); + _game->endOfTurn(); } else { Spell::dungeonCast(map); } diff --git a/engines/ultima/ultima1/spells/prayer.cpp b/engines/ultima/ultima1/spells/prayer.cpp index 941d87ebe89..d6fee27f455 100644 --- a/engines/ultima/ultima1/spells/prayer.cpp +++ b/engines/ultima/ultima1/spells/prayer.cpp @@ -67,6 +67,8 @@ void Prayer::cast(Maps::MapBase *map) { addInfoMsg(_game->_res->NO_EFFECT); _game->playFX(6); } + + _game->endOfTurn(); } void Prayer::dungeonCast(Maps::MapDungeon *map) { diff --git a/engines/ultima/ultima1/spells/spell.cpp b/engines/ultima/ultima1/spells/spell.cpp index d6e58d2e3fc..912c3f892b0 100644 --- a/engines/ultima/ultima1/spells/spell.cpp +++ b/engines/ultima/ultima1/spells/spell.cpp @@ -35,7 +35,7 @@ void Spell::setGame(Ultima1Game *game) { void Spell::addInfoMsg(const Common::String &text, bool newLine) { Shared::CInfoMsg msg(text, newLine); - msg.execute(_game->getView()); + msg.execute("Game"); } void Spell::cast(Maps::MapBase *map) { @@ -43,12 +43,14 @@ void Spell::cast(Maps::MapBase *map) { addInfoMsg(""); addInfoMsg(_game->_res->DUNGEON_SPELL_ONLY); _game->playFX(6); + _game->endOfTurn(); } void Spell::dungeonCast(Maps::MapDungeon *map) { // This is the fallback the spells call if it fails addInfoMsg(_game->_res->FAILED); _game->playFX(6); + _game->endOfTurn(); } } // End of namespace Spells diff --git a/engines/ultima/ultima1/u1gfx/view_game.cpp b/engines/ultima/ultima1/u1gfx/view_game.cpp index 892a94160c4..3507942e038 100644 --- a/engines/ultima/ultima1/u1gfx/view_game.cpp +++ b/engines/ultima/ultima1/u1gfx/view_game.cpp @@ -45,18 +45,18 @@ namespace Ultima1 { namespace Actions { MAP_ACTION(Cast, 2, cast) MAP_ACTION(Drop, 3, drop) -MAP_ACTION(Enter, 4, enter) -MAP_ACTION(Fire, 5, fire) -MAP_ACTION(Get, 6, get) -MAP_ACTION(HyperJump, 7, hyperjump) -MAP_ACTION(Inform, 8, inform) -MAP_ACTION(Climb, 10, climb) -MAP_ACTION(Open, 14, open) -MAP_ACTION(Steal, 18, steal) -MAP_ACTION(Transact, 19, talk) -MAP_ACTION(Unlock, 20, unlock) -MAP_ACTION(ViewChange, 21, view) -MAP_ACTION(ExitTransport, 23, disembark) +MAP_ACTION_END_TURN(Enter, 4, enter) +MAP_ACTION_END_TURN(Fire, 5, fire) +MAP_ACTION_END_TURN(Get, 6, get) +MAP_ACTION_END_TURN(HyperJump, 7, hyperjump) +MAP_ACTION_END_TURN(Inform, 8, inform) +MAP_ACTION_END_TURN(Climb, 10, climb) +MAP_ACTION_END_TURN(Open, 14, open) +MAP_ACTION_END_TURN(Steal, 18, steal) +MAP_ACTION_END_TURN(Transact, 19, talk) +MAP_ACTION_END_TURN(Unlock, 20, unlock) +MAP_ACTION_END_TURN(ViewChange, 21, view) +MAP_ACTION_END_TURN(ExitTransport, 23, disembark) } namespace U1Gfx { @@ -204,9 +204,10 @@ void dispatchKey(ViewGame *game) { #define CHECK(KEYCODE, MSG_CLASS) else if (msg._keyState.keycode == KEYCODE) { dispatchKey(this); } bool ViewGame::checkMovement(const Common::KeyState &keyState) { - switch (keyState.keycode) { - case Common::KEYCODE_LEFT: - case Common::KEYCODE_KP4: { + Shared::Maps::Direction dir = Shared::Maps::MapWidget::directionFromKey(keyState.keycode); + + switch (dir) { + case Shared::Maps::DIR_WEST: { if (keyState.flags & Common::KBD_SHIFT) { Shared::CAttackMsg attack(Shared::Maps::DIR_LEFT); attack.execute(this); @@ -216,8 +217,7 @@ bool ViewGame::checkMovement(const Common::KeyState &keyState) { } break; } - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_KP6: { + case Shared::Maps::DIR_EAST: { if (keyState.flags & Common::KBD_SHIFT) { Shared::CAttackMsg attack(Shared::Maps::DIR_RIGHT); attack.execute(this); @@ -227,8 +227,7 @@ bool ViewGame::checkMovement(const Common::KeyState &keyState) { } break; } - case Common::KEYCODE_UP: - case Common::KEYCODE_KP8: { + case Shared::Maps::DIR_UP: { if (keyState.flags & Common::KBD_SHIFT) { Shared::CAttackMsg attack(Shared::Maps::DIR_UP); attack.execute(this); @@ -238,8 +237,7 @@ bool ViewGame::checkMovement(const Common::KeyState &keyState) { } break; } - case Common::KEYCODE_DOWN: - case Common::KEYCODE_KP2: { + case Shared::Maps::DIR_DOWN: { if (keyState.flags & Common::KBD_SHIFT) { Shared::CAttackMsg attack(Shared::Maps::DIR_DOWN); attack.execute(this);