Page 76 of 118

Re: Scripters cove

Posted: Sun Mar 01, 2015 11:11 am
by Diziet Sma
Thanks! I'll see what I can cobble together.

Re: Scripters cove

Posted: Thu Mar 05, 2015 4:00 am
by phkb
Is there a way using JS to tell if a new game has just been started?

Re: Scripters cove

Posted: Thu Mar 05, 2015 5:15 am
by Wildeblood
phkb wrote:
Is there a way using JS to tell if a new game has just been started?
Context - why would you care?

Re: Scripters cove

Posted: Thu Mar 05, 2015 5:38 am
by phkb
I'd like to send an email to the player telling about their purchase of their ship.

Re: Scripters cove

Posted: Thu Mar 05, 2015 7:37 am
by cim
phkb wrote:
Is there a way using JS to tell if a new game has just been started?
Not strictly, no - the routine to load a saved game and the routine to start a new scenario differ only in which directory they get the oolite-save file from.

You can probably make a fair guess by looking at the clock, but I don't guarantee to take care to preserve that to the second between Oolite versions. (To the day, probably - if the day is 2084004, and you haven't already delivered that email, you can safely do so)

Re: Scripters cove

Posted: Thu Mar 05, 2015 7:43 am
by Smivs
phkb wrote:
I'd like to send an email to the player telling about their purchase of their ship.
Then you can spam them with market research surveys, customer satisfaction questionaires and offers linked to the purchase. And they'll probably need reminding to leave Feedback!

Re: Scripters cove

Posted: Thu Mar 05, 2015 7:49 am
by Wildeblood
Clock won't be reliable if scenarios catch on with OXPers. Folk won't always start with a new Jameson to create their oolite-save files. More likely the'll use an old one and just delete the mission variables; it wouldn't occur to me to reset the clock, and if it did why should all scenarios start at the same time?

Re: Scripters cove

Posted: Thu Mar 05, 2015 4:43 pm
by spara
I'm trying to get my head around these new docking toys. I managed to create a highly restricted station that allows the player to dock only if specifically allowed. And player actually crashes, if he/she tries to dock without permission. However, getting disallowedDockingCollides to work was a bit of a pain as I first need to set allowsDocking to false. To my understanding that affects possible NPCs too. I'm wondering what happens, if the station launches a defense ship that tries to dock later if allowsDocking is set to false.

Is there a way to set a station to disallowedDockingCollides so that all ships without docking permission would collide? A shipdata property disallowed_docking_collides would be nice :mrgreen: .

Re: Scripters cove

Posted: Thu Mar 05, 2015 6:34 pm
by cim
Wildeblood wrote:
Clock won't be reliable if scenarios catch on with OXPers. Folk won't always start with a new Jameson to create their oolite-save files. More likely the'll use an old one and just delete the mission variables; it wouldn't occur to me to reset the clock, and if it did why should all scenarios start at the same time?
Given that scenarios may not even allow the email OXP to load in the first place, and even if they do might have their own ideas for what initial emails the player should get - "Congratulations on your recent theft of this Boa Freighter" - that's probably more a feature than a bug if the OXP has to have specific checks for each separate scenario.

Re: Scripters cove

Posted: Thu Mar 05, 2015 6:37 pm
by cim
spara wrote:
Is there a way to set a station to disallowedDockingCollides so that all ships without docking permission would collide? A shipdata property disallowed_docking_collides would be nice :mrgreen: .
allowsDocking false is really intended for situations like "this is a launch-only dock with some sort of high-speed launch catapult, and you're not getting your ship back in there" or "you could dock here, but not while the bay doors are closed"

I could set it up so that per-ship rejection on the dock through a method parallel to acceptDockingRequestFrom would have disallowedDockingCollides apply in that case, but that would need re-testing every frame. (That's probably acceptable as the method shouldn't be particularly intensive)

Re: Scripters cove

Posted: Sun Mar 08, 2015 3:27 pm
by spara
cim wrote:
spara wrote:
Is there a way to set a station to disallowedDockingCollides so that all ships without docking permission would collide? A shipdata property disallowed_docking_collides would be nice :mrgreen: .
allowsDocking false is really intended for situations like "this is a launch-only dock with some sort of high-speed launch catapult, and you're not getting your ship back in there" or "you could dock here, but not while the bay doors are closed"

I could set it up so that per-ship rejection on the dock through a method parallel to acceptDockingRequestFrom would have disallowedDockingCollides apply in that case, but that would need re-testing every frame. (That's probably acceptable as the method shouldn't be particularly intensive)
A game mechanic change of crashing the player when docking without permission instead of fining would be an interesting one :twisted: .

Anyway, I solved my little problem of conditionally offering higher TL services with a simple mission screen override so I'm happy with the current status quo.

Re: Scripters cove

Posted: Tue Mar 10, 2015 5:40 am
by phkb
I'm still working on my little rename ship tweak (talked about here), but I'm going into bits of Oolite I have no experience with whatsoever.

In case your wondering, I'm trying to add some purpose to the process of renaming your ship, and giving the player the opportunity to use this strategically. Rename the ship (with a small cost), and potentially confuse any assassins waiting for you at the end of the witchspace tunnel. cim suggested a method of just overwriting the players roles, which I am testing as well, but (I think I'm correct in saying) this method would only work if the player is not carrying any parcels. If the assassins are after the player with a parcel, this wouldn't do anything.

So, my blunt force method, is to attach a JS script to any assassins in view when the player exits the wormhole. The script file has the following code in it:

Code: Select all

// if the ship targets the player, potentially untarget them
this.shipTargetAcquired = function(target) {
	if (this._debug) log(this.name, "target acquired");
	var w = worldScripts.RenameShipTweak;
	if (target == player.ship && w._confusionActive == true && this._disable == false) {
		if (this._debug) log(this.name, "player ship targetted");
		if (Math.random() < (1 / w._chanceOfSuccess)) {
			this._retarget = true;
			this.ship.target = null;
			if (w._confusedMessageSent == false) {
				log(this.name, "sending confused message");
				this.ship.commsMessage(expandDescription("[confused-message]", {shipname:w._storedShipName}), player.ship);
				w._confusedMessageSent = true;
			}
		}
	}
}
Essentially, if the ship's target is the player, and our confusion process is in operation, and the player hasn't done anything silly like attack the ship (which would set the "this._disable" to true, then we get into the nuts and bolts of the confusion. The "chanceOfSuccess" is 1 the first time the player renames the ship - this results in a 100% chance that the assassin will become confused. We then set the ship's target to null to clear their target. They just became confused. The ship might then send a message out, saying to keep looking for the original ship name.

Now, this code works. Player is targeted, ship is confused, and they un-target the player, message goes out, all is well.

Except I get this error:

Code: Select all

13:53:41.072 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (Oolite Assassin AI 1.80): TypeError: this.ship.target is null
13:53:41.072 [script.javaScript.exception.unexpectedType]:       Resources/Scripts/oolite-priorityai.js, line 2767.
Which is not in my code at all, but in the default libraries. From what I can understand, because I've set the ship's target to null in the "shipTargetAcquired", there's a flowon impact in the core code.

So, I'm guessing that the "shipTargetAcquired" is the wrong place to set the ship's target to null. Is there a better place to do this? Should I do something a little more adventurous (and scary) with the AI stuff? I'm a little lost here!

Re: Scripters cove

Posted: Tue Mar 10, 2015 7:34 am
by cim
So what's happening here is that the AI routine will have something like this:

Code: Select all

this.ship.target = nearbySuitableTarget;
// later...
if (this.ship.target.property == something) {
It doesn't expect anything to have updated this.ship.target in between selecting it and trying to use it, so it doesn't check if it's still defined.

The easiest way to do it is probably to override conditionScannerContainsCourier in the ship AIs. Currently it's this:

Code: Select all

PriorityAIController.prototype.conditionScannerContainsCourier = function()
{
	return (this.checkScannerWithPredicate(function(s) { 
		return (this.shipInRoleCategory(s,"oolite-courier")) || (s.isPlayer && this.shipHasRiskyContracts(s));
	}));
}
by doing something like

Code: Select all

ship.AIScript.oolite_priorityai.conditionScannerContainsCourier = function() {  
        return (this.checkScannerWithPredicate(function(s) { 
		if (s.isPlayer) {
			// do the "recently renamed" checks here, return false if is ignoring the player
			// this also means that the assassins will go after another courier instead if one happens to be about
		}
		return (this.shipInRoleCategory(s,"oolite-courier")) || (s.isPlayer && this.shipHasRiskyContracts(s));
	}));
}
(Note that overriding core AI methods like this is possible and even encouraged, but should be carefully documented on your OXP's page so that OXPs which require the core behaviour for an AI method can use appropriate methods - including if necessary declaring incompatibility at the manifest level - to coexist)

One of the other problems - even if the log error didn't occur - with using shipTargetAcquired and then breaking the lock, is that this will trigger an almost immediate reevaluation of the AI's priorities (as always happens when they lose primary target). Since probably nothing material has changed, they will then attempt again to target the player... If w._chanceOfSuccess is even slightly greater than 1, this will mean that within seconds they realise their mistake.

Re: Scripters cove

Posted: Tue Mar 10, 2015 8:17 am
by phkb
Thanks cim. That helps a lot.

Re: Scripters cove

Posted: Wed Mar 11, 2015 8:36 am
by phkb
Cim, I'm really sorry. I'm a programmer and I should be able to work this out, but I mustn't have enough caffeine in my system, or I've eaten too many dark side cookies, or something, because I can't work this out.

So, I need to override conditionScannerContainsCourier - I created a JS file with my code in it, put it in the Scripts folder, then for each assassin at the witchpoint I tried ship.setScript("assassin-confused.js");. I get this error:

Code: Select all

17:28:51.434 [script.javaScript.load.failed]: ***** Error loading JavaScript script ../AddOns/RenameShipTweak.oxp/Scripts/assassin-confused.js -- could not run script
17:28:51.561 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (RenameShipTweak 1.0.0): TypeError: ship.AIScript.oolite_priorityai is undefined
I tried a number of combinations of ship.AIScript.oolite_priorityai.conditionScannerContainsCourier = function() trying to get it to work, including (but not limited to):

Code: Select all

this.ship.AIScript.oolite_priorityai.conditionScannerContainsCourier
this.AIScript.oolite_libpriorityai.conditionScannerContainsCourier (for this one, the error was "this.AIScript is undefined")
ship.AIScript.PriorityAIController.conditionScannerContainsCourier
ship.AIScript["oolite-libPriorityAI"].conditionScannerContainsCourier
ship.AIScript.oolite_priorityAI.conditionScannerContainsCourier
ship.AIScript["Oolite Assassin AI"].conditionScannerContainsCourier
Then I had a lightbulb moment and thought, what if I've been setting the script the wrong way? Yes, there is a setAI method! So I moved my script file to the AIs folder, and tried again.

Code: Select all

19:16:43.227 [script.javaScript.exception.unexpectedType]: ***** JavaScript exception (RenameShipTweak 1.0.0): TypeError: ship.AIScript.oolite_priorityai is undefined
So, I've run out of ideas and really need some pointers. I guess, to summarise, I need to know these things: (1) Do I use the setAI or setScript method on the assassin ships? (2) Does my script need anything other than my overridden function in it? For instance, do I need a this.aiStarted = function() if I load it via setAI? (3) Have I missed anything obvious? (Actually, I think that's a given - feel free to answer that one or not!).