Just when I thought I was out...

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: another_commander, winston

Post Reply
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

OK... So, uh, would I do this?

Code: Select all

"ROLL_3" = ("sendScriptMessage: launchtaranis_traffic3");
And then I set up a "ship script", uh, somehow...

OK, I've got no idea how to proceed. I'm guessing I need to create a file called script.js, but as for what to put in that file... I don't understand JavaScript. Nor do I know which ship(s) the file should relate to - the station, or the ships I want to be generated as traffic (there are a lot of them, all with the same role)?

I think what I want to do is pretty simple (have ships of a specified role appear near the witchpoint at random intervals when you're in one particular system), but without any examples to work from (that I can find), I'm kind of screwed :(
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

It’s a daunting new world, I know. :-)

The idea is that you have a ship script attached to the same ship as the AI. Typically this would be called “roberto-shipname.js” and live in the Scripts folder of your OXP.

The parameter to sendScriptMessage: is the name of a method in the ship script. In this case, it would look something like:

Code: Select all

this.name = "roberto-shipname"; // Each script must set a name

this.launchTaranisTraffic3 = function ()
{
    system.legacy_addShips("taranis_traffic3", 1); // Equivalent to "addShips: taranis_traffic3 1" in a legacy script
}
Your AI action would then be:

Code: Select all

ROLL_3 = ( "sendScriptMessage: launchTaranisTraffic3" ); // Send message to my ship script
User avatar
TGHC
---- E L I T E ----
---- E L I T E ----
Posts: 2157
Joined: Mon Jan 31, 2005 4:16 pm
Location: Berkshire, UK

Post by TGHC »

What would we do without you Big A!

We are not worthy!
The Grey Haired Commander has spoken!
OK so I'm a PC user - "you know whats scary? Out of billions of sperm I was the fastest"
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

The idea is that you have a ship script attached to the same ship as the AI. Typically this would be called “roberto-shipname.js” and live in the Scripts folder of your OXP.
And the ship in shipdata.plist must have a key with name "script" and the scriptname you choose.

Look e.g. in the latest UPS version and look at the ship with name "ups-fuelship1". That does some complicated stuff with those scripts.
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

Thanks Ahruman! Hopefully I'll get the hang of JS in the end, when I've seen enough of it :)

@Eric Walsh
Ah - I knew I'd forgotten something! Cheers :)
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Eric Walch wrote:
And the ship in shipdata.plist must have a key with name "script" and the scriptname you choose.
Er, yes. Good plan.
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

That all worked out nicely, so thank you both :)

Now I've moved on to the AI for ships hyperspacing out... which isn't quite working yet, given that they're not, uh, hyperspacing out :) Here's what I've got:

Code: Select all

{
	GLOBAL = { 
		ENTER = ("setStateTo: PREP_FOR_DEPARTURE"); 
		EXIT = (); 
		UPDATE = (); 
	}; 
	"PREP_FOR_DEPARTURE" = {
		ENTER = (getWitchspaceEntryCoordinates, setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.75", performFlyToRangeFromDestination);
		"DESIRED_RANGE_ACHIEVED" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: EXIT_SYSTEM");
        	"ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
       		"OFFENCE_COMMITTED" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
        	"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
        	ATTACKED = (setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
		EXIT = ();
		UPDATE = ();
		RESTARTED = ("setStateTo: GLOBAL");
	};
	"EXIT_SYSTEM" = {
		ENTER = ();
		EXIT = ();
		UPDATE = (performHyperSpaceExitWithoutReplacing);
		"WITCHSPACE OKAY" = (wormholeEscorts);
		"WITCHSPACE BLOCKED" = (setTargetToFoundTarget, setDestinationWithinTarget, "setDesiredRangeTo: 10000.0", performFlyToRangeFromDestination);
		"WITCHSPACE UNAVAILABLE" = ("switchAITo: taranisTraffic3AI.plist");
        	"ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
       		"OFFENCE_COMMITTED" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
        	"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
        	ATTACKED = (setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
		RESTARTED = ("setStateTo: GLOBAL");
	}; 
}
I've only had time for a brief test tonight, but it looks as though ships (launched from the Taranis station) are almost instantly going to EXIT_SYSTEM (presumably because they're so far from the system station, DESIRED_RANGE is indeed achieved), attempting to hyperspace, receiving the message "WITCHSPACE BLOCKED" (because they're too close to the Taranis station?) and then flying 10km away to try again. Which is fine... except that after flying 10km, they then fail to hyperspace yet again, and repeat the whole process (for some reason appearing to be circling around the station - at a distance - rather than moving increasingly further away). Could the solution be as simple as upping the range (because the Taranis station is far bigger than most), or have I missed something?

Also, am I correct in my assumption that wormholeEscorts is the correct method to use to get a single ship to exit, regardless of whether or not it has escorts (I doubt any of mine will)?
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2867
Joined: Tue Apr 04, 2006 7:02 pm
Location: On a survey mission for GalCop. Ship: Cobra Corvette: Hidden Dragon Rated: Deadly.

Post by LittleBear »

Probabley is because of the size of the HQ. To clear a Tours station you need to be about 15km away, so maybe even higher for the HQ as its pretty large!
OXPS : The Assassins Guild, Asteroid Storm, The Bank of the Black Monks, Random Hits, The Galactic Almanac, Renegade Pirates can be downloaded from the Elite Wiki here.
User avatar
Eric Walch
Slightly Grand Rear Admiral
Slightly Grand Rear Admiral
Posts: 5536
Joined: Sat Jun 16, 2007 3:48 pm
Location: Netherlands

Post by Eric Walch »

Roberto wrote:
I've only had time for a brief test tonight, but it looks as though ships (launched from the Taranis station) are almost instantly going to EXIT_SYSTEM (presumably because they're so far from the system station, DESIRED_RANGE is indeed achieved), attempting to hyperspace, receiving the message "WITCHSPACE BLOCKED" (because they're too close to the Taranis station?) and then flying 10km away to try again. Which is fine... except that after flying 10km, they then fail to hyperspace yet again, and repeat the whole process (for some reason appearing to be circling around the station - at a distance - rather than moving increasingly further away).
LB already gave the answer. Your station is to big. An other problem is how getWitchspaceEntryCoordinates works. The name is a little misleading. It is the command that "exitting Traders" use. You probably copied that part from the AI.

getWitchspaceEntryCoordinates is not giving you the coordinates of the witchpoint but just a point on 10 km distance of the station. For normal stations this is far enough to hyperspace away. But look how the "exittingTraderAI.plist" is solving this. It uses an other routine to get further away when blocked.

When you are using getWitchspaceEntryCoordinates again, it just is giving you an other point in the plain of rotation on 10 km of the station centre.

EDIT. I noticed you are already doing it at that way. The second command is telling to go 10 km away from the last coordinates and you must have passed that point otherwise you will be send back. (I think)
Maybe it helps to set the first desired range a little shorter to 10. It is essential that the ship has overshot its target when using the second command to travel another 10 km.
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

Turns out the required distance is 23km, so that's sorted now - cheers :)

The next issue... Since it's possible players might want to follow one of these ships through hyperspace, I want them to behave realistically at the other end, i.e. fly to the station there instead of just jumping again. So (after some dice-rolling to determine whether they'll go to Lerelace's system station or Taranis in the first place) I've added a state in which they should scan for Taranis, and head for the system station if they don't find it. Trouble is, it seems they're not finding Taranis, even though it's *right behind them*! I added a pause to see if that would help, but it hasn't. What gives?

Code: Select all

{
	GLOBAL = { 
		ENTER = ("setStateTo: CHOOSE_DESTINATION"); 
		EXIT = (); 
		UPDATE = (); 
	}; 
	"CHOOSE_DESTINATION" = {
		ENTER = ("rollD: 3"); 
	        "ROLL_1" = ("setStateTo: GO_TO_STATION");
		"ROLL_2" = ("setStateTo: CHECK_FOR_TARANIS"); 
		"ROLL_3" = ("setStateTo: CHECK_FOR_TARANIS"); 
		EXIT = (); 
		UPDATE = (); 
	}; 
	"CHECK_FOR_TARANIS" = {
		ENTER = ("scanForNearestShipWithPrimaryRole: taranis", "pauseAI: 10.0"); 
		EXIT = (); 
	        "TARGET_FOUND" = ("setStateTo: PREP_FOR_DEPARTURE"); 
	        "NOTHING_FOUND" = ("setStateTo: GO_TO_STATION"); 
		UPDATE = (); 
	}; 
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Are you checking that they’re in the right state? (The Dump Target State key is useful here. In 1.70, it’s shift-H; in 1.69, you can enable it in keyconfig.plist.)

When a ship is “unpickled” from a wormhole, it gets the AI message EXITED WITCHSPACE (note space, not underscore). In 1.71, there will also be a script message, shipExitedWormhole().
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

Ah - I've managed to figure it out! (And yes, they were in the right state.)

Code: Select all

  "CHECK_FOR_TARANIS" = { 
      ENTER = (); 
      EXIT = (); 
           "TARGET_FOUND" = ("setStateTo: PREP_FOR_DEPARTURE"); 
           "NOTHING_FOUND" = ("setStateTo: GO_TO_STATION"); 
      UPDATE = ("scanForNearestShipWithPrimaryRole: taranis"); 
   }; 
Moving the scan from ENTER to UPDATE seems to have done the trick (and it turns out I don't need the pause). One side-effect of all this checking and dice-rolling, though, is that the ships take a little longer before they begin their FlyToRange - and whereas before they were turning up and to the right before heading out (for some reason), now they're flying straight towards the ad board, and in most cases hitting it! So I'll add something to force a turn before they get going.

One further question (related to putting stuff in ENTER):

Code: Select all

	"PREP_FOR_DEPARTURE" = {
		ENTER = (getWitchspaceEntryCoordinates, setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
		"DESIRED_RANGE_ACHIEVED" = ("setSpeedFactorTo: 1.0", "pauseAI: 15.0", "setStateTo: DEPART_SYSTEM");
        	"ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
       		"OFFENCE_COMMITTED" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
        	"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
        	ATTACKED = (setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
		EXIT = ();
		UPDATE = ();
		RESTARTED = ("setStateTo: PREP_FOR_DEPARTURE");
Do you think the RESTARTED at the end will work, in the sense of making ships "returning from combat" to this state move to jump coordinates? (I already know that the state works in general.)

*EDIT* I've just grasped the significance of the EXITED WITCHSPACE message. Does that mean I could just do...

Code: Select all

	"CHOOSE_DESTINATION" = {
		ENTER = ("rollD: 3"); 
	        "ROLL_1" = ("setStateTo: GO_TO_STATION");
		"ROLL_2" = ("setStateTo: CHECK_FOR_TARANIS"); 
		"ROLL_3" = ("setStateTo: CHECK_FOR_TARANIS"); 
		"EXITED WITCHSPACE" = ("setStateTo: GO_TO_STATION");
              EXIT = (); 
		UPDATE = (); 
	}; 
...and abolish the checking state altogether? (CHOOSE_DESTINATION is the first state it goes to after GLOBAL; am I right in thinking that ships default to GLOBAL when they appear in a new/another system?)
User avatar
JensAyton
Grand Admiral Emeritus
Grand Admiral Emeritus
Posts: 6657
Joined: Sat Apr 02, 2005 2:43 pm
Location: Sweden
Contact:

Post by JensAyton »

Probably. Give it a shot. :-) (I’m not really very familiar with the practicalities of writing AIs. I just fiddle with the infrastructure.)
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

No worries :) I've been tweaking for hours and finally got things how I want them:

Code: Select all

{
	GLOBAL = { 
		ENTER = (); 
		"EXITED WITCHSPACE" = ("setStateTo: GO_TO_STATION");
		EXIT = (); 
		UPDATE = ("setStateTo: CHOOSE_DESTINATION"); 
	}; 
	"CHOOSE_DESTINATION" = {
		ENTER = ("rollD: 3"); 
	        "ROLL_1" = ("setStateTo: GO_TO_STATION");
		"ROLL_2" = ("setStateTo: STEERING"); 
		"ROLL_3" = ("setStateTo: STEERING"); 
		EXIT = (); 
		UPDATE = (); 
	}; 
	"STEERING" = {
		ENTER = ("rollD: 10"); 
	        "ROLL_1" = ("setCoordinates: pwm 142653.45 -27832.78 57463.84", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_2" = ("setCoordinates: pwm 143166.81 -29220.01 59293.16", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_3" = ("setCoordinates: pwm 143971.92 -27108.34 58484.39", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_4" = ("setCoordinates: pwm 143581.45 -27807.32 59565.06", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_5" = ("setCoordinates: pwm 142959.56 -28632.24 57902.22", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_6" = ("setCoordinates: pwm 143780.75 -27055.29 59093.81", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_7" = ("setCoordinates: pwm 144091.70 -27321.55 57644.63", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_8" = ("setCoordinates: pwm 142990.44 -28428.13 59655.61", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_9" = ("setCoordinates: pwm 142287.39 -25442.38 52039.16", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
	        "ROLL_10" = ("setCoordinates: pwm 143891.75 -24652.42 53534.86", setDestinationFromCoordinates, "setDesiredRangeTo: 100.0", "setSpeedFactorTo: 0.9", performFlyToRangeFromDestination);
		"DESIRED_RANGE_ACHIEVED" = ("setStateTo: PREP_FOR_DEPARTURE");
        	"ACCEPT_DISTRESS_CALL" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
       		"OFFENCE_COMMITTED" = (setTargetToFoundTarget, "setAITo: taranisTrafficFightAI.plist"); 
        	"INCOMING_MISSILE" = (fightOrFleeMissile, setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
        	ATTACKED = (setTargetToPrimaryAggressor, broadcastDistressMessage, "setAITo: taranisTrafficFightAI.plist"); 
		EXIT = (); 
		UPDATE = (); 
		RESTARTED = ("setStateTo: PREP_FOR_DEPARTURE");
	}; 
The EXITED WITCHSPACE thing works as it should, and ships about to depart will turn to one of the ten sets of coordinates (all out of the "firing line" between the dock and the billboard) before heading out to jump range (which I've increased to 23.5km, as a couple of Morays, for some reason, were still getting stuck!). I removed some checkCourseToDestination/COURSE_OK/pauseAI stuff for the sake of smoothness; now ships slow to a near-stop, before turning again to head out. They always go in the direction of the sun - or rather, just to the side of it - which I guess is where Oolite likes its witchspace-entry coordinates to be!

Now to sort out the randomly appearing Frigate's "weapons testing" AI...
User avatar
Roberto
---- E L I T E ----
---- E L I T E ----
Posts: 318
Joined: Sun Jun 11, 2006 1:16 pm
Location: London, UK

Post by Roberto »

@Matt634

Would it be OK to actually incorporate your Frigate model and texture into the Taranis OXP? Using like_ship won't cut it, due to the way you've set up your AI (it overrides mine), and in any case, I'd prefer it if the new OXP could work on its own (I'm even going to incorporate my earlier Outrider OXP within it).

*EDIT* I'm not sure if you still fancy making a new texture using the logo I sent you; if not, I can just use the normal one (I'm easy either way).
Post Reply