Page 48 of 117

Re: Scripters cove

Posted: Fri Jul 06, 2012 7:43 pm
by JensAyton
El Viejo wrote:
I believe a star can go nova multiple times, and fade-back in between. It's supernovae that destroy themselves.
Only white dwarfs (cinders of burned-out stars consisting of degenerate matter) in close binary formation with another normal-matter star can go nova. It can indeed happen repeatedly (with intervals as low as a few decades). A white dwarf that undergoes repeated novae gets heavier and may eventually go supernova.

The Oolite nova effect, with much of the star’s volume disappearing, is more like a supernova but not much like either.

Re: Scripters cove

Posted: Sun Jul 08, 2012 1:10 am
by marcusrg
I was looking for a script which makes an NPC send a messsage to a player ship if it enters his scanner view. Something like "Hello, Commander!". I looked up in the wiki and the forums here but I couldn't find it... What I read already, is that is better to create a script for it. How can I do that? I tried to find an example in other oxp's, but I couldn't find some for this...
Thanks for the help.

Re: Scripters cove

Posted: Sun Jul 08, 2012 10:17 am
by BuggyBY
marcusrg wrote:
I was looking for a script which makes an NPC send a messsage to a player ship if it enters his scanner view. Something like "Hello, Commander!". I looked up in the wiki and the forums here but I couldn't find it... What I read already, is that is better to create a script for it. How can I do that? I tried to find an example in other oxp's, but I couldn't find some for this...
Thanks for the help.
Doesn't [wiki]Rebecca Weston[/wiki] at the [wiki]Tianve Pulsar[/wiki] do just that? The relevant bit from the OXP's tianve-rebecca-script.js is below:

Code: Select all

this.shipSpawned = function()
{
	// sets primary role to "hunter", to make it accept distress calls
	this.ship.primaryRole = "hunter";
/*	
	// establishes the station group of the monitoring station
	var pulsarStationGroup = system.shipsWithRole("tianve-pulsar-station", this.ship)[0].group;

	// adds Rebecca to the station group
	pulsarStationGroup.addShip(this.ship);

	// and makes her aware of that
	this.ship.group = pulsarStationGroup;
*/	
	// starts a timer that periodically looks for the player
	// the timer looks every ten seconds (second number)
	this.scanForPlayerTimer = new Timer(this, this.scanForPlayer, 0, 10);
}

this.scanForPlayer = function()
{
	//  when having the player in scanner range for the first time ...
	if(this.ship.position.distanceTo(player.ship.position) < 25600)
	{
		// ... a message is sent ...
		this.ship.commsMessage("So it's Commander " + expandDescription("[commander_name]") + ", eh? I've heard of you. Just behave yourself around here, or else!");
		// ... and the timer is stopped
		this.scanForPlayerTimer.stop();
	}
}

Re: Scripters cove

Posted: Sun Jul 08, 2012 11:33 am
by Switeck
Hoopy Casino OXP sends messages too when you get near it.

Re: Scripters cove

Posted: Sun Jul 08, 2012 11:50 am
by marcusrg
The exemple above was good. I will try it. As for the Hoopy Cassino, I looked for the codes, but it was hard to me to understand them. The example above is much clear to me. Thanks.

Re: Scripters cove

Posted: Sun Jul 08, 2012 1:45 pm
by Fatleaf
Coyote's Run has a lot of that as well.

Re: Scripters cove

Posted: Sun Jul 08, 2012 2:13 pm
by marcusrg
Iknow, but it is hard for me to understand and sepatate the right codes.

Re: Scripters cove

Posted: Sun Jul 08, 2012 4:42 pm
by marcusrg
BuggyBY wrote:
Doesn't [wiki]Rebecca Weston[/wiki] at the [wiki]Tianve Pulsar[/wiki] do just that? The relevant bit from the OXP's tianve-rebecca-script.js is below:

Code: Select all

this.shipSpawned = function()
{
	// sets primary role to "hunter", to make it accept distress calls
	this.ship.primaryRole = "hunter";
/*	
	// establishes the station group of the monitoring station
	var pulsarStationGroup = system.shipsWithRole("tianve-pulsar-station", this.ship)[0].group;

	// adds Rebecca to the station group
	pulsarStationGroup.addShip(this.ship);

	// and makes her aware of that
	this.ship.group = pulsarStationGroup;
*/	
	// starts a timer that periodically looks for the player
	// the timer looks every ten seconds (second number)
	this.scanForPlayerTimer = new Timer(this, this.scanForPlayer, 0, 10);
}

this.scanForPlayer = function()
{
	//  when having the player in scanner range for the first time ...
	if(this.ship.position.distanceTo(player.ship.position) < 25600)
	{
		// ... a message is sent ...
		this.ship.commsMessage("So it's Commander " + expandDescription("[commander_name]") + ", eh? I've heard of you. Just behave yourself around here, or else!");
		// ... and the timer is stopped
		this.scanForPlayerTimer.stop();
	}
}
Ok, in this code, I tried to use only the part from "this.scanForPlayeTimer" on... I made a test with some "Hello, Commander", but it didn't work... in the log, there's an error message as follows:

09:50:18.279 [script.javaScript.exception.syntaxError]: ***** JavaScript exception (pizzaship.anon-script): SyntaxError: syntax error
09:50:18.279 [script.javaScript.exception.syntaxError]: /home/beagle/.Oolite/AddOns/pizzaship.oxp/Config/script.js, line 10: }
09:50:18.279 [script.javaScript.load.failed]: ***** Error loading JavaScript script /home/beagle/.Oolite/AddOns/pizzaship.oxp/Config/script.js -- compilation failed

Did I miss something in the code?

Re: Scripters cove

Posted: Sun Jul 08, 2012 4:52 pm
by Smivs
Firstly the script should be a shipscript attached to the ship, so you will need to add a line to shipdata, something like

Code: Select all

script = pizzaship_script.js;
then your script called pizzaship_script.js will need to go in a 'Scripts' folder.
The above example script is as good as any to work on, but you will need to use most/all of it, with suitable changes to reflect how it relates to your ship, and to get the message you want.

Re: Scripters cove

Posted: Sun Jul 08, 2012 4:54 pm
by marcusrg
Thanks, Smivs, trying this.

Update: It worked! Thanks! :D

Re: Scripters cove

Posted: Tue Jul 10, 2012 5:29 am
by Wildeblood
A question about conditional tests and returning from functions (the third line in both the examples below).

I've just been looking in Trading Assistant and found this:-

Code: Select all

this.guiScreenChanged = function(to,from)
	{
	if (to !== "GUI_SCREEN_MARKET" || guiScreen !== "GUI_SCREEN_MARKET" || player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") !== "EQUIPMENT_OK") {return;}
	this.originalManifest = this.getManifest();
	this.originalCredits = player.credits;
	this.monitorManifestCallBack = addFrameCallback(this.monitorManifest.bind(this));
	}
Apart from the insertion of the equipment status test, it's unchanged from what Capt. Murphy originally wrote (including the unnecessary braces around {return;}).

If I had created it myself, I would have written:-

Code: Select all

this.guiScreenChanged = function(to,from)
	{
	if (to === "GUI_SCREEN_MARKET" && guiScreen === "GUI_SCREEN_MARKET" && player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") === "EQUIPMENT_OK")
      {
	   this.originalManifest = this.getManifest();
	   this.originalCredits = player.credits;
	   this.monitorManifestCallBack = addFrameCallback(this.monitorManifest.bind(this));
      }
	}
So, what's the difference? Which is better?

Re: Scripters cove

Posted: Tue Jul 10, 2012 7:23 am
by Eric Walch
marcusrg wrote:
Thanks, Smivs, trying this.

Update: It worked! Thanks! :D
What is missing in the code is a cleanup code. You should also add:

Code: Select all

this.entityDestroyed = function ()
{
    if (this.scanForPlayerTimer) {this.scanForPlayerTimer.stop(); delete this.scanForPlayerTimer};
}
This makes sure that the timer is stopped and removed when the ship is destroyed before it sees the player. this.entityDestroyed is not only triggered on destruction by combat, but also when the ship is removed because the player jumps to another system. Oolite has code in place to remove the timer itself, but it is always better to let the ship script do it.
Wildeblood wrote:

Code: Select all

if (to !== "GUI_SCREEN_MARKET" || guiScreen !== "GUI_SCREEN_MARKET" || player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") !== "EQUIPMENT_OK") {return;}

Code: Select all

if (to === "GUI_SCREEN_MARKET" && guiScreen === "GUI_SCREEN_MARKET" && player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") === "EQUIPMENT_OK")
So, what's the difference? Which is better?
Both are equal. In both cases the evaluation stops after the first check when not at the right screen. In most cases 'to' check can be skipped as in most cases you only want to know the current guiScreen you are on. 'to' itself as check is not enough as another oxp might already have changed the current screen to a missionscreen.

Re: Scripters cove

Posted: Tue Jul 10, 2012 9:35 am
by Wildeblood
Eric Walch wrote:
Wildeblood wrote:

Code: Select all

if (to !== "GUI_SCREEN_MARKET" || guiScreen !== "GUI_SCREEN_MARKET" || player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") !== "EQUIPMENT_OK") {return;}

Code: Select all

if (to === "GUI_SCREEN_MARKET" && guiScreen === "GUI_SCREEN_MARKET" && player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") === "EQUIPMENT_OK")
So, what's the difference? Which is better?
Both are equal. In both cases the evaluation stops after the first check when not at the right screen. In most cases 'to' check can be skipped as in most cases you only want to know the current guiScreen you are on. 'to' itself as check is not enough as another oxp might already have changed the current screen to a missionscreen.
Follow-up question, the reason I was looking at it anyway: there is no test whether the player is actually docked. You can check prices on the market screen before you dock, but there is no possibility of buying or selling, so Capt. Murphy's code can start Yet Another Damned Frame Callback running for No Good Reason. Am I right? Wouldn't this be better:-

Code: Select all

if (guiScreen === "GUI_SCREEN_MARKET" && player.ship.docked === true && player.ship.equipmentStatus("EQ_AI_TRADING_ASSISTANT") === "EQUIPMENT_OK")

Re: Scripters cove

Posted: Tue Jul 10, 2012 10:25 am
by JensAyton
Wildeblood wrote:
So, what's the difference? Which is better?
Since it’s a stylistic difference, “better” is largely subjective, but it’s worth considering why you’d do one over the other.

One school of thought is that it’s good to keep the main path of the function “to the left”, i.e. not heavily indented, so that the structure of the “important” code is easy to see without having to match up many levels of nested braces. In this view, “early exits” dealing with cases where your function doesn’t need to do anything are good, because those cases can then be ignored in the rest of the code. Capt. Murphy’s original code follows this approach.

Another perspective is that having multiple return statements in a function is always bad, because it makes it harder to follow the control flow. It also means that if you need to clean up anything before returning, that code gets duplicated and it’s easy to miss one spot if you’re updating the code.

It’s possible to mix these philosophies. For instance, you might choose to use early exits for trivial cases and bad parameters (like “don’t bother doing any collision testing work in this region if there are fewer than two objects in it”), but use a single-return approach for the “meat” of a function. This is the broad tendency in Oolite itself, although I wouldn’t want to give the impression that Oolite is self-consistent.

Which it should be. The most important thing about code structure is consistency, because if you use the same pattern in all relevant parts of your code it becomes easy to read the pattern itself rather than the steps it’s made up of. Good coding style is about making code readable to humans.

That said, this is honestly a few steps beyond most OXP coders. The #1 code structure tip for beginners is: use a consistent indentation style. Code at the same nesting level (mostly meaning the same number of enclosing {}s, although there are other types of nesting) should be aligned on their left margin. This makes it vastly easier to see the structure of the code. If you don’t have an established preference, try to match the appearance of Oolite’s scripts and plists. A programmers’s editor like Notepad++ or Gedit or Xcode will help you do this automatically for .js files. (If your editor has a setting for indentation style, the Oolite norm is similar to Allman style.)

Re: Scripters cove

Posted: Fri Jul 13, 2012 4:02 pm
by Wildeblood
I'm hesitant to ask about orientation again after the kerfuffle last time I asked a month ago (I never did get that ship to back out of the dock, but I did get some weird screenshots of being trapped inside the docking tunnel effect), but reading back over all your responses (thank you) I'm not certain whether the question was ever resolved. Today I'm wondering whether it is possible to rotate the station away from the planet and buoy, so that a ship can launch at ludicrous speed without slamming straight into the buoy? I'm looking at Thargoid's example:-

Code: Select all

player.ship.orientation = player.ship.orientation.rotate(player.ship.vectorForward, Math.PI);
And I'm going to try this:-

Code: Select all

system.mainStation.orientation = system.mainStation.orientation.rotate(system.mainStation.vectorForward, Math.PI);
Wish me luck!