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
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Ahruman wrote:
  • var trumbleNumber = missionVariables.trumbleNumber should be:

    Code: Select all

    var trumbleNumber = 0
    if (missionVarables.AH_trumbleNumber != undefined)
    {
        trumbleNumber = parseInt(missionVarables.AH_trumbleNumber)
    }
    This is necessary for two reasons: one, foo = bar, where bar is undefined, is an error. Also, mission variables are always strings, so you need to convert to a number (integer). The first issue will (probably) be resolved in future by making unused mission variables null rather than undefined, but you’ll still need the check in this case because parseInt(null) is NaN (“not a number”).
Whoops! My mistake. Oolite already converts to a number if possible.
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 for the help.
wasn't sure whether you could have multiple functions/eventtriggers in one JScriptfile, I guess your solution to the timer-problem answers that. :)
there is no player.trumbleCount property
Whaat?
But I started learning to see the future through coffeegrounds for explicidly this property access!
I got this property call from the shaders-bindings, I figured I could acces the property from script as would a shader.

Wanna see my trumblepusher script?
(it's a bit more missionlike, but not working yet...maybe because I call upon variables set in trumblecheck..maybe because I made lots of mistakes)
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 »

var trumbleNumber = missionVariables.trumbleNumber should be:
Code:
var trumbleNumber = 0
if (missionVariables.AH_trumbleNumber != undefined)
{
trumbleNumber = parseInt(missionVariables.AH_trumbleNumber)
}
So...what is neccesary here?
Also: why are you using 'trumbleNumber' and 'AH_trumbleNumber' in the same code?

OKay next incarnation:

Code: Select all

// timer not yet working...
//this.timerAH = new Timer(this, function() {this.trumblecheck}, 30, 30)
//using tickle in place of timer untill it works (expected: v1.70)

//trumblecheck function
	//setup variable to remember trumbles_at_last_count
	//check playerproperty trumbleCount against the remembered variable
	//if not identical, (a)lower: print message, save new value. (b)higher: print message, save new value to variable
this.trumbleCheck = function()
{
   //set variable AH_trumbleNumber to 0 if not yet defined, may not be neccesary but looks neater if called for the first time.    
	if (missionVariables.AH_trumbleNumber == undefined) 
	{
		var AH_trumbleNumber = 0;
	};
	if (missionVariables.AH_trumbleNumber != undefined) 
	{
		AH_trumbleNumber = parseInt(missionVariables.AH_trumbleNumber); 
		let trumbleCount = player.call("trumbleCount"); //Request for JS trumbleCount method (or access to every entity property)
		Log("I has " + trumbleCount + " trumbles");
		if (trumbleCount != AH_trumbleNumber)
		{
			if (trumbleCount <= AH_trumbleNumber)
			{
				(consoleMessage("Trumbles decreasing: [trumbleCount] remaining"));
				(missionVariables.AH_trumbleNumber = trumbleCount);
			};
			if (trumbleCount >= AH_trumbleNumber)
			{
				(consoleMessage("Trumbles multiplying: increased to [trumbleCount]"));
				(missionVariables.AH_trumbleNumber = trumbleCount);
			}
		}
	}
}

this.startLookingForTrumbles = function()
{
    this.tickle = this.trumbleCheck
    // OR timerAH.start()
}

this.stopLookingForTrumbles = function()
{
    delete this.tickle;
    // OR timerAH.stop()
}

this.didLaunch = function()
{
    if (player.hasEquipment("EQ_TRUMBLE"))
    {
        this. startLookingForTrumbles()
    }
    else
    {
        this.stopLookingForTrumbles()
    }
}

this.didScoop = this.didLaunch; // Not called in 1.69, so this version wouldn’t notice trumbles from cannisters until the next launch.

this.reset = this.stopLookingForTrumbles // Redundant if timers are being used, but not harmful.
I'll test it after lunch and some non-code coffee.
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:
there is no player.trumbleCount property
Whaat?
But I started learning to see the future through coffeegrounds for explicidly this property access!
I got this property call from the shaders-bindings, I figured I could acces the property from script as would a shader.
It doesn’t work that way. Shader bindings use methods of the underlying Objective-C object – any method whose return type is a number, a number wrapped in an object, a vector, a quaternion or a colour. JavaScript methods are defined individually, and don’t necessarily correspond directly to Objective-C methods. The Player.call() method in 1.69, or the Entity.call() method in 1.70 and onwards has functionality somewhat similar to bindings; it can call any method which returns an object that can be converted to a JavaScript object (or nothing), and takes zero or one arguments (which must be JS objects that can be converted to Objective-C objects). In particular, this means almost any legacy scripting method, which is what it’s intended for.
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:
var trumbleNumber = missionVariables.trumbleNumber should be:
Code:
var trumbleNumber = 0
if (missionVariables.AH_trumbleNumber != undefined)
{
trumbleNumber = parseInt(missionVariables.AH_trumbleNumber)
}
So...what is neccesary here?
The parseInt isn’t necessary; if (missionVariables.AH_trumbleNumber != undefined) trumbleNumber = missionVariables.AH_trumbleNumber should be sufficient. The test for undefined is necessary.
Arexack_Heretic wrote:
Also: why are you using 'trumbleNumber' and 'AH_trumbleNumber' in the same code?
I’m not. ;-)
trumbleNumber is a local variable, used only in that function. Since it can’t be seen from anywhere else, its name doesn’t matter. AH_trumbleNumber is a mission variable name. It can be seen by any script, so a unique (and moderately sensible) name is required.
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 »

maybe I'll just go with using a local_* prefix for local variables to remind me...on the otherhand I will probably go lazy and forget it half the time.

Thanks on the parseInt intell!
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 »

Code: Select all

   if (missionVariables.AH_trumbleNumber == undefined) 
   { 
      var AH_trumbleNumber = 0; 
   }; 
   if (missionVariables.AH_trumbleNumber != undefined)
This is a tad confused. You seem to be confusing the local variable (var AH_trumbleNumber) with the mission variable (missionVariables.AH_trumbleNumber). You’d probably be better of with:

Code: Select all

    if (missionVariables.AH_trumbleNumber == undefined) missionVariables.AH_trumbleNumber = 0
    var trumbleNumber = missionVariables.AH_trumbleNumber
    // Do stuff
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 »

yes I am getting quite confused. :lol:

I am under the impression trumbleCount also is a local variable that has the value of player.call("trumbleCount").

I will rename the local_variable to new_trumbleNumber to avoid some confusion.

Give me a few minutes to update the above code....

edit: how about this:

Code: Select all

this.trumbleCheck = function()
{
   //set variable AH_trumbleNumber to 0 if not yet defined, 
   //may not be neccesary but looks neater if called for the first time.    
   if (missionVariables.AH_trumbleNumber == undefined) 
	{
		var old_trumbleNumber = 0;
	};
	if (missionVariables.AH_trumbleNumber != undefined) 
	{
		old_trumbleNumber = missionVariables.AH_trumbleNumber;
		let new_trumbleNumber = player.call("trumbleCount"); 
		//Request for JS trumbleCount method (or access to every entity property)
		Log("I has " + new_trumbleNumber + " trumbles");
		if (new_trumbleNumber != old_trumbleNumber)
		{
			if (new_trumbleNumber <= old_trumbleNumber)
			{
				(consoleMessage("Trumbles decreasing: [new_trumbleNumber] remaining"));
				(missionVariables.AH_trumbleNumber = new_trumbleNumber);
			};
			if (new_trumbleNumber >= old_trumbleNumber)
			{
				(consoleMessage("Trumbles multiplying: increased to [new_trumbleNumber]"));
				(missionVariables.AH_trumbleNumber = new_trumbleNumber);
			}
		}
	}
}
there is an error in the let statement, I can't find out what.
"SyntaxError: missing ; before statement"
Last edited by Arexack_Heretic on Fri Oct 19, 2007 2:48 pm, edited 3 times in total.
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 »

about mission scripting:
How does the syntax for a missionscreen function look?

Code: Select all

if (something) 
{
imageFileName = itsfulloftrumbles.png; //place before function 
function showMissionScreen();
missionScreenTextKey = "trumble_pusher_maintext"; //place after function 
choicesKey = "trumble_pusher_yesno"; //place after function

if (choice == NEVER) 
{do stuff}
}
doent work, do the 'missionScreenTextKey' and 'choicesKey' need to be in the function parentheses as arguments.
edit: there was a { missing here, lets test again. (will delete if fixed.)
not yet, still whining about "SyntaxError: missing { before function body"
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:
bout this:

Code: Select all

this.trumbleCheck = function()
{
   //set variable AH_trumbleNumber to 0 if not yet defined, 
   //may not be neccesary but looks neater if called for the first time.    
   if (missionVariables.AH_trumbleNumber == undefined) 
	{
		var old_trumbleNumber = 0;
	};
	if (missionVariables.AH_trumbleNumber != undefined)
You’re still doing it. Since you never set missionVariables.AH_trumbleNumber, it will always be undefined, and the rest of the code isn’t called.
old_trumbleNumber = missionVariables.AH_trumbleNumber;
Since var old_trumbleNumber is inside the if (... == undefined) block, old_trumbleNumber will be undefined.
(consoleMessage("Trumbles decreasing: [new_trumbleNumber] remaining"));
consoleMessage() by itself is undefined. Did you mean player.consoleMessage()? What’s with the parentheses around the statement? Also, the “[new_trumbleNumber]” in a string will just be printed out as text, as mentioned above.
there is an error in the let statement, I can't find out what.
"SyntaxError: missing ; before statement"
Isn’t there a nice, helpful line number? Come to think of it, though, this is probably due to the use of “let” rather than “var” (requires JavaScript 1.7, Oolite 1.69 supports JavaScript 1.6). Sorry about that.

Try this:

Code: Select all

this.trumbleCheck = function() 
{ 
    var old_trumbleNumber = 0
    if (missionVariables.AH_trumbleNumber != undefined)
    {
        old_trumbleNumber = missionVariables.AH_trumbleNumber
    }
    var new_trumbleNumber = player.call("trumbleCount")
    
    Log("I has " + new_trumbleNumber + " trumbles")
    if (new_trumbleNumber < old_trumbleNumber) 
    { 
        consoleMessage("Trumbles decreasing: " + new_trumbleNumber + " remaining")
        missionVariables.AH_trumbleNumber = new_trumbleNumber
    }
    else if (new_trumbleNumber > old_trumbleNumber) 
    { 
        consoleMessage("Trumbles multiplying: increased to " + new_trumbleNumber)
        missionVariables.AH_trumbleNumber = new_trumbleNumber
    }
}
Note: semicolons are generally not necessary in JavaScript, unless you’re putting more than one statement on a line (which is bad style), and in the for loop. I’m trying to leave them out to reduce the number of confusing syntax elements.
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:
about mission scripting:
How does the syntax for a missionscreen function look?

Code: Select all

if (something) 
{
imageFileName = itsfulloftrumbles.png; //place before function 
function showMissionScreen();
missionScreenTextKey = "trumble_pusher_maintext"; //place after function 
choicesKey = "trumble_pusher_yesno"; //place after function

if (choice == NEVER) 
{do stuff}
}
The “itsfulloftrumbles.png” requires quotation marks. The word function on the next line shouldn’t be there. showMissionScreen() by itself is undefined; you want mission.showMissionScreen(), and equivalently mission. missionScreenTextKey and mission.choicesKey. Putting if (mission.choice == "NEVER") (quotation marks and mission. needed again) immediately after showing a mission screen is pointless, because the player won’t have had time to respond. Unfortunately, in 1.69 you’ll have to look for mission.choice changes in tickle(); 1.70 will have a better mechanism for this. In fact, I’d recommend not trying to do mission screens in JavaScript in 1.69. You’d probably be better off doing that part in a legacy script (note that you can specify one or more plist scripts as well as JavaScript scripts in world-scripts.plist).
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 »

sorry if i'm being a thickhead. I am trying to get a feeling for the structure of JS, but almost all example code I can find is only single command.

As a consequence I'm stringing things together in the same manner as legacy scripts do.
I am starting to see that JS has a fundamentally different architecture.


so in order to establish the variables, I need to do that before the this.function () {do stuff}?

I'll be at my GFs this weekend, without acces to these files, but hopefully I'll have some time to go online and learn.
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 in order to establish the variables, I need to do that before the this.function () {do stuff}?
No. A local variable comes into existence when the var foo line is reached, and persists until the end of the function. A local variable declared with let foo persists until the end of the scope – usually the current {} block, although there are some special cases. A mission variable comes into existence when you assign a value to it, and persists until you delete it (or the game resets).

To illustrate the difference between var and let, consider:

Code: Select all

this.foo = function()
{
    var a = 0
    let b = 0
    if (Math.random() < 0.5) // 50% chance
    {
        var c = 1
        let d = 1
    }
    Log("a: " + a) // Always OK
    Log("b: " + b) // Always OK
    Log("c: " + c) // OK if the random number was less than 0.5, otherwise error
    Log("d: " + d) // Always an error
}
As you can see, the use of var can lead to errors that happen only some of the time, potentially under subtle conditions. The behaviour of let is also far more common in other programming and scripting languages. For these reasons, once 1.70 is out, I recommend using let unless there’s a specific reason to use var. However, let will not work in 1.69.x.
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 »

you say that mission_variables are deleted when the game resets, but they are saved(and reloaded) in the commander file aren't they?
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:
you say that mission_variables are deleted when the game resets, but they are saved(and reloaded) in the commander file aren't they?
Yes. By reset, I mean when the player dies, starts a new game, or loads a new game; at this time, mission variables are reset, and thus some that existed earlier – from the script’s point of view – might no longer exist. In other words, scripts are not reloaded at these times.
Post Reply