Scripters cove

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:

Re: Scripters cove

Post 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.
User avatar
marcusrg
Deadly
Deadly
Posts: 216
Joined: Fri Jun 08, 2012 3:48 pm
Location: Somewhere in Brazil

Re: Scripters cove

Post 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.
User avatar
BuggyBY
Dangerous
Dangerous
Posts: 108
Joined: Thu Feb 09, 2012 9:03 am

Re: Scripters cove

Post 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();
	}
}
Switeck
---- E L I T E ----
---- E L I T E ----
Posts: 2411
Joined: Mon May 31, 2010 11:11 pm

Re: Scripters cove

Post by Switeck »

Hoopy Casino OXP sends messages too when you get near it.
User avatar
marcusrg
Deadly
Deadly
Posts: 216
Joined: Fri Jun 08, 2012 3:48 pm
Location: Somewhere in Brazil

Re: Scripters cove

Post 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.
User avatar
Fatleaf
Intergalactic Spam Assassin
Intergalactic Spam Assassin
Posts: 1988
Joined: Tue Jun 08, 2010 5:11 am
Location: In analysis mode on Phaelon
Contact:

Re: Scripters cove

Post by Fatleaf »

Coyote's Run has a lot of that as well.
Find out about the early influences of Fatleaf here. Also his OXP's!
Holds the Ooniversal record for "Thread Necromancy"
User avatar
marcusrg
Deadly
Deadly
Posts: 216
Joined: Fri Jun 08, 2012 3:48 pm
Location: Somewhere in Brazil

Re: Scripters cove

Post by marcusrg »

Iknow, but it is hard for me to understand and sepatate the right codes.
User avatar
marcusrg
Deadly
Deadly
Posts: 216
Joined: Fri Jun 08, 2012 3:48 pm
Location: Somewhere in Brazil

Re: Scripters cove

Post 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?
User avatar
Smivs
Retired Assassin
Retired Assassin
Posts: 8408
Joined: Tue Feb 09, 2010 11:31 am
Location: Lost in space
Contact:

Re: Scripters cove

Post 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.
Commander Smivs, the friendliest Gourd this side of Riedquat.
User avatar
marcusrg
Deadly
Deadly
Posts: 216
Joined: Fri Jun 08, 2012 3:48 pm
Location: Somewhere in Brazil

Re: Scripters cove

Post by marcusrg »

Thanks, Smivs, trying this.

Update: It worked! Thanks! :D
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post 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?
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: Scripters cove

Post 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.
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

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

Re: Scripters cove

Post 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.)
User avatar
Wildeblood
---- E L I T E ----
---- E L I T E ----
Posts: 2453
Joined: Sat Jun 11, 2011 6:07 am
Location: Western Australia
Contact:

Re: Scripters cove

Post 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!
Post Reply