Scripters cove

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Forcing re-draw of GUI screen without changing screens?

Post 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?
In your heart, you know it's flat.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4830
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post 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.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4830
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post 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.
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post by Wildeblood »

phkb wrote: Mon Jul 29, 2024 10:45 pm
I 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. :mrgreen:
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?
In your heart, you know it's flat.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4830
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post by phkb »

Wildeblood wrote: Tue Jul 30, 2024 6:22 pm
Can I call that without harming anything?
Absolutely!
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post by Wildeblood »

phkb wrote: Fri Aug 02, 2024 7:15 am
Absolutely!
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?
In your heart, you know it's flat.
User avatar
hiran
Theorethicist
Posts: 2403
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Scripters cove

Post 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?
Sunshine - Moonlight - Good Times - Oolite
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6682
Joined: Wed Feb 28, 2007 7:54 am

Re: Scripters cove

Post 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.
User avatar
hiran
Theorethicist
Posts: 2403
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Scripters cove

Post 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
Sunshine - Moonlight - Good Times - Oolite
User avatar
Nite Owl
---- E L I T E ----
---- E L I T E ----
Posts: 556
Joined: Sat Jan 20, 2018 4:08 pm
Location: In The Dark

Re: Scripters cove

Post 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?
Humor is the second most subjective thing on the planet

Brevity is the soul of wit and vulgarity is wit's downfall

Good Night and Good Luck - Read You Soon
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post 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).
Last edited by Wildeblood on Fri Aug 09, 2024 7:37 am, edited 1 time in total.
In your heart, you know it's flat.
User avatar
hiran
Theorethicist
Posts: 2403
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Scripters cove

Post 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?
Sunshine - Moonlight - Good Times - Oolite
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post 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.
User avatar
hiran
Theorethicist
Posts: 2403
Joined: Fri Mar 26, 2021 1:39 pm
Location: a parallel world I created for myself. Some call it a singularity...

Re: Scripters cove

Post 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?
Sunshine - Moonlight - Good Times - Oolite
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post 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
In your heart, you know it's flat.
Post Reply