Initial commit
This commit is contained in:
290
engines/ultima/ultima1/u1gfx/view_game.cpp
Normal file
290
engines/ultima/ultima1/u1gfx/view_game.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima1/u1gfx/view_game.h"
|
||||
#include "ultima/shared/actions/huh.h"
|
||||
#include "ultima/shared/actions/pass.h"
|
||||
#include "ultima/shared/maps/map.h"
|
||||
#include "ultima/ultima1/game.h"
|
||||
#include "ultima/ultima1/u1gfx/drawing_support.h"
|
||||
#include "ultima/ultima1/u1gfx/info.h"
|
||||
#include "ultima/ultima1/u1gfx/status.h"
|
||||
#include "ultima/ultima1/u1gfx/viewport_dungeon.h"
|
||||
#include "ultima/ultima1/u1gfx/viewport_map.h"
|
||||
#include "ultima/ultima1/actions/map_action.h"
|
||||
#include "ultima/ultima1/actions/move.h"
|
||||
#include "ultima/ultima1/actions/attack.h"
|
||||
#include "ultima/ultima1/actions/quit.h"
|
||||
#include "ultima/ultima1/actions/ready.h"
|
||||
#include "ultima/ultima1/actions/stats.h"
|
||||
#include "ultima/ultima1/core/resources.h"
|
||||
#include "ultima/shared/gfx/text_cursor.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima1 {
|
||||
namespace Actions {
|
||||
MAP_ACTION(Board, 1, board)
|
||||
MAP_ACTION(Cast, 2, cast)
|
||||
MAP_ACTION(Drop, 3, drop)
|
||||
MAP_ACTION_END_TURN(Enter, 4, enter)
|
||||
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(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 {
|
||||
|
||||
BEGIN_MESSAGE_MAP(ViewGame, Shared::Gfx::VisualContainer)
|
||||
ON_MESSAGE(ShowMsg)
|
||||
ON_MESSAGE(EndOfTurnMsg)
|
||||
ON_MESSAGE(FrameMsg)
|
||||
ON_MESSAGE(CharacterInputMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
ViewGame::ViewGame(TreeItem *parent) : Shared::Gfx::VisualContainer("Game", Rect(0, 0, 320, 200), parent), _frameCtr(0) {
|
||||
_info = new Info(this);
|
||||
_status = new Status(this);
|
||||
_viewportDungeon = new ViewportDungeon(this);
|
||||
|
||||
Ultima1Game *game = static_cast<Ultima1Game *>(getGame());
|
||||
_viewportMap = new ViewportMap(this);
|
||||
|
||||
_actions.resize(22);
|
||||
_actions[0] = new Actions::Move(this);
|
||||
_actions[1] = new Shared::Actions::Huh(this, game->_res->HUH);
|
||||
_actions[2] = new Actions::Attack(this);
|
||||
_actions[3] = new Actions::Board(this);
|
||||
_actions[4] = new Actions::Cast(this);
|
||||
_actions[5] = new Actions::Drop(this);
|
||||
_actions[6] = new Actions::Enter(this);
|
||||
_actions[7] = new Actions::Fire(this);
|
||||
_actions[8] = new Actions::Get(this);
|
||||
_actions[9] = new Actions::HyperJump(this);
|
||||
_actions[10] = new Actions::Inform(this);
|
||||
_actions[11] = new Actions::Climb(this);
|
||||
_actions[12] = new Actions::Open(this);
|
||||
_actions[13] = new Shared::Actions::Pass(this, game->_res->ACTION_NAMES[15]);
|
||||
_actions[14] = new Actions::Quit(this);
|
||||
_actions[15] = new Actions::Ready(this);
|
||||
_actions[16] = new Actions::Steal(this);
|
||||
_actions[17] = new Actions::Transact(this);
|
||||
_actions[18] = new Actions::Unlock(this);
|
||||
_actions[19] = new Actions::ViewChange(this);
|
||||
_actions[20] = new Actions::ExitTransport(this);
|
||||
_actions[21] = new Actions::Stats(this);
|
||||
}
|
||||
|
||||
ViewGame::~ViewGame() {
|
||||
delete _info;
|
||||
delete _status;
|
||||
delete _viewportDungeon;
|
||||
delete _viewportMap;
|
||||
for (uint idx = 0; idx < _actions.size(); ++idx)
|
||||
delete _actions[idx];
|
||||
}
|
||||
|
||||
void ViewGame::draw() {
|
||||
Shared::Gfx::VisualSurface s = getSurface();
|
||||
|
||||
if (_isDirty) {
|
||||
// Draw the overal frame
|
||||
s.clear();
|
||||
DrawingSupport ds(s);
|
||||
ds.drawGameFrame();
|
||||
drawIndicators();
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
if (_info->isDirty())
|
||||
_info->draw();
|
||||
if (_status->isDirty())
|
||||
_status->draw();
|
||||
|
||||
Maps::Ultima1Map *map = static_cast<Maps::Ultima1Map *>(getGame()->getMap());
|
||||
switch (map->_mapType) {
|
||||
case Maps::MAP_DUNGEON:
|
||||
_viewportDungeon->draw();
|
||||
break;
|
||||
default:
|
||||
_viewportMap->draw();
|
||||
break;
|
||||
}
|
||||
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
void ViewGame::drawIndicators() {
|
||||
Ultima1Game *game = static_cast<Ultima1Game *>(getGame());
|
||||
Maps::Ultima1Map *map = static_cast<Maps::Ultima1Map *>(game->getMap());
|
||||
|
||||
Shared::Gfx::VisualSurface s = getSurface();
|
||||
DrawingSupport ds(s);
|
||||
|
||||
if (map->_mapType == Maps::MAP_DUNGEON) {
|
||||
// Draw the dungeon level indicator
|
||||
ds.drawRightArrow(TextPoint(15, 0));
|
||||
s.writeString(game->_res->DUNGEON_LEVEL, TextPoint(16, 0));
|
||||
s.writeString(Common::String::format("%2d", map->getLevel()), TextPoint(23, 0));
|
||||
ds.drawLeftArrow(TextPoint(26, 0));
|
||||
|
||||
// Draw the current direction
|
||||
const char *dir = game->_res->DIRECTION_NAMES[map->getDirection() - 1];
|
||||
ds.drawRightArrow(TextPoint(16, 19));
|
||||
s.writeString(" ", TextPoint(17, 19));
|
||||
s.writeString(dir, TextPoint(19 - (7 - strlen(dir)) / 2, 19));
|
||||
ds.drawLeftArrow(TextPoint(24, 19));
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewGame::ShowMsg(CShowMsg *msg) {
|
||||
// Set the info area to prompt for a command
|
||||
Shared::CInfoGetCommandKeypress cmdMsg(this);
|
||||
cmdMsg.execute(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewGame::EndOfTurnMsg(CEndOfTurnMsg *msg) {
|
||||
// Set the info area to prompt for the next command
|
||||
Shared::CInfoGetCommandKeypress cmdMsg(this);
|
||||
cmdMsg.execute(this);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define FRAME_REDUCTION_RATE 5
|
||||
|
||||
bool ViewGame::FrameMsg(CFrameMsg *msg) {
|
||||
if (_frameCtr == FRAME_REDUCTION_RATE) {
|
||||
// Ignore frame message at the start of passing reduced frame rate to child views
|
||||
return false;
|
||||
} else if (++_frameCtr == FRAME_REDUCTION_RATE) {
|
||||
msg->execute(this, nullptr, Shared::MSGFLAG_SCAN);
|
||||
_frameCtr = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch action
|
||||
*/
|
||||
template<class T>
|
||||
void dispatchKey(ViewGame *game) {
|
||||
T dMsg;
|
||||
dMsg.execute(game);
|
||||
}
|
||||
#define CHECK(KEYCODE, MSG_CLASS) else if (msg->_keyState.keycode == KEYCODE) { dispatchKey<MSG_CLASS>(this); }
|
||||
|
||||
bool ViewGame::checkMovement(const Common::KeyState &keyState) {
|
||||
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);
|
||||
} else {
|
||||
Shared::CMoveMsg move(Shared::Maps::DIR_LEFT);
|
||||
move.execute(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Shared::Maps::DIR_EAST: {
|
||||
if (keyState.flags & Common::KBD_SHIFT) {
|
||||
Shared::CAttackMsg attack(Shared::Maps::DIR_RIGHT);
|
||||
attack.execute(this);
|
||||
} else {
|
||||
Shared::CMoveMsg move(Shared::Maps::DIR_RIGHT);
|
||||
move.execute(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Shared::Maps::DIR_UP: {
|
||||
if (keyState.flags & Common::KBD_SHIFT) {
|
||||
Shared::CAttackMsg attack(Shared::Maps::DIR_UP);
|
||||
attack.execute(this);
|
||||
} else {
|
||||
Shared::CMoveMsg move(Shared::Maps::DIR_UP);
|
||||
move.execute(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Shared::Maps::DIR_DOWN: {
|
||||
if (keyState.flags & Common::KBD_SHIFT) {
|
||||
Shared::CAttackMsg attack(Shared::Maps::DIR_DOWN);
|
||||
attack.execute(this);
|
||||
} else {
|
||||
Shared::CMoveMsg move(Shared::Maps::DIR_DOWN);
|
||||
move.execute(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewGame::CharacterInputMsg(CCharacterInputMsg *msg) {
|
||||
if (checkMovement(msg->_keyState)) {}
|
||||
CHECK(Common::KEYCODE_a, Shared::CAttackMsg)
|
||||
CHECK(Common::KEYCODE_b, Shared::CBoardMsg)
|
||||
CHECK(Common::KEYCODE_c, Shared::CCastMsg)
|
||||
CHECK(Common::KEYCODE_d, Shared::CDropMsg)
|
||||
CHECK(Common::KEYCODE_e, Shared::CEnterMsg)
|
||||
CHECK(Common::KEYCODE_f, Shared::CFireMsg)
|
||||
CHECK(Common::KEYCODE_g, Shared::CGetMsg)
|
||||
CHECK(Common::KEYCODE_h, Shared::CHyperJumpMsg)
|
||||
CHECK(Common::KEYCODE_i, Shared::CInformMsg)
|
||||
CHECK(Common::KEYCODE_k, Shared::CClimbMsg)
|
||||
CHECK(Common::KEYCODE_o, Shared::COpenMsg)
|
||||
CHECK(Common::KEYCODE_q, Shared::CQuitMsg)
|
||||
CHECK(Common::KEYCODE_r, Shared::CReadyMsg)
|
||||
CHECK(Common::KEYCODE_s, Shared::CStealMsg)
|
||||
CHECK(Common::KEYCODE_t, Shared::CTransactMsg)
|
||||
CHECK(Common::KEYCODE_u, Shared::CUnlockMsg)
|
||||
CHECK(Common::KEYCODE_v, Shared::CViewChangeMsg)
|
||||
CHECK(Common::KEYCODE_x, Shared::CExitTransportMsg)
|
||||
CHECK(Common::KEYCODE_z, Shared::CStatsMsg)
|
||||
CHECK(Common::KEYCODE_SPACE, Shared::CPassMsg)
|
||||
else {
|
||||
// Fallback for unknown key
|
||||
dispatchKey<Shared::CPassMsg>(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace U1Gfx
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
Reference in New Issue
Block a user