Are sub-OXPs possible?
Moderators: winston, another_commander
- Cmdr. Maegil
- Sword-toting nut-job
- Posts: 1294
- Joined: Tue Feb 27, 2007 10:28 pm
- Location: On the mend in Western Africa
Are sub-OXPs possible?
Is it possible for an OXP to read data from another?
More specifically, can wr make the Hoopy OXP search for others (e.g.: Lounge*.OXP), choose one of the available, print text from it on the mission screen and then start the second OXP's script?
This came to me while muling over the pilot's lounge screen: even if Ahruman won't fit one to the game itself, it could still be made on the Hoopys.
Beguinning by adding an option to go to the lounge to the gamble yes/no screen, do a brief description of the ambient and some of the patrons, -adding one from the mission OXP- and putting a sequence of choices that will trigger the mission (or not).
What do you think?
More specifically, can wr make the Hoopy OXP search for others (e.g.: Lounge*.OXP), choose one of the available, print text from it on the mission screen and then start the second OXP's script?
This came to me while muling over the pilot's lounge screen: even if Ahruman won't fit one to the game itself, it could still be made on the Hoopys.
Beguinning by adding an option to go to the lounge to the gamble yes/no screen, do a brief description of the ambient and some of the patrons, -adding one from the mission OXP- and putting a sequence of choices that will trigger the mission (or not).
What do you think?
You know those who, having been mugged and stabbed, fired, dog run over, house burned down, wife eloped with best friend, daughters becoming prostitutes and their countries invaded - still say that "all is well"?
I'm obviously not one of them.
I'm obviously not one of them.
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
OXPs can use each other’s resources. This has happened a few times accidentally. It’s also why it’s so important to make an effort to have unique names. :-)
There’s no way for legacy scripts to communicate with each other. However, I intend to make it possible to look for world scripts in JavaScript. Something like this:
This tells you whether the OXP with a script called “name-of-hoopy-script” is installed. It also lets you call methods on that script or set properties of that script.
Rather than having HOopy search for other scripts at startup, I’d have scripts which offer services/extensions to HOopy register themselves with HOopy at startup time. Conveniently, the startUp() event handler is called once at startup time, after all world scripts have been loaded. I’ve cooked up an example, but can’t test it yet because I have to implement the worldScripts object in Oolite first. (It was already on my to-do list.) Oh, and I’ve got to do some other stuff first.
There’s no way for legacy scripts to communicate with each other. However, I intend to make it possible to look for world scripts in JavaScript. Something like this:
Code: Select all
let hoopyScript = worldScripts["name-of-hoopy-script"]
if (hoopyScript)
{
// Do stuff relying on/interacting with hoopy script
}
Rather than having HOopy search for other scripts at startup, I’d have scripts which offer services/extensions to HOopy register themselves with HOopy at startup time. Conveniently, the startUp() event handler is called once at startup time, after all world scripts have been loaded. I’ve cooked up an example, but can’t test it yet because I have to implement the worldScripts object in Oolite first. (It was already on my to-do list.) Oh, and I’ve got to do some other stuff first.
E-mail: [email protected]
- LittleBear
- ---- E L I T E ----
- Posts: 2882
- Joined: Tue Apr 04, 2006 7:02 pm
- Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.
You could do it (in the current version of Oolite) by giving the piolts lounge screen when the player is docked at the HoOpy and the screen is status. This would mean the player only see the Lounge screen if docked at a HoOpy and had either said no to gambling or had finished gambling. Eg:-
Murgh uses this key to give the No option:-
Then your text would replace the No option in HoOpy and the player would know that by selecting No he goes to the piolts loung.
Your OXP would never do anything if the player didn't have HoOpy installed as the player could never meet the conditions. But if the player did and was docked at a HoOpy then your script with choices would be executed as soon as the Status screen came up and the player had chosen not to gamble.[/code]
Code: Select all
{
conditions = ("status_string equal STATUS_DOCKED", "dockedStationName_string equal CoachWhip hOopy Casino", "mission_hoopy_casino equal HOOPY_ENTER", missionChoice_string equal NO" "gui_screen_string equal GUI_SCREEN_STATUS);
do = (your stuff here...
Code: Select all
<key>NO</key>
<string>No games of hazard for me.</string>
[code]
If you put the same key in your OXP, but changed it to:-
[code]
<key>NO</key>
<string>No games of hazard for me, I'd rather check out the piolts lounge</string>
Your OXP would never do anything if the player didn't have HoOpy installed as the player could never meet the conditions. But if the player did and was docked at a HoOpy then your script with choices would be executed as soon as the Status screen came up and the player had chosen not to gamble.[/code]
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
LittleBear: yes, you could do that, but it’s rather inflexible. For instance, you couldn’t have more than one script extending HOopy that way. Cmdr. Maegil’s question suggested, to me, a need for greater flexibility.
Anyway, here’s a pair of scripts (currently only usable on my computer, but hey) which implement a client-server model. Any number of “client” scripts can register with the “server”, which can then call the client scripts to, well, do whatever needs to be done. In this case, to select mission screen contents and choices. (Actually, the ability to do this is somewhat limited since choices can still only be set by a missiontext.plist key. Hmm.)
This is somewhat more programmerese-intensive JavaScript than you’re likely to need for typical mission script ports. There are ostensibly similar, but clunkier, ways of achieving the same thing. Fortunately, it’s copy-and-pasteable; just copy-and-paste everything except the last two testing methods and *poof*!, your script is a server.
Incidentally, this is quite similar to the technique I outlined earlier for the racing OXP, except there a ship would be the server.
Server script template:
Example client script
Anyway, here’s a pair of scripts (currently only usable on my computer, but hey) which implement a client-server model. Any number of “client” scripts can register with the “server”, which can then call the client scripts to, well, do whatever needs to be done. In this case, to select mission screen contents and choices. (Actually, the ability to do this is somewhat limited since choices can still only be set by a missiontext.plist key. Hmm.)
This is somewhat more programmerese-intensive JavaScript than you’re likely to need for typical mission script ports. There are ostensibly similar, but clunkier, ways of achieving the same thing. Fortunately, it’s copy-and-pasteable; just copy-and-paste everything except the last two testing methods and *poof*!, your script is a server.
Incidentally, this is quite similar to the technique I outlined earlier for the racing OXP, except there a ship would be the server.
Server script template:
Code: Select all
this.name = "ahruman-test-server"
this.version = "1.0"
this.scriptRegistry = [] // empty array
// Add a script to the registry. Each client script should register itself this way.
this.registerScript = function(script)
{
if (script)
{
// Add script to scriptRegistry
this.scriptRegistry.push(script)
}
}
// Returns an array of the registered scripts.
this.registeredScripts = function()
{
return this.scriptRegistry
}
/* Calls the method "methodName" on each script, with arbitrary arguments.
Example: serverScript.callScripts("doSomething", 1, 3)
Calls doSomething(1, 3) on each registered script
which has a doSomething() method.
*/
this.callScripts = function(methodName)
{
/* Create an array variable based on the special variable "arguments",
which contains all the arguments (parameters) of the current function.
arguments looks like an Array, but it isn't. In particular, it doesn't
have the slice() method we'd otherwise use to get all but the first
element. (We want to remove the first element because that's the same
as methodNames, and we don't want to pass that to the script method.
*/
let methodArgs = []
for (let i = 1; i < arguments.length; i++)
{
methodArgs.push(arguments[i])
}
// Function which will be called for each script by forEach
function callScriptOn(script)
{
// If the script has a property called methodName...
if (script[methodName] != undefined)
{
let method = script[methodName]
// ...and the property is actually a method...
if (typeof method == "function")
{
// ...call method with object as "this" and the arguments.
method.apply(script, methodArgs)
}
}
}
// Apply callScriptOn() to all elements of scriptRegistry.
scriptRegistry.forEach(callScriptOn, this)
}
// For testing purposes, call script methods each time the player launches or docks.
this.didDock = function()
{
this.callScripts("testDockCallback", 42)
}
this.didLaunch = function()
{
this.callScripts("testLaunchCallback", "banana")
}
Code: Select all
this.name = "ahruman-test-client"
this.version = "1.0"
this.startUp = function()
{
if (worldScripts["ahruman-test-server"] != undefined)
{
// Server script is installed, register.
let server = worldScripts["ahruman-test-server"]
this.setUpClientMethods()
server.registerScript(this)
}
// Conserve memory by not keeping functions around that won't be called again.
delete this.startUp
delete this.setUpClientMethods
}
this.setUpClientMethods = function()
{
// Set up the methods the server will call.
this.testDockCallback = function(number)
{
LogWithClass("clientServerTest.dock", "The server tells me the player docked at docking slot " + number + ".")
}
this.testLaunchCallback = function(fruit)
{
LogWithClass("clientServerTest.launch", "The server tells me the player launched. The in-flight snack will be " + fruit + ".")
}
}
E-mail: [email protected]
- Eric Walch
- Slightly Grand Rear Admiral
- Posts: 5536
- Joined: Sat Jun 16, 2007 3:48 pm
- Location: Netherlands
LB's advise to change
into
Will not work. Both OXP's could react on the NO answer. Your response should be:
Make sure your OXP is loaded after HoOpy and you use the same keyname so it overwrites the original. HoOpy will never be triggered by the NO and your OXP is triggered by the "NO_PIOLTS_LOUNGE" response.
EDIT: and leave the mission_varriables as HoOpy intended, so change than as a NO would have done. And don't be supprised when things don't work when a new HoOpy release comes out. Fiddling with others OXP's should be avoided if possible.
Code: Select all
<key>NO</key>
<string>No games of hazard for me.</string>
into
Code: Select all
<key>NO</key>
<string>No games of hazard for me, I'd rather check out the piolts lounge</string>
Will not work. Both OXP's could react on the NO answer. Your response should be:
Code: Select all
<key>NO_PIOLTS_LOUNGE</key>
<string>No games of hazard for me, I'd rather check out the piolts lounge</string>
Make sure your OXP is loaded after HoOpy and you use the same keyname so it overwrites the original. HoOpy will never be triggered by the NO and your OXP is triggered by the "NO_PIOLTS_LOUNGE" response.
EDIT: and leave the mission_varriables as HoOpy intended, so change than as a NO would have done. And don't be supprised when things don't work when a new HoOpy release comes out. Fiddling with others OXP's should be avoided if possible.
- Arexack_Heretic
- Dangerous Subversive Element
- Posts: 1876
- Joined: Tue Jun 07, 2005 7:32 pm
- Location: [%H] = Earth surface, Lattitude 52°10'58.19"N, longtitude 4°30'0.25"E.
- Contact:
A reasonably safe way to acces other scripts is via the mission_variables they set.
Still, this leaves your OXP-dependent-OXP disables should the author of the primary OXP change it.
Safest way is to ask permission to use the content of said OXP and just add an alternate version of the hoopy or whatever.
No need to always have access to that lounge.
Offcourse this only works for scripts that add something, where the stuff happens. If things are triggered in a standard station, you are back to using the mission_variables.
(I don't think you can hijack another OXP, while it's running its script...
)
Still, this leaves your OXP-dependent-OXP disables should the author of the primary OXP change it.
Safest way is to ask permission to use the content of said OXP and just add an alternate version of the hoopy or whatever.
No need to always have access to that lounge.
Offcourse this only works for scripts that add something, where the stuff happens. If things are triggered in a standard station, you are back to using the mission_variables.
(I don't think you can hijack another OXP, while it's running its script...
)
Riding the Rocket!
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
That’s a thought… with JavaScript, it’s entirely possible for one script to rewrite another.Arexack_Heretic wrote:(I don't think you can hijack another OXP, while it's running its script...
)
E-mail: [email protected]
- Cmdr. Maegil
- Sword-toting nut-job
- Posts: 1294
- Joined: Tue Feb 27, 2007 10:28 pm
- Location: On the mend in Western Africa
@Ahruman: thanks for the code, how long until it works?
Although perfect to add&use Your Add Here batches and racing team OXPs, how to do to choose a random sub-OXPs when there are two or more on the registry? The idea is both to create some ambient, and to open a new starting point for shady ("Assassins" could certainly have used the setting) or informal missions with reduced risk of interfering with the normal mission screens on the stations, and to have them appear only one at a time.
As for the need for flexibility, I was thinking on the lines of allowing someting of the sort:where each OXP after the basic/default could be done by different people.
...and, of course you'd need the parent OXPs to run an add-on!
Although perfect to add&use Your Add Here batches and racing team OXPs, how to do to choose a random sub-OXPs when there are two or more on the registry? The idea is both to create some ambient, and to open a new starting point for shady ("Assassins" could certainly have used the setting) or informal missions with reduced risk of interfering with the normal mission screens on the stations, and to have them appear only one at a time.
As for the need for flexibility, I was thinking on the lines of allowing someting of the sort:
Code: Select all
|-hOopyCasino.OXP
|-BarTalkHoopy.OXP (default chit-chat)
|-NoQuestionsAskedHoopy.OXP (randomly triggered add-on)
|-PirateGuildHoopy.OXP (add-on)
| PirateGuildMission1.OXP (basic mission)
| PirateGuildMission2.OXP (sequel)
| PirateGuildFencers.OXP (add-on)
| PirateGuildWars.OXP (Mission)
| PirateGuildWarsVendettas.OXP (randomly triggered sequel)
| PirateGuildWarsPirateKings.OXP (sequel)
|-ShadyPassagersHoopy.OXP (add-on)
| ShadyPassagersBatch1.OXP (basic batch)
| ShadyPassagersBatch2.OXP (add-on)
Of course I wouldn't go against its creator, even if the license allows derivative work! Let's be civil about it.Arexack_Heretic wrote:Still, this leaves your OXP-dependent-OXP disables should the author of the primary OXP change it.
Safest way is to ask permission to use the content of said OXP and just add an alternate version of the hoopy or whatever.
Arexack_Heretic wrote:No need to always have access to that lounge.
So, the lounge would still be there to have a drink and enjoy the scenary, but you aren't forced to visit it.Eric Walch wrote:Will not work. Both OXP's could react on the NO answer. Your response should be:Code: Select all
<key>NO</key> <string>No games of hazard for me, I'd rather check out the piolts lounge</string>
Make sure your OXP is loaded after HoOpy and you use the same keyname so it overwrites the original. HoOpy will never be triggered by the NO and your OXP is triggered by the "NO_PIOLTS_LOUNGE" response.Code: Select all
<key>NO_PIOLTS_LOUNGE</key> <string>No games of hazard for me, I'd rather check out the piolts lounge</string>
...and, of course you'd need the parent OXPs to run an add-on!
You know those who, having been mugged and stabbed, fired, dog run over, house burned down, wife eloped with best friend, daughters becoming prostitutes and their countries invaded - still say that "all is well"?
I'm obviously not one of them.
I'm obviously not one of them.
- JensAyton
- Grand Admiral Emeritus
- Posts: 6657
- Joined: Sat Apr 02, 2005 2:43 pm
- Location: Sweden
- Contact:
Cmdr. Maegil wrote:Although perfect to add&use Your Add Here batches and racing team OXPs, how to do to choose a random sub-OXPs when there are two or more on the registry?
Code: Select all
let myRandomlyChosenScript = this.scriptRegistry[Math.floor(Math.random() * this.scriptRegistry.length)]
Code: Select all
let selector = Math.random() * probabilitySum
let accumulator = 0
let selectedScript = null
for (let i = 0; i < scriptRegistry.length(); i++)
{
accumulator += scriptRegistry[i].probability
if (accumulator >= selector)
{
selectedScript = scriptRegistry[i]
break
}
}
For the nested hierarchy of scripts, there are two ways to go about it. Either extendable subscripts have their own script registry in the same way as the parent script, or the sub-subscripts check to see whether their immediate parent is installed. For instance, for PirateGuildWars in your example, you’d have something like:
Code: Select all
this.startUp = function()
{
if (worldScripts["author-pirate-guild-hoopy"] != undefined)
{
// PirateGuildHoopy is installed, register self.
this.setUpStuff()
}
}
Last edited by JensAyton on Fri Oct 12, 2007 11:21 pm, edited 1 time in total.
E-mail: [email protected]
- LittleBear
- ---- E L I T E ----
- Posts: 2882
- Joined: Tue Apr 04, 2006 7:02 pm
- Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.
In the Shaders Outpost Griff has posted a lovely model for a space bar. You could just use this instead of the HoOpy, script them to appear in Anarchies / fudals and trigger the missions when docked here.
With Assassins they contact you by Comms Message wherever you are, but you have to have a special piece of equipment fitted first, which you obtain by joining the Guild in an Anarchy. Sort of like Electra being rung by her Agent with a 'job'.
With Assassins they contact you by Comms Message wherever you are, but you have to have a special piece of equipment fitted first, which you obtain by joining the Guild in an Anarchy. Sort of like Electra being rung by her Agent with a 'job'.
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.