Java & Beagels - another one of those spacer hang-outs.

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

Moderators: winston, another_commander

User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

unless you specifically use the event triggers for reload/reset etc.. I understand.
Riding the Rocket!
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

so I have been browsing on some JavaScript tutorials.

I can set

Code: Select all

var Xmark1Shiptype=new Array()
Xmark1Shiptype[0]="Adder"
Xmark1Shiptype[1]="Asp MkII"
Xmark1Shiptype[2]="Anaconda"
etc
then use this array to call the strings at will?

for instance
shipdata:

Code: Select all

{
 "Xmark1Shipdata" =
 {
  like_ship = "Xmark1Shiptype[0]";
  bounty = "missionVariable.Xmark1_bounty_number";
  pilot = "missionVariable.Xmark1_pilot_name";
  roles = "Xmark1";
  etc.
 }
(I know it is better to alter by script a returned entity, but I figured using a specific role to call the entity of which there should only be 0<1 at any given time...Ok forget it, you had some more fundamental reasons for not wanting variables in the plists. I'm thinking on how to do that post-call-alteration-by-script thing, so the above is just to examplify the use of a self defined array)

---
Howe does oolite acces arrays?
and can I read existing plist-arrays into a variable?
something like:
var Xmark1Shiptype=array(some_uncomplicated_array)
where the var Xmark1Shiptype becomes an array the size of some_uncomplicated_array and containing the same data.

i'll try to construct a simple variable ship test-oxp now...
--edit: a problem I run into is that most entity properties are read-only, I'll have to check the dev-notes, to be sure the wiki is uptodate.
Riding the Rocket!
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 »

Arexack_Heretic wrote:
so I have been browsing on some JavaScript tutorials.

I can set

Code: Select all

var Xmark1Shiptype=new Array()
Xmark1Shiptype[0]="Adder"
Xmark1Shiptype[1]="Asp MkII"
Xmark1Shiptype[2]="Anaconda"
etc
then use this array to call the strings at will?
Yes, although a more efficient notation is:

Code: Select all

var Xmark1Shiptype = ["Adder", "Asp MkII", "Anaconda"]
for instance
shipdata:

Code: Select all

{
 "Xmark1Shipdata" =
 {
  like_ship = "Xmark1Shiptype[0]";
  bounty = "missionVariable.Xmark1_bounty_number";
  pilot = "missionVariable.Xmark1_pilot_name";
  roles = "Xmark1";
  etc.
 }
You can’t use JavaScript variables or expressions in a plist file. You could use a declaration similar to the above to declare a property list in JavaScript:

Code: Select all

XMark1Shipdata =
{
    like_ship: Xmark1Shiptype[0],
    bounty: missionVariable.Xmark1_bounty_number
    // etc.
}
...but this wouldn’t be very helpful since you can’t stuff it into shipdata.
Howe does oolite acces arrays?
In what context?
and can I read existing plist-arrays into a variable?
script_info entries will be copied into the scriptInfo property of a created ship object, and may contain arrays. For instance, if your shipdata.plist entry contains:

Code: Select all

<key>script_info</key>
<dict>
    <key>AH_testArray</key>
    <array>
        <string>test1</string>
        <string>test2</string>
    </array>
</dict>
you can access it in JavaScript as:

Code: Select all

this.ship.scriptInfo.AH_testArray[0] // == "test1"
something like:
var Xmark1Shiptype=array(some_uncomplicated_array)
The code foo = bar will cause foo and bar to refer to the same object (in this case, the same array). If you actually want a copy of an array, you can achieve this with the (somewhat obtuse) method foo = bar.slice(0) (which means “copy all elements from element 0 – that is, the first element – to the end of the array).
i'll try to construct a simple variable ship test-oxp now...
--edit: a problem I run into is that most entity properties are read-only, I'll have to check the dev-notes, to be sure the wiki is uptodate.
Another problem you’re likely to run into is that no entity properties are implemented in 1.69.x. Note that the documentation in Oolite scripting refers to 1.69.x, and the documentation in Oolite scripting drafts is upcoming functionality.

But yes, most Entity and Ship properties are read-only. There is not and will not be any support for creating new types of ship from JavaScript, only modifying individual ships in certain ways – although in more ways than the old scripting model allows.

Let’s rewind a bit. What is it you are actually trying to do?
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

What I am trying to do:

1) save a set of random numbers to mission_variables.
2) use these numbers to display predictable message missionscript.
(create JS-arrays from descriptions.plistkeys, use array[#] to select 'name', 'ship', 'bounty', etc strings)
3) worldscript determines whether a mark should be added to the system
(by combining chancefactor and scnanning for mark# roles.)
4) use some of the arrays created in (2) to determine the ship mark# will use. (addShip: mV.mark#_shiptype 1)
5) alter this ship according to additional demands (ship.bounty=mV.mark#_bounty, ship.name=mV.mark#_name, max_speed, max_energy,etc)

6) death_actions can set a missionVariable.mark_killed and reset the random values.
Riding the Rocket!
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

Would this code work as expected?
(for setting 5 seperate randomSeedValues in a range of 0-30 and save them in missionVariables, but only if an earlier mark has been alreadyset. This should ensure filling the slots slowly. )
NB this will only be usefull for spawnscripts that persist longer than one system, so I'll probably not be using this.

Code: Select all

this.didExitWitchSpace = function()
{
	var mark1 = missionVariables.mission_mark1_seed1;
	var mark2 = missionVariables.mission_mark2_seed1;
	var mark3 = missionVariables.mission_mark3_seed1;
	var mark4 = missionVariables.mission_mark4_seed1;
	var mark5 = missionVariables.mission_mark5_seed1;
	if (mark1 == undefined)	this.setSeed1(mark1);
	else if (mark2 == undefined) this.setSeed1(mark2);
	else if (mark3 == undefined) this.setSeed1(mark3);
	else if (mark4 == undefined) this.setSeed1(mark4);
	else if (mark5 == undefined) this.setSeed1(mark5);
};

this.setSeed1 = function(m)
{
	var m = missionVariables.mission_mark1_seed1;
	m = Math.floor(Math.random()*30); //random value between 0-29, not a float I hope.
};
I'll probably do somehing along the lines of:
var i = missionVariable.AH_MaxNumberMarks
for i
if i>=0
this.addmark (check existing marks: + addship + script to set important variables)
i--
Last edited by Arexack_Heretic on Wed Oct 24, 2007 4:34 pm, edited 1 time in total.
Riding the Rocket!
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 »

Arexack_Heretic wrote:
What I am trying to do:

1) save a set of random numbers to mission_variables.
2) use these numbers to display predictable message missionscript.
(create JS-arrays from descriptions.plistkeys, use array[#] to select 'name', 'ship', 'bounty', etc strings)
This is the wrong approach. Instead, generate random strings, then store the strings.
5) alter this ship according to additional demands (ship.bounty=mV.mark#_bounty, ship.name=mV.mark#_name, max_speed, max_energy,etc)
I don’t see why you’d need to do this. Why wouldn’t the marks be using normal ships with the normal stats?

On the other hand, in 1.70 you can change a ship’s primary role… although there’s no particular reason why you’d need to use numbered roles at all.
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

Ahruman wrote:
This is the wrong approach. Instead, generate random strings, then store the strings.
5) alter this ship according to additional demands (ship.bounty=mV.mark#_bounty, ship.name=mV.mark#_name, max_speed, max_energy,etc)
I don’t see why you’d need to do this. Why wouldn’t the marks be using normal ships with the normal stats?

On the other hand, in 1.70 you can change a ship’s primary role… although there’s no particular reason why you’d need to use numbered roles at all.
I don't see how i can turn a random string into a number. the random number may be needed to set defferent parameters. such as bounty and shiptype may be linked. OK so I can use a descriptions array containing available shiptypes to call a ship.

Why change the ship? because I want to. just adding a random ship doesn't cut it.
I want it to have a specified pilot (can set bounty here) and a specified shiptype.
changing the name would be required otherwise you can't find the mark. (unless the super advanced scanner can identify pilots as well as their bounties/legalrating)
The other properties I mentioned were just examples of possible things that may be usefull to scale the difficulty level, they are not required in the least.

I think I need numbered role, because I only want a single instance of a mark(at most) to be present in the system.
...maybe I'm still thinkning in plist terms, but I was concerned abut multiple copies created.
I set the characteristics at didExitHyoerspace,
adding the markships at this time may be premature...as a player needs to visit the station to read the wanted-board. So I could add them on did.Launch .... no, this doen't solve multiple dock/launchings though...
I still need a way to check if a marks-ship is already in play, hence the roles.

sorry if i sound stupid
edit: just read your post in script-requests.
Riding the Rocket!
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 »

Arexack_Heretic wrote:
I don't see how i can turn a random string into a number. the random number may be needed to set defferent parameters. such as bounty and shiptype may be linked. OK so I can use a descriptions array containing available shiptypes to call a ship.
Generate and store a random number when you need a random number. When you need a random string, generate and store a random string. Storing a random number and using it to select the same string over and over again is unlikely to be useful.
Why change the ship? because I want to. just adding a random ship doesn't cut it.
I want it to have a specified pilot (can set bounty here) and a specified shiptype.
changing the name would be required otherwise you can't find the mark.
Bounty is writable, but was incorrectly marked read-only in the wiki. Ship name (shipDescription) is writeable.

Hmm, maybe the ability to add a secondary description to ships might be useful, as in:
Missile locked on to Cobra Mk III (guild target)

Cobra Mk III
guild target
6.394 km (Clean)
I think I need numbered role, because I only want a single instance of a mark(at most) to be present in the system.
This can be handled in multiple ways using JS scripts. For instance, you could add a special property (say, ah_markID) to marks, and then search for them with system.filteredEntities(), as in:

Code: Select all

this.findMarkWithID(targetID)
{
    function filterPredicate(entity)
    {
        return entity.isShip && entity.ah_markID != undefined && entity.markID = targetID
    }
    let matches = system.filteredEntities(this, filterPredicate)
    if (matches.length == 0)  return null
    else  return matches[0]
}
Alternatively, you could use an array in the mission script to track marks, and use the isValid property to check if they still exist. This behaves slightly differently, as it considers a ship to still exist if it’s “suspended” in a wormhole.

Digression on wormholes: when a ship enters a wormhole, it is removed from the system but continues to exist, and any JS references to it have an isValid property of true. Ships in a wormhole continue to exist for fifteen minutes after the last ship enters the wormhole, as long as the player stays in the system and doesn’t die (even though the wormhole will have disappeared from the system well before then). They are then restored if the player jumps to the system the wormhole leads to. I intend to add two ship script event handlers, willEnterWormhole() and didExistWormhole() (deliberately different from the world script/player script witchspace methods) and a ship attribute isInWormhole to help deal with this type of situation.
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

Alternatively, you could use an array in the mission script to track marks, and use the isValid property to check if they still exist. This behaves slightly differently, as it considers a ship to still exist if it’s “suspended” in a wormhole
This may be important for L_Bs random_marks project as they will only be spawned in a single sytem. having them leave player would need to follow.
Which would be fun. :D (have ship check location on spawn, setAI to exitsystem_if_attackedAI in homesystem, if in homesystem)
having the script add a new markto the system just because it jumped away would break reality a little.


Small question on variables again:
when I exit a function, all variables defined inside this function are deleted.
when I call a function or method inside a function, do the variables of the first function carry over to the second one?
eg.

Code: Select all

var variable2 = outside
this.funcA = function()
 {
   var var1=2;
   if (var1!=1) {this.funcB;};
  }
this.funcB = function()
 {
   if (var1<=1) {stuff}
   else {var1--;};
  }

is funcA exited when calling funcB and the variable lost?
if so would putting the "var variable" outside the function keepit existing for as long as the script is being run?
or does this need to be "this.variable = value", as a property of the script?
...I think I'm confusing functions with methods now.
:roll:
Riding the Rocket!
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 »

Arexack_Heretic wrote:
Small question on variables again:
when I exit a function, all variables defined inside this function are deleted.
when I call a function or method inside a function, do the variables of the first function carry over to the second one?
eg.

Code: Select all

var variable2 = outside
this.funcA = function()
 {
   var var1=2;
   if (var1!=1) {this.funcB;};
  }
this.funcB = function()
 {
   if (var1<=1) {stuff}
   else {var1--;};
  }

is funcA exited when calling funcB and the variable lost?
Arexack_Heretic wrote:
if so would putting the "var variable" outside the function keepit existing for as long as the script is being run?
or does this need to be "this.variable = value", as a property of the script?
...I think I'm confusing functions with methods now.
:roll:
Methods are functions. A method is simply an object property which is a function. (Incidentally, I’m writing a JavaScript Concepts page for the wiki…)

In the case you show, the variables are not transferred between the functions. You can pass variables explicitly, like this:

Code: Select all

var variable2 = outside
this.funcA = function()
{
    var var1 = 2
    if (var1 != 1) { var1 = this.funcB(var1) }
}


this.funcB = function(var1)
{
    if (var1 <= 1) { stuff }
    else { var1-- }
    return var1
}
Note that although the name var1 is used in both functions, it doesn’t have to be. You could use x in the second function without changing behaviour.

However, a function defined inside another function has access to the variables of the surrounding function. It can even continue to use them if called from outside the surrounding function (this is called a closure).

Code: Select all

this.funcA = function()
{
    var var1 = 2
    function funcB()
    {
        if (var1 <= 1) { stuff }
        else { var1-- }
    }
    if (var1 != 1) { this.funcB() }
}


// This is where it starts to get weird:
this.outer = function(x)
{
    var y = x + 2
    function closure(n)
    {
        return y + n
    }
    return closure // Returns the function itself; does not call the function.
}

this.sevenPlus = this.outer(5)    // this.sevenPlus is a now function which returns 7 + its argument
Log("Ten: " + sevenPlus(3))       // logs "Ten: 10"
Log("Twelve: " + sevenPlus(5))    // logs "Twelve: 12"
You probably won’t need to use closures in this way in mission scripting, but you’re bound to run across code doing weird things with them if you look at a lot of JS tutorials. Passing functions as parameters to other functions is done quite a bit for things like selecting elements from arrays, or selecting entities in the system, and the ability to “inherit” variables like in the second-last example is useful there.
Last edited by JensAyton on Fri Oct 26, 2007 11:44 am, edited 1 time in total.
User avatar
Arexack_Heretic
Dangerous Subversive Element
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:

Post by Arexack_Heretic »

thanks!
those are really usefull examples.

I was thining halfway "if you pass a variable to a function doesn't it become a parameter" but then in the last paragraph you clear this up. ;)
Riding the Rocket!
Post Reply