Scripts/contextual_help.js |
"use strict";
this.name = "ContextualHelp";
this.author = "phkb";
this.copyright = "2023 phkb";
this.description = "Implements a contextual help system to most gui screens.";
this.licence = "CC BY-NC-SA 4.0";
// handling help on OXP pages?
this._page = 0;
this._text = "";
this._selectedKey = "";
this._keyDict = {
"guiOPTIONS": "GUI_SCREEN_OPTIONS",
"guiEQUIP": "GUI_SCREEN_EQUIP_SHIP",
"guiSHIP": "GUI_SCREEN_SHIPYARD",
"guiINTER": "GUI_SCREEN_INTERFACES",
"guiSTATUS": "GUI_SCREEN_STATUS",
"guiMAN": "GUI_SCREEN_MANIFEST",
"guiLRC": "GUI_SCREEN_LONG_RANGE_CHART",
"guiSRC": "GUI_SCREEN_SHORT_RANGE_CHART",
"guiSYS": "GUI_SCREEN_SYSTEM_DATA",
"guiMKT": "GUI_SCREEN_MARKET",
"guiMINF": "GUI_SCREEN_MARKETINFO"
};
this._backgroundDict = {};
this._overlayDict = {};
this._extraText = {};
this._shownHints = [];
//-------------------------------------------------------------------------------------------------------------
this.startUp = function() {
// register our hot key on the various GUI screens
var keys = Object.keys(this._keyDict);
var i = keys.length;
while (i--) {
var options = {};
options["guiScreen"] = this._keyDict[keys[i]];
options["registerKeys"] = {};
options["registerKeys"][keys[i]] = [{key:"h",mod1:true}];
options["callback"] = this.$setupHelpPage.bind(this);
setExtraGuiScreenKeys(this.name, options);
}
if (missionVariables.ContextualHelp_Hints) {
this._shownHints = JSON.parse(missionVariables.ContextualHelp_Hints);
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function() {
missionVariables.ContextualHelp_Hints = JSON.stringify(this._shownHints);
}
//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function(to, from) {
var showHint = false;
if (this._shownHints.indexOf(to) == -1) {
if (to == "GUI_SCREEN_OPTIONS") showHint = true;
if (to == "GUI_SCREEN_EQUIP_SHIP") showHint = true;
if (to == "GUI_SCREEN_SHIPYARD") showHint = true;
if (to == "GUI_SCREEN_INTERFACES") showHint = true;
if (to == "GUI_SCREEN_STATUS") showHint = true;
if (to == "GUI_SCREEN_MANIFEST") showHint = true;
if (to == "GUI_SCREEN_LONG_RANGE_CHART") showHint = true;
if (to == "GUI_SCREEN_SHORT_RANGE_CHART") showHint = true;
if (to == "GUI_SCREEN_SYSTEM_DATA") showHint = true;
if (to == "GUI_SCREEN_MARKET") showHint = true;
if (to == "GUI_SCREEN_MARKETINFO") showHint = true;
}
if (showHint == true) {
this._shownHints.push(to);
player.consoleMessage("Press Ctrl-H to display help");
}
}
//-------------------------------------------------------------------------------------------------------------
// allows custom help text to be appended to the rest of the help screen text.
// usage $addHelpTextToGuiScreen(this.name, "GUI_SCREEN_MANIFEST", "Some extra helpful notes, hints or suggestions.");
this.$addHelpTextToGuiScreen = function(source, gui, text) {
if (!source || source == "") {
log(this.name, "Invalid source specified. Must be a valid text string (eg 'myoxp')");
return;
}
var keys = Object.keys(this._keyDict);
var i = keys.length;
var found = false;
while (i--) {
if (this._keyDict[keys[i]] == gui) {found = true; break;}
}
if (found == false) {
log(this.name, "Invalid GUI screen code specified: " + gui);
return;
}
if (!this._extraText.hasOwnProperty(source)) {
this._extraText[source] = {};
}
this._extraText[source][gui] = text;
}
//-------------------------------------------------------------------------------------------------------------
// allows custom background images to be set for the various help screens
// usage: $setBackgroundForHelpScreen("GUI_SCREEN_MANIFEST", "my_background_image.png");
this.$setBackgroundForHelpScreen = function(gui, background) {
this._backgroundDict[gui] = background;
}
//-------------------------------------------------------------------------------------------------------------
// allows custom overlay images to be set for the variable help screens
// usage: $setOverlayForHelpScreen("GUI_SCREEN_MANIFEST", "my_overlay_image.png");
this.$setOverlayForHelpScreen = function(gui, overlay) {
this._overlayDict[gui] = overlay;
}
//-------------------------------------------------------------------------------------------------------------
this.$setupHelpPage = function(key) {
this._selectedKey = key;
var gui = this._keyDict[this._selectedKey];
var lookup = "[help_" + gui + "]";
this._text = expandDescription(lookup);
// add in additional OXP help here
var keys = Object.keys(this._extraText);
if (keys && keys.length > 0) {
for (var i = 0; i < keys.length; i++) {
if (this._extraText[keys[i]][gui]) this._text += "\n" + expandDescription(this._extraText[keys[i]][gui]);
}
}
this._page = 1;
this.$showHelpPage();
}
//-------------------------------------------------------------------------------------------------------------
this.$showHelpPage = function $showHelpPage() {
var that = $showHelpPage;
var columnText = (that.columnText = that.columnText || this.$columnText);
// arrange the text into an array of text items that don't overflow the page
var textLines = columnText(this._text, 32);
// max rows of text to show
var rows = 19; // could fit an extra line in, but having a one-line gap at the bottom looks better
if (player.ship.hudAllowsBigGui) rows = 25;
// work out the max number of pages we have
var maxPage = parseInt((textLines.length - 1) / rows) + 1;
var text = "";
var counter = 0;
// set teh start point, based on the current page
var line = (this._page - 1) * rows;
// start compiling the text for this page
do {
text += textLines[line] + "\n";
line += 1;
counter += 1;
if (line > textLines.length - 1) break;
} while (counter < rows)
// build up the options for the mission screen
var extra = "";
if (this._page < maxPage || this._page != 1) extra += "Use Page Up/Page Down for more. ";
var opts = {
screenID: "oolite-contextual-help-map",
title: "Help" + (maxPage > 1 ? " (Page " + this._page + " of " + maxPage + ")" : ""),
allowInterrupt: true,
exitScreen: this._keyDict[this._selectedKey],
choices: {"99_EXIT":extra + "Press ESC or Enter to return"},
registerKeys: {"keyEsc":[{key:"esc"}]},
message: text
};
// if we've been given a background image for this page, set it now
if (this._backgroundDict[this._keyDict[this._selectedKey]] != "") {
opts["background"] = this._backgroundDict[this._keyDict[this._selectedKey]];
}
// if we've been given an overlay image for this page, set it now
if (this._overlayDict[this._keyDict[this._selectedKey]] != undefined && this._overlayDict[this._keyDict[this._selectedKey]] != "") {
//log(this.name, "overlay = " + this._overlayDict[this._keyDict[this._selectedKey]]);
opts["overlay"] = this._overlayDict[this._keyDict[this._selectedKey]];
} else {
// use our default overlay
log(this.name, "overlay default");
opts["overlay"] = {name:"ch-info.png", height:546};
}
// only add the page up or down keys if there are pages to go to.
if (this._page > 1) opts["registerKeys"]["keyPgUp"] = [{key:"pageUp"}];
if (this._page < maxPage) opts["registerKeys"]["keyPgDn"] = [{key:"pageDown"}];
mission.runScreen(opts, this.$screenHandler, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function(choice, key) {
switch (key) {
case "keyPgUp": this._page -= 1; this.$showHelpPage(); break;
case "keyPgDn": this._page += 1; this.$showHelpPage(); break;
case "enter": // we'll accept enter as well for the exit
case "keyEsc": return;
}
}
//-------------------------------------------------------------------------------------------------------------
// arranges text into a array of strings with a particular column width
// handles \n codes in the text
this.$columnText = function $columnText(originalText, columnWidth) {
var returnText = [];
if (defaultFont.measureString(originalText) > columnWidth) {
var paras = originalText.split("\n");
for (var p = 0; p < paras.length; p++) {
var words = paras[p].split(" ");
var word = "";
var line = "";
for (var w = 0; w < words.length; w++) {
word = words[w].trim();
// make sure we have a word to add before trying to add it
if (word !== "") {
if (defaultFont.measureString(line + " " + word) <= columnWidth) {
line += (line === "" ? "" : " ") + word;
} else {
returnText.push(line);
line = word;
}
}
}
// add any remainder
returnText.push(line);
}
} else {
returnText.push(originalText);
}
return returnText;
}
|