Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
/* 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/ultima0/views/acknowledgements.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
static const char *LINES[] = {
"Akalabeth PC-Conversion",
"",
"",
"Written by Richard Garriott",
"",
"",
"",
"PC-Conversion by",
"Corey Roth",
"with special assistance by",
"Nathan Tucker",
"",
"",
"",
"",
"Greets and Thanx go out to",
"Jake Groshong",
"Ronny McCrory",
"Adrian Dilley",
"Russell Kabir",
"James Ashley",
"Chris Harjo",
"and everyone else out there",
"who helped me out",
"",
"",
"",
"",
"This game made possible by:",
"",
"Origin",
"and",
"JUiCEY Bird Productions"
};
bool Acknowledgements::msgFocus(const FocusMessage &msg) {
// Set up the lines to display
_ctr = -1;
_lines.clear();
for (const char *line : LINES)
_lines.push(line);
for (int i = 0; i < 25; ++i)
_lines.push("");
auto s = getSurface();
s.clear();
// Create a buffer for rendering new lines
_pendingLine.create(s.w, Gfx::GLYPH_HEIGHT);
return true;
}
void Acknowledgements::draw() {
auto s = getSurface();
// Shift up by one line
s.blitFrom(s, Common::Rect(0, 1, s.w, s.h), Common::Point(0, 0));
s.blitFrom(_pendingLine, Common::Rect(0, 0, _pendingLine.w, 1),
Common::Point(0, s.h - 1));
_pendingLine.blitFrom(_pendingLine, Common::Rect(0, 1, s.w, Gfx::GLYPH_HEIGHT),
Common::Point(0, 0));
}
bool Acknowledgements::tick() {
_ctr = (_ctr + 1) % Gfx::GLYPH_HEIGHT;
if (_ctr == 0) {
if (_lines.empty()) {
showTitle();
} else {
Common::String line = _lines.pop();
_pendingLine.writeString(Common::Point(20, 0), line, Graphics::kTextAlignCenter);
}
}
redraw();
return View::tick();
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,66 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_ACKNOWLEDGEMENTS_H
#define ULTIMA0_VIEWS_ACKNOWLEDGEMENTS_H
#include "common/queue.h"
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Acknowledgements : public View {
private:
Common::Queue<Common::String> _lines;
Gfx::GfxSurface _pendingLine;
int _ctr = 0;
void showTitle() {
replaceView("Title");
}
public:
Acknowledgements() : View("Acknowledgements") {}
~Acknowledgements() override {}
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool tick() override;
bool msgKeypress(const KeypressMessage &msg) override {
showTitle();
return true;
}
bool msgMouseDown(const MouseDownMessage &msg) override {
showTitle();
return true;
}
bool msgAction(const ActionMessage &msg) override {
showTitle();
return true;
}
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,330 @@
/* 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/ultima0/views/attack.h"
#include "ultima/ultima0/data/data.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Attack::Attack() : View("Attack") {
setBounds(Gfx::TextRect(1, 22, 26, 24));
}
bool Attack::msgFocus(const FocusMessage &msg) {
_mode = WHICH_WEAPON;
_message = "";
MetaEngine::setKeybindingMode(KBMODE_MENUS);
return true;
}
bool Attack::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
return true;
}
void Attack::draw() {
auto s = getSurface();
s.clear();
if (_mode == AMULET) {
s.writeString(Common::Point(0, 0), "1] Ladder Up");
s.writeString(Common::Point(0, 1), "2] Ladder Down");
s.writeString(Common::Point(0, 2), "3] Attack Monster");
s.writeString(Common::Point(0, 3), "4] Bad Magic");
return;
}
s.writeString(Common::Point(1, 1), "Which Weapon? ");
if (_mode != WHICH_WEAPON)
s.writeString(_weapon <= 0 ? "Hands" : OBJECT_INFO[_weapon]._name);
if (!_message.empty())
s.writeString(Common::Point(1, 2), _message);
}
bool Attack::msgKeypress(const KeypressMessage &msg) {
if (_mode == WHICH_WEAPON) {
selectObject(-1);
return true;
}
return false;
}
bool Attack::msgAction(const ActionMessage &msg) {
int objNum;
switch (_mode) {
case WHICH_WEAPON:
// Check for object selection, anything but food
objNum = -1;
for (uint i = OB_RAPIER; i < MAX_OBJ; ++i) {
if (msg._action == OBJECT_INFO[i]._action) {
objNum = i;
break;
}
}
selectObject(objNum);
break;
case AMULET:
if (msg._action >= KEYBIND_AMULET1 && msg._action <= KEYBIND_AMULET4) {
selectMagic(msg._action - KEYBIND_AMULET1);
}
break;
case THROW_SWING:
if (msg._action == KEYBIND_THROW) {
_message += "Throw\n";
attackMissile();
} else if (msg._action == KEYBIND_SWING) {
_message += "Swing\n";
attackWeapon();
}
break;
default:
break;
}
return true;
}
void Attack::selectObject(int objNum) {
auto &player = g_engine->_player;
_weapon = objNum;
_damage = (objNum <= 0) ? 0 : OBJECT_INFO[objNum]._maxDamage;
// Must own an object
if (player._object[_weapon] == 0) {
showMessage("Not owned.");
return;
}
// Mages are limited
if (player._class == 'M' && (objNum == OB_BOW || objNum == OB_RAPIER)) {
showMessage("Mages can't use that.");
return;
}
// Use an amulet
if (objNum == OB_AMULET) {
if (player._class == 'M') {
// Mages can properly select the magic to use
_mode = AMULET;
// Amulet selection requires all four lines
_bounds = Gfx::TextRect(0, 22, 26, 24);
redraw();
} else {
// Fighters get a random effect
selectMagic(g_engine->getRandomNumber(3));
}
return;
}
if (objNum == OB_BOW) {
attackMissile();
} else if (objNum == OB_AXE) {
_mode = THROW_SWING;
_message += "Throw or Swing ? ";
redraw();
} else {
attackWeapon();
}
}
void Attack::selectMagic(int magicNum) {
auto &dungeon = g_engine->_dungeon;
auto &player = g_engine->_player;
int i;
// Last charge?
Common::String msg;
if (urand() % 5 == 0) {
msg = "Last charge on this Amulet.\n";
player._object[OB_AMULET]--;
}
switch (magicNum) {
case 0:
// Ladder up
dungeon._map[player._dungeonPos.x][player._dungeonPos.y] = DT_LADDERUP;
break;
case 1:
// Ladder down
dungeon._map[player._dungeonPos.x][player._dungeonPos.y] = DT_LADDERDN;
break;
case 2:
// Amulet Attack
attackMissile();
break;
case 3:
// Bad Magic
switch (urand() % 3) {
case 0:
msg += "You have been turned into a Toad.\n";
for (i = AT_STRENGTH; i <= AT_WISDOM; i++)
player._attr[i] = 3;
break;
case 1:
msg += "You have been turned into a Lizard Man.\n";
for (i = AT_HP; i <= AT_WISDOM; i++)
player._attr[i] = floor(player._attr[i] * 5 / 2);
break;
case 2:
msg += "Backfire !!\n";
player._attr[AT_HP] = floor(player._attr[AT_HP]) / 2;
break;
}
break;
}
if (msg.empty()) {
timeout();
} else {
redraw();
delaySeconds(1);
}
}
void Attack::attackMissile() {
const auto &dungeon = g_engine->_dungeon;
auto &player = g_engine->_player;
Common::Point c1, c = player._dungeonPos;
int Dist = -1;
// A maximum distance of 5
for (int y = 0; y < 5; y++) {
c += player._dungeonDir;
int n = dungeon.findMonster(c); // Monster there ?
if (n >= 0) {
c1 = c;
Dist = n;
}
// If wall, or door, stop
if (!ISDRAWOPEN(dungeon._map[c.x][c.y]))
break;
}
if (Dist < 0) {
// Hit nothing
_message += "You missed !!\n";
_mode = DONE;
delaySeconds(1);
} else {
attackHitMonster(c1);
}
}
void Attack::attackWeapon() {
const auto &player = g_engine->_player;
Common::Point c = player._dungeonPos + player._dungeonDir;
attackHitMonster(c);
}
void Attack::attackHitMonster(const Common::Point &c) {
auto &player = g_engine->_player;
auto &dungeon = g_engine->_dungeon;
int n = 0, monNum, damage;
MonsterEntry *m = nullptr;
// Is there a monster there ?
monNum = dungeon.findMonster(c);
if (monNum >= 0) {
// Set up a pointer
m = &dungeon._monsters[monNum];
n = m->_type;
}
// Get weaponry info
damage = 0;
if (_weapon >= 0 && _weapon != OB_AMULET)
damage = OBJECT_INFO[_weapon]._maxDamage;
if (_weapon == OB_AMULET)
// Amulet Special Case
damage = 10 + player._level;
// If no, or not dexterous
if (monNum < 0 || player._attr[AT_DEXTERITY] - ((int)urand() % 25) < n + player._level) {
// Then a miss.
_message += "\nMissed!";
_mode = DONE;
redraw();
delaySeconds(1);
return;
}
// Scored a hit
_message += "Hit !!!\n";
// Calculate HPs lost
n = 0;
if (damage > 0)
n = (urand() % damage);
n = n + player._attr[AT_STRENGTH] / 5;
m->_strength = m->_strength - n; // Lose them
if (m->_strength < 0)
m->_strength = 0;
_message += Common::String::format("%s's Hit\nPoints now %d.\n",
MONSTER_INFO[m->_type]._name, m->_strength);
// Killed it ?
if (m->_strength == 0) {
m->_alive = false; // It has ceased to be
int gold = (m->_type + player._level); // Amount of gold
_message += Common::String::format("You get %d pieces of eight.\n", gold);
player._attr[AT_GOLD] += gold;
player._hpGain += (m->_type * player._level) / 2; // Calculate Gain
if (m->_type == player._task) // Check done LB's task
player._taskCompleted = true;
}
_mode = DONE;
redraw();
delaySeconds(1);
}
void Attack::showMessage(const Common::String &msg) {
_message = msg;
_mode = DONE;
redraw();
delaySeconds(1);
}
void Attack::timeout() {
close();
g_events->send("Dungeon", GameMessage("ENDOFTURN"));
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,66 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_ATTACK_H
#define ULTIMA0_VIEWS_ATTACK_H
#include "ultima/ultima0/views/view.h"
#include "ultima/ultima0/data/data.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Attack : public View {
private:
enum Mode {
WHICH_WEAPON, AMULET, THROW_SWING, DONE
};
Mode _mode = WHICH_WEAPON;
int _weapon = -1;
int _damage = 0;
Common::String _message;
void selectObject(int objNum);
void selectMagic(int magicNum);
void attackMissile();
void attackWeapon();
void attackHitMonster(const Common::Point &c);
void showMessage(const Common::String &msg);
public:
Attack();
~Attack() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
void timeout() override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,218 @@
/* 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/ultima0/views/castle.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
static const char *GO_FORTH = " Go now upon this quest, and may\n"
"Lady Luck be fair unto you.....\n"
".....Also I, British, have increased\n"
"each of thy attributes by one.!";
bool Castle::msgFocus(const FocusMessage &msg) {
const auto &player = g_engine->_player;
if (Common::String(player._name).empty())
_mode = NAMING;
else if (player._taskCompleted) {
_mode = TASK_COMPLETE;
} else {
_mode = TASK_INCOMPLETE;
}
g_engine->playMidi("lordbrit.mid");
return true;
}
bool Castle::msgUnfocus(const UnfocusMessage &msg) {
g_engine->stopMidi();
return true;
}
void Castle::draw() {
auto s = getSurface();
s.clear();
if (_mode <= FIRST_TASK) {
firstTime();
} else if (_mode == TASK_COMPLETE) {
taskCompleted();
} else if (_mode == TASK_INCOMPLETE) {
taskIncomplete();
}
}
void Castle::firstTime() {
auto s = getSurface();
const auto &player = g_engine->_player;
if (_mode >= NAMING && _mode <= FIRST_TASK) {
s.writeString(Common::Point(5, 2), "Welcome Peasant into the halls of\n"
"the mighty Lord British. Herein thou\n"
"may choose to dare battle with the\n"
"evil creatures of the depths, for\n"
"great reward!\n\n"
"What is thy name peasant? ");
s.setColor(C_GREY);
s.writeString(_playerName);
s.setColor(C_TEXT_DEFAULT);
}
if (_mode >= GRAND_ADVENTURE && _mode <= FIRST_TASK)
s.writeString(Common::Point(0, 10), "Doest thou wish for great adventure ?\n\n");
if (_mode == BEGONE) {
s.writeString("Then leave and begone!");
} else if (_mode == FIRST_TASK) {
s.writeString("Good! Thou shalt try to become a\nKnight!!!\n\n"
"Thy first task is to go into the\n"
"dungeons and to return only after\n"
"killing ");
s.setColor(C_VIOLET);
s.writeString(getTaskName(player._task));
pressAnyKey();
}
}
void Castle::taskCompleted() {
auto &player = g_engine->_player;
auto s = getSurface();
s.writeString(Common::Point(0, 3), "Aaaahhhh.... ");
s.writeString(player._name);
s.writeString("\n\nThou has accomplished\nthy quest.\n\n");
if (player._task == MAX_MONSTERS) {
s.writeString("Thou hast proved thyself worthy of\n"
"Knighthood, continue if thou doth wish\n"
"but thou hast accomplished the\n"
"main objective of the game.\n\n"
"Now, maybe thou art foolhardy enough to\n"
"try difficulty level ");
s.writeString(Common::String::format("%d.", player._skill + 1));
} else {
// LB gives you extra attributes
for (int i = 0; i < MAX_ATTR; i++)
player._attr[i]++;
// Choose the next task
nextTask();
s.writeString("Unfortunately, this is not enough to\n"
"become a knight.\n\n");
s.writeString("Thou must now kill ");
s.setColor(C_VIOLET);
s.writeString(getTaskName(player._task));
s.setColor(C_TEXT_DEFAULT);
s.writeString("\n\n");
s.writeString(GO_FORTH);
pressAnyKey();
}
}
void Castle::taskIncomplete() {
const auto &player = g_engine->_player;
auto s = getSurface();
s.writeString(Common::Point(0, 3),
"Why hast thou returned ?\n"
"Thou must kill ");
s.setColor(C_VIOLET);
s.writeString(getTaskName(player._task));
s.setColor(C_TEXT_DEFAULT);
s.writeString("\n\nGo now and complete thy quest");
}
void Castle::pressAnyKey() {
auto s = getSurface();
s.writeString(Common::Point(20, 23), "Press any Key to Continue",
Graphics::kTextAlignCenter);
}
bool Castle::msgKeypress(const KeypressMessage &msg) {
auto &player = g_engine->_player;
switch (_mode) {
case NAMING:
if (msg.keycode == Common::KEYCODE_BACKSPACE && !_playerName.empty()) {
_playerName.deleteLastChar();
} else if (msg.keycode == Common::KEYCODE_RETURN && !_playerName.empty()) {
Common::strcpy_s(player._name, _playerName.c_str());
_mode = GRAND_ADVENTURE;
} else if (Common::isAlpha(msg.ascii) && _playerName.size() < MAX_NAME) {
_playerName += msg.ascii;
}
redraw();
break;
case GRAND_ADVENTURE:
if (msg.keycode == Common::KEYCODE_y) {
nextTask();
_mode = FIRST_TASK;
} else if (msg.keycode == Common::KEYCODE_n) {
_mode = BEGONE;
}
redraw();
break;
default:
// All other modes exit the castle
replaceView("WorldMap");
break;
}
return true;
}
bool Castle::msgAction(const ActionMessage &msg) {
if (_mode >= FIRST_TASK) {
replaceView("WorldMap");
}
return true;
}
void Castle::nextTask() {
auto &player = g_engine->_player;
player._task = CLIP(player._attr[AT_WISDOM] / 3, 1, 10);
player._taskCompleted = false;
}
Common::String Castle::getTaskName(int taskNum) const {
Common::String mons = MONSTER_INFO[taskNum]._name;
return Common::String::format("%s %s",
strchr("aeiou", tolower(mons.firstChar())) != nullptr ? "an" : "a",
mons.c_str());
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,61 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_CASTLE_H
#define ULTIMA0_VIEWS_CASTLE_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Castle : public View {
private:
enum Mode {
NAMING, GRAND_ADVENTURE, BEGONE, FIRST_TASK, TASK_COMPLETE, TASK_INCOMPLETE
};
Mode _mode = NAMING;
Common::String _playerName;
void firstTime();
void taskCompleted();
void taskIncomplete();
void nextTask();
void pressAnyKey();
Common::String getTaskName(int taskNum) const;
public:
Castle() : View("Castle") {}
~Castle() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,136 @@
/* 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/ultima0/views/create_character.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
bool CreateCharacter::msgFocus(const FocusMessage &msg) {
g_engine->_player.init();
_mode = LUCKY_NUMBER;
_input = "";
return true;
}
void CreateCharacter::draw() {
auto s = getSurface();
const auto &player = g_engine->_player;
s.clear();
// Lucky number
s.writeString(Common::Point(1, 4), "Type thy Lucky Number.....");
if (_mode == LUCKY_NUMBER)
s.writeString(_input);
else
s.writeString(Common::String::format("%d", player._luckyNumber));
// Level of play
if (_mode >= LEVEL) {
s.writeString(Common::Point(1, 6), "Level of play (1-10)......");
if (_mode == LEVEL)
s.writeString(_input);
else
s.writeString(Common::String::format("%d", player._skill));
}
// Stats
if (_mode >= STATS) {
for (int i = 0; i < MAX_ATTR; ++i) {
Common::String line = ATTRIB_NAMES[i];
while (line.size() < 15)
line += ".";
line += Common::String::format("%d", player._attr[i]);
s.writeString(Common::Point(1, 9 + i), line);
}
s.writeString(Common::Point(0, 16), "Shallt thou play with these qualities?");
}
// Class selection
if (_mode == CLASS) {
s.writeString(Common::Point(0, 18), "And shalt thou be a Fighter or a Mage?");
}
}
bool CreateCharacter::msgKeypress(const KeypressMessage &msg) {
auto &player = g_engine->_player;
if (_mode == LUCKY_NUMBER || _mode == LEVEL) {
if (Common::isDigit(msg.ascii) && _input.size() < 6) {
_input += msg.ascii;
redraw();
} else if (msg.keycode == Common::KEYCODE_BACKSPACE && _input.size() > 0) {
_input.deleteLastChar();
redraw();
} else if (msg.keycode == Common::KEYCODE_RETURN && !_input.empty()) {
if (_mode == LUCKY_NUMBER) {
player._luckyNumber = atoi(_input.c_str());
_input.clear();
_mode = LEVEL;
redraw();
} else {
player._skill = atoi(_input.c_str());
if (player._skill >= 1 && player._skill <= 10) {
_input.clear();
_mode = STATS;
player.rollAttributes();
redraw();
}
}
}
} else if (msg.keycode == Common::KEYCODE_y) {
_mode = CLASS;
redraw();
} else if (msg.keycode == Common::KEYCODE_n) {
player.rollAttributes();
redraw();
} else if (_mode == CLASS && (msg.keycode == Common::KEYCODE_f ||
msg.keycode == Common::KEYCODE_m)) {
player._class = toupper(msg.ascii);
characterDone();
}
return true;
}
bool CreateCharacter::msgAction(const ActionMessage &msg) {
if (msg._action == KEYBIND_ESCAPE) {
replaceView("Title");
return true;
}
return true;
}
void CreateCharacter::characterDone() {
// Generate the world map
g_engine->_worldMap.init(g_engine->_player);
// Enter the town
replaceView("Town");
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_CREATE_CHARACTER_H
#define ULTIMA0_VIEWS_CREATE_CHARACTER_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class CreateCharacter : public View {
private:
enum Mode { LUCKY_NUMBER, LEVEL, STATS, CLASS };
Mode _mode = LUCKY_NUMBER;
Common::String _input;
void characterDone();
public:
CreateCharacter() : View("CreateCharacter") {}
~CreateCharacter() override {}
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,51 @@
/* 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/ultima0/views/dead.h"
#include "ultima/ultima0/gfx/font.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Dead::Dead() : View("Dead") {
setBounds(Common::Rect(0, DEFAULT_SCY - 4 * Gfx::GLYPH_HEIGHT, DEFAULT_SCX, DEFAULT_SCY));
}
void Dead::draw() {
const auto &player = g_engine->_player;
auto s = getSurface();
s.clear();
const char *name = player._name;
if (*name == '\0')
name = "the peasant";
s.writeString(Common::Point(20, 0), "We mourn the passing of", Graphics::kTextAlignCenter);
s.writeString(Common::Point(20, 1), Common::String::format("%s and his Computer", name), Graphics::kTextAlignCenter);
s.writeString(Common::Point(20, 2), "To invoke a miracle of resurrection", Graphics::kTextAlignCenter);
s.writeString(Common::Point(20, 3), "Press a Key", Graphics::kTextAlignCenter);
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_DEAD_H
#define ULTIMA0_VIEWS_DEAD_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Dead : public View {
private:
void showTitle() {
replaceView("Title");
}
public:
Dead();
~Dead() override {}
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override {
showTitle();
return true;
}
bool msgMouseDown(const MouseDownMessage &msg) override {
showTitle();
return true;
}
bool msgAction(const ActionMessage &msg) override {
showTitle();
return true;
}
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,300 @@
/* 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/ultima0/views/dungeon.h"
#include "ultima/ultima0/ultima0.h"
#include "ultima/ultima0/metaengine.h"
#include "ultima/ultima0/gfx/font.h"
#include "ultima/ultima0/gfx/dungeon.h"
#include "ultima/ultima0/data/monster_logic.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Dungeon::Dungeon() : View("Dungeon") {
}
bool Dungeon::msgFocus(const FocusMessage &msg) {
showMessage("");
showLines("");
MetaEngine::setKeybindingMode(KBMODE_DUNGEONS);
if (!g_engine->isMidiPlaying())
g_engine->playMidi("dungeon.mid");
return true;
}
bool Dungeon::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
return true;
}
void Dungeon::draw() {
auto s = getSurface();
s.clear();
// Draw the dungeon view
Graphics::ManagedSurface dungArea(s, Common::Rect(0, 0, s.w, s.h - Gfx::GLYPH_HEIGHT * 4));
Gfx::Dungeon::draw(&dungArea);
// Allow the status area to draw
View::draw();
if (g_engine->_showMinimap) {
s.frameRect(Common::Rect(s.w - DUNGEON_MINIMAP_SIZE - 4, 0, s.w, DUNGEON_MINIMAP_SIZE + 4), C_GREY);
s.frameRect(Common::Rect(s.w - DUNGEON_MINIMAP_SIZE - 3, 1, s.w - 1, DUNGEON_MINIMAP_SIZE + 3), C_GREY);
Graphics::ManagedSurface minimapArea(s, Common::Rect(s.w - DUNGEON_MINIMAP_SIZE - 2, 2, s.w - 2, DUNGEON_MINIMAP_SIZE + 2));
drawMinimap(minimapArea);
}
}
void Dungeon::drawMinimap(Graphics::ManagedSurface &mapArea) {
const auto &player = g_engine->_player;
const auto &dungeon = g_engine->_dungeon;
int tile;
for (int y = 0; y < DUNGEON_MAP_SIZE; ++y) {
for (int x = 0; x < DUNGEON_MAP_SIZE; ++x) {
const Common::Rect r(x * MINIMAP_TILE_SIZE, y * MINIMAP_TILE_SIZE,
(x + 1) * MINIMAP_TILE_SIZE, (y + 1) * MINIMAP_TILE_SIZE);
if (x == player._dungeonPos.x && y == player._dungeonPos.y) {
mapArea.fillRect(r, C_CYAN);
} else if (dungeon.findMonster(Common::Point(x, y)) >= 0) {
mapArea.fillRect(r, C_RED);
} else {
tile = dungeon._map[x][y];
if (tile == DT_SPACE || tile == DT_DOOR || tile == DT_HIDDENDOOR)
mapArea.fillRect(r, C_BLACK);
else if (tile == DT_SOLID)
mapArea.fillRect(r, C_WHITE);
else if (tile == DT_LADDERUP || tile == DT_LADDERDN)
mapArea.fillRect(r, C_GREEN);
else
mapArea.fillRect(r, C_ROSE);
}
}
}
}
bool Dungeon::msgAction(const ActionMessage &msg) {
auto &player = g_engine->_player;
if (isDelayActive())
return false;
switch (msg._action) {
case KEYBIND_UP:
showMessage("Move Forward");
moveForward();
break;
case KEYBIND_DOWN:
showMessage("Turn Around");
player.dungeonTurnLeft();
player.dungeonTurnLeft();
break;
case KEYBIND_LEFT:
showMessage("Turn Left");
player.dungeonTurnLeft();
break;
case KEYBIND_RIGHT:
showMessage("Turn Right");
player.dungeonTurnRight();
break;
case KEYBIND_INFO:
// Show character info screen
showMessage("");
replaceView("Info");
break;
case KEYBIND_ENTER:
interact();
break;
case KEYBIND_PASS:
showMessage("");
break;
case KEYBIND_ATTACK:
showMessage(" \x9""Attack!");
_status.draw(); // Render the message before we switch views
addView("Attack");
break;
case KEYBIND_QUIT:
// "Quit" in the original which merely saves the game. For ScummVM,
// we open the GMM, allowing the user to either save or quit
g_engine->openMainMenuDialog();
return true;
case KEYBIND_MINIMAP:
g_engine->_showMinimap = !g_engine->_showMinimap;
redraw();
break;
default:
showMessage("Huh???");
break;
}
endOfTurn();
return true;
}
bool Dungeon::msgKeypress(const KeypressMessage &msg) {
if (isDelayActive())
return false;
showMessage("Huh???");
endOfTurn();
return true;
}
void Dungeon::endOfTurn() {
auto &player = g_engine->_player;
auto &dungeon = g_engine->_dungeon;
if (player._attr[AT_HP] <= 0) {
g_engine->stopMidi();
replaceView("Dead");
return;
}
// Check for monster attacks
MonsterLogic::checkForAttacks(player, dungeon);
player._object[OB_FOOD] = MAX(player._object[OB_FOOD] - 0.1, 0.0);
if (player._object[OB_FOOD] == 0) {
showMessage("You have starved...");
g_engine->stopMidi();
delaySeconds(1);
}
redraw();
}
void Dungeon::moveForward() {
auto &dungeon = g_engine->_dungeon;
auto &player = g_engine->_player;
Common::Point newPos = player._dungeonPos + player._dungeonDir;
if (!ISWALKTHRU(dungeon._map[newPos.x][newPos.y]) || dungeon.findMonster(newPos) >= 0)
return;
// Set new position
player._dungeonPos = newPos;
// What's here ?
int n = dungeon._map[player._dungeonPos.x][player._dungeonPos.y];
if (n == DT_PIT) {
// Fell in a pit
player._level++; // Down a level
showMessage("Aaarrrgghhh! A Trap !");
showLines(Common::String::format("Falling to Level %d.", player._level));
player._attr[AT_HP] -= (3 + urand() % (3 * player._level));
dungeon.create(player); // Create the new level
} else if (n == DT_GOLD) {
// Gold here
// Remove the gold
dungeon._map[player._dungeonPos.x][player._dungeonPos.y] = DT_SPACE;
int gold = (urand() % (5 * player._level)) + player._level; // Calculate amount
showMessage("Gold !!!!!");
Common::String msg = Common::String::format("%d pieces of eight ", gold);
player._attr[AT_GOLD] = MIN<int>(player._attr[AT_GOLD] + gold, 9999); // Add to total
if (gold > 0) {
int objNum = urand() % MAX_OBJ; // Decide which object
const char *name = OBJECT_INFO[objNum]._name;
const char *prefix = "a"; // Decide a,an or some
if (strchr("aeiou", tolower(*name)))
prefix = "an";
if (objNum == 0)
prefix = "some";
msg += Common::String::format("\nand %s %s.", prefix, name);
player._object[objNum] = MIN<int>(player._object[objNum] + 1, 9999); // Bump the total
}
showLines(msg);
}
}
void Dungeon::interact() {
auto &dungeon = g_engine->_dungeon;
auto &player = g_engine->_player;
// Identify what's there
int t = dungeon._map[player._dungeonPos.x][player._dungeonPos.y];
bool done = false;
if (t == DT_LADDERUP) {
// Climbing up a ladder
player._level--;
done = true;
if (player._level == 0) {
showMessage("Leave Dungeon.");
if (player._hpGain > 0)
showLines(Common::String::format("Thou has gained %d HP", player._hpGain));
player._attr[AT_HP] += player._hpGain;
player._hpGain = 0;
delaySeconds(1); // Brief delay to show text before leaving dungeon
} else {
showMessage("Use Ladder");
showLines(Common::String::format("Go up to Level %d.", player._level));
}
} else if (t == DT_LADDERDN) {
// Climbing down a ladder
player._level++;
done = true;
showMessage("Use Ladder");
showLines(Common::String::format("Go down to Level %d.\n", player._level));
}
if (done) {
if (player._level > 0)
// New Dungeon Map Required
dungeon.create(player);
} else {
showMessage("Huh???");
}
}
bool Dungeon::msgGame(const GameMessage &msg) {
if (msg._name == "ENDOFTURN") {
endOfTurn();
return true;
}
return false;
}
void Dungeon::timeout() {
const auto &player = g_engine->_player;
g_engine->stopMidi();
replaceView((player._level == 0) ? "WorldMap" : "Dead");
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,64 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_DUNGEON_H
#define ULTIMA0_VIEWS_DUNGEON_H
#include "ultima/ultima0/views/view.h"
#include "ultima/ultima0/views/status.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Dungeon : public View {
private:
DungeonStatus _status = DungeonStatus(this);
void drawMinimap(Graphics::ManagedSurface &mapArea);
void moveForward();
void interact();
void endOfTurn();
void showMessage(const Common::String &msg) {
_status.send(GameMessage("MSG", msg));
}
void showLines(const Common::String &msg) {
_status.send(GameMessage("LINES", msg));
}
public:
Dungeon();
~Dungeon() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
void timeout() override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,146 @@
/* 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/ultima0/views/info.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Info::Info(const char *viewName) : View(viewName) {
}
bool Info::msgFocus(const FocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MENUS);
return true;
}
bool Info::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
return true;
}
void Info::draw() {
const auto &player = g_engine->_player;
auto s = getSurface();
int i;
s.clear();
View::draw();
// Stats
for (i = 0; i < MAX_ATTR; ++i) {
Common::String line = ATTRIB_NAMES[i];
while (line.size() < 15)
line += '.';
s.writeString(Common::Point(0, 4 + i), line);
}
// Price/Damage/Item
for (i = 0; i < MAX_OBJ; ++i) {
s.writeString(Common::Point(5, 18 + i),
Common::String::format("%d", OBJECT_INFO[i]._cost));
if (i == 0) {
s.writeString(" For 10");
s.writeString(Common::Point(15, 18 + i), "N/A");
} else if (i == 5) {
s.writeString(Common::Point(15, 18 + i), "?????");
} else {
s.writeString(Common::Point(15, 18 + i),
Common::String::format("1-%d", OBJECT_INFO[i]._maxDamage));
}
s.writeString(Common::Point(25, 18 + i), OBJECT_INFO[i]._name);
}
// Headers
s.setColor(255, 0, 128);
s.writeString(Common::Point(6, 2), "Stat's");
s.writeString(Common::Point(21, 2), "Weapons");
s.writeString(Common::Point(5, 16), "Price Damage Item");
// Amounts
s.setColor(C_VIOLET);
for (i = 0; i < MAX_ATTR; ++i)
s.writeString(Common::Point(15, 4 + i),
Common::String::format("%d", player._attr[i]));
for (i = 0; i < MAX_OBJ; ++i)
s.writeString(Common::Point(21, 4 + i),
Common::String::format("%4d-", (int)player._object[i]));
s.writeString(Common::Point(18, 10), "Q-Quit");
}
void Info::leave() {
const auto &player = g_engine->_player;
replaceView(player._level == 0 ? "WorldMap" : "DungeonMap");
}
bool Info::msgAction(const ActionMessage &msg) {
if (isDelayActive())
return false;
if (msg._action == KEYBIND_ESCAPE || msg._action == KEYBIND_QUIT) {
leave();
return true;
}
for (int i = 0; i < MAX_OBJ; ++i) {
if (msg._action == OBJECT_INFO[i]._action) {
selectObject(i);
return true;
}
}
return false;
}
bool Info::msgGame(const GameMessage &msg) {
if (msg._name == "SELECTION") {
selectObject(msg._value);
return true;
}
return false;
}
/*-------------------------------------------------------------------*/
Info::InfoObject::InfoObject(Info *parent, const Common::Point &pt, int id,
const Common::String &text) :
UIElement("InfoObject", parent), _id(id), _text(text) {
setBounds(Gfx::TextRect(pt.x, pt.y, pt.x + text.size(), pt.y));
}
void Info::InfoObject::draw() {
auto s = getSurface();
s.writeString(_text);
}
bool Info::InfoObject::msgMouseDown(const MouseDownMessage &msg) {
_parent->send(GameMessage("SELECTION", _id));
return true;
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,73 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_INFO_H
#define ULTIMA0_VIEWS_INFO_H
#include "ultima/ultima0/views/view.h"
#include "ultima/ultima0/data/data.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Info : public View {
class InfoObject : public UIElement {
public:
Common::String _text;
int _id;
public:
InfoObject(Info *parent, const Common::Point &pt, int id, const Common::String &text);
void draw() override;
bool msgMouseDown(const MouseDownMessage &msg) override;
};
private:
InfoObject _options[6] = {
InfoObject(this, Common::Point(26, 4), 0, OBJECT_INFO[0]._name),
InfoObject(this, Common::Point(26, 5), 1, OBJECT_INFO[1]._name),
InfoObject(this, Common::Point(26, 6), 2, OBJECT_INFO[2]._name),
InfoObject(this, Common::Point(26, 7), 3, OBJECT_INFO[3]._name),
InfoObject(this, Common::Point(26, 8), 4, OBJECT_INFO[4]._name),
InfoObject(this, Common::Point(26, 9), 5, OBJECT_INFO[5]._name)
};
protected:
virtual void selectObject(int item) {
}
virtual void leave();
public:
Info(const char *viewName = "Info");
~Info() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,124 @@
/* 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/ultima0/views/intro.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
bool Intro::msgFocus(const FocusMessage &msg) {
_page = 0;
return true;
}
void Intro::draw() {
auto s = getSurface();
s.clear();
switch (_page) {
case 0:
s.writeString(Common::Point(5, 1), "Many, many, many years ago the");
s.writeString(Common::Point(0, 3), "Dark Lord Mondain, Archfoe of British,");
s.writeString(Common::Point(0, 5), "traversed the lands of Akalabeth,");
s.writeString(Common::Point(0, 7), "spreading evil and death as he passed.");
s.writeString(Common::Point(0, 9), "By the time Mondain was driven from the");
s.writeString(Common::Point(0, 11), "land by British, bearer of the White");
s.writeString(Common::Point(0, 13), "Light, he had done much damage unto");
s.writeString(Common::Point(0, 15), "the lands.");
s.writeString(Common::Point(0, 17), "`Tis thy duty to help rid Akalabeth of");
s.writeString(Common::Point(0, 19), "the foul beasts which infest it,");
s.writeString(Common::Point(0, 21), "while trying to stay alive!!!");
break;
case 1:
s.writeString(Common::Point(0, 0), "The Player's Stats:");
s.writeString(Common::Point(0, 2), "Hit Points- Amount of Damage a Player");
s.writeString(Common::Point(0, 4), " can absorb before Death");
s.writeString(Common::Point(0, 6), "Strength--- Related to Damage Inflicted");
s.writeString(Common::Point(0, 8), " by Player against Monsters.");
s.writeString(Common::Point(0, 10), "Dexterity-- Related to the Probability");
s.writeString(Common::Point(0, 12), " of a Player hitting a Monst.");
s.writeString(Common::Point(0, 14), "Stamina---- Related to Player Defense");
s.writeString(Common::Point(0, 16), " against Monsters");
s.writeString(Common::Point(0, 18), "Wisdom----- This Attribute is used");
s.writeString(Common::Point(0, 20), " in Special (Quest!) Routines");
s.writeString(Common::Point(0, 22), "Gold------- Money!! Cash!! Assets!!");
break;
case 2:
s.writeString(Common::Point(0, 0), "The Towns and Buying Items:");
s.writeString(Common::Point(0, 2), " To buy any items one need only");
s.writeString(Common::Point(0, 4), "type the first letter of the item");
s.writeString(Common::Point(0, 6), "wanted. The cost of the respective");
s.writeString(Common::Point(0, 8), "items is displayed while in the town.");
s.writeString(Common::Point(0, 10), "The Game is started in a town somewhere");
s.writeString(Common::Point(0, 12), "on the 20x20 map");
s.writeString(Common::Point(20, 14), "Fighters and Magi", Graphics::kTextAlignCenter);
s.writeString(Common::Point(0, 16), " The disadvantage of being a");
s.writeString(Common::Point(0, 18), "fighter is the lack of the ability to");
s.writeString(Common::Point(0, 20), "control the magic amulet, whereas magi");
s.writeString(Common::Point(0, 22), "can not use rapier and bows.");
break;
case 3:
s.writeString(Common::Point(1, 0), "Movement:");
s.writeString(Common::Point(1, 2), "-Key- Outdoors Dungeon");
s.writeString(Common::Point(1, 4), " UP Move North Move Forward");
s.writeString(Common::Point(1, 6), " LEFT Move West Turn Left");
s.writeString(Common::Point(1, 8), "RIGHT Move East Turn Right");
s.writeString(Common::Point(1, 10), " DOWN Move South Turn Around");
s.writeString(Common::Point(1, 12), " Z Statistics Statistics");
s.writeString(Common::Point(1, 14), " A N/A Attack");
s.writeString(Common::Point(1, 16), " P Pause Pause");
s.writeString(Common::Point(1, 18), " E Go Into Town Climb Ladder");
s.writeString(Common::Point(1, 20), " E Go Castle Go Hole");
s.writeString(Common::Point(1, 22), "SPACE Pass Pass");
break;
case 4:
s.writeString(Common::Point(0, 2), " Thou doest know the basics of");
s.writeString(Common::Point(0, 4), "the game, experiment with the commands.");
s.writeString(Common::Point(0, 6), "There is much left unsaid for");
s.writeString(Common::Point(0, 8), "thee to discover in the future...");
s.writeString(Common::Point(0, 10), "Go now unto the world and seek");
s.writeString(Common::Point(0, 12), "adventure where thou might!!!");
s.writeString(Common::Point(0, 14), "P.S.-Search out the Castle of");
s.writeString(Common::Point(0, 16), "Lord British, Use the -E- Key to go in!");
default:
break;
}
s.writeString(Common::Point(20, (_page == 4) ? 18 : 24), "Press any Key to Continue",
Graphics::kTextAlignCenter);
}
void Intro::nextPage() {
if (++_page < 5)
redraw();
else
replaceView("Title");
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,62 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_INTRO_H
#define ULTIMA0_VIEWS_INTRO_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Intro : public View {
private:
int _page = 0;
void nextPage();
public:
Intro() : View("Intro") {}
~Intro() override {}
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override {
nextPage();
return true;
}
bool msgMouseDown(const MouseDownMessage &msg) override {
nextPage();
return true;
}
bool msgAction(const ActionMessage &msg) override {
nextPage();
return true;
}
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,37 @@
/* 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/ultima0/views/startup.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
void Startup::draw() {
auto s = getSurface();
s.clear();
s.writeString(Common::Point(5, 10), "Ultima 0 - Akalabeth!");
s.writeString(Common::Point(2, 19), "Ready?");
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,60 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_STARTUP_H
#define ULTIMA0_VIEWS_STARTUP_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Startup : public View {
private:
void showTitle() {
replaceView("Title");
}
public:
Startup() : View("Startup") {}
~Startup() override {}
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override {
showTitle();
return true;
}
bool msgMouseDown(const MouseDownMessage &msg) override {
showTitle();
return true;
}
bool msgAction(const ActionMessage &msg) override {
showTitle();
return true;
}
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,114 @@
/* 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/ultima0/views/status.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Status::Status(const Common::String &name, UIElement *parent) : View(name, parent) {
setBounds(Common::Rect(0, DEFAULT_SCY - 4 * Gfx::GLYPH_HEIGHT, DEFAULT_SCX, DEFAULT_SCY));
}
bool Status::msgFocus(const FocusMessage &msg) {
_message.clear();
return View::msgFocus(msg);
}
void Status::draw() {
const auto &player = g_engine->_player;
auto s = getSurface();
s.clear();
if (!_message.empty())
s.writeString(Common::Point(1, 0), _message);
s.writeString(Common::Point(28, 1), "Food=");
s.writeString(Common::Point(28, 2), "H.P.=");
s.writeString(Common::Point(28, 3), "Gold=");
s.setColor(C_VIOLET);
s.writeString(Common::Point(33, 1), Common::String::format("%d", (int)player._object[OB_FOOD]));
s.writeString(Common::Point(33, 2), Common::String::format("%d", player._attr[AT_HP]));
s.writeString(Common::Point(33, 3), Common::String::format("%d", player._attr[AT_GOLD]));
}
bool Status::msgGame(const GameMessage &msg) {
if (msg._name == "MSG") {
_message = msg._stringValue;
redraw();
return true;
}
return false;
}
/*-------------------------------------------------------------------*/
bool DungeonStatus::msgFocus(const FocusMessage &msg) {
_lines.clear();
return Status::msgFocus(msg);
}
void DungeonStatus::draw() {
Status::draw();
const auto &player = g_engine->_player;
auto s = getSurface();
// Display the current direction
if (player._level > 0)
s.writeString(Common::Point(15, 0), DIRECTION_NAMES[player.dungeonDir()]);
// Draw any extra lines
for (uint i = 0; i < _lines.size(); ++i)
s.writeString(Common::Point(1, 1 + i), _lines[i]);
}
bool DungeonStatus::msgGame(const GameMessage &msg) {
if (msg._name == "LINES") {
_lines.clear();
Common::String str = msg._stringValue;
uint p;
while ((p = str.findFirstOf('\n')) != Common::String::npos) {
_lines.push_back(Common::String(str.c_str(), str.c_str() + p));
str = Common::String(str.c_str() + p + 1);
}
if (!str.empty())
_lines.push_back(str);
redraw();
return true;
} else {
if (msg._name == "MSG")
// Changing message also resets any message lines
_lines.clear();
return Status::msgGame(msg);
}
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,68 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_STATUS_H
#define ULTIMA0_VIEWS_STATUS_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Status : public View {
private:
Common::String _message;
Common::String _direction;
public:
Status(const Common::String &name, UIElement *parent);
~Status() override {}
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgGame(const GameMessage &msg) override;
};
class OverworldStatus : public Status {
public:
OverworldStatus(UIElement *parent) : Status("OverworldStatus", parent) {
}
};
class DungeonStatus : public Status {
private:
Common::StringArray _lines;
public:
DungeonStatus(UIElement *parent) : Status("DungeonStatus", parent) {
}
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgGame(const GameMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,144 @@
/* 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/ultima0/views/title.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
Title::Title() : View("Title") {
}
bool Title::msgFocus(const FocusMessage &msg) {
_highlightedOption = 0;
updateSelections();
MetaEngine::setKeybindingMode(KBMODE_MENUS);
Common::String priorView = msg._priorView->getName();
if (priorView == "Startup" || priorView == "Dead") {
g_engine->playMidi("intro.mid");
}
return true;
}
bool Title::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
return true;
}
void Title::updateSelections() {
const int selected = getColor(255, 0, 128);
const int white = getColor(255, 255, 255);
for (int i = 0; i < 4; ++i) {
auto &opt = _options[i];
opt._color = opt._index == _highlightedOption ? selected : white;
opt.redraw();
}
}
void Title::draw() {
auto s = getSurface();
s.clear();
View::draw();
s.writeString(Common::Point(20, 8), "Ultima 0 - Akalabeth!", Graphics::kTextAlignCenter);
}
bool Title::msgAction(const ActionMessage &msg) {
switch (msg._action) {
case KEYBIND_UP:
_highlightedOption = _highlightedOption ? _highlightedOption - 1 : 3;
updateSelections();
break;
case KEYBIND_DOWN:
_highlightedOption = (_highlightedOption + 1) % 4;
updateSelections();
break;
case KEYBIND_SELECT:
selectOption();
break;
default:
break;
}
return true;
}
bool Title::msgGame(const GameMessage &msg) {
if (msg._name == "SELECTION") {
_highlightedOption = msg._value;
updateSelections();
return true;
}
return false;
}
bool Title::msgMouseDown(const MouseDownMessage &msg) {
selectOption();
return true;
}
void Title::selectOption() {
if (_highlightedOption == 1 || _highlightedOption == 3)
g_engine->stopMidi();
if (_highlightedOption == 3) {
if (g_engine->savegamesExist()) {
g_engine->loadGameDialog();
} else {
// Otherwise to go the Create Character view
replaceView("CreateCharacter");
}
} else {
const char *VIEW_NAMES[4] = { "Intro", "CreateCharacter", "Acknowledgements" };
replaceView(VIEW_NAMES[_highlightedOption]);
}
}
/*-------------------------------------------------------------------*/
Title::TitleOption::TitleOption(Title *parent, int index, const Common::String &text, int row) :
UIElement("TitleOption", parent), _index(index), _text(text) {
int xs = 20 - text.size() / 2;
setBounds(Gfx::TextRect(xs, row, xs + text.size(), row));
}
void Title::TitleOption::draw() {
auto s = getSurface();
s.setColor(_color);
s.writeString(_text);
}
bool Title::TitleOption::msgMouseEnter(const MouseEnterMessage &msg) {
_parent->send(GameMessage("SELECTION", _index));
return true;
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,71 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_TITLE_H
#define ULTIMA0_VIEWS_TITLE_H
#include "ultima/ultima0/views/view.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Title : public View {
class TitleOption : public UIElement {
public:
int _index;
Common::String _text;
byte _color = 0;
public:
TitleOption(Title *parent, int index, const Common::String &text, int row);
void draw() override;
bool msgMouseEnter(const MouseEnterMessage &msg) override;
};
private:
TitleOption _options[4] = {
TitleOption(this, 0, "Introduction", 16),
TitleOption(this, 1, "Create a Character", 17),
TitleOption(this, 2, "Acknowledgements", 18),
TitleOption(this, 3, "Journey Onwards", 19)
};
int _highlightedOption = 0;
void updateSelections();
void selectOption();
public:
Title();
~Title() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
bool msgGame(const GameMessage &msg) override;
bool msgMouseDown(const MouseDownMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,97 @@
/* 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/ultima0/views/town.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
static const char *WELCOME = "Welcome to the Adventure Shop";
static const char *THANK_YOU = "Thank you m'lord";
//static const char *DONT_HAVE_THAT = "I'm Sorry We Don't have that.";
static const char *NOT_ENOUGH = "M'Lord thou can not afford that item.";
static const char *MAGES_CANT_USE = "I'm sorry, Mages can't use that.";
static const char *BYE = "Bye";
Town::Town() : Info("Town") {
}
bool Town::msgFocus(const FocusMessage &msg) {
_message = WELCOME;
g_engine->playMidi("shop.mid");
return Info::msgFocus(msg);
}
bool Town::msgUnfocus(const UnfocusMessage &msg) {
g_engine->stopMidi();
return Info::msgUnfocus(msg);
}
void Town::draw() {
Info::draw();
// General message
auto s = getSurface();
s.writeString(Common::Point(1, 12), _message.empty() ? THANK_YOU : _message);
s.writeString(Common::Point(1, 13), "Which item shallt thou buy");
_message.clear();
}
void Town::selectObject(int item) {
auto &player = g_engine->_player;
const auto &obj = OBJECT_INFO[item];
// Some things mages can't use
if (player._class == 'M') {
if (item == OB_BOW || item == OB_RAPIER) {
_message = MAGES_CANT_USE;
redraw();
return;
}
}
if (obj._cost > player._attr[AT_GOLD]) {
_message = NOT_ENOUGH;
} else {
player._attr[AT_GOLD] -= obj._cost; // Lose the money
player._object[item] = MIN<int>(player._object[item] + (item == OB_FOOD ? 10 : 1), 999);
_message = THANK_YOU;
}
redraw();
}
void Town::leave() {
_message = BYE;
delaySeconds(1);
redraw();
}
void Town::timeout() {
replaceView("WorldMap");
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,54 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_TOWN_H
#define ULTIMA0_VIEWS_TOWN_H
#include "ultima/ultima0/views/info.h"
#include "ultima/ultima0/data/data.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class Town : public Info {
private:
Common::String _message;
protected:
void selectObject(int item) override;
void leave() override;
public:
Town();
~Town() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
void timeout() override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,90 @@
/* 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/ultima0/views/view.h"
#include "ultima/ultima0/ultima0.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
void View::checkFocusedControl(const Common::Point &mousePos) {
if (_focusedElement) {
if (!_focusedElement->getBounds().contains(mousePos)) {
_focusedElement->send(MouseLeaveMessage());
_focusedElement = nullptr;
}
} else {
for (UIElement *child : _children) {
if (child->getBounds().contains(mousePos)) {
_focusedElement = child;
child->send(MouseEnterMessage());
break;
}
}
}
}
UIElement *View::getElementAtPos(const Common::Point &pos) const {
for (UIElement *child : _children) {
if (child->getBounds().contains(pos))
return child;
}
return nullptr;
}
bool View::msgFocus(const FocusMessage &msg) {
_focusedElement = nullptr;
return UIElement::msgFocus(msg);
}
bool View::msgUnfocus(const UnfocusMessage &msg) {
if (_focusedElement)
_focusedElement->send(MouseLeaveMessage());
return UIElement::msgUnfocus(msg);
}
bool View::msgMouseMove(const MouseMoveMessage &msg) {
checkFocusedControl(msg._pos);
return true;
}
bool View::msgMouseDown(const MouseDownMessage &msg) {
UIElement *child = getElementAtPos(msg._pos);
return child ? child->send(msg) : false;
}
bool View::msgMouseUp(const MouseUpMessage &msg) {
UIElement *child = getElementAtPos(msg._pos);
return child ? child->send(msg) : false;
}
byte View::getColor(byte r, byte g, byte b) {
return g_engine->_palette.findBestColor(r, g, b);
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,80 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_VIEW_H
#define ULTIMA0_VIEWS_VIEW_H
#include "ultima/ultima0/events.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
/**
* Base view class for screens and dialogs that appear on-screen.
* The View class takes care of two important things:
* 1) By default events get sent to all controls on a view until one
* handles it. For mouse events, we instead want only the control the
* mouse cursor is over to receive the events, saving the individual
* controls from having to check if the mouse is within their bounds.
* 2) Individual elements will get a Focus/Unfocus message as the
* mouse enters and leaves them. This allows, for example, buttons
* that have been pressed to de-select if the mouse leaves their bounds.
*/
class View : public UIElement {
private:
UIElement *_focusedElement = nullptr;
/**
* Checks if a control is entered or left
*/
void checkFocusedControl(const Common::Point &mousePos);
/**
* Check for an element at the given position
*/
UIElement *getElementAtPos(const Common::Point &pos) const;
protected:
byte getColor(byte r, byte g, byte b);
public:
View(const Common::String &name, UIElement *uiParent) :
UIElement(name, uiParent) {
}
View(const Common::String &name) :
UIElement(name) {
}
virtual ~View() {
}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
bool msgMouseMove(const MouseMoveMessage &msg) override;
bool msgMouseDown(const MouseDownMessage &msg) override;
bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,61 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_H
#define ULTIMA0_VIEWS_H
#include "ultima/ultima0/views/acknowledgements.h"
#include "ultima/ultima0/views/attack.h"
#include "ultima/ultima0/views/castle.h"
#include "ultima/ultima0/views/create_character.h"
#include "ultima/ultima0/views/dead.h"
#include "ultima/ultima0/views/dungeon.h"
#include "ultima/ultima0/views/info.h"
#include "ultima/ultima0/views/intro.h"
#include "ultima/ultima0/views/startup.h"
#include "ultima/ultima0/views/title.h"
#include "ultima/ultima0/views/town.h"
#include "ultima/ultima0/views/world_map.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
struct Views {
Acknowledgements _acknowledgements;
Attack _attack;
Castle _castle;
CreateCharacter _createCharacter;
Dead _dead;
Dungeon _dungeon;
Info _info;
Intro _intro;
Startup _startup;
Title _title;
Town _town;
WorldMap _worldMap;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif

View File

@@ -0,0 +1,223 @@
/* 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/ultima0/views/world_map.h"
#include "ultima/ultima0/ultima0.h"
#include "ultima/ultima0/metaengine.h"
#include "ultima/ultima0/gfx/font.h"
#include "ultima/ultima0/gfx/map.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
WorldMap::WorldMap() : View("WorldMap") {
}
bool WorldMap::msgFocus(const FocusMessage &msg) {
showMessage("");
MetaEngine::setKeybindingMode(KBMODE_OVERWORLD);
if (!g_engine->isMidiPlaying())
g_engine->playMidi("over.mid");
return true;
}
bool WorldMap::msgUnfocus(const UnfocusMessage &msg) {
MetaEngine::setKeybindingMode(KBMODE_MINIMAL);
return true;
}
void WorldMap::draw() {
auto s = getSurface();
// Draw the map
Graphics::ManagedSurface mapArea(s, Common::Rect(0, 0, s.w, s.h - Gfx::GLYPH_HEIGHT * 4));
Gfx::Map::draw(&mapArea);
// Allow the status area to draw
View::draw();
if (g_engine->_showMinimap) {
s.frameRect(Common::Rect(s.w - WORLD_MINIMAP_SIZE - 4, 0, s.w, WORLD_MINIMAP_SIZE + 4), C_GREY);
s.frameRect(Common::Rect(s.w - WORLD_MINIMAP_SIZE - 3, 1, s.w - 1, WORLD_MINIMAP_SIZE + 3), C_GREY);
Graphics::ManagedSurface minimapArea(s, Common::Rect(s.w - WORLD_MINIMAP_SIZE - 2, 2, s.w - 2, WORLD_MINIMAP_SIZE + 2));
Gfx::Map::draw(&minimapArea, true);
}
}
bool WorldMap::msgAction(const ActionMessage &msg) {
if (isDelayActive())
return false;
switch (msg._action) {
case KEYBIND_UP:
showMessage("North");
move(0, -1);
break;
case KEYBIND_DOWN:
showMessage("South");
move(0, 1);
break;
case KEYBIND_LEFT:
showMessage("West");
move(-1, 0);
break;
case KEYBIND_RIGHT:
showMessage("East");
move(1, 0);
break;
case KEYBIND_INFO:
// Show character info screen
showMessage("");
replaceView("Info");
break;
case KEYBIND_ENTER:
enter();
break;
case KEYBIND_PASS:
showMessage("");
break;
case KEYBIND_QUIT:
// "Quit" in the original which merely saves the game. For ScummVM,
// we open the GMM, allowing the user to either save or quit
g_engine->openMainMenuDialog();
return true;
case KEYBIND_MINIMAP:
g_engine->_showMinimap = !g_engine->_showMinimap;
redraw();
break;
default:
showMessage("");
break;
}
endOfTurn();
return true;
}
bool WorldMap::msgKeypress(const KeypressMessage &msg) {
if (isDelayActive())
return false;
endOfTurn();
return true;
}
void WorldMap::endOfTurn() {
auto &player = g_engine->_player;
if (player._attr[AT_HP] <= 0) {
g_engine->stopMidi();
replaceView("Dead");
} else {
player._object[OB_FOOD] = MAX(player._object[OB_FOOD] - 1.0, 0.0);
if (player._object[OB_FOOD] == 0) {
showMessage("You have starved...");
delaySeconds(1);
}
}
}
void WorldMap::timeout() {
const auto &map = g_engine->_worldMap;
auto &player = g_engine->_player;
auto &dungeon = g_engine->_dungeon;
g_engine->stopMidi();
if (player._attr[AT_HP] <= 0 || player._object[OB_FOOD] <= 0) {
// Timeout from displaying player was killed
replaceView("Dead");
} else {
// Otherwise a timeout from entering a location
int t = map.read(player._worldPos.x, player._worldPos.y);
switch (t) {
case WT_TOWN:
replaceView("Town");
break;
case WT_DUNGEON:
player._level = 1; // Go to level 1
player._dungeonPos.x = 1; // Set initial position
player._dungeonPos.y = 1;
player._dungeonDir.x = 1; // And direction
player._dungeonDir.y = 0;
dungeon.create(player);
replaceView("Dungeon");
break;
case WT_BRITISH:
replaceView("Castle");
break;
default:
break;
}
}
}
void WorldMap::move(int xi, int yi) {
auto &player = g_engine->_player;
auto &map = g_engine->_worldMap;
// Calculate new position
int x1 = player._worldPos.x + xi;
int y1 = player._worldPos.y + yi;
if (map.read(x1, y1) == WT_MOUNTAIN) {
showMessage("You can't pass the mountains.");
} else {
// Move
player._worldPos.x = x1;
player._worldPos.y = y1;
redraw();
}
}
void WorldMap::enter() {
const auto &player = g_engine->_player;
const auto &map = g_engine->_worldMap;
int t = map.read(player._worldPos.x, player._worldPos.y);
switch (t) {
case WT_TOWN:
showMessage("Enter Town.");
delaySeconds(1);
break;
case WT_DUNGEON:
showMessage("Enter Dungeon.");
delaySeconds(1);
break;
case WT_BRITISH:
showMessage("Enter Castle.");
delaySeconds(1);
break;
default:
// Nope....
showMessage("Huh???");
break;
}
}
} // namespace Views
} // namespace Ultima0
} // namespace Ultima

View File

@@ -0,0 +1,59 @@
/* 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/>.
*
*/
#ifndef ULTIMA0_VIEWS_WORLD_MAP_H
#define ULTIMA0_VIEWS_WORLD_MAP_H
#include "ultima/ultima0/views/view.h"
#include "ultima/ultima0/views/status.h"
namespace Ultima {
namespace Ultima0 {
namespace Views {
class WorldMap : public View {
private:
OverworldStatus _status = OverworldStatus(this);
void move(int xi, int yi);
void enter();
void endOfTurn();
void showMessage(const Common::String &msg) {
_status.send(GameMessage("MSG", msg));
}
public:
WorldMap();
~WorldMap() override {}
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
void timeout() override;
};
} // namespace Views
} // namespace Ultima0
} // namespace Ultima
#endif