mission.runScreen and callback

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

Moderators: winston, another_commander

Post Reply
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

mission.runScreen and callback

Post by Commander McLane »

I am still trying to get my head around the new and changed methods in Oolite 1.74, in order to update my OXPs.

One major change is the new mission screen handling, and the introduction of the callback function for mission screens.

Before I go and translate a lot of code in my OXPs with a lot of mission screens, I have a question. For the sake of simplicity (and laziness, and keeping mission screens together in my script), I want to change as little as possible in the general structure of my script. Therefore I'd like to know whether the following code would work, or whether calling the own mother function as a call back would be able to bring about the end of the world as we know it (actually: some sort of stack overflow and crash):

Code: Select all

this.missionScreens = function()
{
	if(!missionVariables.mymission && system.ID == 100)
	{
		mission.runScreen({messageKey:"mymission_message1a", choicesKey:"mymission_continue"}, this.missionScreens);
		missionVariables.mymission = "STAGE1a";
	}
	else if(missionVariables.mymission == "STAGE1a")
	{
		mission.runScreen({messageKey:"mymission_message1b", choicesKey:"mymission_continue"}, this.missionScreens);
		missionVariables.mymission = "STAGE1b";
	}
	else if(missionVariables.mymission == "STAGE1b")
	{
		mission.runScreen({messageKey:"mymission_message1c", choicesKey:"mymission_continue"}, this.missionScreens);
		missionVariables.mymission = "STAGE1c";
	}
	else if(missionVariables.mymission == "STAGE1c")
	{
		mission.runScreen({messageKey:"mymission_message1d"});
		missionVariables.mymission = "STAGE2";
	}
	else if(missionVariables.mymission == "STAGE2" && system.ID == 150)
	{
		mission.runScreen({messageKey:"mymission_message2a", choicesKey:"mymission_continue"}, this.missionScreens);
		missionVariables.mymission = "STAGE2a";
	}
	else if(missionVariables.mymission == "STAGE2a")
	{
		mission.runScreen({messageKey:"mymission_message2b"});
		missionVariables.mymission = "STAGE3";
	}
}

this.missionScreenOpportunity = function()
{
	this.missionScreens();
}
The general idea is that the script shall display a series of four consecutive mission screens in system 100 and later a series of two consecutive mission screens in system 150. Of course other stuff should be done as well, but I want to keep the example simple.

Another question: do I actually need to define a choices-key with one choice only for this type of consecutive mission screens (as it was necessary in the old model), or could I alternatively use the call back function without a choicesKey?
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 »

Good question!
That reminds me that I should add a "PRESS SPACE COMMANDER" choice to my screens....or should I? :?
Last edited by Arexack_Heretic on Thu Jul 22, 2010 10:42 am, edited 2 times in total.
Riding the Rocket!
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

That would result in each of the first stage mission screen being displayed in turn, one after the other presuming the conditions for the first display are true. The choices key will be ignored, as you're not actually checking it for anything. If you just want to press space between mission screens then you don't need to set the choice key.

Basically after displaying the first one (message1a) the mV will be set to STAGE1a and the function called again. It will then filter down through the if statements and display message1b, set the mV to STAGE1c and so on until it gets to the bottom of the stage 1 section of the list.

At this point the mV would be set to STAGE2, but as the system.ID check would be false it would stop until you flew to system #150, at which the sequence would repeat but for stage2 & 3 this time.

Remember that this.missionScreenOpportunity will fire not just at first docking, but also directly after the end of the display of a mission screen (to allow for a queue of such screens). Hence if the triggering condition is not set in the right way, it is perfectly possible to have the same screen re-appear once it is closed (if the conditions are still true for it) - which will basically lock the player in the screen unless they jump out of the screen by pressing F1 to force a relaunch. Your code is OK for that though as both sequences will end in mV settings that don't trigger any further mission screens.

What you may be better doing is using a second function for all of the callbacks, equivalent to how it used to be done when mission.choice was set and use that to ensure that the missionScreenOpportunity is not triggered when it shouldn't be. That is the most direct way to port the old method to the new one, although it's less optimal in usage.
Last edited by Thargoid on Thu Jul 22, 2010 10:36 am, edited 1 time in total.
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

Arexack_Heretic wrote:
Good question!
That reminds me that I should add a "PRESS SPACE COMMANDER" choice to my screens....or should I? :?
No, that's automagically added if no choice selection is offered.
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

Re: mission.runScreen and callback

Post by Kaks »

ChoicesKey is only needed if you want the player to actually make choices.
If you're not interested in choices, don't add that option, just call the callback function.

It won't destroy Oolite, afaik, but I'd make sure to change mymission before actually callling runScreen:

Code: Select all

this.missionScreens = function()
{
	if(!missionVariables.mymission && system.ID == 100)
	{
		missionVariables.mymission = "STAGE1a";
		mission.runScreen({messageKey:"mymission_message1a"}, this.missionScreens);
	}
	else if(missionVariables.mymission == "STAGE1a")
	{
		missionVariables.mymission = "STAGE1b";
		mission.runScreen({messageKey:"mymission_message1b"}, this.missionScreens);
	}
	else if(missionVariables.mymission == "STAGE1b")
	{
		missionVariables.mymission = "STAGE1c";
		mission.runScreen({messageKey:"mymission_message1c"}, this.missionScreens);
	}
	else if(missionVariables.mymission == "STAGE1c")
	{
		missionVariables.mymission = "STAGE2";
		mission.runScreen({messageKey:"mymission_message1d"});
	}
	else if(missionVariables.mymission == "STAGE2" && system.ID == 150)
	{
		missionVariables.mymission = "STAGE2a";
		mission.runScreen({messageKey:"mymission_message2a"}, this.missionScreens);
	}
	else if(missionVariables.mymission == "STAGE2a")
	{
		missionVariables.mymission = "STAGE3";
		mission.runScreen({messageKey:"mymission_message2b"});
	}
}

this.missionScreenOpportunity = function()
{
	this.missionScreens();
}
By the way, you should be able to enter this.missionScreens in its entirety in the javascript console, you can then type

Code: Select all

		missionVariables.mymission = "STAGE1a";
		mission.runScreen({messageKey:"mymission_message1a"}, this.missionScreens);
to get the ball rolling... :)
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
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 »

I think the elseif will only run if all conditions above are not met, so the planetX condition will actually be negative for those below?
Better to nest the conditions:

Code: Select all

if at planetX,
  if undefined > stage1
  else if stage1 > stage1a
  else if stage1a > stage1b
etc
els if at planet Y,
  if stage1complete >stage2
  elseif stage2 >stage2a
etc.
Last edited by Arexack_Heretic on Thu Jul 22, 2010 11:21 am, edited 1 time in total.
Riding the Rocket!
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 »

Don't quite know which computer language you're using there.

and I've no idea which ones are the 'ones below'.

If you give me an example in javascript, and define 'ones below' with some clarity, I'll be able to tell you! :)


What you used there bears some similarity with python, but we're not making OXPs in python, are we?
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
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 »

*sigh* pedantic anti-pseudocode-ist :p

with below in a nested structure I mean deeper inside the 'nest', the conditions for stage are 'below' the condition for planet location.

Code: Select all

if (system.ID === 100)
{
  if (!missionVariables.Boo) 
  {missionVariables.Boo = "GO"};
  else if(missionVariables.Boo === "GO")
  {//doyourstuff};
  ...
  else if(missionVariables.Boo === "ALMOST_DONE")
  {missionVariables.Boo = "SYS100done"; //dostuff};
}
else if (system.ID === 50)
{
  if(missionVariables.Boo === "SYS100done")
  {//doyourstuff};
  etc.
}
edit: I misunderstood the 'else if' function a bit there, just woke up. never mind.
Still, nesting does provide a safety against the player F1-ing at the first screen and encountering the missionscreens at a different location.

edit2: yes, most of my meager skillz derive from messing with python, don't tell me that nesting is not allowed in JS!?
edit3: uh oh, does JS evaluate code line by line as python does? I'll have a problem if not...
Last edited by Arexack_Heretic on Thu Jul 22, 2010 12:55 pm, edited 3 times in total.
Riding the Rocket!
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Re: mission.runScreen and callback

Post by Eric Walch »

Kaks wrote:
By the way, you should be able to enter this.missionScreens in its entirety in the javascript console, you can then type

Code: Select all

		missionVariables.mymission = "STAGE1a";
		mission.runScreen({messageKey:"mymission_message1a"}, this.missionScreens);
to get the ball rolling... :)
Should work, copy the whole content of that function and paste it in the console. The 1.74 console supports now such long, multiline code.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Post by Commander McLane »

Thanks, that's all I wanted to know. :D (Oh, and I have been doing multi-line inputs into the console for a long time, I'd say even pre-1.73.)
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post by Thargoid »

One other thought, you could perhaps simplify your code a bit by using the switch command, with a couple of if checks for system.ID in the cases for STAGE1 and STAGE2. Could be neater, simpler and faster executing than the nested if's.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Post by Commander McLane »

Thargoid wrote:
One other thought, you could perhaps simplify your code a bit by using the switch command, with a couple of if checks for system.ID in the cases for STAGE1 and STAGE2. Could be neater, simpler and faster executing than the nested if's.
Ah! Yes, I indeed wanted to adopt this method, since I saw it in your scripts. Thanks for reminding me. :D
User avatar
docwild
Dangerous
Dangerous
Posts: 64
Joined: Thu Mar 29, 2007 1:36 pm

Post by docwild »

Just as an aside, javascript supports the ?: operator too which goes:

Code: Select all

boolean condition ? do this if true : do this if false ;
so...

Code: Select all

missionVariables.Boo ? dothis() : dothat() ;
Which is handy for when you're nesting simple conditionals.
Post Reply