/* 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 3 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, see .
*
*/
#include "ultima/ultima1/maps/map_overworld.h"
#include "ultima/ultima1/widgets/transport.h"
#include "ultima/ultima1/widgets/overworld_monster.h"
#include "ultima/ultima1/widgets/transport.h"
#include "ultima/ultima1/maps/map_tile.h"
#include "ultima/ultima1/maps/map.h"
#include "ultima/ultima1/game.h"
#include "ultima/ultima1/core/resources.h"
namespace Ultima {
namespace Ultima1 {
namespace Maps {
void MapOverworld::load(Shared::Maps::MapId mapId) {
Shared::Maps::MapBase::load(mapId);
setDimensions(Point(168, 156));
_tilesPerOrigTile = Point(1, 1);
Shared::File f("map.bin");
byte b;
for (int y = 0; y < _size.y; ++y) {
for (int x = 0; x < _size.x; x += 2) {
b = f.readByte();
_data[y][x] = b >> 4;
_data[y][x + 1] = b & 0xf;
}
}
// Load widgets
loadWidgets();
}
void MapOverworld::loadWidgets() {
// Note: the overworld player, transports, and monsters are persistent, so we only have to set up
// the initial "on foot" transport the first time
if (_widgets.empty()) {
// Set up widget for the player
_playerWidget = new Widgets::TransportOnFoot(_game, this);
addWidget(_playerWidget);
}
}
Point MapOverworld::getDeltaPosition(const Point &delta) {
Point pt = _playerWidget->_position + delta;
if (pt.x < 0)
pt.x += _size.x;
else if (pt.x >= _size.x)
pt.x -= _size.x;
if (pt.y < 0)
pt.y += _size.y;
else if (pt.y >= _size.y)
pt.y -= _size.y;
return pt;
}
Point MapOverworld::getViewportPosition(const Point &viewportSize) {
Point &topLeft = _viewportPos._topLeft;
if (!_viewportPos.isValid() || _viewportPos._size != viewportSize) {
// Calculate the new position
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)
topLeft.x += width();
else if (topLeft.x >= (int)width())
topLeft.x -= width();
if (topLeft.y < 0)
topLeft.y += height();
else if (topLeft.y >= (int)height())
topLeft.y -= height();
_viewportPos._mapId = _mapId;
_viewportPos._size = viewportSize;
}
return topLeft;
}
void MapOverworld::shiftViewport(const Point &delta) {
Point &topLeft = _viewportPos._topLeft;
topLeft += delta;
if (topLeft.x < 0)
topLeft.x += width();
else if (topLeft.x >= (int16)width())
topLeft.x -= width();
if (topLeft.y < 0)
topLeft.y += height();
else if (topLeft.y >= (int16)height())
topLeft.y -= height();
}
void MapOverworld::board() {
Maps::U1MapTile tile;
getTileAt(getPosition(), &tile);
Widgets::Transport *transport = dynamic_cast(tile._widget);
if (!dynamic_cast(_playerWidget)) {
addInfoMsg(_game->_res->EXIT_CRAFT_FIRST, true, true);
_game->playFX(1);
_game->endOfTurn();
} else if (!transport) {
addInfoMsg(_game->_res->NOTHING_TO_BOARD, true, true);
_game->playFX(1);
_game->endOfTurn();
} else {
transport->board();
}
}
void MapOverworld::enter() {
Maps::U1MapTile tile;
getTileAt(getPosition(), &tile);
if (tile._locationNum == -1) {
// Fall back to base unknown action
MapBase::enter();
} else {
// Load the location
Shared::Maps::Map *map = _game->getMap();
map->load(tile._locationNum);
// Add message for location having been entered
addInfoMsg(_game->_res->ENTERING);
addInfoMsg(map->getName());
}
}
void MapOverworld::inform() {
Maps::U1MapTile tile;
getTileAt(getPosition(), &tile, false);
addInfoMsg("");
if (tile._locationNum != -1) {
if (tile._locationNum < 33)
addInfoMsg(Common::String::format("%s %s", _game->_res->THE_CITY_OF, _game->_res->LOCATION_NAMES[tile._locationNum - 1]));
else
addInfoMsg(_game->_res->LOCATION_NAMES[tile._locationNum - 1]);
} else if (tile.isOriginalWater()) {
addInfoMsg(_game->_res->YOU_ARE_AT_SEA);
} else if (tile.isOriginalWoods()) {
addInfoMsg(_game->_res->YOU_ARE_IN_WOODS);
} else {
addInfoMsg(_game->_res->YOU_ARE_IN_LANDS);
addInfoMsg(_game->_res->LAND_NAMES[getLandsNumber()]);
}
}
void MapOverworld::disembark() {
Widgets::Transport *transport = dynamic_cast(_playerWidget);
if (transport) {
addInfoMsg("");
transport->disembark();
} else {
addInfoMsg(_game->_res->WHAT);
}
}
uint MapOverworld::getLandsNumber() const {
Point pt = getPosition();
return (pt.y > 77 ? 2 : 0) + (pt.x > 83 ? 1 : 0);
}
void MapOverworld::addOnFoot() {
_widgets.insert_at(0, Shared::Maps::MapWidgetPtr(new Widgets::TransportOnFoot(_game, this)));
_playerWidget = _widgets[0].get();
}
uint MapOverworld::getEnemyVesselCount() const {
uint total = 0;
for (uint idx = 0; idx < _widgets.size(); ++idx) {
if (dynamic_cast(_widgets[idx].get()))
++total;
}
return total;
}
void MapOverworld::attack(int direction, int effectId, uint maxDistance, uint amount, uint agility, const Common::String &hitWidget) {
}
} // End of namespace Maps
} // End of namespace Ultima1
} // End of namespace Ultima