ULTIMA1: Added direction selection for spell casting

This commit is contained in:
dreammaster
2020-02-01 13:13:51 -08:00
committed by Paul Gilbert
parent a9c9c3939a
commit 10f6bb9206
16 changed files with 115 additions and 35 deletions
+2 -3
View File
@@ -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<class T>
+4 -10
View File
@@ -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;
}
+23
View File
@@ -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);
+6
View File
@@ -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;
@@ -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); \
+1
View File
@@ -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
+1
View File
@@ -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);
@@ -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);
@@ -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<Widgets::DungeonMonster *>(tile._widget);
if (monster) {
monster->attackMonster(5, 101, Widgets::ITS_OVER_9000);
_game->endOfTurn();
} else {
// Failed
KillMagicMIssile::dungeonCast(map);
@@ -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;
};
/**
@@ -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);
@@ -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);
@@ -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);
}
+2
View File
@@ -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) {
+3 -1
View File
@@ -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
+19 -21
View File
@@ -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<MSG_CLASS>(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);