Page 116 of 118
Forcing re-draw of GUI screen without changing screens?
Posted: Mon Jul 29, 2024 8:58 am
by Wildeblood
My friend wrote this simple script to change the colour of the status screen background when the alert condition changes.
Code: Select all
this.name = "background_changer";
this.alertConditionChanged = function (newAlert, oldAlert) {
if (newAlert == 1) { // green
setScreenBackgroundForKey("status_in_flight", { name: "my_green.png", height: 512 });
} else if (newAlert == 2) { // orange
setScreenBackgroundForKey("status_in_flight", { name: "my_orange.png", height: 512 });
} else if (newAlert == 3) {
setScreenBackgroundForKey("status_red_alert", { name: "my_red.png", height: 512 });
} else if (newAlert == 0) {
setScreenBackgroundForKey("status_docked", { name: "my_blue.png", height: 512 });
}
}
Obviously, the red and blue are superfluous hammering, because other people write scripts that don't play nicely together (allegedly). But the question is about the green and orange background images. Changing these values using setScreenBackgroundForKey() does not cause the screen to re-draw.
You're hooning along at 32x max speed, and think, "Now would be a good time to check the status screen."
While you're looking at that screen, you become mass-locked.
The screen background instantly changes from green to orange, to alert you to what has happened.
Except it doesn't. The change only takes effect once you leave the status screen and come back to it again.
What my friend would really like to do is change the background image on the market screen on every playerBoughtCargo event, but I've advised him not to even bother trying. Is my advice correct?
Re: Scripters cove
Posted: Mon Jul 29, 2024 10:41 pm
by phkb
The problem your friend is facing is that he is setting the background for the screen
key for green and orange status. Oolite only looks at the key value when it draws the screen. After that, no matter how often you change the key setting, the screen will stay the same until Oolite gets a message to redraw the screen (for instance, when the status changes to condition red). For green and orange alerts, the screen key doesn't change, so the screen isn't redrawn.
One side effect of this is, your friend could set the "status_red_alert" key when the game starts, and assuming no other OXP overrides it, it will always be used for background of the status screen in red alert, and the same applies to "status_docked".
To get the effect your friend desires, you could do something like this:
Code: Select all
this.alertConditionChanged = function (newAlert, oldAlert) {
if (newAlert == 1) { // green
setScreenBackgroundForKey("status_in_flight", { name: "my_green.png", height: 512 });
if (guiScreen == "GUI_SCREEN_STATUS") setScreenBackground({ name: "my_green.png", height: 512 })
} else if (newAlert == 2) { // orange
setScreenBackgroundForKey("status_in_flight", { name: "my_orange.png", height: 512 });
if (guiScreen == "GUI_SCREEN_STATUS") setScreenBackground({ name: "my_orange.png", height: 512 })
} else if (newAlert == 3) {
setScreenBackgroundForKey("status_red_alert", { name: "my_red.png", height: 512 });
} else if (newAlert == 0) {
setScreenBackgroundForKey("status_docked", { name: "my_blue.png", height: 512 });
}
}
Your friend should be aware, though, that changing the backgrounds in this way will likely create incompatibilities with the Library GUI, which was built to enable OXP authors to swap in/out their backgrounds based on user preferences.
Re: Scripters cove
Posted: Mon Jul 29, 2024 10:45 pm
by phkb
Wildeblood wrote: ↑Mon Jul 29, 2024 8:58 am
What my friend would really like to do is change the background image on the market screen on every playerBoughtCargo event, but I've advised him not to even bother trying. Is my advice correct?
Changing the screen key on every playerBoughtCargo event would probably work, as the content of the screen is being updated, so Oolite would need to refresh the background screen, so a change of the screen background key would likely get the desired result. I haven't tested that scenario though.
Re: Scripters cove
Posted: Tue Jul 30, 2024 6:22 pm
by Wildeblood
phkb wrote: ↑Mon Jul 29, 2024 10:45 pmI haven't tested that scenario though.
I've been looking at the EmailSystem script. I can't see what I'm hoping to find: a simple flag
$unreadEmails == true
or
$unreadEmails > 0
that I can check. If it's there somewhere, then I can set a distinctive, attention-grabbing screen background on entering the F4 screen.
Edit: I found it a moment later. I just hadn't scrolled
quite far enough through the script.
This one:
Code: Select all
// counts how many unread items are in the inbox
this.$totalUnreadItems = function() {
var itms = 0;
if (this._emails != null && this._emails.length > 0) {
for (var i = 0; i < this._emails.length; i++) {
if (this._emails[i].Read === false && this._emails[i].TransmitDate <= clock.seconds) itms += 1;
}
}
return itms;
}
Can I call that without harming anything?
Re: Scripters cove
Posted: Fri Aug 02, 2024 7:15 am
by phkb
Wildeblood wrote: ↑Tue Jul 30, 2024 6:22 pm
Can I call that without harming anything?
Absolutely!
Re: Scripters cove
Posted: Mon Aug 05, 2024 7:24 pm
by Wildeblood
phkb wrote: ↑Fri Aug 02, 2024 7:15 am
I'm still having fun with screen backgrounds, and my next question is, can I switch off the rotating planet model on the F7 screen?
Here's the scenario: a "Postcards from Vetitice" script changes the usual screen background to a custom image of Wildeblood Manor when F7 is set to view 0, 100. But... there's a rotating planet thingamajig blocking the view. So, I don't want to edit plist config files to move the model always; can I move aside or switch off the model temporarily from javascript?
Re: Scripters cove
Posted: Wed Aug 07, 2024 5:40 am
by hiran
Beginner problem. I am new to JavaScript and want to organize my code. That means I want to split it across several source files.
I ran through tutorials which lead me to modules and import/export directives. Unfortunately when I create a .js file and try to import it into my world script Oolite complains that 'import' is a reserved word.
How can I make use of modules?
Re: Scripters cove
Posted: Wed Aug 07, 2024 6:30 am
by another_commander
hiran wrote: ↑Wed Aug 07, 2024 5:40 am
Beginner problem. I am new to JavaScript and want to organize my code. That means I want to split it across several source files.
I ran through tutorials which lead me to modules and import/export directives. Unfortunately when I create a .js file and try to import it into my world script Oolite complains that 'import' is a reserved word.
How can I make use of modules?
Not sure if you will be able to use
import /export
. According to
this link these keywords are part of the ECMA v6 specification, but we are using ECMA v5 in Oolite.
Disclaimer: this is my own interpretation, I am not JS-savvy and could be wrong, but this is what a brief net search turned up for me.
Re: Scripters cove
Posted: Wed Aug 07, 2024 8:10 pm
by hiran
another_commander wrote: ↑Wed Aug 07, 2024 6:30 am
hiran wrote: ↑Wed Aug 07, 2024 5:40 am
Beginner problem. I am new to JavaScript and want to organize my code. That means I want to split it across several source files.
I ran through tutorials which lead me to modules and import/export directives. Unfortunately when I create a .js file and try to import it into my world script Oolite complains that 'import' is a reserved word.
How can I make use of modules?
Not sure if you will be able to use
import /export
. According to
this link these keywords are part of the ECMA v6 specification, but we are using ECMA v5 in Oolite.
Disclaimer: this is my own interpretation, I am not JS-savvy and could be wrong, but this is what a brief net search turned up for me.
So the Oolite version of JavaScript does not know about modules and imports? Why does it complain then?
And if modules are out of scope, what can I use to organize my code? I want to put reusable class definitions into separate files.
Just to give some more detail: With a world script like this...
Code: Select all
"use strict";
import {ink} from "ink/ink.js"
import {storyContent} from "story.js"
this.name = "InkTemplate"; // this name must be unique among all OXPs
...I am getting log output like that:
Code: Select all
22:16:54.892 [script.javaScript.exception.reservedID]: ***** JavaScript exception (InkTemplate.anon-script): SyntaxError: import is a reserved identifier
22:16:54.892 [script.javaScript.exception.reservedID]: AddOns/InkTemplate.oxp/Config/script.js, line 3: import {ink} from "ink/ink.js"
22:16:54.893 [script.javaScript.load.failed]: ***** Error loading JavaScript script AddOns/InkTemplate.oxp/Config/script.js -- compilation failed
Re: Scripters cove
Posted: Thu Aug 08, 2024 1:39 am
by Nite Owl
By no means an expert but until an expert does show up lets give this a shot.
You have several uniquely named JavaScript files in a folder named
Scripts in your OXZ/OXP. You want these to be loaded by Oolite when the game starts. What you need is a
world-scripts.plist file in the
Config folder of your OXZ/OXP. You are going too deep with the
import and
this.name functions. They should not be needed as the
world-scripts.plist file is just an array of the JavaScript files in the
Scripts folder that Oolite will load at startup. For more on the
world-scripts.plist file see
HERE.
Is this what you are looking for?
Re: Scripters cove
Posted: Thu Aug 08, 2024 1:59 am
by Wildeblood
hiran wrote: ↑Wed Aug 07, 2024 8:10 pm
So the Oolite version of JavaScript does not know about modules and imports? Why does it complain then?
It complains because javascript, like any competently written specification, includes a list of reserved words pertaining to features hoped to be included in future versions.
hiran wrote: ↑Wed Aug 07, 2024 8:10 pm
And if modules are out of scope, what can I use to organize my code? I want to put reusable class definitions into separate files.
There's your problem: you want something that is not allowed: access to the file system. There's no access to script
files after Oolite loads.
hiran wrote: ↑Wed Aug 07, 2024 8:10 pm
Just to give some more detail: With a world script like this...
Code: Select all
"use strict";
import {ink} from "ink/ink.js"
import {storyContent} from "story.js"
this.name = "InkTemplate"; // this name must be unique among all OXPs
Put anything you want accessible from other scripts into a world-script. And, if re-usable by more than one script, copy it across (at startUp, startUpComplete or any time after). That's the best you're going to get.
Code: Select all
"use strict";
this.startUpComplete = function () {
let that = worldScripts.hiran_helper_scripts // script's name property, not filename.
this.storyContent = that.storyContent;
}
this.name = "InkTemplate"; // this name must be unique among all OXPs
Grab a micro-OXZ called "Untrumbled" for an example of looping over (prop in that) to
delete, um I mean manipulate,
almost the whole script (there are three properties you can't touch).
Re: Scripters cove
Posted: Thu Aug 08, 2024 7:59 pm
by hiran
The world-script.plist approach helped. At least Oolite loads the different scripts and complained about them not having "use strict" - which I fixed.
But then I still see this output:
Code: Select all
21:53:07.644 [script.javaScript.exception.illegalCharacter]: ***** JavaScript exception (main.js.anon-script): SyntaxError: illegal character
21:53:07.644 [script.javaScript.exception.illegalCharacter]: AddOns/InkTemplate.oxp/Scripts/main.js, line 65: choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>`;
21:53:07.644 [script.javaScript.load.failed]: ***** Error loading JavaScript script AddOns/InkTemplate.oxp/Scripts/main.js -- compilation failed
21:53:07.644 [script.load.notFound]: ***** ERROR: Could not find script file main.js.
21:53:07.657 [script.javaScript.exception.notDefined]: ***** JavaScript exception (ink.js.anon-script): ReferenceError: Map is not defined
21:53:07.657 [script.javaScript.exception.notDefined]: AddOns/InkTemplate.oxp/Scripts/ink/ink.js, line 2.
21:53:07.661 [script.javaScript.load.failed]: ***** Error loading JavaScript script AddOns/InkTemplate.oxp/Scripts/ink/ink.js -- could not run script
21:53:07.661 [script.load.notFound]: ***** ERROR: Could not find script file ink/ink.js.
So both script files main.js and ink.js still have a problem, for which they do not get loaded and thus I have the resulting last line "Could not find script file".
But for the errors themselves I am unsure:
- what is the illegal character I need to look for? Line 65 is even quoted in the error log and I do not see a flaw.
- Oolite is right about ink.js.anon-script: this file does not exist. Should It? Is it possible the compiler tries to create some intermediate file that is not part of my world-script.plist and thus there is a problem?
Re: Scripters cove
Posted: Thu Aug 08, 2024 9:31 pm
by Wildeblood
hiran wrote: ↑Thu Aug 08, 2024 7:59 pm
The world-script.plist approach helped. At least Oolite loads the different scripts and complained about them not having "use strict" - which I fixed.
But then I still see this output:
- what is the illegal character I need to look for? Line 65 is even quoted in the error log and I do not see a flaw.
- Oolite is right about ink.js.anon-script: this file does not exist. Should It?
Code: Select all
line 65: choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>` <------ Probably that Spanish apostrophe, or whatever it is.
ink.js.anon-script is just a reference to ink.js before it has been successfully parsed, AFAIK.
Re: Scripters cove
Posted: Fri Aug 09, 2024 5:02 am
by hiran
Wildeblood wrote: ↑Thu Aug 08, 2024 9:31 pm
hiran wrote: ↑Thu Aug 08, 2024 7:59 pm
The world-script.plist approach helped. At least Oolite loads the different scripts and complained about them not having "use strict" - which I fixed.
But then I still see this output:
- what is the illegal character I need to look for? Line 65 is even quoted in the error log and I do not see a flaw.
- Oolite is right about ink.js.anon-script: this file does not exist. Should It?
Code: Select all
line 65: choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>` <------ Probably that Spanish apostrophe, or whatever it is.
Got it! I had checked the backticks, they are needed because that is a 'template string literal' (see
https://www.freecodecamp.org/news/templ ... avascript/). But the caveat is that it was introduced in ES6, and Oolite is not on that level.
I turned this back into classic stream concatenation and am hitting the next error. So far ok.
Wildeblood wrote: ↑Thu Aug 08, 2024 9:31 pm
ink.js.anon-script is just a reference to ink.js before it has been successfully parsed, AFAIK.
Ok, then I will ignore that item and focus on the other messages.
So now I have Oolite trying to load three scripts. One of them wants to access a variable defined in one of the others. How can I refer to that?
Re: Scripters cove
Posted: Fri Aug 09, 2024 7:33 am
by Wildeblood
hiran wrote: ↑Fri Aug 09, 2024 5:02 am
Wildeblood wrote: ↑Thu Aug 08, 2024 9:31 pm
hiran wrote: ↑Thu Aug 08, 2024 7:59 pm
The world-script.plist approach helped. At least Oolite loads the different scripts and complained about them not having "use strict" - which I fixed.
But then I still see this output:
- what is the illegal character I need to look for? Line 65 is even quoted in the error log and I do not see a flaw.
- Oolite is right about ink.js.anon-script: this file does not exist. Should It?
Code: Select all
line 65: choiceParagraphElement.innerHTML = `<a href='#'>${choice.text}</a>` <------ Probably that Spanish apostrophe, or whatever it is.
Got it! I had checked the backticks, they are needed because that is a 'template string literal' (see
https://www.freecodecamp.org/news/templ ... avascript/). But the caveat is that it was introduced in ES6, and Oolite is not on that level.
I turned this back into classic stream concatenation and am hitting the next error. So far ok.
Wildeblood wrote: ↑Thu Aug 08, 2024 9:31 pm
ink.js.anon-script is just a reference to ink.js before it has been successfully parsed, AFAIK.
Ok, then I will ignore that item and focus on the other messages.
So now I have Oolite trying to load three scripts. One of them wants to access a variable defined in one of the others. How can I refer to that?
Define "access". Read, copy or change? You'll need to use the full reference from worldScripts up/down the object tree/path at least once.
worldScripts["Big chunks of data"].$omeCategory.someSubCat.onAndOn.anActualValue
Once you've located an object that doesn't have any more sub-objects and will evaluate to a number, string or Boolean, you can just use it immediately then forget about it...
if (5 < worldScripts["Big chunks of data"].$omeCategory.someSubCat.onAndOn.anActualValue) {}
Or, if you're suspicious of its character, you can (evaluate) it and use it...
if (5 < (worldScripts["Big chunks of data"].$omeCategory.someSubCat.onAndOn.anActualValue) ) {}
If the words iterate, loop or re-use are being mentioned, you'll want a local copy...
within a function...
var i = worldScripts["Big chunks of data"].$omeCategory.someSubCat.onAndOn.anActualValue
for your worldScript...
this.importantValue = worldScripts["Big chunks of data"].$omeCategory.someSubCat.onAndOn.anActualValue