How to make a simple OXP?
Moderators: winston, another_commander
How to make a simple OXP?
Sorry for partially asking this in another thread but I'll really struggling to get anywhere with this and need a basic example to get going. I have tried trolling through the wiki and used the search but alas no joy. Any help would be much appreciated
Very simple OXP #1
How do I make the game simply have a message pop up at docking that says "welcome space ball"
Slightly more complex OXP #2
For system LAVE only, make pythons the only NPC ships in it (other than GALCop vipers). Am interested to see which file is used and what probabilities are assigned to each ship type per sys
Slightly more complex yet OXP #3
Inputing a new ship into the game. Lets say I've created a ship called "PumaClipper.dat". Now I can sort of see from existing OXP's (snippet from Awing Below is copied) what the ship.plist files do but is there a reference guide as to what each value means? - I've asked some questions amidst the text below
Q1. How does the source code know to read this oxp in and does it replace another ship with the A wing?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>a-wing</key>
<dict>
<key>aft_eject_position</key>
<string>0.0 0.0 -1.0</string>
Q2. What do these values mean for aft_eject_position?
<key>ai_type</key>
<string>pirateAI.plist</string>
Q3. Is this saying make it a pirate ship? How could I make it also a ship used for trading etc?
<key>bounty</key>
<string>200</string>
<key>cargo_type</key>
<string>CARGO_NOT_CARGO</string>
<key>energy_recharge_rate</key>
<real>3.5</real>
Q4. WHat is 3.5 - is this good or only average recharge rate- what do other ships have?
Very simple OXP #1
How do I make the game simply have a message pop up at docking that says "welcome space ball"
Slightly more complex OXP #2
For system LAVE only, make pythons the only NPC ships in it (other than GALCop vipers). Am interested to see which file is used and what probabilities are assigned to each ship type per sys
Slightly more complex yet OXP #3
Inputing a new ship into the game. Lets say I've created a ship called "PumaClipper.dat". Now I can sort of see from existing OXP's (snippet from Awing Below is copied) what the ship.plist files do but is there a reference guide as to what each value means? - I've asked some questions amidst the text below
Q1. How does the source code know to read this oxp in and does it replace another ship with the A wing?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>a-wing</key>
<dict>
<key>aft_eject_position</key>
<string>0.0 0.0 -1.0</string>
Q2. What do these values mean for aft_eject_position?
<key>ai_type</key>
<string>pirateAI.plist</string>
Q3. Is this saying make it a pirate ship? How could I make it also a ship used for trading etc?
<key>bounty</key>
<string>200</string>
<key>cargo_type</key>
<string>CARGO_NOT_CARGO</string>
<key>energy_recharge_rate</key>
<real>3.5</real>
Q4. WHat is 3.5 - is this good or only average recharge rate- what do other ships have?
Re: How to make a simple OXP?
The absolute simplest way to do this: your OXP folder contains a single sub-folderhangar18 wrote:Very simple OXP #1
How do I make the game simply have a message pop up at docking that says "welcome space ball"
Config
, which contains a single script.js
file. That file contains Javascript code:
Code: Select all
this.name = "hangar18's first OXP"; // this name must be unique among all OXPs
// defines code to be run at the start of the docking sequence
this.shipWillDockWithStation = function(station) {
player.addMessageToArrivalReport("welcome space ball"); // add the message to the arrival report
}
Slightly more complex would be to use
mission.runScreen
to display a mission screen, rather than a short-text arrival report.This is quite a bit more than "slightly more complex". It's not impossible, but this is difficult.hangar18 wrote:Slightly more complex OXP #2
For system LAVE only, make pythons the only NPC ships in it (other than GALCop vipers). Am interested to see which file is used and what probabilities are assigned to each ship type per sys
In summary:
- all systems have the same ship type probability distribution
- ships are added to the system by role, rather than by ship type (see the "roles" key in shipdata.plist)
- the roles from shipdata.plist are added together to make a probability distribution for each role. So if you had only three ships in the game with roles:
A =>
roles = "pirate hunter";
B =>
roles = "pirate(2) trader";
C =>
roles = "hunter trader";
and you asked the game to add a large number of pirates, two-thirds of them would be Bs, one-third would be As, and none would be Cs.
- the initial distribution of roles throughout the system is currently hard-coded for the standard roles (hunter, pirate, trader, miner, police, asteroid, thargoid)
- once the initial distribution has been gone through, you can use
system.addShips
or system.addGroup
in the shipWillExitWitchspace
event handler to add extra ships, and ship.remove
to remove ships you don't want.Later versions will probably include a more flexible way of influencing the initial ship distribution.
This is quite a bit easier than OXP 2, at the moment. [wiki]shipdata.plist[/wiki] is, along with the other plist files, linked from [wiki]OXP_howto[/wiki] and should answer most of your questions on specific keys.hangar18 wrote:Slightly more complex yet OXP #3
Inputing a new ship into the game. Lets say I've created a ship called "PumaClipper.dat". Now I can sort of see from existing OXP's (snippet from Awing Below is copied) what the ship.plist files do but is there a reference guide as to what each value means? - I've asked some questions amidst the text below
As above, see the "roles" key. When the game (either the core game, or another OXP) asks for a ship with one of those roles, the game may add it.hangar18 wrote:Q1. How does the source code know to read this oxp in and does it replace another ship with the A wing?
This is where mines and cargo pods will be ejected from the ship, relative to the origin of the model. The A-wing is a bad example, as this position really needs to be slightlyhangar18 wrote:<key>aft_eject_position</key>
<string>0.0 0.0 -1.0</string>
Q2. What do these values mean for aft_eject_position?
outside
the ship model.This is the AI it will get if added in a non-standard role. Ships added in the standard roles (trader, hunter, pirate, police, etc.) get given a different AI by default (unlesshangar18 wrote:<key>ai_type</key>
<string>pirateAI.plist</string>
Q3. Is this saying make it a pirate ship? How could I make it also a ship used for trading etc?
"auto_ai"
has been turned off). So you could add this ship with a non-standard role to add a pack of specifically A-wing pirates to the system.To make a ship in a non-standard role act like a trader, use
route1traderAI.plist
here.Energy recharge rate is measured in 64ths of an energy bank per second. 3.5 is decent though not particularly notable, 4 is good, and anything over 4.5 is outside the range used by playable core Oolite ships (and has game balance implications if used on a player ship, though on an NPC-only variant it's fine)hangar18 wrote:<key>energy_recharge_rate</key>
<real>3.5</real>
Q4. WHat is 3.5 - is this good or only average recharge rate- what do other ships have?
- Diziet Sma
- ---- E L I T E ----
- Posts: 6311
- Joined: Mon Apr 06, 2009 12:20 pm
- Location: Aboard the Pitviper S.E. "Blackwidow"
Re: How to make a simple OXP?
To begin with, I should caution you that I'm an utter neophyte when it comes to this stuff, but here's what I can tell you...
b) The A-Wing does not replace any ships. It is added to the Ooniverse as simply another ship-type which the game-engine may choose from when populating a system. Replacing a core ship is a little more involved than simply adding another ship type. (this is not an area I'm familiar with, so I'll leave that to someone else to discuss)
In it, it says:
Useful Reference Links:
http://wiki.alioth.net/index.php/OXP_tutorial
http://wiki.alioth.net/index.php/Catego ... _Reference (This one points to lots of good info)
http://wiki.alioth.net/index.php/Script ... JavaScript
Some other useful references:
http://wiki.alioth.net/index.php/OXP_howto_plist
http://wiki.alioth.net/index.php/Shipdata.plist
http://wiki.alioth.net/index.php/Shipyard.plist
http://wiki.alioth.net/index.php/Hud.plist
http://wiki.alioth.net/index.php/Equipment.plist
http://wiki.alioth.net/index.php/Planetinfo.plist
http://wiki.alioth.net/index.php/Script.plist
http://wiki.alioth.net/index.php/Customsounds.plist
http://wiki.alioth.net/index.php/Effectdata.plist
There's probably more, but that lot should help..
Edit: ninja'd by cim!
Yes, there certainly is.. see below.hangar18 wrote:Slightly more complex yet OXP #3
Inputing a new ship into the game. Lets say I've created a ship called "PumaClipper.dat". Now I can sort of see from existing OXP's (snippet from Awing Below is copied) what the ship.plist files do but is there a reference guide as to what each value means?
a) The source code doesn't read anything.. that's handled by the running Oolite code. As part of the startup sequence, Oolite checks the AddOns folder to see if any OXP folders have been added or removed. If this is found to be the case, (or a cache-rebuild has been forced by shift-starting the game) it will reload all the OXP files, parse them for correctness, and add the resulting set of OXP files and code to its' cache, in order to speed up the next game-start.hangar18 wrote:- I've asked some questions amidst the text below
Q1. How does the source code know to read this oxp in and does it replace another ship with the A wing?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>a-wing</key>
<dict>
b) The A-Wing does not replace any ships. It is added to the Ooniverse as simply another ship-type which the game-engine may choose from when populating a system. Replacing a core ship is a little more involved than simply adding another ship type. (this is not an area I'm familiar with, so I'll leave that to someone else to discuss)
This seems as good a place as any to introduce the Reference for the shipdata.plist: http://wiki.alioth.net/index.php/Shipdata.plisthangar18 wrote:<key>aft_eject_position</key>
<string>0.0 0.0 -1.0</string>
Q2. What do these values mean for aft_eject_position?
In it, it says:
Soaft_eject_position
Determines the XYZ point on the model from which cargo is ejected.
Example:
"aft_eject_position" = "0.0 -4.5 -23.0";
<string>0.0 0.0 -1.0</string>
can be interpreted as 'on the X-axis midpoint, on the Y-axis midpoint, one metre aft of the Z-axis midpoint'. In the example quoted from the Wiki, it would be, 'on the X-axis midpoint, 4.5 metres below the Y-axis midpoint, and 23 metres aft of the Z-axis midpoint'.See cim's reply above.hangar18 wrote:<key>ai_type</key>
<string>pirateAI.plist</string>
Q3. Is this saying make it a pirate ship? How could I make it also a ship used for trading etc?
Again, the shipdata.plist Reference tell us that:hangar18 wrote:<key>energy_recharge_rate</key>
<real>3.5</real>
Q4. WHat is 3.5 - is this good or only average recharge rate- what do other ships have?
Energy_recharge_rates can vary quite a bit.. the best way for you to get a feel for what is typical is to look at the energy_recharge_rate of a variety of ships, both core and OXP, and see what ships in the class(es) similar to what you have in mind are using.energy_recharge_rate
The rate at which energy is replenished. Stations are at 100, Adders at 2. (Default value: 1)
Example:
"energy_recharge_rate" = "3.5";
Useful Reference Links:
http://wiki.alioth.net/index.php/OXP_tutorial
http://wiki.alioth.net/index.php/Catego ... _Reference (This one points to lots of good info)
http://wiki.alioth.net/index.php/Script ... JavaScript
Some other useful references:
http://wiki.alioth.net/index.php/OXP_howto_plist
http://wiki.alioth.net/index.php/Shipdata.plist
http://wiki.alioth.net/index.php/Shipyard.plist
http://wiki.alioth.net/index.php/Hud.plist
http://wiki.alioth.net/index.php/Equipment.plist
http://wiki.alioth.net/index.php/Planetinfo.plist
http://wiki.alioth.net/index.php/Script.plist
http://wiki.alioth.net/index.php/Customsounds.plist
http://wiki.alioth.net/index.php/Effectdata.plist
There's probably more, but that lot should help..
Edit: ninja'd by cim!
Most games have some sort of paddling-pool-and-water-wings beginning to ease you in: Oolite takes the rather more Darwinian approach of heaving you straight into the ocean, often with a brick or two in your pockets for luck. ~ Disembodied
- PhantorGorth
- ---- E L I T E ----
- Posts: 647
- Joined: Wed May 20, 2009 6:48 pm
- Location: Somewhere off the top left of Galaxy 1 map
Re: How to make a simple OXP?
hangar18 wrote:Sorry for partially asking this in another thread but I'll really struggling to get anywhere with this and need a basic example to get going. I have tried trolling through the wiki and used the search but alas no joy. Any help would be much appreciated
Very simple OXP #1
How do I make the game simply have a message pop up at docking that says "welcome space ball"
That involves one event "shipWillDockWithStation" you use to add an arrival message:
Code: Select all
this.name = "My OXP Name";
this.author = "Me";
this.copyright = "Some license: e.g. Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.";
this.description = "Welcome Message";
this.version = "0.0.1";
this.shipWillDockWithStation = function (station)
{
player.addMessageToArrivalReport("welcome space ball");
}
Why would you want to do this? If it is purely to find out how the system populator works that I will say that it is well documented. Check this out: http://wiki.alioth.net/index.php/System_Populator. The details are in the source code in the file Universe.m in the method populateSpaceFromHyperPoint though unless you are used to reading source code that may be more effort than you are wanting to do. I won't bother to discuss weighting values as Cim has covered that. Diziet Sma has pointed you at other wiki resources for your 3rd OXP.hangar18 wrote:Slightly more complex OXP #2
For system LAVE only, make pythons the only NPC ships in it (other than GALCop vipers). Am interested to see which file is used and what probabilities are assigned to each ship type per sys
Last edited by PhantorGorth on Wed Apr 24, 2013 7:51 am, edited 1 time in total.
Chat and relax with other commanders in the [url=irc://irc.oftc.net/oolite]DS's Seedy Space Bar[/url]. The Coolest Bar in the Eight.
Phantor's OXPs: GalCop Rewards and Safe Docking
Phantor's OXPs: GalCop Rewards and Safe Docking
Re: How to make a simple OXP?
Many thanks guys! In the case of OXP 1 how did you know the variable/function names to use - is there a reference guide somewhere?
e.g. how does the 'source code' know what this line means 'this.shipWillDockWithStation' and what to do with it once its read in. Is the original source code defined in terms of a variable or oop called shipwilldockwithstation or is each part of this interpreted separated eg ship then wildoock then withstation...Can you give me the step by step 'thought process' of the computer so I can get a feel of what to do in changing other bits of code?
e.g. how does the 'source code' know what this line means 'this.shipWillDockWithStation' and what to do with it once its read in. Is the original source code defined in terms of a variable or oop called shipwilldockwithstation or is each part of this interpreted separated eg ship then wildoock then withstation...Can you give me the step by step 'thought process' of the computer so I can get a feel of what to do in changing other bits of code?
- PhantorGorth
- ---- E L I T E ----
- Posts: 647
- Joined: Wed May 20, 2009 6:48 pm
- Location: Somewhere off the top left of Galaxy 1 map
Re: How to make a simple OXP?
This is all documented in the wiki's javascript reference: http://wiki.alioth.net/index.php/Catego ... _Reference.hangar18 wrote:Many thanks guys! In the case of OXP 1 how did you know the variable/function names to use - is there a reference guide somewhere?
e.g. how does the 'source code' know what this line means 'this.shipWillDockWithStation' and what to do with it once its read in. Is the original source code defined in terms of a variable or oop called shipwilldockwithstation or is each part of this interpreted separated eg ship then wildoock then withstation...Can you give me the step by step 'thought process' of the computer so I can get a feel of what to do in changing other bits of code?
It's a function stored as a variable. (Called an anonymous function) the "this." object is your OXP script which is loaded using the variable this.name. So in future you can reference code in your OXP using the form worldScripts.<oxpname>.<functionname> or worldScripts.["<oxpname>"].<functionname> (the second form is required if your script name has space in it.)
When it Oolite reaches the point in its code for the appropriate event eg shipWillDockWithStation it looks though the worldscripts and calls all the this.shipWillDockWithStation loaded. In this case passing the station object to the function. (Which we happen not to bother using.)
It will call your OXP's shipWillDockWithStation function: The line player.addMessageToArrivalReport is then called passing the text "welcome space ball" to it. This method of the player object then adds that message to the arrival messages and Oolite when it get to the right point displays those messages.
Please note shipWillDockWithStation is not broken down is it just a function name that oolite recognises as a whole name.
Edited for grammatical errors and typos
Last edited by PhantorGorth on Wed Apr 24, 2013 8:10 am, edited 4 times in total.
Chat and relax with other commanders in the [url=irc://irc.oftc.net/oolite]DS's Seedy Space Bar[/url]. The Coolest Bar in the Eight.
Phantor's OXPs: GalCop Rewards and Safe Docking
Phantor's OXPs: GalCop Rewards and Safe Docking
Re: How to make a simple OXP?
All the Javascript properties and methods are listed at Oolite Javascript Referencehangar18 wrote:Many thanks guys! In the case of OXP 1 how did you know the variable/function names to use - is there a reference guide somewhere?
shipWillDockWithStation
is a world script event handler (there's a link on the above page for a list of those).Event handlers are initiated within the core game code when particular things happen. When the core game code decides that the "
shipWillDockWithStation
" world event handler should be run (which happens whenever the player is starting to dock with a station), it does the following:1) Look through all the worldscripts. Worldscripts are any
Config/script.js
file in an OXP, and any file in the Scripts/
directory of an OXP which is listed in the Config/world-scripts.plist
file of that OXP.2) For each worldscript, see if it defines the variable
this.shipWillDockWithStation
. (this
is the Javascript reference to the worldscript itself)3) If it does, see if that variable contains a Javascript function.
4) If it does, run that function (and in this case, pass it the
station
parameter to say what station is being docked with)The order in which worldscripts are checked for event handlers is not defined and will vary from install to install.
Handler names are exact strings, not made up of components (though we try to keep a consistent naming scheme for them, so they might look like they're made of components).
There are also ship script event handlers. These are defined in the ship's script file (many ships do not need a script file at all as they do not need to do anything special for event handlers). Each ship may have one and only one ship script. The ship script event handlers run for that ship when the event happens to that ship. So "shipWillDockWithStation" will fire in a ship script when that ship docks with a station, but not when a different ship docks with a station, even if that other ship is using the same script file.
- Commander McLane
- ---- E L I T E ----
- Posts: 9520
- Joined: Thu Dec 14, 2006 9:08 am
- Location: a Hacker Outpost in a moderately remote area
- Contact:
Re: How to make a simple OXP?
I'm sorry, but I don't understand what you're doing here.hangar18 wrote:Many thanks guys! In the case of OXP 1 how did you know the variable/function names to use - is there a reference guide somewhere?
At the point where you ask the question you have already been given more than a dozen links to the very reference guides that you're asking for. Do you intentionally ignore the answers you are given, in order to ask the same question again and again? Are you perhaps not aware that blue text in the answers you are given is a clickable link? Please click on it. You will arrive at something called the Elite Wiki, which has a huge section dedicated to documentation of every scripting feature in Oolite.
In another thread you were given a link to a how-to-guide for creating OXPs very early on. On that page you find links to all the rest of the documentation and reference documents. Cim gave you the link again in his answer above. I don't understand why you keep asking questions that are clearly answered in the documentation that you were already given. If you want to learn to create OXPs, you are supposed to read the documentation and reference documents, not having other people do that for you.
Again, sorry for stepping on your toes. You have mentioned that you already have programming experience. Therefore I think you can be expected to actually read and understand the documentation and reference documents that helpful souls have provided for exactly this purpose. Please take the time and do.
- Smivs
- Retired Assassin
- Posts: 8408
- Joined: Tue Feb 09, 2010 11:31 am
- Location: Lost in space
- Contact:
Re: How to make a simple OXP?
Also, there are two alternative languages that can be used for plists. The example you have used is the old XML code which is cumbersome and much harder to read and bugfix than the prefered OpenStep. The above code in OpenStep iscim wrote:... The A-wing is a bad example, as this position really needs to be slightlyhangar18 wrote:<key>aft_eject_position</key>
<string>0.0 0.0 -1.0</string>
Q2. What do these values mean for aft_eject_position?outside
the ship model.
Code: Select all
aft_eject_position = "0.0 0.0 -1.0";
Both types are detailed here on the wiki.
The actual Oolite plists (for the core game) are written in OpenStep so they are probably the best resource/example to use, or choose a more up-to-date OXP to use as a template.
Commander Smivs, the friendliest Gourd this side of Riedquat.
Re: How to make a simple OXP?
You're sorry for stepping on my toes as you continue to trample on regardless. Hmmm does your left hand not know what the right is doing perhaps? I clicked on a few of the guides...yes they were helpful but didn't answer the specific questions I was asking. I was looking for quick answers to get started quickly as I don't have much free time these days (who does, I know). So Yes i probably did overstep the mark in terms of spoon feeding and apologise for that as it seems to have 'agitated' you somewhat.Commander McLane wrote:I'm sorry, but I don't understand what you're doing here.hangar18 wrote:Many thanks guys! In the case of OXP 1 how did you know the variable/function names to use - is there a reference guide somewhere?
At the point where you ask the question you have already been given more than a dozen links to the very reference guides that you're asking for. Do you intentionally ignore the answers you are given, in order to ask the same question again and again? Are you perhaps not aware that blue text in the answers you are given is a clickable link? Please click on it. You will arrive at something called the Elite Wiki, which has a huge section dedicated to documentation of every scripting feature in Oolite.
In another thread you were given a link to a how-to-guide for creating OXPs very early on. On that page you find links to all the rest of the documentation and reference documents. Cim gave you the link again in his answer above. I don't understand why you keep asking questions that are clearly answered in the documentation that you were already given. If you want to learn to create OXPs, you are supposed to read the documentation and reference documents, not having other people do that for you.
Again, sorry for stepping on your toes. You have mentioned that you already have programming experience. Therefore I think you can be expected to actually read and understand the documentation and reference documents that helpful souls have provided for exactly this purpose. Please take the time and do.
I certainly know what I'm doing on here....less certain with you, apart from bashing new guys in order to stroke your mighty ego. In future drop the schoolmaster tone, Ok champ?
Many thanks to the rest of you (who seem to have a fuse longer than 6mm) for your help...am slowly getting there.
Re: How to make a simple OXP?
Surprise! (Yep, kind of still around - well, not really - but RL, oh dear, RL!)
About 'simple OXP' #2: create a lavepytons.oxp containing a Config directory.
Inside that directory create a shipdata.plist file containig the following:
Discuss!
Cheers,
Kaks.
PS: Tinkering-wise, it's really worth looking through the whole alioth net wiki at least once: what looks like a jumble of semi-random information does tend to yield some surprising rewards, a fewweeks months years down the line!
PPS: I had very little time just now, so the above is 'slightly' untested, but from a distance, and squinting a bit, it looks like it might just work! Apologies in advance if there's a missing semicolon or some such...
About 'simple OXP' #2: create a lavepytons.oxp containing a Config directory.
Inside that directory create a shipdata.plist file containig the following:
Code: Select all
{
"lavepython" =
{
like_ship = "python";
conditions = (
"galaxy_number equal 0",
"planet_number equal 7"
);
roles = "pirate(999999.9) hunter(999999.9) miner(999999.9) scavenger(999999.9) trader(999999.9) sunskim-trader(999999.9)";
}
}
Cheers,
Kaks.
PS: Tinkering-wise, it's really worth looking through the whole alioth net wiki at least once: what looks like a jumble of semi-random information does tend to yield some surprising rewards, a few
PPS: I had very little time just now, so the above is 'slightly' untested, but from a distance, and squinting a bit, it looks like it might just work! Apologies in advance if there's a missing semicolon or some such...
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
Re: How to make a simple OXP?
Many thanks manKaks wrote:Surprise! (Yep, kind of still around - well, not really - but RL, oh dear, RL!)
About 'simple OXP' #2: create a lavepytons.oxp containing a Config directory.
Inside that directory create a shipdata.plist file containig the following:
Discuss!Code: Select all
{ "lavepython" = { like_ship = "python"; conditions = ( "galaxy_number equal 0", "planet_number equal 7" ); roles = "pirate(999999.9) hunter(999999.9) miner(999999.9) scavenger(999999.9) trader(999999.9) sunskim-trader(999999.9)"; } }
Cheers,
Kaks.
PS: Tinkering-wise, it's really worth looking through the whole alioth net wiki at least once: what looks like a jumble of semi-random information does tend to yield some surprising rewards, a fewweeksmonthsyears down the line!
PPS: I had very little time just now, so the above is 'slightly' untested, but from a distance, and squinting a bit, it looks like it might just work! Apologies in advance if there's a missing semicolon or some such...