From bf8b4cece34d6124e4e8bbb630c0ff90c97d491f Mon Sep 17 00:00:00 2001 From: Mark Long Date: Wed, 29 Jun 2016 19:35:33 -0500 Subject: [PATCH] Added MazeViewer class for exploring "The Missing Ring" by DataMost --- src/ui/viewers/mazeviewer.cpp | 385 ++++++++++++++++++++++++++++++++++ src/ui/viewers/mazeviewer.h | 50 +++++ 2 files changed, 435 insertions(+) create mode 100644 src/ui/viewers/mazeviewer.cpp create mode 100644 src/ui/viewers/mazeviewer.h diff --git a/src/ui/viewers/mazeviewer.cpp b/src/ui/viewers/mazeviewer.cpp new file mode 100644 index 0000000..2796fb8 --- /dev/null +++ b/src/ui/viewers/mazeviewer.cpp @@ -0,0 +1,385 @@ +#include "mazeviewer.h" +#include +#include + +#include "memory.h" + +MazeViewer::MazeViewer(QWidget *parent) : QWidget(parent) +{ + setMinimumSize(480,600); + m_maze = QPixmap(width(),height()); + drawMaze(); +} + +void MazeViewer::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + m_maze = QPixmap(event->size().width(), + event->size().height()); + drawMaze(); +} + +void MazeViewer::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + drawMaze(); + QPainter painter(this); + painter.drawPixmap(0,0,m_maze); +} + +void MazeViewer::setFile(BinaryFile *file) +{ + m_file = file; + + QString title = QString("Maze Viewer: %1").arg(m_file->filename()); + setWindowTitle(title); + + quint16 address = file->address(); + mem.addFile(file->data(), address); + +} + + +void MazeViewer::drawMaze() +{ + QPainter painter(&m_maze); + + painter.setBrush(QColor(0xff,0xff,0xff)); + painter.setPen(QColor(0xff,0xff,0xff)); + painter.drawRect(0,0,m_maze.width(),m_maze.height()); + + double cellWidth = width()/8; + double cellHeight = height()/10; + + painter.setBrush(QColor(0xff,0xff,0xff)); + + QPen lockedDoorPen(Qt::red); + lockedDoorPen.setStyle(Qt::DashLine); + + QPen hiddenDoorPen(Qt::blue); + hiddenDoorPen.setStyle(Qt::DashLine); + hiddenDoorPen.setWidth(2); + + for (int idx = 0; idx < 8; idx++) + { + for (int jdx = 0; jdx < 10; jdx++) + { + double cellTop = jdx * cellHeight + 1; + double cellBot = (jdx+1) * cellHeight - 1; + + double cellTopQuarter = cellTop + (cellHeight/4); + double cellBotQuarter = cellBot - (cellHeight/4); + + double cellLeft = idx * cellWidth + 1; + double cellRight = (idx+1) * cellWidth - 1; + + double cellLeftQuarter = cellLeft + (cellWidth/4); + double cellRightQuarter = cellRight - (cellWidth/4); + + + if (cellHasWalls(idx,jdx)) + { + painter.setPen(QColor(0xff,0xff,0xff)); + painter.setBrush(QColor(0xff,0xff,0xff)); + painter.drawRect(cellLeft, cellTop, cellWidth-2, cellHeight-2); + painter.setPen(Qt::black); + if (cellHasEastDoor(idx,jdx)) + { + painter.drawLine(QPointF(cellRight,cellTop),QPointF(cellRight,cellTopQuarter)); + painter.drawLine(QPointF(cellRight,cellBotQuarter),QPointF(cellRight,cellBot)); + + if (cellHasSpecialEast(idx,jdx)) { // Locked Door + QPen oldpen = painter.pen(); + + painter.setPen(lockedDoorPen); + painter.drawLine(QPointF(cellRight,cellTopQuarter),QPointF(cellRight,cellBotQuarter)); + painter.setPen(oldpen); + } + } + else + { + painter.drawLine(QPointF(cellRight,cellTop),QPointF(cellRight,cellBot)); + if (cellHasSpecialEast(idx,jdx)) { // Hidden Door + QPen oldpen = painter.pen(); + + painter.setPen(hiddenDoorPen); + painter.drawLine(QPointF(cellRight,cellTopQuarter),QPointF(cellRight,cellBotQuarter)); + painter.setPen(oldpen); + } + } + + if (cellHasWestDoor(idx,jdx)) + { + painter.drawLine(QPointF(cellLeft,cellTop),QPointF(cellLeft,cellTopQuarter)); + painter.drawLine(QPointF(cellLeft,cellBotQuarter),QPointF(cellLeft,cellBot)); + + if (cellHasSpecialWest(idx,jdx)) { // Locked Door + QPen oldpen = painter.pen(); + + painter.setPen(lockedDoorPen); + painter.drawLine(QPointF(cellLeft,cellTopQuarter),QPointF(cellLeft,cellBotQuarter)); + painter.setPen(oldpen); + } + } + else + { + painter.drawLine(QPointF(cellLeft,cellTop),QPointF(cellLeft,cellBot)); + if (cellHasSpecialWest(idx,jdx)) { // Hidden Door + QPen oldpen = painter.pen(); + + painter.setPen(hiddenDoorPen); + painter.drawLine(QPointF(cellLeft+1,cellTopQuarter),QPointF(cellLeft+1,cellBotQuarter)); + painter.setPen(oldpen); + } + } + + if (cellHasNorthDoor(idx,jdx)) + { + painter.drawLine(QPointF(cellLeft,cellTop),QPointF(cellLeftQuarter,cellTop)); + painter.drawLine(QPointF(cellRight,cellTop),QPointF(cellRightQuarter,cellTop)); + + + if (cellHasSpecialNorth(idx,jdx)) { // Locked Door + QPen oldpen = painter.pen(); + + painter.setPen(lockedDoorPen); + painter.drawLine(QPointF(cellLeftQuarter,cellTop),QPointF(cellRightQuarter,cellTop)); + painter.setPen(oldpen); + } + } + else + { + painter.drawLine(QPointF(cellLeft,cellTop),QPointF(cellRight,cellTop)); + if (cellHasSpecialNorth(idx,jdx)) { // Hidden Door + QPen oldpen = painter.pen(); + + painter.setPen(hiddenDoorPen); + painter.drawLine(QPointF(cellLeftQuarter,cellTop+1),QPointF(cellRightQuarter,cellTop+1)); + painter.setPen(oldpen); + } + } + + if (cellHasSouthDoor(idx,jdx)) + { + painter.drawLine(QPointF(cellLeft,cellBot),QPointF(cellLeftQuarter,cellBot)); + painter.drawLine(QPointF(cellRightQuarter,cellBot),QPointF(cellRight,cellBot)); + + + if (cellHasSpecialSouth(idx,jdx)) { // Locked Door + QPen oldpen = painter.pen(); + + painter.setPen(lockedDoorPen); + painter.drawLine(QPointF(cellLeftQuarter,cellBot),QPointF(cellRightQuarter,cellBot)); + painter.setPen(oldpen); + } + } + else + { + painter.drawLine(QPointF(cellLeft,cellBot),QPointF(cellRight,cellBot)); + if (cellHasSpecialSouth(idx,jdx)) { // Hidden Door + QPen oldpen = painter.pen(); + + painter.setPen(hiddenDoorPen); + painter.drawLine(QPointF(cellLeftQuarter,cellBot),QPointF(cellRightQuarter,cellBot)); + painter.setPen(oldpen); + } + + } + } + else + { + painter.setPen(QColor(0xef,0xef,0xef)); + painter.setBrush(QColor(0xef,0xef,0xef)); + painter.drawRect(cellLeft, cellTop, cellWidth-2, cellHeight-2); + } + + painter.setPen(Qt::black); + quint8 cv = getCellDesc(idx,jdx); + quint8 tr = getCellInventory(idx,jdx); + QString trs = inventoryToString(tr); + quint8 mo = getCellMonsters(idx,jdx); + QString mos = monsterToString(mo); + + //QString str = QString("%1\nInv:0x%3\nMo:0x%4") + // .arg(idx+(jdx*8)) + // .arg(cv,2,16,QChar('0')) + // .arg(tr,2,16,QChar('0')) + // .arg(mo,2,16,QChar('0')); + + QString str = QString("%1\n%2\n%3") + .arg(idx+(jdx*8)) + .arg(mos) + .arg(trs); + + painter.drawText(QRect(cellLeft+2,cellTop+2,cellWidth-2,cellHeight-2),str); + } + } + +} + +bool MazeViewer::cellHasWalls(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc != 0xFF); +} + +bool MazeViewer::cellHasNorthDoor(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x04); +} + +bool MazeViewer::cellHasSpecialNorth(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x40); +} + +bool MazeViewer::cellHasEastDoor(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x08); +} + +bool MazeViewer::cellHasSpecialEast(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x80); +} + +bool MazeViewer::cellHasSouthDoor(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x01); +} + +bool MazeViewer::cellHasSpecialSouth(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x10); +} + +bool MazeViewer::cellHasWestDoor(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x02); +} + +bool MazeViewer::cellHasSpecialWest(int x, int y) +{ + quint8 cellDesc = getCellDesc(x,y); + return (cellDesc & 0x20); +} + +quint8 MazeViewer::getCellDesc(int x, int y) +{ + return mem.at(0x8100+x+(y*8)); +} + +quint8 MazeViewer::getCellMonsters(int x, int y) +{ + return mem.at(0x81A0+x+(y*8)); +} + +quint8 MazeViewer::getCellInventory(int x, int y) +{ + return mem.at(0x8150+x+(y*8)); +} + +QString MazeViewer::inventoryToString(quint8 inv) +{ + quint8 gems = (inv & 0xf0) >> 4; + quint8 gold_or_special = (inv & 0x0f); + + if (gems == 0) // Special item; + { + if (gold_or_special == 0x00) { return ""; } + if (gold_or_special == 0x01) { return "Key1"; } + if (gold_or_special == 0x02) { return "Key2"; } + if (gold_or_special == 0x03) { return "Key3"; } + if (gold_or_special == 0x04) { return "Mirror"; } + if (gold_or_special == 0x05) { return "Goblet"; } + if (gold_or_special == 0x06) { return "Stauette"; } + if (gold_or_special == 0x07) { return "UNKN 7"; } + if (gold_or_special == 0x08) { return "UNKN 8"; } + if (gold_or_special == 0x09) { return "UNKN 9"; } + if (gold_or_special == 0x0A) { return "UNKN 10"; } + if (gold_or_special == 0x0B) { return "UNKN 11"; } + if (gold_or_special == 0x0C) { return "UNKN 12"; } + if (gold_or_special == 0x0D) { return "UNKN 13"; } + if (gold_or_special == 0x0E) { return "UNKN 14"; } + if (gold_or_special == 0x0F) { return "UNKN 15"; } + return ""; + } + else + { + return QString("%1Gm,%2Au").arg(gems).arg(gold_or_special * 4); + } +} + +QString MazeViewer::monsterToString(quint8 mc) +{ + quint8 count = mc & 0x0f; + quint8 monster = (mc & 0xf0) >> 4; + + QString name; + switch (monster) { + case 0x00: + name = ""; + break; + case 0x01: + name = "LgSpdr"; + break; + case 0x02: + name = "GntRat"; + break; + case 0x03: + name = "Orc"; + break; + case 0x04: + name = "FrBtle"; + break; + case 0x05: + name = "Goblin"; + break; + case 0x06: + name = "Sklton"; + break; + case 0x07: + name = "Zombie"; + break; + case 0x08: + name = "Grgyle"; + break; + case 0x09: + name = "DgOfWr"; + break; + case 0x0a: + name = "HlHnd"; + break; + case 0x0b: + name = "Wrght"; + break; + case 0x0c: + name = "HgSpdr"; + break; + case 0x0d: + name = "Hmncls"; + break; + case 0x0e: + name = "UNKN"; + break; + case 0x0f: + name = "EvlMage"; + break; + default: + name = "UNK"; + break; + } + + if (count > 0 && monster > 0) + { + return QString("%1 %2").arg(count).arg(name); + } + return ""; +} diff --git a/src/ui/viewers/mazeviewer.h b/src/ui/viewers/mazeviewer.h new file mode 100644 index 0000000..a221c33 --- /dev/null +++ b/src/ui/viewers/mazeviewer.h @@ -0,0 +1,50 @@ +#ifndef MAZEVIEWER_H +#define MAZEVIEWER_H + +#include +#include +#include + +#include "binaryfile.h" +#include "memory.h" + + +/// A class for viewing maze files in "The Missing Ring" by DataMost. + +class MazeViewer : public QWidget +{ + Q_OBJECT +public: + MazeViewer(QWidget *parent = 0); + + void drawMaze(); + void resizeEvent(QResizeEvent *event); + void paintEvent(QPaintEvent *event); + + void setFile(BinaryFile *file); + +private: + QPixmap m_maze; + BinaryFile *m_file; + Memory mem; + + bool cellHasWalls(int x, int y); + bool cellHasNorthDoor(int x, int y); + bool cellHasSouthDoor(int x, int y); + bool cellHasEastDoor(int x, int y); + bool cellHasWestDoor(int x, int y); + + bool cellHasSpecialNorth(int x, int y); + bool cellHasSpecialSouth(int x, int y); + bool cellHasSpecialEast(int x, int y); + bool cellHasSpecialWest(int x, int y); + + quint8 getCellDesc(int x, int y); + quint8 getCellMonsters(int x, int y); + quint8 getCellInventory(int x, int y); + + QString inventoryToString(quint8 inv); + QString monsterToString(quint8 mc); +}; + +#endif // MAZEVIEWER_H