Scripters cove

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

Moderators: another_commander, winston

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

Re: Scripters cove

Post by Wildeblood »

Vincentz wrote:
Actually my request shouldn't even have been in this thread, but in this one : https://bb.oolite.space/viewtopic.php?f=6&t=3296
No, definitely not. This is the right place. The practical problem you face here is that the new way of defining markets is horrendously complicated, and also fundamentally BBD. Just ignore it completely, do your own calculations in JS, and use the set market price/quantity functions. That way you get something compatible with both 1.80 & 1.81, and never need to look into either commodities.plist or whatever the new thing is called.
User avatar
Vincentz
Deadly
Deadly
Posts: 174
Joined: Sun Mar 22, 2015 11:26 pm

Re: Scripters cove

Post by Vincentz »

Wildeblood wrote:
Vincentz wrote:
Actually my request shouldn't even have been in this thread, but in this one : https://bb.oolite.space/viewtopic.php?f=6&t=3296
No, definitely not. This is the right place. The practical problem you face here is that the new way of defining markets is horrendously complicated, and also fundamentally BBD. Just ignore it completely, do your own calculations in JS, and use the set market price/quantity functions. That way you get something compatible with both 1.80 & 1.81, and never need to look into either commodities.plist or whatever the new thing is called.
The thing is, that the trade-goods.plist would be pretty darn perfect to configure the different types of economies, if multiple instances were possible. Mostly because it would be easier to control the difference in same-type economies (Agri vs Adv Agri, Indus vs HiTech Indus etc), but also because especially Financial type economies would be "Stock-market"'ish effect, with very random prices/stock for all commodities (though still within the normal games boundaries. No extremes).

I was going through my Nova Lux HUD thread, as it needed to be updated/fixed with a Hud-small.plist, when I saw a post Norby had made to make it compatible with HUD-selector, and noticed that the HUD Selector can change between .plists, and while it is done manually with equipment, I think a script that changed trade-goods.plist on arrival depending on the economy level would be much simpler.

So... Norby... if you are reading this. I will name my first born after you (ah, maybe not my firstborn, but atleast my 3rd born ;)
"There is a single light of science, and to brighten it anywhere is to brighten it everywhere." - Isaac Asimov
User avatar
Norby
---- E L I T E ----
---- E L I T E ----
Posts: 2577
Joined: Mon May 20, 2013 9:53 pm
Location: Budapest, Hungary (Mainly Agricultural Democracy, TL10)
Contact:

Re: Scripters cove

Post by Norby »

Thanks :) but I am a bit occupied and there are enough projects in my list for the next few years. Your ideas seems to be possible via station.market, just need more work than I would like to accept at the moment. Maybe later if nobody precede me.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

Wildeblood wrote:
Just ignore it completely, do your own calculations in JS, and use the set market price/quantity functions.
The problem with this approach is the excessive amount of work required to be compatible with any other OXP which adjusts markets. You don't know when writing a market manipulation OXP what new commodities, economies and stations are going to be defined by other OXPs, which means you either have to be incompatible with them to some extent, or spend a lot of time accounting for those cases.

The current setup effectively involves - for non-trivial cases - using JS to do calculations to set price and quantity: the timing of the setting allows OXPs to cooperate without necessarily having to be directly aware of each other.
Vincentz wrote:
and noticed that the HUD Selector can change between .plists, and while it is done manually with equipment, I think a script that changed trade-goods.plist on arrival depending on the economy level would be much simpler.
Not practical in that form, unfortunately.

The Oolite architecture is that - with a few exceptions - plists with the same name get merged together (with the OXP entries getting priority over the core entries). That merged set up is then used to populate various internal data structures - some of which are subsequently editable by JS, and some of which aren't (and a few of those can't be editable rather than it just being a matter of "not implemented yet"). This loading and merging process takes a little while (a second up to a few minutes, depending on the computer speed and the number of installed OXPs, but either way not something practical to run in real time).

So what you have to do instead is use JS to change the merged resource definitions later - in this case, you could probably use trade-goods.plist on its own for all the non-Financial economies, and apply a market script to those economies to override the default behaviour - or, perhaps simpler to write, apply the market script everywhere but have it just return the market data unchanged for non-Financial economies.

HUDs are an exception to this in that a HUD is a single self-contained resource definition - and they overwrite, rather than merging, if multiple files with the same name exist. That's unusual for Oolite - we have shipdata.plist defining all the ships rather than separate adder.plist, boa.plist, etc. - but not worth the effort in OXP rewrites it would be to change at this stage.
User avatar
Vincentz
Deadly
Deadly
Posts: 174
Joined: Sun Mar 22, 2015 11:26 pm

Re: Scripters cove

Post by Vincentz »

cim wrote:
Vincentz wrote:
So... (sorry for being so code illiterate) how would a market_script.js look like, and how would it be able to differentiate from different economiy levels?
You'd set a market script on the system (through planetinfo.plist, most likely) with something like this in:

Code: Select all

this.updateLocalCommodityDefinition = function(marketdef, station, system) {
    var systemInfo = System.infoForSystem(galaxyNumber,system); // get the system info
    var economyNumber = systemInfo.economy; // get the economy number for the system
    // you can also get other system properties or variables at this point

    // the precalculated details for the tradegood are in the marketdef object at this point
    // so you can still use the plist to set up a lot of the basic calculations, and only need
    // to adjust the result here

    var price = ...; // calculation of price based on economy
    var quantity = ...; // calculation of price based on economy

    // set the calculated price and quantity back onto the market definition
    marketdef.price = price;
    marketdef.quantity = quantity;
    // and give the market definition back to Oolite to use
    return marketdef;
};
cim wrote:
So what you have to do instead is use JS to change the merged resource definitions later - in this case, you could probably use trade-goods.plist on its own for all the non-Financial economies, and apply a market script to those economies to override the default behaviour - or, perhaps simpler to write, apply the market script everywhere but have it just return the market data unchanged for non-Financial economies.
I'm still unsure how I would do this (even down to the syntax).

I'm thinking I'm going to make 8 different market_script.js (market_script0.js, market_script1.js etc), but then you write it should be set via planetinfo.plist.
Does that mean that I have to set the different market_script for each and every system?

Wouldn't it be easier if the market script (which would have to be a total overhaul of the trade-goods.plist as making a general plist wouldn't fit very well.), was loaded as I originally planned :

Code: Select all

this.name = "neweconomy.js";
this.author = "YOURNAMEHERE";
this.copyright = "April 2015";
this.description = "World Script for adding new types of economies";
this.version = "1.0";

this.setUpSystem = function()

{   
   if(system.economy = 7)
            {run market_script7.js}
    if(system.economy = 6)
            {run market_script6.js}
etc.
}
"There is a single light of science, and to brighten it anywhere is to brighten it everywhere." - Isaac Asimov
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

Vincentz wrote:
Wouldn't it be easier if the market script (which would have to be a total overhaul of the trade-goods.plist as making a general plist wouldn't fit very well.), was loaded as I originally planned :

Code: Select all

this.name = "neweconomy.js";
this.author = "YOURNAMEHERE";
this.copyright = "April 2015";
this.description = "World Script for adding new types of economies";
this.version = "1.0";

this.setUpSystem = function()

{   
   if(system.economy = 7)
            {run market_script7.js}
    if(system.economy = 6)
            {run market_script6.js}
etc.
}
Yes. Something equivalent is possible - set a single market script for every system (you can do this in the universal section of [wiki]planetinfo.plist[/wiki], so you only need to do it once rather than 2048 times) and then in the market script:

Code: Select all

this.updateLocalCommodityDefinition = function(marketdef, station, system) {
    if (system.economy == 7) {
        return this._updateForMarket7(marketdef,station,system);
    } else if (system.economy == 6) {
        return this._updateForMarket6(marketdef,station,system);
    } else if (system.economy == 5) {
        // and so on
    }
}

this._updateForMarket7 = function(marketdef, station, system) {
    // code for market 7 goes here
    return marketdef;
}

// and the same for the other markets
Rather than having eight different market scripts, have one market script which calls eight different sub-functions as needed.

(Ordinarily at this stage I'd recommend looking at a couple of other OXPs which do similar things to see how they did it, but no-one has released any yet)
Layne
---- E L I T E ----
---- E L I T E ----
Posts: 355
Joined: Sat Mar 28, 2015 11:14 pm

Re: Scripters cove

Post by Layne »

Ok, this one might be easy to solve with the right snippet of code, but I've got no idea how to do it.

I'm working on the Docking Fees OXP I proposed a few days ago, and am very close to finishing a working version. (I was hoping to have it running and posted tonight, in fact, until I ran into this.)

My problem seems to be that when two stations share a role, the formula for calculating the fees either cancels out (if one of them has no fee) or combines and increases (if they both have a fee set up). This only seems to happen for the special stations such as rock hermits or other OXP added stations. An example is this:

Code: Select all

if (station.hasRole("rockhermit")) {fee = 0; dock_mess = "rock";} // rockhermits are free
if (station.hasRole("astromine")) {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
In this example, both astromines and Rock Hermits share the role of 'rock hermit' (I believe the Commies OXP spawns astromines in place of normal Rock Hermits), in addition to the astromine's unique role as that station. The overlapping roles are causing a conflict when it calculates the fee, though not when it posts the specific message for each station upon docking (the oxp adds unique docking messages for a large number of station types).

What's needed is a way to tell the code 'if station has role X and only take that role into account'. Ignore all other roles not specified in this script-- keeping in mind that telling it to look for stations with only that single role may just make it ignore anything that has multiple roles, which isn't what should happen, either. I'm hoping it's an easy fix, because the rest of the code took me some time to hammer into shape. What's the simplest way of adding this property to the above lines? Ideally, I'd like the final code to exclude all stations /not/ GalCop or specified in the script to have messages, so that it doesn't just add docking fees willy-nilly to every assorted station that gets added by missions or OXPs I don't know about. (Hey! My assassin's guild base just charged me 12 credits to dock and gave me restaurant coupons!)
Reports of my death have been greatly underestimated.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4646
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post by phkb »

My suggestion would be to do something like this:

Code: Select all

var dock_mess = "";
if (station.hasRole("astromine") && dock_mess == "") {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
...other station role checks...
if (station.hasRole("ignore this station role") && dock_mess == "") {dock_mess == "ignore";} // stations to completely ignore
if (station.hasRole("rockhermit") && dock_mess == "") {fee = 0; dock_mess = "rock";} // rockhermits are free

if (dock_mess != "" && dock_mess != "ignore") {
    ...do the docking fee stuff...
}
Move the roles that are shared to the end of the list. That way, the stations that share that role will be picked up by their specific role first.
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2286
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia

Re: Scripters cove

Post by Wildeblood »

Layne wrote:
Ok, this one might be easy to solve with the right snippet of code, but I've got no idea how to do it.

I'm working on the Docking Fees OXP I proposed a few days ago, and am very close to finishing a working version. (I was hoping to have it running and posted tonight, in fact, until I ran into this.)

My problem seems to be that when two stations share a role, the formula for calculating the fees either cancels out (if one of them has no fee) or combines and increases (if they both have a fee set up). This only seems to happen for the special stations such as rock hermits or other OXP added stations. An example is this:

Code: Select all

if (station.hasRole("rockhermit")) {fee = 0; dock_mess = "rock";} // rockhermits are free
if (station.hasRole("astromine")) {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
Note the word "else" and corrected order...

Code: Select all

if (station.hasRole("astromine")) {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
else if (station.hasRole("rockhermit")) {fee = 0; dock_mess = "rock";} // rockhermits are free
Layne
---- E L I T E ----
---- E L I T E ----
Posts: 355
Joined: Sat Mar 28, 2015 11:14 pm

Re: Scripters cove

Post by Layne »

phkb wrote:
My suggestion would be to do something like this:

Code: Select all

var dock_mess = "";
Move the roles that are shared to the end of the list. That way, the stations that share that role will be picked up by their specific role first.
var dock_mess is already in use to define standard GalCop Stations by their tech level. Part of the problem with moving the shared roles to the end of the list is that I don't /know/ all the shared roles. Every OXP that adds a new station can introduce a shared role without my being able to see it. I didn't realize that astromines shared a role with rock hermits until the error cropped up and I looked back into the code for the Commies OXP.
Wildeblood wrote:
Note the word "else" and corrected order...

Code: Select all

if (station.hasRole("astromine")) {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
else if (station.hasRole("rockhermit")) {fee = 0; dock_mess = "rock";} // rockhermits are free
I tried this solution and the reverse happened-- it used the rock hermit message for the astromine (earlier it used the correct astromine message but wasn't calculating the fee correctly) and no fee was charged at all (which is correct for the rock hermit). The shared roles are still snarling up the works.

The full list as it stands after this attempt looks like this:

Code: Select all

var fee = (system.techLevel * 0.5 + 0.5);
    // make sure the "dock_mess" value is the same as what you used in the descriptions.plist file
    var dock_mess = system.techLevel;
    if (station.hasRole("constore")) {fee = 0; dock_mess = "store";} // con stores are free for encouraging customers
    if (station.hasRole("random_hits_any_spacebar")) {fee *= 1.5; dock_mess = "spacebar";} // space bars are a little bit more expensive
    if (station.hasRole("rrs_group_spacestation")) {fee = 0; dock_mess = "RRS";} // rescue stations are free
    if (station.hasRole("casinoship")) {fee *= 2; dock_mess = "hoopy";} // casinos are a bit more expensive
    if (station.hasRole("wildShips_kiota")) {fee *= 1.3; dock_mess = "kiota";} // kiota ships are a little bit more expensive
    if (station.hasRole("rrs-mining-outpost")) {fee = 0; dock_mess = "mining";} // mining outposts are free
    if (station.hasRole("smivs_pizza_giftshop")) {fee = 0; dock_mess = "";} // space-pizza charges a fee of its own, so disable the dock message
    if (station.hasRole("free_trade_zone")) {fee = 0; dock_mess = "FTZ";} // free trade zones charge huge fuel prices in lieu of fee
    if (station.hasRole("astromine")) {fee *= 2.2; dock_mess = "astromine";} // penal colonies require a small bribe to enter
    if (station.hasRole("comczgf")) {fee *= 1.5; dock_mess = "ZGF";} // Zero-G-Factories require a small bribe to enter
    if (station.hasRole("comslapu")) {fee *= 1.5; dock_mess = "SLAPU";} // SLAPU collectives require a small bribe to enter
    if (station.hasRole("astrofactory")) {fee *= 1.5; dock_mess = "astrofactory";} // imperial factories require a small bribe to enter
    if (station.hasRole("anarchies_hacker_outpost")) {fee = 0; dock_mess = "hackers";} // if you can find them, hacker outposts are free
    if (station.hasRole("anarchies_salvage_gang")) {fee *= 2; dock_mess = "salvager";} // salvage gangs need a bribe to grease the wheels
    if (station.hasRole("navystat")) {fee = 0; dock_mess = "secom";} // navy stations are free (your tax dollars at work)
    if (station.hasRole("behemoth")) {fee = 0; dock_mess = "behemoth";} // behemoths are free
    if (station.hasRole("liners_liner")) {fee = 0; dock_mess = "liner";} // passenger liners are free
    if (station.hasRole("feudal-hunting-lodge")) {fee = 0; dock_mess = "hunting";} // royal lodges are free
    if (station.hasRole("planetFall_surface")) {fee *= 1.2; dock_mess = "planet";} // planets are slighly more to discourage spacers
    if (station.hasRole("monkbranch")) {fee = 0; dock_mess = "monks";} // black monk monasteries are free
    if (station.hasRole("taxi_station")) {fee *= 0.5; dock_mess = "taxi";} // taxi stations just charge for the parking
    else if (station.hasRole("rockhermit")) {fee = 0; dock_mess = "rock";} // rockhermits are free
Also as long as that's up, if anyone knows if any of those roles are incorrect for those stations (the planetfall one had me guessing) I'd love to know early. Thanks.
Reports of my death have been greatly underestimated.
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2286
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia

Re: Scripters cove

Post by Wildeblood »

Use the else, Luke.

I dunno how many conditions you want to check for, or in what priority, but I know that you're continuing to check for them all even after you have a match because you're omitting all the else-s.

P.S. Alternatively, use a switch. But again, get the syntax right or it won't work.
Layne
---- E L I T E ----
---- E L I T E ----
Posts: 355
Joined: Sat Mar 28, 2015 11:14 pm

Re: Scripters cove

Post by Layne »

Wildeblood wrote:
Use the else, Luke.

I dunno how many conditions you want to check for, or in what priority, but I know that you're continuing to check for them all even after you have a match because you're omitting all the else-s.

P.S. Alternatively, use a switch. But again, get the syntax right or it won't work.
So apply an else to every one of those?

If A;
else B;
else C;
else D...

All the way down the list?

And break a switch down for me, please-- coding is not my forte; I'm a tinkerer, not a programmer. What is a switch and how would that work for the example above?

What would be ideal would be to have the script ignore any stations /not/ explicitly defined as GalCop or on the list. That way, if an OXP adds a new kind of station with shared roles, it won't suddenly start charging docking fees unless somebody wants it to do so. Looking ahead to future OXP's as well as the ones I don't know about that people are using.
Reports of my death have been greatly underestimated.
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2286
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia

Re: Scripters cove

Post by Wildeblood »

OTTOMH...

Code: Select all

if (station.isMainStation) {
    // your code here...
} else {
    switch (station.primayRole) {
        case "constore":
            // your code here...
             break;
        case "casinoship":
            // your code here...
            break;
        case "astromine":
            // your code here...
            break;
    }
}
List each case in the order you want to check them, and break out of the switch after you find your match.
Layne
---- E L I T E ----
---- E L I T E ----
Posts: 355
Joined: Sat Mar 28, 2015 11:14 pm

Re: Scripters cove

Post by Layne »

Ahh, good, good-- isMainStation and primaryRole seem to be the key useful factors there, I think those will help. I will tinker some more.
Reports of my death have been greatly underestimated.
phasted_too
Poor
Poor
Posts: 4
Joined: Sun Apr 26, 2015 10:15 am

Re: Scripters cove (the new station.market object (in v1.81+

Post by phasted_too »

cim wrote:
You'd set a market script on the system (through planetinfo.plist, most likely) with something like this in:

Code: Select all

this.updateLocalCommodityDefinition = function(marketdef, station, system) {
    var systemInfo = System.infoForSystem(galaxyNumber,system); // get the system info
    var economyNumber = systemInfo.economy; // get the economy number for the system
    // you can also get other system properties or variables at this point

    // the precalculated details for the tradegood are in the marketdef object at this point
    // so you can still use the plist to set up a lot of the basic calculations, and only need
    // to adjust the result here

    var price = ...; // calculation of price based on economy
    var quantity = ...; // calculation of price based on economy

    // set the calculated price and quantity back onto the market definition
    marketdef.price = price;
    marketdef.quantity = quantity;
    // and give the market definition back to Oolite to use
    return marketdef;
};
cim old buddy,

I've just started to sit down and think about how all of this new stuff can be used to make Real-life Economics better... I think RLE v2.0 will be for Oolite v1.81+, but I'm still puzzled about the exact sequence of events.

The central concept in RLE is the econBalance. econBalance is calculated by the _determineMarket() method which is called by the shipWillExitWitchspace() event handler... unless I'm misunderstanding something, I think I need econBalance to be in place before trade-goods.plist works its magic, but I'm not sure it will be.

So, my question: does Oolite v1.81+ calculate prices and quantities after the player has "arrived" in the new system (after the tunnel effect)? Is shipWillExitWitchspace() called before Oolite calculates prices and quantities?

Another thing that has me absolutely stumped: what's the difference between the market script specified in planetinfo.plist and the one called for by trade-goods.plist. Do I need both? Do I need either one? An actual working example (even a silly trivial one) would be a gift from heaven...
Post Reply