Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Scripters cove

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

Moderators: winston, another_commander

User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Just finished translating the last part of UPS to Java. In the container series there was some IN_FLIGHT action I could remove and replace with a timer to only evaluate a small part of my script. Now I am left with just one IN_FLIGHT condition in the parcel series. For this I could use some help in avoiding it.

Problem: Midair, there is a ship hailing the player he has a parcel for delivery. When the player accepts, the ship sets the mission destination with a red X. But a ship can not set a mission description as it is not linked to a certain mission. (when one tries, the description of a "random" mission is set)

In the current legacy version, the ship sets a variable that the parcel mission reads out on a " in_flight" condition and than the mission itself sets the mission description. I now do the same in Java. But is there a way for a ship to directly call a function in the "parcels.js" file that act like it is issued by the parcel file itself?
User avatar
Kaks
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 3009
Joined: Mon Jan 21, 2008 11:41 pm
Location: The Big Smoke

Post by Kaks »

I'm fairly sure it can be done, in the js version of asteroidstorm I sent LittleBear I do something similar, but it's a bit messy to describe. Could you PM me with the OXP you've got so far? I'll have a look & should be able to give you an answer by tomorrow evening!

Cheers,

Kaks.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

If “parcels.js” is a world script (i.e., not a ship script), it should be possible to call worldScripts["parcels.js"].someMethod(). (Y’know, I really should get around to updating the documentation for global objects and functions for 1.70.)

I can’t think of any case were this would actually behave differently from doing the same work in a ship script, though. I don’t think the object the script is attached to is ever used, and if it is it’ll be in terms of the running script rather than the script performing a given call.

What is it you’re trying to call? mission.markSystem()?
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

I need to call:

Code: Select all

         mission.setInstructionsKey("ups_parcel_midair")
         mission.markSystem(system.ID)

mission.markSystem(system.ID) works well of course, but mission.setInstructionsKey("ups_parcel_midair") is internally stored as "Key: missionname, String:ups_parcel_midair".

And when called from within the shipscript, the ship does not know with mission it belongs to. It is the same problem I had in legacy scripting. The message showed up in the F5-F5 screen, but could be attached to any random mission. So often not clearable by the script and it could overwrite other mission briefings. In legacy I set up a variable by the ship and let the script itself wait for that variable to occur IN_FLIGHT. I have not checked if it does work for Java, but I assume the problem will be the same.

But it is a worldscript, so Ill give it a try with your method.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Ahh, right.

setInstructionsKey() currently uses [[OOJSScript currentlyRunningScript] name] as the mission key. Even if you call through a function in a world script, this will use the ship script’s name.

For 1.71, I’ll add an optional missionKey parameter to setInstructionsKey(), so you can use the form mission.setInstructionsKey("ups_parcel_midair", "ewalch_parcel_mission").
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Ahruman wrote:
Ahh, right.

setInstructionsKey() currently uses [[OOJSScript currentlyRunningScript] name] as the mission key. Even if you call through a function in a world script, this will use the ship script’s name.
Thanks Ahruman,
worldScripts["ups_parcel"].midair() does start the function this.midair() that I put in the ups_parcel script from within the ship script.

Code: Select all

this.midair = function(status)
{
    missionVariables.ups_parcel = "MIDAIR_DELIVERY" 
    mission.setInstructionsKey("ups_parcel_midair")
    mission.markSystem(system.ID)
    player.consoleMessage("I tranfered " +  missionVariables.ups_parcel_appearance + " parcels to your cargobay.", 6)
}
But is does the same as called directly from the ship script. e.g. the line mission.setInstructionsKey("ups_parcel_midair") does not work as if called from within the "ups_parcel" script itself. (no instructions are set). I have still problems with the referencing. (Not only in Java but also in C)

But seeing your last reaction It is not possible with other way of referencing and I have to wait for 1.71. The tickle does work however, but I only need it for one single mission. For now I will delete the tickleEvent and activate it on spawning the ship. That also saved needles calling unused functions when the mission is inactive.
Ahruman wrote:
For 1.71, I’ll add an optional missionKey parameter to setInstructionsKey(), so you can use the form mission.setInstructionsKey("ups_parcel_midair", "ewalch_parcel_mission").
That would be very useful. In the past I wanted that function also to change the mission description on eliminating the target. eg. to change the text: "kill the pirate Leviathan" into " report to base" after destruction of the ship. I could have done it in the way I did with the parcel mission, but i didn't fount it worth the trouble and the extra execution time"
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Question: is it possible to see from JS that a certain legacy.OXP is installed?

In UPS I didn't want to be depended on installation of other OXP's and also didn't want to include to much graphics. I experimented with:

if(worldScripts.transportSchedule) system.legacy_addShips("woma 1")

but it only works when an JS script is attached. When I look at an non present legacy script the javascript console in debug menu generates an error, while when I look at an existing legacy script the console returns a "null". (meaning debug menu sees a difference) For me it would be enough as I don't need the script itself, but only want to know if there is a shipdata.plist. How can I detect the difference with javacode as a null result is almost the same as a error result: the if statement would in both cased be false.

I now added "like_ships" references to the fuel-tanker from transports in UPS and only add them when the transports.OXP is present. But very few will have the new JavaScript version installed while the presence old version would be enough.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

You can test whether a legacy script of a given name is installed using:

Code: Select all

if (worldScripts["foo"] !== undefined)
!== and === are “non-coercing comparison” operators, which treat false, 0, null and undefined as distinct values. (By design, worldScripts["foo"] is undefined for non-existent scripts, and null for legacy scripts.)
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Ahruman wrote:
You can test whether a legacy script of a given name is installed using:

Code: Select all

if (worldScripts["foo"] !== undefined)
Thanks, it is working and I can also check the presence of an old legacy script.

In case of the TransportOXP that still means two checks as Kaks used a slightly different name for the JS version (transportschedule/transportSchedule). But now I also can add the fueltankers (or anything else) when an old OXP was installed. Actually I use a like_ship, but when adding I now know for sure the original is also installed.
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

By the way, Eric, if you ever run out of things to do you could always take a shot at converting the rest of oolite-legacy.script.plist. Just saying. ;-)
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Ahruman wrote:
By the way, Eric, if you ever run out of things to do you could always take a shot at converting the rest of oolite-legacy.script.plist. Just saying. ;-)
Ill take that. But first I have to convince myself that the way I have set up my own OXP is a good example and has no structural flaws. I just rearranged something in UPS in anticipating of the "missionChoiceWasReset" eventhandler. With this new handler the timer can get removed.
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Ahruman wrote:
By the way, Eric, if you ever run out of things to do you could always take a shot at converting the rest of oolite-legacy.script.plist. Just saying. ;-)
Ill take that. But first I have to convince myself that the way I have set up my own OXP is a good example and has no structural flaws. I just rearranged something in UPS in anticipating of the "missionChoiceWasReset" eventhandler. With this new handler the timer can get removed. I will use next setup.

When all scripts would respect active missionscreens and active mission choices, they would be able to live in harmony.

Code: Select all

this.missionOffers = function()
{
   if (guiScreen == "GUI_SCREEN_MISSION" ||missionVariables.offering || (mission.choice && mission.choice != "")) return;
   // Don't do new missionoffers when there is a mission screen present or an active mission.choice
   // wait till later, on either clearing there will be an event.
   {
      // body, do here your missionoffers
   }
}

this.choiceEvaluation = function()
{
  //  body evaluate here your choices
}

this.shipDockedWithStation = function()
{
    this.missionOffers()
}

this.missionScreenEnded = function()
{
   if(!player.docked) return;
   this.choiceEvaluation()
   this.missionOffers()
}

this.missionChoiceWasReset = function() // available in 1.71
{
   if(!player.docked) return;
   this.missionOffers()
}
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

I'm stuck with a orientation problem. I want to add a station near the planet and than re-orientate it so the docking slit is always pointing to the planet. I tried several ways with no result. I know orientation needs a quarternion but the errors suggest it should also accept a vector. At last I explicitly created a vector with new Vector() but even here I get an error saying it is no vector.

Code: Select all

        system.legacy_addShipsAt("factoryStation", 1, "pwp", 0.5, 0.5, 1.5)
        let factory = system.shipsWithPrimaryRole("factoryStation")[0];
        let planet = system.mainPlanet.position
        let factoryVector = new Vector(planet.subtract(factory.position))
        factory.setOrientation(factoryVector)
Above lines give the following error:

Code: Select all

Exception: Error: Entity.setOrientation(): could not construct vector from parameters ((-44084.5, -35743.7, 57463)) -- expected Vector, Entity or three numbers.
    Active script: "ups_sun" 1.3.8
    script.js, line 48:
            factory.setOrientation(factoryVector)
An other strange thing is that the error line is not in the ups_sun script but in line 48 of a script in an other OXP.
User avatar
Kaks
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 3009
Joined: Mon Jan 21, 2008 11:41 pm
Location: The Big Smoke

Post by Kaks »

I'll have a look! :)
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
User avatar
Kaks
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 3009
Joined: Mon Jan 21, 2008 11:41 pm
Location: The Big Smoke

Post by Kaks »

The copy'n'paste bug strikes again! The quaternion class was originally copied from the vector class, and - while the code does the right thing - the error message inside it hasn't been changed from the original vector error message. You do need a quaternion (4 numbers) instead of a vector(3): if you change the setOrientation line to:

Code: Select all

factory.setOrientation(1,factoryVector.x,factoryVector.y,factoryVector.z);
you should get the result you wanted.
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
Post Reply