Page 7 of 7

Re: Split: Deployable subentities

Posted: Mon Aug 18, 2014 3:41 pm
by dertien
Eric Walch wrote:
One piece of code that is also needed in shipscripts that use timers:

Code: Select all

this.entityDestroyed = function ()
{
    this.$cleanupTimers();
}
And in this.$cleanupTimers you have the code to stop and delete the timer. This is to prevent errors when the ship explodes while there is still a timer running.
Done!

Re: Split: Deployable subentities

Posted: Mon Aug 18, 2014 4:17 pm
by dertien
So here are 2 screenshots of the "HPCcobramk3_trader_hauler" each with a different role. In the first example :

Code: Select all

roles = "trader-courier(2) shuttle";
Drops its gear and executes the code
Image

File for testing: here: https://app.box.com/s/g9c2gxaud7t3sojpqltr

And here is the same ship entry in the same shipdata.plist file but with the role below (the one it should get)

Code: Select all

roles = "trader(0.375) trader-courier(0.2) trader-smuggler(0.75)";
Does not drop its gear, thus does not execute the code.
Image


File for testing: here: https://app.box.com/s/kivpx14rny6lyjf3cf3o

As Spock would say this defies logic.

Any suggestions as to what is happening ?

These errors also show up in the log, don't know if this is related or not.

Code: Select all

18:00:19.666 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (oolite-populator 1.81): TypeError: h is null
18:00:19.666 [script.javaScript.exception.unexpectedType]:       Resources/Scripts/oolite-populator.js, line 1526.
18:00:19.669 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (oolite-populator 1.81): TypeError: h is null
18:00:19.669 [script.javaScript.exception.unexpectedType]:       Resources/Scripts/oolite-populator.js, line 1526.
18:00:19.839 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (oolite-populator 1.81): TypeError: pg is null
18:00:19.839 [script.javaScript.exception.unexpectedType]:       Resources/Scripts/oolite-populator.js, line 1651.
Also tried with 1.80, same error.

Re: Split: Deployable subentities

Posted: Mon Aug 18, 2014 5:31 pm
by cim
Those log errors suggest that your current OXP combination has entirely undefined all ships with "hunter" or "pirate" roles. I assume you've undefined every ship except your Cobra variants for easier testing?

As for the other issue, the only events in your script which define the landing gear timer for NPCs are "shipLaunchedFromStation", "shipExitedWitchspace" and "shipLeavingPlanetSurface".

For roles roles = "trader-courier(2) shuttle";, as couriers are relatively rare and often sunskim anyway, the ship which arrives at the station first is very likely to be a shuttle launched from the planet. Its timer will have started in "shipLeavingPlanetSurface" as it launched.

For roles roles = "trader(0.375) trader-courier(0.2) trader-smuggler(0.75)"; the ship which reaches the planet first is likely to be a trader, which will have been added mid-flight to the system by the populator, and therefore will never (in the period of its existence which Oolite considers) launched from a station or planet, or exited witchspace. Therefore it doesn't have the timer and doesn't lower its gear.

If you have things which you need to do as part of an NPC's setup, then the shipSpawned function is the right place to do it: that will work no matter how the ship appears in the system. It doesn't work for the player, though.

Re: Split: Deployable subentities

Posted: Mon Aug 18, 2014 6:22 pm
by dertien
cim wrote:
Those log errors suggest that your current OXP combination has entirely undefined all ships with "hunter" or "pirate" roles. I assume you've undefined every ship except your Cobra variants for easier testing?
Yes I have :)
cim wrote:
As for the other issue, the only events in your script which define the landing gear timer for NPCs are "shipLaunchedFromStation", "shipExitedWitchspace" and "shipLeavingPlanetSurface".

For roles roles = "trader-courier(2) shuttle";, as couriers are relatively rare and often sunskim anyway, the ship which arrives at the station first is very likely to be a shuttle launched from the planet. Its timer will have started in "shipLeavingPlanetSurface" as it launched.

For roles roles = "trader(0.375) trader-courier(0.2) trader-smuggler(0.75)"; the ship which reaches the planet first is likely to be a trader, which will have been added mid-flight to the system by the populator, and therefore will never (in the period of its existence which Oolite considers) launched from a station or planet, or exited witchspace. Therefore it doesn't have the timer and doesn't lower its gear.

If you have things which you need to do as part of an NPC's setup, then the shipSpawned function is the right place to do it: that will work no matter how the ship appears in the system. It doesn't work for the player, though.
That's logical, so ships are not spawned just by missions or by oxp but also by the populator. Good to know, I assumed everything must come from somewhere, so stations, planet surfaces and witchspace seemed an obvious choice to implement the timer.

Still working on that

Code: Select all

shipSpawned
function though, it doesn't code the same as the others.

thx

Re: Split: Deployable subentities

Posted: Mon Aug 18, 2014 9:06 pm
by dertien
Right, here's what I've got so far after some spit and polish. Still needs some testing, some things not yet working.

Code: Select all

this.name      = "HPC Cobra Mk3 ship scripts"; 
this.author    = "Cim, Dertien"; 
this.contributors = "Cim, Neelix, Zirael, Eric Walsh";
this.copyright = "Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) http://creativecommons.org/licenses/by-nc-sa/3.0/"; 
this.version   = "1.00";

// Cim: So, what you can do is search through the subentities list until you find the one you want.

this._findSubEntity = function(key)
					{
					for (var i = this.ship.subEntities.length - 1 ; i >=0 ; --i)
						{
						if (this.ship.subEntities[i].dataKey == key)
							{
							return this.ship.subEntities[i];
							}
						}
						return null; // couldn't find it.
					}
					
//	reusable function that retracts the gear (not animated yet)			
					
this.retractGear = function()

{
   var actuatorsR = this._findSubEntity("HPC_actuatorR"); 
               if (actuatorsR)
               {
                  actuatorsR.position = [0, 6.155206, 2.648078];
               }
	var actuatorsF = this._findSubEntity("HPC_actuatorF");
               if (actuatorsF)
               {
                  actuatorsF.position = [0, 3.80, -21.3];
               }
   var reargearextendPRT = this._findSubEntity("HPC_reargearPRT");
                  if (reargearextendPRT)
               {
               reargearextendPRT.position = [-17.392771, -8.961073, 2.796213];
			   reargearextendPRT.orientation = [0.9953, 0.0908, 0, 0];
               }
   var reargearextendSTB = this._findSubEntity("HPC_reargearSTB");
                  if (reargearextendSTB)
               {
               reargearextendSTB.position = [17.552752, -8.847222, 3.028129];
			   reargearextendPRT.orientation = [-0.9953, -0.0908, 0, 0];
               }
	var frontgearextendPRT = this._findSubEntity("HPC_frontgearPRT");
                  if (frontgearextendPRT)
               {
               frontgearextendPRT.position = [-13.038872, -5.954015, 25.049587];
			   reargearextendPRT.orientation = [0, 0, 0.9959, -0.0905];
               }
	var frontgearextendSTB = this._findSubEntity("HPC_frontgearSTB");
                  if (frontgearextendSTB)
               {
               frontgearextendSTB.position = [13.038872, -5.954015, 25.049587];
			   reargearextendPRT.orientation = [0.9959, 0.0905, 0, 0];
               }
	   
}

//	reusable function that extends the gear (not animated yet)

this.extendGear = function()
{

		var actuatorsR = this._findSubEntity("HPC_actuatorR"); 
               if (actuatorsR)
               {
                  actuatorsR.position = [0,0,0];
               }
		var actuatorsF = this._findSubEntity("HPC_actuatorF"); 
               if (actuatorsF)
               {
                  actuatorsF.position = [0,0,0];
               }
		var reargearextendPRT = this._findSubEntity("HPC_reargearPRT");
                  if (reargearextendPRT)
               {
               reargearextendPRT.position = [-17.351349,-17.408951,-3.749173];
               }
		var reargearextendSTB = this._findSubEntity("HPC_reargearSTB");
                  if (reargearextendSTB)
               {
               reargearextendSTB.position = [17.435233,-17.338642,-3.50929];
               }
		var frontgearextendPRT = this._findSubEntity("HPC_frontgearPRT");
                  if (frontgearextendPRT)
               {
               frontgearextendPRT.position = [-12.765342,-11.194131,27.818142];
               }
		var frontgearextendSTB = this._findSubEntity("HPC_frontgearSTB");
                  if (frontgearextendSTB)
               {
               frontgearextendSTB.position = [12.765342,-11.194131,27.818142];
               }
}					

// functions to switch the navlights on and off

this.switchFlashersOn = function()
{
	this.ship.lightsActive = true; // turns flashers on
}

this.switchFlashersOff = function()
{
	this.ship.lightsActive = false; // turns flashers off
}

// Function that controls gear, if no autopilot is used.

this.noDockingComputer = function()
{
	// OPTION 1
	// if target is a station in range lower gear
	if (this.ship !== player.ship && this.ship.dockingInstructions)
		{
			this.extendGear();
			this.$dockingTargetChecker.start();
			return;
		}
	// OPTION 2
	// if the player's target is a station which is less than 5000 Km away, gear down ! 
	if (this.ship == player.ship && this.ship.target && this.ship.target.isStation && player.ship.position.distanceTo(player.ship.target) < 5000)
		{
			// player.consoleMessage("station in range - gear is down");
			this.extendGear();
			this.$dockingTargetChecker.start();
			return;
		}
	// OPTION 2
	// if the player's target is a station but is more than 5000 Km, gear up !
	if (this.ship == player.ship && this.ship.target && this.ship.target.isStation && player.ship.position.distanceTo(player.ship.target) > 5000)
		{
			// player.consoleMessage("station too far");
			this.retractGear();
			this.$dockingTargetChecker.start();
			return;
		}
	// OPTION 3
    //if the player's target is not a station retract gear
	if (this.ship == player.ship && (!player.ship.target || !player.ship.target.isStation))
		{
			// player.consoleMessage("Invalid target");
			this.retractGear();
			return;
		}
}


this.shipSpawned = function()
{
//player.consoleMessage("Ship spawned !");
 this.$checkvalid = function()
	{
	//player.consoleMessage("Ship Spawned in range for docking instructions?");
	if (this.ship.dockingInstructions && this.ship !== player.ship)
		{
			this.extendGear();
			//player.consoleMessage("SPAWN TESTER");
		}	
	 }
 }


this.shipEnteredStationAegis = function(station)
{
   this.switchFlashersOn();
}
this.shipExitedStationAegis = function(station)
{
	this.switchFlashersOff();
}

// if a ship launches (NPC and Player), show gear deployed and automatically retract after 5 seconds

this.shipLaunchedFromStation = function(station)
{
	this.extendGear(); // extend gear
	this.tenSecTimer = new Timer(this, this.retractGear,5); // retract gear after 5 sec
	// player.consoleMessage("Exiting Station");
	// player.consoleMessage("GEAR UP in 10 Sec");
	this.switchFlashersOn(); //turn on nav lights on wingtips
	// since it's not necessary to see NPC's drop their gear when inside station, only trigger when player ship lauches.  
	if (this.ship == player.ship)
		{
		this.$dockingTargetChecker = new Timer(this, this.noDockingComputer,6, 2);
		this.$spawnchecker = new Timer(this, this.$checkvalid,1, 5);
		}
}

// when player hits C key with docking computers installed gear drops

this.playerStartedAutoPilot = function()
{
	player.consoleMessage("Docking sequence started");
	player.consoleMessage("GEAR DOWN & LOCKED");
	this.switchFlashersOn(); // to turn them on outside of aegis ex. constore docking
	this.extendGear();
	if(this.$dockingTargetChecker) {
			this.$dockingTargetChecker.stop();
			delete this.$dockingTargetChecker;
		}   
}

// if player cancels docking computers, gear retracts

this.playerCancelledAutoPilot = function() 
{
	player.consoleMessage("Docking sequence aborted");
	player.consoleMessage("GEAR UP");
	this.retractGear();
	this.$dockingTargetChecker = new Timer(this, this.noDockingComputer,1, 2);
}

// about same as shipLaunchedFromStation function

this.shipLeavingPlanetSurface = function(planet)
{
    //player.consoleMessage("Ship Departing");
	//player.consoleMessage("Exiting Atmosphere");
	this.extendGear(); 
	this.tenSecTimer = new Timer(this, this.retractGear,10);
	if (this.ship == player.ship)
		{
		this.$dockingTargetChecker = new Timer(this, this.noDockingComputer,12, 2);
		this.$spawnchecker = new Timer(this, this.$checkvalid,1, 5);
		}
	this.ship.commsMessage("GEAR UP 10 Seconds");
}

// if player exits witchspace, start both timers.

this.shipWillExitWitchspace = function()
{
    this.switchFlashersOff();
	if (this.ship == player.ship)
		{
		this.$dockingTargetChecker = new Timer(this, this.noDockingComputer,12, 2);
		this.$spawnchecker = new Timer(this, this.$checkvalid,1, 5);
		}
}

// ship NPC and Player drops gear before planetary landing

this.shipApproachingPlanetSurface = function(planet)
{
	 this.extendGear();
	 // Player ship landed on surface, no need for timer or flashers.
	 if (this.ship == player.ship)
		{	
			player.consoleMessage("SHIP LANDING !");
			this.switchFlashersOff();
			this.extendGear();
			this.$cleanupTimers();
		}
}

this.shipWillEnterWitchspace = function()
{
    this.switchFlashersOff();
	this.$cleanupTimers();
}

this.stationWithdrewDockingClearance = function()
{
	this.retractGear();
	if(this.$dockingTargetChecker) {
	this.$dockingTargetChecker.start();
	}
}

this.shipWillLaunchFromStation = function(station)
{
	  this.extendGear();
}

this.shipDockedWithStation = function(station)
{
		if (this.ship == player.ship)
		{	
			player.consoleMessage("SHIP DOCKED !");
			this.switchFlashersOff();
			this.extendGear();
			this.$cleanupTimers();
		}	
		
}

this.$cleanupTimers = function()
{
		if(this.$dockingTargetChecker) {
			this.$dockingTargetChecker.stop();
			delete this.$dockingTargetChecker;
			}
		if(this.$spawnchecker) {
			this.$spawnchecker.stop();
			delete this.$spawnchecker;
		}
}

this.entityDestroyed = function ()
{
    this.$cleanupTimers();
}

Will look at it tomorrow.
Comments welcome !

Re: Split: Deployable subentities

Posted: Tue Aug 19, 2014 7:10 am
by Zireael
1) what doesn't work?
2) it'd be easier if you provided a beta version to go with HPC.oxp to test.

Re: Split: Deployable subentities

Posted: Tue Aug 19, 2014 10:19 am
by dertien
Zireael wrote:
1) what doesn't work?
2) it'd be easier if you provided a beta version to go with HPC.oxp to test.
Yes,

That was the plan, apparently I forgot to press the send button in this post, after updating the main HPC Cobra Mk3 thread.
Made some last code changes, testing results welcome. The link is already up since yesterday :D

Here is the file which is the same as on the HPC page.

ZZ_aOoniverseofCobraMk3s.oxp is optional, and will make all other ships Cobra Mk 3's (for framerate testing purposes, and also for easier testing)
https://app.box.com/s/uffj7esu1f0nlrzh6anr
Longrange scanner link again here as well for testing:
LRS: https://app.box.com/s/7ticwbnhnvcck75rvck3
F6 - F6 - F5

Re: Split: Deployable subentities

Posted: Tue Aug 19, 2014 11:25 am
by dertien
I think I just have to split up the code for NPC's and Player into two different javascript files. This should solve the conflict problems.

EDIT:

Most problems have been resolved up until now.

Re: Split: Deployable subentities

Posted: Sat Aug 23, 2014 7:10 pm
by dertien
I am having a little issue, which is bugging me bigtime.

In the npc_cobramk3_actions.js file (ZZ_HPC_Cobra_mk3.oxp) there is some code that checks the status of the NPC's hostility and opens/closes weapon bay doors for the NPC's based on a the timer which seems to cause a "stutter" ingame, right after it has been executed every time.

The code works, since the NPC's react to it well. I put a debug message in there, to make it easier to spot, and about half a second later there will be a stutter, which is terribly annoying.

Yet I cannot get rid of it, since removing or placing timers at a different place usually amounts to a garbage collected timer.

Can anyone have a look at the code and help me out with this please ?

https://app.box.com/s/dkzpkhtgb8cw3ks501u3

Thank you.

Re: Split: Deployable subentities

Posted: Sun Aug 24, 2014 12:12 am
by dertien
Ok, got this stutter issue sorted by getting rid of the timer and using only functions instead.

Everything is working perfectly now without stuttering.

So instead of using this function:

Code: Select all

this.checkNPCalert = function()
{
	if (this.ship.hasHostileTarget == false || this.ship.alertCondition == 2)
      {
	  this.$laserDoorClosed();
	  player.consoleMessage("Condition yellow");
      }
	if (this.ship.hasHostileTarget == true || this.ship.alertCondition == 3)
      {
		this.$laserDoorOpen();
		this.$NPC_retractGear(); // in case the gear is down in the aegis while docking, NPC will retract it.
		this.ship.commsMessage("Condition red");
      }
};
combined with a timer:

Code: Select all

this.$alertchecker = new Timer(this,this.checkNPCalert,0,9);
this.$alertchecker.stop();
and a shipSpawned handler

Code: Select all

this.shipSpawned = function() 
{
	 this.$alertchecker.start();
	 this.$laserDoorClosed();
}
I simply used these functions:

Code: Select all

this.shipSpawned = function() 
{
	 this.$laserDoorClosed();
}
this.shipLaunchedFromStation = function(station)
{
	 this.$laserDoorClosed();
}
this.shipLeavingPlanetSurface = function(planet)
{
	 this.$laserDoorClosed();
}

this.shipAttackedOther = function()
{
    this.$laserDoorOpen();
}

this.shipBeingAttacked = function()
{
    this.$laserDoorOpen();
}

this.shipAttackedWithMissile = function()
{
    this.$laserDoorOpen();
}

this.shipTargetLost = function()
{
     this.$laserDoorClosed();
}

this.shipTargetDestroyed = function()
{
    this.$laserDoorClosed();
}
Keeps things nice and easy and works all the time without a timer.