NANCY: Remove cheat dialogs

Removed the cheat and event flags dialogs, since they were always
a hacky solution and console commands are much easier to maintain.
This commit is contained in:
Kaloyan Chehlarski 2023-03-03 17:34:47 +02:00
parent 900e4666c0
commit 8a378fb89b
8 changed files with 2 additions and 399 deletions

View File

@ -52,7 +52,7 @@ enum NancyState {
kHelp,
kScene,
// CD change
kCheat,
// Cheat,
kQuit,
// regain focus
kNone,

View File

@ -83,308 +83,4 @@ bool NancyOptionsWidget::isInGame() const {
return _domain.equals(ConfMan.getActiveDomainName());
}
// TODO rewrite this class so its layout is not hardcoded
CheatDialog::CheatDialog() : GUI::Dialog(20, 20, 600, 440) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
State::SceneInfo scene = NancySceneState.getSceneInfo();
Time playerTime = NancySceneState._timers.playerTime;
Time timerTime = NancySceneState._timers.timerTime;
bool timerIsActive = NancySceneState._timers.timerIsActive;
if (!timerIsActive) {
timerTime = 0;
}
GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
new GUI::ButtonWidget(this, 420, 410, 60, 20, _("Cancel"), Common::U32String(), GUI::kCloseCmd);
new GUI::ButtonWidget(this, 520, 410, 60, 20, _("OK"), Common::U32String(), GUI::kOKCmd);
_tabs->addTab(_("General"), "Cheat.General");
new GUI::StaticTextWidget(_tabs, 30, 20, 150, 20, _("Scene Data"), Graphics::kTextAlignLeft);
_restartScene = new GUI::CheckboxWidget(_tabs, 35, 50, 150, 20, _("Restart the Scene"));
_scene = new GUI::EditTextWidget(_tabs, 35, 75, 45, 20, Common::U32String::format("%u", scene.sceneID), Common::U32String(), kInputSceneNr, kInputSceneNr);
new GUI::StaticTextWidget(_tabs, 85, 75, 150, 20, _("Scene Number"), Graphics::kTextAlignLeft);
_frame = new GUI::EditTextWidget(_tabs, 35, 100, 45, 20, Common::U32String::format("%u", scene.frameID), Common::U32String(), kInputFrameNr, kInputFrameNr);
new GUI::StaticTextWidget(_tabs, 85, 100, 150, 20, _("Frame Number"), Graphics::kTextAlignLeft);
_offset = new GUI::EditTextWidget(_tabs, 35, 125, 45, 20, Common::U32String::format("%u", scene.verticalOffset), Common::U32String(), kInputScroll, kInputScroll);
// I18N: The Y position (a.k.a vertical scroll) of the background
new GUI::StaticTextWidget(_tabs, 85, 125, 150, 20, _("Background Top (Y)"), Graphics::kTextAlignLeft);
new GUI::StaticTextWidget(_tabs, 30, 160, 150, 20, _("Hints Remaining"), Graphics::kTextAlignLeft);
new GUI::StaticTextWidget(_tabs, 35, 185, 45, 20, _("Easy"), Graphics::kTextAlignLeft);
_hintsRemainingEasy = new GUI::EditTextWidget(_tabs, 35, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[0]), Common::U32String(), kInputHintsEasy, kInputHintsEasy);
new GUI::StaticTextWidget(_tabs, 85, 185, 45, 20, _("Medium"), Graphics::kTextAlignLeft);
_hintsRemainingMedium = new GUI::EditTextWidget(_tabs, 85, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[1]), Common::U32String(), kInputHintsMedium, kInputHintsMedium);
new GUI::StaticTextWidget(_tabs, 135, 185, 45, 20, _("Hard"), Graphics::kTextAlignLeft);
_hintsRemainingHard = new GUI::EditTextWidget(_tabs, 135, 205, 45, 20, Common::U32String::format("%u", NancySceneState._hintsRemaining[2]), Common::U32String(), kInputHintsHard, kInputHintsHard);
new GUI::StaticTextWidget(_tabs, 250, 20, 150, 20, _("Player Data"), Graphics::kTextAlignLeft);
new GUI::StaticTextWidget(_tabs, 255, 50, 150, 20, _("Player Time:"), Graphics::kTextAlignLeft);
_playerTimeDays = new GUI::EditTextWidget(_tabs, 255, 75, 35, 20, Common::U32String::format("%u", playerTime.getDays()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
new GUI::StaticTextWidget(_tabs, 295, 75, 40, 20, _("Days"), Graphics::kTextAlignLeft);
_playerTimeHours = new GUI::EditTextWidget(_tabs, 335, 75, 35, 20, Common::U32String::format("%u", playerTime.getHours()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
new GUI::StaticTextWidget(_tabs, 375, 75, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
_playerTimeMinutes = new GUI::EditTextWidget(_tabs, 415, 75, 35, 20, Common::U32String::format("%u", playerTime.getMinutes()), Common::U32String(), kInputPlayerTime, kInputPlayerTime);
new GUI::StaticTextWidget(_tabs, 455, 75, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
_difficulty = new GUI::EditTextWidget(_tabs, 255, 105, 35, 20, Common::U32String::format("%u", NancySceneState._difficulty), Common::U32String(), kInputDifficulty, kInputDifficulty);
new GUI::StaticTextWidget(_tabs, 295, 105, 150, 20, _("Player Difficulty Level"), Graphics::kTextAlignLeft);
new GUI::StaticTextWidget(_tabs, 250, 140, 150, 20, _("Software Timer"), Graphics::kTextAlignLeft);
_timerOn = new GUI::CheckboxWidget(_tabs, 255, 170, 150, 20, _("Timer On"));
_timerOn->setState(timerIsActive);
_timerHours = new GUI::EditTextWidget(_tabs, 255, 195, 35, 20, Common::U32String::format("%u", timerTime.getTotalHours()), Common::U32String(), kInputTimer, kInputTimer);
new GUI::StaticTextWidget(_tabs, 295, 195, 40, 20, _("Hours"), Graphics::kTextAlignLeft);
_timerMinutes = new GUI::EditTextWidget(_tabs, 335, 195, 35, 20, Common::U32String::format("%u", timerTime.getMinutes()), Common::U32String(), kInputTimer, kInputTimer);
new GUI::StaticTextWidget(_tabs, 375, 195, 50, 20, _("Minutes"), Graphics::kTextAlignLeft);
_timerSeconds = new GUI::EditTextWidget(_tabs, 425, 195, 35, 20, Common::U32String::format("%u", timerTime.getSeconds()), Common::U32String(), kInputTimer, kInputTimer);
new GUI::StaticTextWidget(_tabs, 465, 195, 50, 20, _("Seconds"), Graphics::kTextAlignLeft);
_tabs->addTab(_("Inventory"), "Cheat.Inventory");
for (uint i = 0; i < dialogIDs.size(); ++i) {
Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
Common::String idString;
resStream->skip(0x16);
while (true) {
char add = resStream->readByte();
if (add != 0) {
idString += add;
resStream->skip(1);
} else {
resStream->skip(1);
break;
}
}
if (!idString.hasPrefix("Inventory")) {
continue;
}
idString.trim();
uint numItems = 0;
while (resStream->pos() < resStream->size()) {
if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
// Found a resource, read its string id
Common::String itemLabel;
while (true) {
char add = resStream->readByte();
if (add != 0) {
itemLabel += add;
resStream->skip(1);
} else {
resStream->skip(1);
break;
}
}
GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 250 * (numItems / 10) + 20, (350 / 10) * (numItems % 10) + 15, 250, 250/10, Common::U32String(itemLabel));
box->setState(NancySceneState.hasItem(numItems) == kTrue);
_inventory.push_back(box);
++numItems;
}
}
break;
}
_tabs->setActiveTab(0);
}
void CheatDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case GUI::kOKCmd: {
if (_restartScene->getState()) {
uint sceneID = atoi(Common::String(_scene->getEditString()).c_str());
IFF iff(Common::String::format("S%u", sceneID));
if (iff.load()) {
NancySceneState.changeScene(
atoi(Common::String(_scene->getEditString()).c_str()),
atoi(Common::String(_frame->getEditString()).c_str()),
atoi(Common::String(_offset->getEditString()).c_str()),
true);
} else {
new GUI::StaticTextWidget(this, 20, 410, 150, 20, _("Invalid Scene ID!"), Graphics::kTextAlignLeft);
return;
}
}
if (_timerOn->getState()) {
NancySceneState._timers.timerIsActive = true;
Time &timer = NancySceneState._timers.timerTime;
timer = 0;
timer += 1000 * atoi(Common::String(_timerSeconds->getEditString()).c_str());
timer += 60000 * atoi(Common::String(_timerMinutes->getEditString()).c_str());
timer += 3600000 * atoi(Common::String(_timerHours->getEditString()).c_str());
} else {
NancySceneState.stopTimer();
}
Time &playerTime = NancySceneState._timers.timerTime;
playerTime = 0;
playerTime += 60000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
playerTime += 3600000 * atoi(Common::String(_playerTimeHours->getEditString()).c_str());
playerTime += 86400000 * atoi(Common::String(_playerTimeMinutes->getEditString()).c_str());
NancySceneState._difficulty = atoi(Common::String(_difficulty->getEditString()).c_str());
NancySceneState._hintsRemaining[0] = atoi(Common::String(_hintsRemainingEasy->getEditString()).c_str());
NancySceneState._hintsRemaining[1] = atoi(Common::String(_hintsRemainingMedium->getEditString()).c_str());
NancySceneState._hintsRemaining[2] = atoi(Common::String(_hintsRemainingHard->getEditString()).c_str());
for (uint i = 0; i < _inventory.size(); ++i) {
if (NancySceneState.hasItem(i) == kTrue && !_inventory[i]->getState()) {
NancySceneState.removeItemFromInventory(i, false);
} else if (NancySceneState.hasItem(i) == kFalse && _inventory[i]->getState()) {
NancySceneState.addItemToInventory(i);
}
}
cmd = GUI::kCloseCmd;
break;
}
case kInputSceneNr:
sanitizeInput(_scene);
break;
case kInputFrameNr:
sanitizeInput(_frame);
break;
case kInputScroll:
sanitizeInput(_offset);
break;
case kInputDifficulty:
sanitizeInput(_scene, 2);
break;
case kInputHintsEasy:
sanitizeInput(_hintsRemainingEasy);
break;
case kInputHintsMedium:
sanitizeInput(_hintsRemainingMedium);
break;
case kInputHintsHard:
sanitizeInput(_hintsRemainingHard);
break;
case kInputPlayerTime:
sanitizeInput(_playerTimeMinutes, 59);
sanitizeInput(_playerTimeHours, 23);
sanitizeInput(_playerTimeDays);
break;
case kInputTimer:
sanitizeInput(_timerSeconds, 59);
sanitizeInput(_timerMinutes, 59);
sanitizeInput(_timerHours, 23);
break;
default:
break;
}
Dialog::handleCommand(sender, cmd, data);
}
void CheatDialog::sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue) {
const Common::U32String &str = textWidget->getEditString();
for (uint i = 0; i < str.size(); ++i) {
if (!Common::isDigit(str[i])) {
textWidget->setEditString(str.substr(0, i));
break;
}
}
if (maxValue > -1) {
int number = atoi(Common::String(str).c_str());
if (number > maxValue) {
textWidget->setEditString(Common::U32String::format("%d", maxValue));
}
}
textWidget->setCaretPos(str.size());
}
EventFlagDialog::EventFlagDialog() : GUI::Dialog(20, 20, 600, 440) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundSpecial;
Common::WinResources *res = Common::WinResources::createFromEXE("game.exe");
Common::Array<Common::WinResourceID> dialogIDs = res->getIDList(Common::kWinDialog);
GUI::TabWidget *_tabs = new GUI::TabWidget(this, 0, 0, 600, 370);
new GUI::ButtonWidget(this, 520, 410, 60, 20, _("Close"), Common::U32String(), GUI::kCloseCmd);
for (uint i = 0; i < dialogIDs.size(); ++i) {
Common::SeekableReadStream *resStream = res->getResource(Common::kWinDialog, dialogIDs[i].getID());
Common::String idString;
resStream->skip(0x16);
while (true) {
char add = resStream->readByte();
if (add != 0) {
idString += add;
resStream->skip(1);
} else {
resStream->skip(1);
break;
}
}
if (!idString.hasPrefix("Event")) {
continue;
}
idString.trim();
_tabs->addTab(idString, Common::String("tab " + idString));
uint numFlags = 0;
while (resStream->pos() < resStream->size()) {
if (resStream->readUint16LE() == 0xFFFF && resStream->readSint16LE() == 0x80) {
// Found a resource, read its string id
Common::String flagLabel;
while (true) {
char add = resStream->readByte();
if (add != 0) {
flagLabel += add;
resStream->skip(1);
} else {
resStream->skip(1);
break;
}
}
// String begins with number so we assume it's an event flag radio button
if (Common::isDigit(flagLabel.firstChar())) {
Common::String num;
uint j = 0;
while (true) {
if (Common::isDigit(flagLabel[j])) {
num += flagLabel[j];
} else {
break;
}
++j;
}
uint32 command = atoi(num.c_str()) << 16 | 'ev';
GUI::CheckboxWidget *box = new GUI::CheckboxWidget(_tabs, 300 * (numFlags / 12) + 20, (350 / 12) * (numFlags % 12) + 15, 300, 350/12, Common::U32String(flagLabel), Common::U32String(), command);
box->setState(NancySceneState.getEventFlag(command >> 16));
++numFlags;
}
}
}
}
_tabs->setActiveTab(0);
}
void EventFlagDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
Dialog::handleCommand(sender, cmd, data);
if (cmd & 'ev') {
cmd >>= 16;
NancySceneState.setEventFlag(cmd, data == 0 ? kFalse : kTrue);
}
}
} // End of namespace Nancy

View File

@ -45,56 +45,6 @@ private:
GUI::CheckboxWidget *_secondChanceCheckbox;
};
class CheatDialog : public GUI::Dialog {
public:
CheatDialog();
protected:
enum Commands {
kInputSceneNr = 'isnr',
kInputFrameNr = 'ifnr',
kInputScroll = 'iscr',
kInputHintsEasy = 'ihea',
kInputHintsMedium = 'ihme',
kInputHintsHard = 'ihha',
kInputPlayerTime = 'plti',
kInputDifficulty = 'diff',
kInputTimer = 'time'
};
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
static void sanitizeInput(GUI::EditTextWidget *textWidget, int maxValue = -1);
GUI::CheckboxWidget *_restartScene;
GUI::EditTextWidget *_scene;
GUI::EditTextWidget *_frame;
GUI::EditTextWidget *_offset;
GUI::EditTextWidget *_hintsRemainingEasy;
GUI::EditTextWidget *_hintsRemainingMedium;
GUI::EditTextWidget *_hintsRemainingHard;
GUI::EditTextWidget *_playerTimeDays;
GUI::EditTextWidget *_playerTimeHours;
GUI::EditTextWidget *_playerTimeMinutes;
GUI::EditTextWidget *_difficulty;
GUI::CheckboxWidget *_timerOn;
GUI::EditTextWidget *_timerHours;
GUI::EditTextWidget *_timerMinutes;
GUI::EditTextWidget *_timerSeconds;
Common::Array<GUI::CheckboxWidget *> _inventory;
};
class EventFlagDialog : public GUI::Dialog {
public:
EventFlagDialog();
protected:
void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
};
} // End of namespace Nancy
#endif // NANCY_DIALOGS_H

View File

@ -75,12 +75,6 @@ void InputManager::processEvents() {
case kNancyActionMoveFast:
_inputs |= NancyInput::kMoveFastModifier;
break;
case kNancyActionRequestCheatMenu:
g_nancy->callCheatMenu(false);
break;
case kNancyActionRequestEventMenu:
g_nancy->callCheatMenu(true);
break;
default:
break;
}
@ -247,16 +241,6 @@ void InputManager::initKeymaps(Common::KeymapArray &keymaps) {
act->addDefaultInputMapping("C+S+TAB+m");
debugKeymap->addAction(act);
act = new Action("CHEAT", _("Open general cheat menu"));
act->setCustomEngineActionEvent(kNancyActionRequestCheatMenu);
act->addDefaultInputMapping("C+S+TAB+c");
debugKeymap->addAction(act);
act = new Action("EVENT", _("Open event flags cheat menu"));
act->setCustomEngineActionEvent(kNancyActionRequestEventMenu);
act->addDefaultInputMapping("C+S+TAB+v");
debugKeymap->addAction(act);
keymaps.push_back(mainKeymap);
keymaps.push_back(debugKeymap);
}

View File

@ -81,9 +81,7 @@ enum NancyAction {
kNancyActionRequestSaveLoad,
kNancyActionRequestSetupMenu,
kNancyActionRequestCredits,
kNancyActionRequestMap,
kNancyActionRequestCheatMenu,
kNancyActionRequestEventMenu
kNancyActionRequestMap
};
public:

View File

@ -70,7 +70,6 @@ NancyEngine::NancyEngine(OSystem *syst, const NancyGameDescription *gd) :
_resource = nullptr;
_startTimeHours = 0;
_overrideMovementTimeDeltas = false;
_cheatTypeIsEventFlag = false;
_horizontalEdgesSize = 0;
_verticalEdgesSize = 0;
}
@ -194,18 +193,6 @@ void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState
return;
}
case NancyState::kCheat:
if (_cheatTypeIsEventFlag) {
EventFlagDialog *dialog = new EventFlagDialog();
runDialog(*dialog);
delete dialog;
} else {
CheatDialog *dialog = new CheatDialog();
runDialog(*dialog);
delete dialog;
}
_input->forceCleanInput();
return;
default:
break;
}
@ -249,11 +236,6 @@ void NancyEngine::setMouseEnabled(bool enabled) {
_cursorManager->showCursor(enabled); _input->setMouseInputEnabled(enabled);
}
void NancyEngine::callCheatMenu(bool eventFlags) {
_cheatTypeIsEventFlag = eventFlags;
setState(NancyState::kCheat);
}
Common::Error NancyEngine::run() {
setDebugger(new NancyConsole());

View File

@ -62,7 +62,6 @@ class InputManager;
class SoundManager;
class GraphicsManager;
class CursorManager;
class CheatDialog;
class NancyConsole;
namespace State {
@ -103,8 +102,6 @@ public:
void setMouseEnabled(bool enabled);
void callCheatMenu(bool eventFlags);
// Managers
ResourceManager *_resource;
GraphicsManager *_graphicsManager;
@ -155,8 +152,6 @@ private:
bool isCompressed();
bool _cheatTypeIsEventFlag;
StaticData _staticData;
const byte _datFileMajorVersion;
const byte _datFileMinorVersion;

View File

@ -44,7 +44,6 @@ namespace Nancy {
class NancyEngine;
class NancyConsole;
class CheatDialog;
struct SceneChangeDescription;
namespace Action {
@ -74,7 +73,6 @@ class Scene : public State, public Common::Singleton<Scene> {
friend class Nancy::Action::SliderPuzzle;
friend class Nancy::NancyConsole;
friend class Nancy::NancyEngine;
friend class Nancy::CheatDialog;
public:
enum GameStateChange : byte {