Page 1 of 1

playerJumpFailed

Posted: Fri Jul 13, 2012 3:08 pm
by Wildeblood
According to this http://wiki.alioth.net/index.php/Oolite ... JumpFailed
The playerJumpFailed handler is called at the end of a witchspace or galactic witchspace countdown, if the jump is not possible. The reason parameter is a string specifying why the jump failed; currently, the possible values are “blocked”, “too far” and “insufficient fuel”. Other values may be added in future.

Code: Select all

this.playerJumpFailed = function(reason)
{
     // Your code here
}
More information, please. Exactly what conditions cause the jump to fail as “blocked”? I want to be able to test for those conditions in my script, before the jump fails. What is the difference between “too far” and “insufficient fuel”?

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 3:20 pm
by cim
"too far" = destination outside 7 LY range (which should be impossible, as it would require the destination to move)
"insufficient fuel" = destination inside 7 LY range but fuel level drops between initiating countdown and completion.
"blocked" = heavy object too near player
"malfunction" = misjump that causes jump to fail
"malfunction" = Galactic Hyperdrive destroyed while GH countdown in progress
"no target" = hyperspace system was set to current system while countdown in progress (which should be impossible, as you can't change the destination when a countdown is in progress)

A heavy object is too close if mass / distance-squared >= 10

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 3:48 pm
by Wildeblood
cim wrote:
"too far" = destination outside 7 LY range (which should be impossible, as it would require the destination to move)
"insufficient fuel" = destination inside 7 LY range but fuel level drops between initiating countdown and completion.
"blocked" = heavy object too near player
"malfunction" = misjump that causes jump to fail
"malfunction" = Galactic Hyperdrive destroyed while GH countdown in progress
"no target" = hyperspace system was set to current system while countdown in progress (which should be impossible, as you can't change the destination when a countdown is in progress)

A heavy object is too close if mass / distance-squared >= 10
Thanks, cim. But I think that raises more questions than it answers:-
- I'm only interested in standard type, not galactic jumps, so I've crossed that one off your list.
- Also, are all those implemented in 1.76.1 - I'm not interested in trunk-only cases?
- What do you mean by '"malfunction" = misjump that causes jump to fail'? Does playerJumpFailed fire for a misjump into interstellar space? If so, before or after the other jump-related events? Or do you mean something else?
- So does playerJumpFailed fire with "too far" when you have insufficient fuel and the countdown refuses to start/aborts immediately?
- And does "no target" occur when you press H without setting a target first, and the countdown refuses to start?

Now the big question, how do I check for this in javascript: "A heavy object is too close if mass / distance-squared >= 10"?

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 4:07 pm
by cim
Wildeblood wrote:
- Also, are all those implemented in 1.76.1 - I'm not interested in trunk-only cases?
I don't believe any of this has changed since 1.76
Wildeblood wrote:
- What do you mean by '"malfunction" = misjump that causes jump to fail'? Does playerJumpFailed fire for a misjump into interstellar space? If so, before or after the other jump-related events? Or do you mean something else?
If the "maintenance level" check on entering witchspace fails, there are three possible outcomes:
1 - ship remains in current system and takes internal damage
2 - ship misjumps into interstellar space
3 - ship jumps to destination system and then has a fuel leak

"malfunction" is returned in case 1.
Wildeblood wrote:
- So does playerJumpFailed fire with "too far" when you have insufficient fuel and the countdown refuses to start/aborts immediately?
- And does "no target" occur when you press H without setting a target first, and the countdown refuses to start?
No to both. playerJumpFailed events only happen after the witchspace countdown has started.
Wildeblood wrote:
Now the big question, how do I check for this in javascript: "A heavy object is too close if mass / distance-squared >= 10"?
Only objects in scanner range are considered, so:

Code: Select all

function() {
// get all entities within scanner range of player ship
  var blockers = system.filteredEntities(this, function() {return true; }, player.ship, 25600);
  for (var i=0; i<blockers.length; i++) {
// if they are a ship
    if (blockers[i].isShip) {
// get distance by comparing positions
      var d = player.ship.position.subtract(blockers[i].position).magnitude();
      if (blockers[i].mass / d*d >= 10) {
// too close and heavy, return the blocking entity
        return blockers[i];
      }
    }
  }
// if we get this far, nothing is blocking
  return null;
}

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 4:48 pm
by Wildeblood
Thanks again, cim. So "too far" and "no target" won't occur in normal game-play, only if a script changes the target system after the countdown starts? I've crossed those off your list, too.

I'll have a bit more of a think about the maintenance / misjump issue. At first sight, I think it's irrelevant. I can't recall seeing this first case happen:-
cim wrote:
If the "maintenance level" check on entering witchspace fails, there are three possible outcomes:
1 - ship remains in current system and takes internal damage
It gives some explanation to the player, so they know it's correct game-play, and not my coming-soon-OXP causing problems?

Code: Select all

// if they are a ship
    if (blockers[i].isShip) {
The most massive object of all - the planet - doesn't count? :shock:

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 5:14 pm
by cim
Wildeblood wrote:
I'll have a bit more of a think about the maintenance / misjump issue. At first sight, I think it's irrelevant. I can't recall seeing this first case happen:-
cim wrote:
1 - ship remains in current system and takes internal damage
The chance of this will depend on what ship you fly and how much equipment and cargo it currently carries. For me it happens far more often than actual misjumps.
Wildeblood wrote:
The most massive object of all - the planet - doesn't count? :shock:
Well, distances are measured centre-to-centre for this check. There are other things which prevent the player from jumping within 25.6km of the planet's (or sun's) centre.

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 5:30 pm
by Wildeblood
Actually, I've had a bit more of a think about it and this maintenance level business is an issue. There is no way I can test for that, is there? What's the story here:- http://wiki.alioth.net/index.php/Oolite ... tedMisjump
scriptedMisjump : Boolean (read/write)

When true, the next hyperspace jump will be a misjump. The scriptedMisjump flag will remain true during the shipWillExitWitchspace() event handler, and will be set to false after the shipExitedWitchspace() event.
Will scriptedMisjump be true if a misjump will occur because of low maintenance?

When can I check this, anytime or only after the jump begins with shipWillEnterWitchspace?

Re: playerJumpFailed

Posted: Fri Jul 13, 2012 5:41 pm
by cim
Wildeblood wrote:
Actually, I've had a bit more of a think about it and this maintenance level business is an issue. There is no way I can test for that, is there?
No.
Wildeblood wrote:
When can I check this, anytime or only after the jump begins with shipWillEnterWitchspace?
scriptedMisjump can be checked at any time, though of course another OXP can set it during shipWillEnterWitchspace, and that OXP may run after your OXP does, so you have no way to detect that.

Misjumps generated by the game engine can happen when scriptedMisjump is false.

EDIT: though, if you get a "stay in same system" jump failure, shipWillEnterWitchspace will not happen at all, of course.

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 9:41 am
by Wildeblood
cim wrote:
A heavy object is too close if mass / distance-squared >= 10
cim wrote:
var d = player.ship.position.subtract(blockers.position).magnitude();
if (blockers.mass / d*d >= 10) {
// too close and heavy, return the blocking entity
return blockers;

I see what you did there. :wink:

I can start by checking alertCondition. If it's green, no need to check further for blocking masses, I can go straight on to checking for sufficient fuel.

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 10:03 am
by cim
Wildeblood wrote:
I can start by checking alertCondition. If it's green, no need to check further for blocking masses, I can go straight on to checking for sufficient fuel.
Some asteroids are heavy enough to block jumps at least a few kilometres away. Some of the really big ones from Asteroid Storm are as heavy as a station.

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 10:18 am
by JensAyton
Wildeblood wrote:
cim wrote:
A heavy object is too close if mass / distance-squared >= 10
cim wrote:
var d = player.ship.position.subtract(blockers.position).magnitude();
if (blockers.mass / d*d >= 10) {
// too close and heavy, return the blocking entity
return blockers;

I see what you did there. :wink:

Personally, I’d suggest player.ship.position.squaredDistanceTo(blockers[i]) – it’s more efficient.

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 11:55 am
by Wildeblood
Version 1

Code: Select all

this.$checkForNearbyMasses = function()
	{
	// get all entities within scanner range of player ship
	var blockers = system.filteredEntities(this, function() {return true;}, player.ship, 25600);
	for (var i = 0; i < blockers.length; i++)
		{
		// if they are a ship
		if (blockers[i].isShip)
			{
			// get distance by comparing positions
			var d = player.ship.position.subtract(blockers[i].position).magnitude();
			if (blockers[i].mass / (d * d) >= 10)
				{
				// too close and heavy, return the blocking entity
				return blockers[i];
				}
			}
		}
	// if we get this far, nothing is blocking
	return null;
	}
Note (blockers.mass / (d * d) >= 10), not (blockers.mass / d * d >= 10).

Version 2

Code: Select all

this.$checkForNearbyMasses = function()
	{
	var blockers = system.filteredEntities(this, function() {return true;}, player.ship, 25600);
	for (var i = 0; i < blockers.length; i++)
		{
		if (blockers[i].isShip)
			{
			var d = player.ship.position.squaredDistanceTo(blockers[i]);
			if (blockers[i].mass / d >= 10) return blockers[i];
			}
		}
	// if we get this far, nothing is blocking
	// return null;
	}
Does "return null" actually do anything when it's the last line anyway?

Version 3

Code: Select all

this.$checkForNearbyMasses = function()
	{
	var blockers = system.filteredEntities(this, function() {return true;}, player.ship, 25600);
	for (var i = 0; i < blockers.length; i++)
		{
		if (blockers[i].isShip
      && blockers[i].mass / player.ship.position.squaredDistanceTo(blockers[i]) >= 10) return blockers[i];
		}
	}
Is this still equivalent, or have I got ahead of myself?

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 12:08 pm
by JensAyton
Wildeblood wrote:
Does "return null" actually do anything when it's the last line anyway?
Not returning anything produces undefined. You probably don’t care about the distinction here.
Wildeblood wrote:
Version 3

Code: Select all

this.$checkForNearbyMasses = function()
	{
	var blockers = system.filteredEntities(this, function() {return true;}, player.ship, 25600);
	for (i = 0; i < blockers.length; i++)
		{
		if (blockers[i].isShip
      && blockers[i].mass / player.ship.position.squaredDistanceTo(blockers[i]) >= 10) return blockers[i];
		}
	}
Is this still equivalent, or have I got ahead of myself?
It looks right, but this would be more efficient:

Code: Select all

this.$checkForNearbyMasses = function ()
{
    var psPos = player.ship.position;
    var blockers = system.filteredEntities(this, function (entity)
    {
        return entity.isShip &&
               entity.mass / psPos.squaredDistanceTo(entity) >= 10;
    }, player.ship, 25600);
    
    if (blockers.length > 0)  return blockers[0];
    // Or, if you don't care about the specific entity, return blockers.length > 0;
}
(It’s more efficient because 1. it doesn’t need to grow an array to hold a bunch of non-blocking entities you don’t care about, 2. it doesn’t need to loop over said array again, looking up blockers.length each time through, and 3. it only looks up global.player.ship.position once.)

Efficiency is kind of important when you’re searching for entities, simply because your code may one day be running in a context where there’s a heck of a lot of them.

Re: playerJumpFailed

Posted: Sat Jul 14, 2012 5:03 pm
by Wildeblood
Now, you've been back and changed that reply, since I first read it seven minutes after you posted it. Specifically, it used to say:-

Code: Select all

	var blockers = system.filteredEntities(this, function (entity) {
		return entity.isShip &&
		entity.mass / player.ship.position.squaredDistanceTo(entity) >= 10;
		}, player.ship, 25600);
and now it says:-

Code: Select all

    var psPos = player.ship.position;
    var blockers = system.filteredEntities(this, function (entity)    {
        return entity.isShip && 
         entity.mass / psPos.squaredDistanceTo(entity) >= 10;
    }, player.ship, 25600);
Which I assume is related to your newly added comment:-
Ahruman wrote:
3. it only looks up global.player.ship.position once.