Page 2 of 3

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 3:15 pm
by Pleb
Commander McLane wrote:
Pleb wrote:
Commander McLane wrote:
Where do you get this idea from? I have never heard of a "template/example" JS file. (I also don't have UPS installed.)
I'm currently at work and therefore unable to supply you with the exact the name of the file, but if you download the UPS OXP and look in its script folder there is an example Javascript file in there.
Misunderstanding. I'm not doubting the existence of demoScript.js (I've looked it up in the meantime) in UPS-courier.oxp. I just find your assumption that "everyone seems to follow" this JS-file when laying out their scripts a little bold. :wink:

And that's because I never ever even once followed its layout, or used it as a template when writing my own scripts, of which I have written a fair number so far.

If you take the time to study a script of mine—for instance anarchies.js as an example for a rather long script—you will see that if it follows a template, it's that of Oolite's own scripts, which I thought to be the sensible thing to follow when I wrote the OXP (or more precisely, when I converted the script from legacy style into JS).
I never meant to imply that everyone follows this kind of style just that the majority of scripts I have looked at seem to follow this kind of working. Agreed, like A_C stated, we should be following the stock scripts as a template in practice, but the reality is that your scripts are among a minority (or at least a minority in the vast amount of OXPs I have installed) that seem to follow the stock scripts. This is why myself, and others as well I would imagine, have adopted a different style of script that has unfortunately seems to have become the "unofficial" standard or norm, by following scripts that were already available, like the ones I have mentioned before.

Perhaps the wiki should reflect the stock scripts and their layout so that this problem can be avoided in future? I know I intend to rework my own scripts now to follow the core scripts so that they are no longer flawed as Ahruman pointed out.
smivs wrote:
I've never used a template of any kind, and was also unaware of the script in UPS which I have never used or even downloaded.
Pleb, you metioned Xeptatl' Sword amongst others in your first post. All the scripting in that OXP is original, mostly written by Okti, but with much by me. It was written the way it is because that's the way we wrote it, not because of any 'template'.
I wonder if what we are seeing here is the simple fact that scripts tend to have the same 'look' to them simply because they are scripts, the same way the HTML/CSS of a web-page will look very similar to the HTML/CSS of a totally different web-page.
Out of interest, I had a quick scan through some of the 'core' scripts to refresh my memory, and I have to be honest and say I can't see much diffrence in the 'layout' of them to most of the OXP scripts I'm familiar with. Yes, they are well laid out and commented, but I like to think my more recent scripting efforts are as well, and I'm just an amateur who's still learning.
I still need to start using $ for custom functions, and 'use strict' I was unaware of, but I'm trying.
It's more the way that missions are offered and how choices are handled in the scripts. Again, being at work I don't have access to the game and have to rely on memory, but from what I can remember the way the script is laid out is more similar to the demoScript.js in UPS than the core scripts, which do look very different in comparison.

I didn't want to start a massive argument about how/how not to write a script and point fingers at anyone, because I am fully aware that I have only written one "working" OXP and that it contains many flaws, I simply wanted to know why there is this difference of style. However on reflection it would seem that perhaps it is simply my misunderstanding and I appologise and will try to re-write my own script to try and make it acceptable to everyone here.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 3:24 pm
by Smivs
Pleb wrote:
I didn't want to start a massive argument about how/how not to write a script and point fingers at anyone, because I am fully aware that I have only written one "working" OXP and that it contains many flaws, I simply wanted to know why there is this difference of style. However on reflection it would seem that perhaps it is simply my misunderstanding and I appologise and will try to re-write my own script to try and make it acceptable to everyone here.
Far from being an 'argument', I think this thread could become very useful indeed.
Consistency is a good thing (although I still don't understand what you mean by 'different styles'), and any good advice regarding scripting will be useful to many of us. I've already learned a few things I didn't know before.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 3:27 pm
by Cody
Smivs wrote:
Consistency is a good thing
I like the word Consistency - it reminds me of custard!

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 3:33 pm
by Tricky
Smivs wrote:
Pleb wrote:
I didn't want to start a massive argument about how/how not to write a script and point fingers at anyone, because I am fully aware that I have only written one "working" OXP and that it contains many flaws, I simply wanted to know why there is this difference of style. However on reflection it would seem that perhaps it is simply my misunderstanding and I appologise and will try to re-write my own script to try and make it acceptable to everyone here.
Far from being an 'argument', I think this thread could become very useful indeed.
Consistency is a good thing (although I still don't understand what you mean by 'different styles'), and any good advice regarding scripting will be useful to many of us. I've already learned a few things I didn't know before.
Smivs is correct. As soon as I saw and read this thread I had a look at the core scripts. I am currently doing minor edits to my scripts to reflect the style. I also already used '$' prefix for my functions.

I also run my scripts through JSlint, ignoring all the errors about system, worldScripts, log et al.

I really need to read up on the Mozilla Javascript dev site.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 3:58 pm
by Wildeblood
cim wrote:
What happens if you have this.foo in a script written for 1.76, and Oolite 1.78 defines this.foo as a script event?
Strange things happen. For a recent, concrete example see AI Trading Assistant - created for Oolite 1.76 on April 5th, broken in Oolite 1.77 r4851 on April 15th.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 4:25 pm
by Commander McLane
Wildeblood wrote:
cim wrote:
What happens if you have this.foo in a script written for 1.76, and Oolite 1.78 defines this.foo as a script event?
Strange things happen. For a recent, concrete example see AI Trading Assistant - created for Oolite 1.76 on April 5th, broken in Oolite 1.77 r4851 on April 15th.
That was a rhetorical question, you know. :wink:

But it's nice that there is already a real example for why not distinguishing self-made functions is a big, fat bug each time it happens.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 6:06 pm
by Eric Walch
Pleb wrote:
It's more the way that missions are offered and how choices are handled in the scripts. Again, being at work I don't have access to the game and have to rely on memory, but from what I can remember the way the script is laid out is more similar to the demoScript.js in UPS than the core scripts, which do look very different in comparison.
A part of the structure of current mission screen handling can be explained by the old way of doing it. I always used a function to deal with the mission screen choices. When we got the new runScreen() function, it was the most easy way to use that function as the callback function for the mission screens. Almost no code change was needed to do that. When rewriting it from scratch, a different structure might have been used.

The template in UPS is there because mission screens were always very buggy. The did work alone, but were likely to clash with other oxps. The new mission screen way is more fool proof as long as you do your actions inside the special designed event handler. Creating mission screens from other places can still clash when two want to draw a screen. A good (actually bad) example is coyote run that still clashes with other oxps drawing a mission screen on entering the commodity market. (Despite all the warnings on the wiki page).

Consistent coding is apparently difficult. When I look inside the widgets on my mac, that apple devs wrote in JS, I always wonder why they mix several stiles. Okay, they copy code from other places and apparently don't want to risk unifying the style as that might introduce errors.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 9:34 pm
by Pleb
As people seem to not be understanding what I mean by different styles, I will give an example. When choices are offered in mission briefings, the majority of OXPs seem to follow this style:

Code: Select all

this.missionOffers = function (){
    if (player.ship.dockedStation.isMainStation)
    {
        //  Your stuff for the main station
        /*
        Missionscreens are set up using the command:
        mission.runScreen({title: "", messageKey: "", etc...}, this.choiceEvaluation)
        
        When you do an offer it is often advisable to set a variable to tell an offer is made. (e.g. this.offering) 
        This prefents comming in a loop of offering. There is no need to use a missionVarriable for this,
        a "this.Foo" will do. But always remember that a player can launch without making a selection, so
        you must clear such variables on launch.
        */
    } else if (player.ship.dockedStation.shipDescription == "My Station"){
        // Your stuff for a special named station
    }
};

this.choiceEvaluation = function (choice){
    if (this.offering === "MY_OFFER"){
         /*
         the choise is only offered to the oxp that created the page, so there is no longer the risk
         of other oxp reacting on a chosen answer.
         */
        if (choice === "YES_MISSION"){
            // put your code here. 
        }else{
            if (choice === "NO_MISSION"){
                // put your code here
            }
        }
    }
    this.offering = null;
};
Where as in the stock scripts, it is offered like this:

Code: Select all

this.missionScreenOpportunity = function missionScreenOpportunity()
{
	if (pendingOffer && player.credits > 6553.5)
	{
		pendingOffer = false;
		
		// Show the mission screen.
		mission.runScreen({
			titleKey: "oolite_trumble_title",
			messageKey: "oolite_trumble_offer",
			background: "trumblebox.png",
			choicesKey: "oolite_trumble_offer_yesno"
		},
		function (choice)
		{
			if (choice === "OOLITE_TRUMBLE_YES")
			{
				player.credits -= 30;
				player.ship.awardEquipment("EQ_TRUMBLE");
				
				missionVariables.trumbles = "TRUMBLE_BOUGHT";
				cleanUp(this);
			}
			else
			{
				missionVariables.trumbles = "NOT_NOW";
			}
		});
	}
};
So you can see, these are very different ways of doing the same thing. This is where my confusion has come from, as the majority but not all seem to follow a style similar to the first example, taken from the demoScript.js file, rather than those in the second example, taken from the oolite-trumbles-mission.js file. Note that they are not all the same as in the demoScript.js file, but they are similar. There are far fewer OXPs that use the stock script way of doing it...

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 9:58 pm
by cim
Pleb wrote:
As people seem to not be understanding what I mean by different styles, I will give an example. When choices are offered in mission briefings, the majority of OXPs seem to follow this style
This is something where there are advantages and disadvantages to doing it both ways, so the right thing to do depends on the script (and to a large extent on what the author prefers).

Using a named callback function (as in demoScript) means that you can call it from multiple instances of mission.runScreen, and you don't get a massive amount of indenting (especially if the callback runs another mission screen itself, or has a lot of complex logic inside it) which can make the code easier to read.

Using an anonymous callback function (as in the core missions) means that your handling of the choice is associated with the mission screen that gives the player that choice, which can make the code easier to read, and means you can't accidentally overwrite or call the choice function from elsewhere in your code.

Re: Stock Missions Scripting Layout

Posted: Wed Jul 11, 2012 11:21 pm
by JensAyton
cim wrote:
This is something where there are advantages and disadvantages to doing it both ways
I would argue that there is no advantage whatsoever to using ifs or a switch to determine which mission screen you’re responding to (which I think is the bigger issue here, although it’s not obvious from Pleb’s example). It used to be necessary, now it isn’t, and it makes the connection between where the mission screen is set up and where in the giant response function it’s handled very unclear.

So, my opinion:
  • There should be exactly one callback per mission screen, except for purely informational ones that require no followup at all. A possible exception would be if you have multiple similar screens leading into the same mission state, but in that case I suggest you should have one function that handles the different variations by setting up the parameter block object appropriately.
  • In general, the callback should be inline. If it needs to do something complicated, it should call out to a separate function to do that. For example: function (choice) { if (choice === "CHALLENGE_ACCEPTED") { this._setUpChallengeStage(); } else { this._showDisappointedFaceMissionScreen(); }}. This communicates the full structure of the mission screen, including what its options mean, without going into the details of what setting up the next stage entails. (The trumbles mission is about at my upper limit for reasonable callback size; moving the stuff from the choice === "OOLITE_TRUMBLE_YES" branch to a separate function certainly wouldn’t make it worse.)
  • When the parameter block is in property list form (as in the examples), use one line per key. Writing {title:"foo",messageKey:"bar",choicesKey:"quux"} crammed together just means more work when you need to read it later.

Re: Stock Missions Scripting Layout

Posted: Thu Jul 12, 2012 6:49 am
by Eric Walch
Pleb wrote:
As people seem to not be understanding what I mean by different styles, I will give an example. When choices are offered in mission briefings, the majority of OXPs seem to follow this style....
I did already understood and answered in my previous message. In the old way of dealing with mission screens the choices were handled during a separate event handler, resulting in all choices dealt with in a single function. When the new way of mission screens was introduced, it was the most easy way of converting to use that old choices function as the callback for all screens. This because it only needed the chance of one variable instead of a complete rewrite of the code to get the call backs in-line.

But, as Cim and Ahruman already noticed, it is not useful to do it always in-line. Especially when using nested screens with a lot of choices it is easier to use a common callback function for a group of related screens.

And when you look at Random Hits, you see there is yet another way used to deal with the screens. There I start with pushing just the page names on a stack on docking and than handle them one by one. That way proofed to be an easy way to add new screens later on and show them in different orders, without the need to restructure much when adding new missions.

Re: Stock Missions Scripting Layout

Posted: Thu Jul 12, 2012 7:15 am
by PhantorGorth
If we are not just restricting ourselves to missions only then it might be pertinent to mention other good scripting practices such as the wiki page I wrote (with help from others) on how to write a OXP startUp function to handle OXP dependencies (see it [EliteWiki] here)

NB I was aware of the "use strict" but not what it actually did. I have seen the use of _ to label local variables (but not the $ for functions though) but never saw that as a preferred convention but more an optional choice.

May be there should be a sticky thread for good scripting/OXP development practices where the results of the discussion should go into the wiki in one clear central place?

Re: Stock Missions Scripting Layout

Posted: Thu Jul 12, 2012 9:14 am
by Pleb
PhantorGorth wrote:
May be there should be a sticky thread for good scripting/OXP development practices where the results of the discussion should go into the wiki in one clear central place?
I agree, more documentation is needed I feel on the scripting methods and practises in Oolite. As more people start to play Oolite and eventually start to write their own OXPs, they are going to look to the wiki for help. If that help is not on there, rather than having to trawl through the forums trying to read every post that references scripting they will do as I and many others have and look at other OXPs for help, regardless of how old/dated they are. The core scripts do cover some of the aspects of scripting but there is much more on offer in OXPs as they are much more varied.

Re: Stock Missions Scripting Layout

Posted: Thu Jul 12, 2012 11:35 am
by Svengali
PhantorGorth wrote:
but never saw that as a preferred convention but more an optional choice.
Heh - it's a 'religious' discussion :mrgreen:

Re: Stock Missions Scripting Layout

Posted: Thu Jul 12, 2012 1:27 pm
by Pleb
PhantorGorth wrote:
I have seen the use of _ to label local variables (but not the $ for functions though) but never saw that as a preferred convention but more an optional choice.
True, I also saw this but was never aware this was the "preferred convention" for as far as I'm aware this was previously undocumented.