ULTIMA1: Split TransportOnFoot into a separate TransportPlayer class for cities & castles

This commit is contained in:
dreammaster
2020-02-01 13:13:51 -08:00
committed by Paul Gilbert
parent 0ce4d68d04
commit ae06eaeeb6
18 changed files with 171 additions and 389 deletions
+1
View File
@@ -87,6 +87,7 @@ MODULE_OBJS += \
ultima1/widgets/person.o \
ultima1/widgets/princess.o \
ultima1/widgets/transport.o \
ultima1/widgets/urban_player.o \
ultima1/widgets/wench.o \
ultima1/game.o
endif
+10 -10
View File
@@ -61,7 +61,7 @@ void Map::MapBase::synchronize(Common::Serializer &s) {
for (uint idx = 0; idx < _widgets.size(); ++idx) {
if (_widgets[idx]->getClassName())
++size;
if (_currentTransport == _widgets[idx].get())
if (_playerWidget == _widgets[idx].get())
transportIndex = (int)idx;
}
assert(transportIndex >= 0);
@@ -89,7 +89,7 @@ void Map::MapBase::synchronize(Common::Serializer &s) {
}
s.syncAsUint16LE(transportIndex);
_currentTransport = _widgets[transportIndex].get();
_playerWidget = _widgets[transportIndex].get();
}
}
@@ -101,7 +101,7 @@ void Map::MapBase::setDimensions(const Point &size) {
}
Point Map::MapBase::getDirectionDelta() const {
switch (_currentTransport->_direction) {
switch (_playerWidget->_direction) {
case DIR_LEFT:
return Point(-1, 0);
case DIR_RIGHT:
@@ -114,7 +114,7 @@ Point Map::MapBase::getDirectionDelta() const {
}
Point Map::MapBase::getDeltaPosition(const Point &delta) {
return _currentTransport->_position + delta;
return _playerWidget->_position + delta;
}
void Map::MapBase::resetViewport() {
@@ -127,8 +127,8 @@ Point Map::MapBase::getViewportPosition(const Point &viewportSize) {
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
// Calculate the new position
topLeft.x = _currentTransport->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _currentTransport->_position.y - (viewportSize.y - 1) / 2;
topLeft.x = _playerWidget->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _playerWidget->_position.y - (viewportSize.y - 1) / 2;
// Fixed maps, so constrain top left corner so the map fills the viewport.
// This will accomodate future renderings with more tiles, or greater tile size
@@ -189,19 +189,19 @@ void Map::MapBase::update() {
}
Point Map::MapBase::getPosition() const {
return _currentTransport->_position;
return _playerWidget->_position;
}
void Map::MapBase::setPosition(const Point &pt) {
_currentTransport->_position = pt;
_playerWidget->_position = pt;
}
Direction Map::MapBase::getDirection() const {
return _currentTransport->_direction;
return _playerWidget->_direction;
}
void Map::MapBase::setDirection(Shared::Direction dir) {
_currentTransport->_direction = dir;
_playerWidget->_direction = dir;
}
/*------------------------------------------------------------------------*/
+5 -5
View File
@@ -173,14 +173,14 @@ public:
Point _size; // X, Y size of the map
Point _tilesPerOrigTile; // For enhanced modes, number of tiles per original game tile
Common::String _name; // Name of map, if applicable
MapWidget *_currentTransport; // Current means of transport, even if on foot
MapWidget *_playerWidget; // Current means of transport, even if on foot
Common::Array<MapWidgetPtr> _widgets; // Party, monsteres, transports, etc.
Common::Array<MapCellsRow> _data; // Data for the map
public:
/**
* Constructor
*/
MapBase(Game *game, Map *map) : _game(game), _map(map), _currentTransport(nullptr), _mapId(0), _mapIndex(0),
MapBase(Game *game, Map *map) : _game(game), _map(map), _playerWidget(nullptr), _mapId(0), _mapIndex(0),
_mapStyle(0) {}
/**
@@ -444,11 +444,11 @@ public:
}
/**
* Returns the currently active transport on the map
* Returns the currently active widget that the player is controlling
*/
MapWidget *getCurrentTransport() const {
MapWidget *getPlayerWidget() const {
assert(_mapArea);
return _mapArea->_currentTransport;
return _mapArea->_playerWidget;
}
/**
-302
View File
@@ -1,302 +0,0 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/system.h"
#include "common/translation.h"
#include "graphics/thumbnail.h"
#include "graphics/scaler.h"
#include "gui/saveload.h"
#include "ultima/ultima.h"
#include "ultima/debugger.h"
#include "ultima/events.h"
#include "ultima/core/resources.h"
#include "ultima/core/mouse_cursor.h"
#include "ultima/gfx/screen.h"
#include "ultima/games/ultima1/game.h"
namespace Ultima {
UltimaEngine *g_vm;
UltimaEngine::UltimaEngine(OSystem *syst, const UltimaGameDescription *gameDesc) :
Engine(syst), _gameDescription(gameDesc), _randomSource("Ultima") {
g_vm = this;
_debugger = nullptr;
_events = nullptr;
_game = nullptr;
_mouseCursor = nullptr;
_screen = nullptr;
}
UltimaEngine::~UltimaEngine() {
delete _debugger;
delete _events;
delete _game;
delete _mouseCursor;
delete _screen;
}
GameId UltimaEngine::getGameID() const {
return _gameDescription->gameId;
}
Common::Language UltimaEngine::getLanguage() const {
return _gameDescription->desc.language;
}
uint32 UltimaEngine::getFeatures() const {
return _gameDescription->features;
}
bool UltimaEngine::isVGAEnhanced() const {
return getFeatures() & GF_VGA_ENHANCED;
}
bool UltimaEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL) ||
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime);
}
bool UltimaEngine::initialize() {
DebugMan.addDebugChannel(kDebugLevelScript, "scripts", "Script debug level");
// Set up the resources datafile
Resources *res = new Resources();
if (!res->open()) {
GUIErrorMessage("Could not find correct ultima.dat datafile");
return false;
}
SearchMan.add("ultima", res);
_debugger = Debugger::init(this);
_events = new Events();
_screen = new Gfx::Screen();
_mouseCursor = new MouseCursor();
// Create the game, and signal to it that the game is starting
_game = createGame();
_events->addTarget(_game);
// If requested, load a savegame instead of showing the intro
if (ConfMan.hasKey("save_slot")) {
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot >= 0 && saveSlot <= 999) {
_game->starting(true);
loadGameState(saveSlot);
return true;
}
}
_game->starting(false);
return true;
}
void UltimaEngine::deinitialize() {
}
Common::Error UltimaEngine::run() {
// Initialize the engine and play the game
if (initialize())
playGame();
// Deinitialize and free the engine
deinitialize();
return Common::kNoError;
}
void UltimaEngine::playGame() {
while (!shouldQuit()) {
_events->pollEventsAndWait();
}
}
Shared::Game *UltimaEngine::createGame() const {
switch (getGameID()) {
case GAME_ULTIMA1:
return new Ultima1::Ultima1Game();
default:
error("Unknown game");
}
}
void UltimaEngine::GUIError(const char *msg, ...) {
char buffer[STRINGBUFLEN];
va_list va;
// Generate the full error message
va_start(va, msg);
vsnprintf(buffer, STRINGBUFLEN, msg, va);
va_end(va);
GUIErrorMessage(buffer);
}
Common::Error UltimaEngine::loadGameState(int slot) {
Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
Common::String::format("%s.%.3d", _targetName.c_str(), slot));
if (!saveFile)
return Common::kReadingFailed;
// Load the savaegame header
UltimaSavegameHeader header;
if (!readSavegameHeader(saveFile, header, false))
return Common::kReadingFailed;
if (header._gameId != getGameID() || header._language != getLanguage()
|| header._videoMode != (isVGAEnhanced() ? 9 : 0))
return Common::kReadingFailed;
// Set the total play time
_events->setFrameCounter(header._totalFrames);
// Read in the game's data
Common::Serializer s(saveFile, nullptr);
_game->synchronize(s);
delete saveFile;
return Common::kNoError;
}
Common::Error UltimaEngine::saveGameState(int slot, const Common::String &desc) {
Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(
Common::String::format("%s.%.3d", _targetName.c_str(), slot));
if (!saveFile)
return Common::kCreatingFileFailed;
// Write the savegame header
writeSavegameHeader(saveFile, desc);
// Write out the game's data
Common::Serializer s(nullptr, saveFile);
_game->synchronize(s);
saveFile->finalize();
delete saveFile;
return Common::kNoError;
}
bool UltimaEngine::canLoadGameStateCurrently() {
return _game->canLoadGameStateCurrently();
}
bool UltimaEngine::canSaveGameStateCurrently() {
return _game->canSaveGameStateCurrently();
}
static const uint32 SAVEGAME_IDENT = MKTAG('U', 'L', 'T', 'S');
static const int SAVEGAME_VERSION = 1;
bool UltimaEngine::readSavegameHeader(Common::InSaveFile *in, UltimaSavegameHeader &header, bool skipThumbnail) {
// Validate the header Id
if (in->readUint32BE() != SAVEGAME_IDENT)
return false;
header._version = in->readByte();
if (header._version > SAVEGAME_VERSION)
return false;
// Read in game, version and language fields
header._gameId = in->readByte();
header._language = in->readByte();
header._videoMode = in->readByte();
// Read in the string
header._saveName.clear();
char ch;
while ((ch = (char)in->readByte()) != '\0')
header._saveName += ch;
// Get the thumbnail
if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
}
// Read in save date/time
header._year = in->readSint16LE();
header._month = in->readSint16LE();
header._day = in->readSint16LE();
header._hour = in->readSint16LE();
header._minute = in->readSint16LE();
header._totalFrames = in->readUint32LE();
return true;
}
void UltimaEngine::writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName) {
out->writeUint32BE(SAVEGAME_IDENT);
out->writeByte(SAVEGAME_VERSION);
out->writeByte(getGameID());
out->writeByte(getLanguage());
out->writeByte(isVGAEnhanced() ? 9 : 0);
out->writeString(saveName);
out->writeByte(0);
// Write a thumbnail of the screen
uint8 thumbPalette[PALETTE_SIZE];
_screen->getPalette(thumbPalette);
Graphics::Surface saveThumb;
::createThumbnail(&saveThumb, (const byte *)_screen->getPixels(),
_screen->w, _screen->h, thumbPalette);
Graphics::saveThumbnail(*out, saveThumb);
saveThumb.free();
// Write out the save date/time
TimeDate td;
g_system->getTimeAndDate(td);
out->writeSint16LE(td.tm_year + 1900);
out->writeSint16LE(td.tm_mon + 1);
out->writeSint16LE(td.tm_mday);
out->writeSint16LE(td.tm_hour);
out->writeSint16LE(td.tm_min);
out->writeUint32LE(_events->getFrameCounter());
}
bool UltimaEngine::saveGame() {
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
int slotNum = dialog->runModalWithCurrentTarget();
Common::String saveName = dialog->getResultString();
delete dialog;
if (slotNum != -1)
saveGameState(slotNum, saveName);
return slotNum != -1;
}
bool UltimaEngine::loadGame() {
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
int slotNum = dialog->runModalWithCurrentTarget();
delete dialog;
if (slotNum != -1)
loadGameState(slotNum);
return slotNum != -1;
}
} // End of namespace Ultima
+8 -8
View File
@@ -53,8 +53,8 @@ bool Move::MoveMsg(CMoveMsg &msg) {
break;
}
} else {
Widgets::Transport *transport = dynamic_cast<Widgets::Transport *>(map->getCurrentTransport());
assert(transport);
Shared::MapWidget *player = map->getPlayerWidget();
assert(player);
// Figure out the new position
Point delta;
@@ -73,14 +73,14 @@ bool Move::MoveMsg(CMoveMsg &msg) {
break;
}
// Check if the given transport type can move to the new position
// Check if the player's widget type can move to the new position
Point newPos = map->getDeltaPosition(delta);
if (transport->canMoveTo(newPos)) {
if (player->canMoveTo(newPos)) {
// Shift the viewport
map->shiftViewport(delta);
// Move to the new position
transport->moveTo(newPos);
player->moveTo(newPos);
addInfoMsg(getRes()->DIRECTION_NAMES[msg._direction - 1]);
} else {
// Nope, so show a blocked message
@@ -164,10 +164,10 @@ void Move::dungeonTurnAround() {
void Move::dungeonMoveForward() {
Map::Ultima1Map *map = getMap();
Point delta = map->getDirectionDelta();
Shared::MapWidget *widget = map->getCurrentTransport();
assert(widget);
Shared::MapWidget *player = map->getPlayerWidget();
assert(player);
if (widget->canMoveTo(map->getPosition() + delta)) {
if (player->canMoveTo(map->getPosition() + delta)) {
map->setPosition(map->getPosition() + delta);
} else {
playFX(0);
+2
View File
@@ -38,6 +38,7 @@
#include "ultima/ultima1/widgets/overworld_monster.h"
#include "ultima/ultima1/widgets/princess.h"
#include "ultima/ultima1/widgets/transport.h"
#include "ultima/ultima1/widgets/urban_player.h"
#include "ultima/ultima1/widgets/wench.h"
#include "ultima/shared/core/file.h"
#include "ultima/shared/early/ultima_early.h"
@@ -217,6 +218,7 @@ Shared::MapWidget *Ultima1Map::createWidget(Shared::Map::MapBase *map, const Com
REGISTER_WIDGET(OverworldMonster);
REGISTER_WIDGET(Princess);
REGISTER_WIDGET(TransportOnFoot);
REGISTER_WIDGET(UrbanPlayer);
REGISTER_WIDGET(Wench);
error("Unknown widget type '%s'", name.c_str());
@@ -21,9 +21,9 @@
*/
#include "ultima/ultima1/map/map_city_castle.h"
#include "ultima/ultima1/widgets/transport.h"
#include "ultima/ultima1/core/resources.h"
#include "ultima/ultima1/game.h"
#include "ultima/ultima1/widgets/urban_player.h"
#include "ultima/ultima1/widgets/bard.h"
#include "ultima/ultima1/widgets/guard.h"
#include "ultima/ultima1/widgets/king.h"
@@ -50,8 +50,8 @@ void MapCityCastle::clear() {
void MapCityCastle::loadWidgets() {
// Set up widget for the player
_currentTransport = new Widgets::TransportOnFoot(_game, this);
addWidget(_currentTransport);
_playerWidget = new Widgets::UrbanPlayer(_game, this);
addWidget(_playerWidget);
for (int idx = 0; idx < 15; ++idx) {
const int *lp = _game->_res->LOCATION_PEOPLE[_mapStyle * 15 + idx];
@@ -92,8 +92,8 @@ Point MapCityCastle::getViewportPosition(const Point &viewportSize) {
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
// Calculate the new position
topLeft.x = _currentTransport->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _currentTransport->_position.y - (viewportSize.y - 1) / 2;
topLeft.x = _playerWidget->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _playerWidget->_position.y - (viewportSize.y - 1) / 2;
// Fixed maps, so constrain top left corner so the map fills the viewport. This will accomodate
// future renderings with more tiles, or greater tile size
+3 -3
View File
@@ -38,7 +38,7 @@ void MapDungeon::load(Shared::MapId mapId) {
_dungeonLevel = 1;
changeLevel(0);
_currentTransport->moveTo(Point(1, 1), Shared::DIR_SOUTH);
_playerWidget->moveTo(Point(1, 1), Shared::DIR_SOUTH);
}
bool MapDungeon::changeLevel(int delta) {
@@ -54,8 +54,8 @@ bool MapDungeon::changeLevel(int delta) {
if (_widgets.empty()) {
// Set up widget for the player
_currentTransport = new Widgets::DungeonPlayer(_game, this);
addWidget(_currentTransport);
_playerWidget = new Widgets::DungeonPlayer(_game, this);
addWidget(_playerWidget);
} else {
_widgets.resize(1);
}
+5 -5
View File
@@ -53,13 +53,13 @@ void MapOverworld::loadWidgets() {
// the initial "on foot" transport the first time
if (_widgets.empty()) {
// Set up widget for the player
_currentTransport = new Widgets::TransportOnFoot(_game, this);
addWidget(_currentTransport);
_playerWidget = new Widgets::TransportOnFoot(_game, this);
addWidget(_playerWidget);
}
}
Point MapOverworld::getDeltaPosition(const Point &delta) {
Point pt = _currentTransport->_position + delta;
Point pt = _playerWidget->_position + delta;
if (pt.x < 0)
pt.x += _size.x;
@@ -78,8 +78,8 @@ Point MapOverworld::getViewportPosition(const Point &viewportSize) {
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
// Calculate the new position
topLeft.x = _currentTransport->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _currentTransport->_position.y - (viewportSize.y - 1) / 2;
topLeft.x = _playerWidget->_position.x - (viewportSize.x - 1) / 2;
topLeft.y = _playerWidget->_position.y - (viewportSize.y - 1) / 2;
// Non-fixed map, so it wraps around the edges if necessary
if (topLeft.x < 0)
+1 -1
View File
@@ -32,7 +32,7 @@ void Bard::movement() {
if (areGuardsHostile())
return;
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
bool stolen = false;
// Choose a new random position to move to
@@ -51,7 +51,7 @@ void DungeonMonster::draw(Shared::DungeonSurface &s, uint distance) {
void DungeonMonster::update(bool isPreUpdate) {
assert(isPreUpdate);
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
Point delta = playerPos - _position;
int distance = ABS(delta.x) + ABS(delta.y);
@@ -67,7 +67,7 @@ void DungeonMonster::movement() {
// Dungeon monsters don't move if they're already in attack range
return;
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
Point delta = playerPos - _position;
if (delta.x != 0 && canMoveTo(Point(_position.x + SGN(delta.x), _position.y)))
@@ -103,7 +103,7 @@ bool DungeonMonster::canMoveTo(Shared::Map::MapBase *map, MapWidget *widget, con
void DungeonMonster::attack() {
Ultima1Game *game = static_cast<Ultima1Game *>(_game);
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
//Point delta = playerPos - _position;
Shared::Character *c = _game->_party._currentCharacter;
uint threshold, damage;
+2 -2
View File
@@ -29,7 +29,7 @@ namespace Ultima1 {
namespace Widgets {
uint Guard::attackDistance() const {
Point diff = _position - _map->_currentTransport->_position;
Point diff = _position - _map->_playerWidget->_position;
return areGuardsHostile() && ABS(diff.x) < 2 && ABS(diff.y) < 2 ? 1 : 0;
}
@@ -38,7 +38,7 @@ void Guard::movement() {
if (!areGuardsHostile() || attackDistance())
return;
Point diff = _position - _map->_currentTransport->_position;
Point diff = _position - _map->_playerWidget->_position;
Point delta(SGN(diff.x), SGN(diff.y));
int totalDiff = ABS(diff.x) + ABS(diff.y);
if (totalDiff >= 13)
@@ -47,7 +47,7 @@ void OverworldMonster::synchronize(Common::Serializer &s) {
}
uint OverworldMonster::attackDistance() const {
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
Point diff = playerPos - _position;
int threshold = _tileNum == 23 || _tileNum == 25 || _tileNum == 31 || _tileNum == 47 ? 3 : 1;
@@ -61,7 +61,7 @@ void OverworldMonster::movement() {
void OverworldMonster::attack() {
Ultima1Game *game = dynamic_cast<Ultima1Game *>(_game);
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
Point diff = playerPos - _position;
Point delta(SGN(diff.x), SGN(diff.y));
Point tempDiff;
+1 -1
View File
@@ -33,7 +33,7 @@ void Princess::movement() {
Wench::movement();
} else {
// When the guards are hostile, keep the princess moving towards the player
Point playerPos = _map->_currentTransport->_position;
Point playerPos = _map->_playerWidget->_position;
Point delta(SGN(_position.x - playerPos.x), SGN(_position.y - playerPos.y));
bool moved = false;
+1 -24
View File
@@ -42,30 +42,7 @@ Map::Ultima1Map::MapBase *Transport::getMap() const {
/*-------------------------------------------------------------------*/
uint TransportOnFoot::getTileNum() const {
Map::Ultima1Map::MapBase *map = getMap();
return dynamic_cast<Map::MapOverworld *>(map) ? 8 : 18;
}
void TransportOnFoot::moveTo(const Point &destPos, Shared::Direction dir) {
Transport::moveTo(destPos, dir);
Shared::Map *map = getGame()->getMap();
if (destPos.x < 0 || destPos.y < 0 || destPos.x >= (int)map->width() || destPos.y >= (int)map->height()) {
// Handling for leaving locations by walking off the edge of the map
if (isPrincessSaved())
princessSaved();
// Load the overworld map
map->load(Map::MAP_OVERWORLD);
}
}
bool TransportOnFoot::isPrincessSaved() const {
return false;
}
void TransportOnFoot::princessSaved() {
// TODO
return 8;
}
} // End of namespace Widgets
@@ -56,16 +56,6 @@ public:
};
class TransportOnFoot : public Transport {
private:
/**
* Checks for whether a princess has been saved from a castle being left
*/
bool isPrincessSaved() const;
/**
* Called for a princess being saved
*/
void princessSaved();
public:
DECLARE_WIDGET(TransportOnFoot)
@@ -83,14 +73,6 @@ public:
* Get the tile for the transport method
*/
virtual uint getTileNum() const override;
/**
* Moves to a given position
* @param destPos Specified new position
* @param dir Optional explicit direction to set. If not specified,
* the direction will be set relative to the position moved from
*/
virtual void moveTo(const Point &destPos, Shared::Direction dir = Shared::DIR_NONE) override;
};
} // End of namespace Widgets
@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ultima/ultima1/widgets/urban_player.h"
#include "ultima/ultima1/map/map.h"
#include "ultima/ultima1/game.h"
namespace Ultima {
namespace Ultima1 {
namespace Widgets {
void UrbanPlayer::moveTo(const Point &destPos, Shared::Direction dir) {
Creature::moveTo(destPos, dir);
Shared::Map *map = _game->getMap();
if (destPos.x < 0 || destPos.y < 0 || destPos.x >= (int)map->width() || destPos.y >= (int)map->height()) {
// Handling for leaving locations by walking off the edge of the map
if (isPrincessSaved())
princessSaved();
// Load the overworld map
map->load(Map::MAP_OVERWORLD);
}
}
bool UrbanPlayer::isPrincessSaved() const {
return false;
}
void UrbanPlayer::princessSaved() {
// TODO
}
} // End of namespace Widgets
} // End of namespace Ultima1
} // End of namespace Ultima
@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ULTIMA_ULTIMA1_URBAN_PLAYER_H
#define ULTIMA_ULTIMA1_URBAN_PLAYER_H
#include "ultima/ultima1/widgets/person.h"
namespace Ultima {
namespace Ultima1 {
namespace Widgets {
/**
* Specialized player class for within cities and castles
*/
class UrbanPlayer : public Person {
private:
/**
* Checks for whether a princess has been saved from a castle being left
*/
bool isPrincessSaved() const;
/**
* Called for a princess being saved
*/
void princessSaved();
public:
DECLARE_WIDGET(UrbanPlayer)
/**
* Constructor
*/
UrbanPlayer(Ultima1Game *game, Map::Ultima1Map::MapBase *map) : Person(game, map, 18) {}
/**
* Moves to a given position
* @param destPos Specified new position
* @param dir Optional explicit direction to set. If not specified,
* the direction will be set relative to the position moved from
*/
virtual void moveTo(const Point &destPos, Shared::Direction dir = Shared::DIR_NONE) override;
};
} // End of namespace Widgets
} // End of namespace Ultima1
} // End of namespace Ultima
#endif