Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Station Defense Minigame

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

Moderators: another_commander, winston

User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

Code: Select all

this.shipExitedWitchspace = function()
    {
    if(galaxyNumber==3 && system.name=="Esenis")
        {
            system.addShips("station", 1, player.ship.position, 8000);
        }
    }
How would I change the last two parameters of system.addShips() to give me a station behind the sun?

Edit: I changed the station it was spawning to one that was identical to the vanilla coriolis, except its ASC letter was Q. However, I now cannot dock with it without dying. I added the models (including the docking slit) to the models folder and the station and slit subent to the shipdata.plist. What's the problem?
Currently in G1.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Station Defense Minigame

Post by cim »

The slit subent needs to be marked as a dock (is_dock=1 on the subentity definition in the station shipdata), and the station as a whole needs to be marked as a station (is_carrier=1).

As regards "behind" the sun, it depends where you're looking from. So I'll assume you meant "from the planet", and you should be able to work it out for other relative positions. Once you work out what's going on you can do this with considerably fewer intermediate variables, of course. (The code is untested, so I don't guarantee it has no bugs...)

Code: Select all

var sunpos = system.sun.position; // get the sun's position
var diff = sunpos.subtract(system.mainPlanet.position); // a vector pointing in the same direction as the sun is from the main planet
var dir = diff.direction(); // a vector of length 1 pointing in that direction
var stationpos = sunpos.add(dir.multiply(system.sun.radius*5))); // from the sun, go 5 stellar radii in that direction

system.addShips("station",1,stationpos,1);
In this case the fourth parameter doesn't really matter, so we might as well put the station within 1m of the calculated position. The fourth parameter is more useful when trying to add multiple objects to a region of space, or where you want to randomise position (or just don't care to that level of detail)
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Re: Station Defense Minigame

Post by Commander McLane »

Commander Xvyto wrote:

Code: Select all

this.shipExitedWitchspace = function()
    {
    if(galaxyNumber==3 && system.name=="Esenis")
        {
            system.addShips("station", 1, player.ship.position, 8000);
        }
    }
How would I change the last two parameters of system.addShips() to give me a station behind the sun?
First of all, make sure you've read the relevant documentation, or at least are aware where to find it.

For system.addShips, see here.

As you see, you need a vector expression for your position. There are several ways to calculate the vector:

You can do it in your script: Take the planet position. Construct a vector to the sun position. Make that vector longer, so that it points to a point behind the sun:

Code: Select all

var myVector = system.sun.position.subtract(system.mainPlanet.position); // this gives the vector from the planet to the sun
myVector = myVector.multiply(2); // this makes the vector longer by a factor of two
myVector = system.mainPlanet.position.add(myVector); // this gives you a position of equal distance exactly behind the sun, as seen from the planet
system.addShips("station", 1, myVector, 0); // you perhaps want it exactly in the calculated position, not randomly within a radius of 8000 meters
Or you can use a conversion method from the legacy coordinate system, which is part of the legacy scripting system. See here. As you see, there is a choice of coordinate systems for your convenience. Obviously for placing a station relative to the planet and the sun, you need either psx or spx. Lets take psx. Now, which third parameter do you want to use? For getting the same result as with the first code, it makes sense to use u. Thus 'psu 0 0 2' is the exact coordinate you want (= the point that is exactly in line from the planet to the sun, at twice the distance between the former to = the point as far behind the sun as the sun is from the planet). Translated to the syntax of fromCoordinateSystem this would be

Code: Select all

var myVector = Vector3D(0, 0, 2).fromCoordinateSystem("psu");
system.addShips("station", 1, myVector, 0);
or shorter

Code: Select all

system.addShips("station", 1, Vector3D(0, 0, 2).fromCoordinateSystem("psu"), 0);
Incidentally, this is exactly the same as

Code: Select all

system.addShips("station", 1, Vector3D(0, 0, -1).fromCoordinateSystem("spu"), 0);
I leave it to you to figure out why. :wink:
Commander Xvyto wrote:
Edit: I changed the station it was spawning to one that was identical to the vanilla coriolis, except its ASC letter was Q. However, I now cannot dock with it without dying. I added the models (including the docking slit) to the models folder and the station and slit subent to the shipdata.plist. What's the problem?
There is a number of reasons I can think of. It would help if you'd post the shipdata snippets in question.
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

First of all, make sure you've read the relevant documentation, or at least are aware where to find it.
Yup. I have http://wiki.alioth.net/index.php/Catego ... _Reference bookmarked.
or shorter:

Code: Select all

system.addShips("station", 1, Vector3D(0, 0, 2).fromCoordinateSystem("psu"), 0);
I like how short this is, but I have one question. You said that this is from the legacy scripting system. Does that mean that the code will eventually be broken? Because if so, I should probably use:

Code: Select all

var myVector = system.sun.position.subtract(system.mainPlanet.position); // this gives the vector from the planet to the sun
myVector = myVector.multiply(2); // this makes the vector longer by a factor of two
myVector = system.mainPlanet.position.add(myVector); // this gives you a position of equal distance exactly behind the sun, as seen from the planet
system.addShips("station", 1, myVector, 0); // you perhaps want it exactly in the calculated position, not randomly within a radius of 8000 meters

Edit: Forgot the station part.
As to the station being undockable, here is shipdata.plist:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>coriolis-stationStationDefense</key>
	<dict>
		<key>beacon</key>
		<string>Q-Coriolis Defense</string>
		<key>ai_type</key>
		<string>stationAI.plist</string>
		<key>cargo_type</key>
		<string>CARGO_NOT_CARGO</string>
		<key>energy_recharge_rate</key>
		<string>100</string>
		<key>forward_weapon_type</key>
		<string>WEAPON_NONE</string>
		<key>frangible</key>
		<string>0</string>
		<key>has_ecm</key>
		<string>yes</string>
		<key>has_escape_pod</key>
		<string>no</string>
		<key>has_scoop</key>
		<string>no</string>
		<key>max_energy</key>
		<string>25000</string>
		<key>max_flight_pitch</key>
		<string>8</string>
		<key>max_flight_roll</key>
		<string>8</string>
		<key>max_flight_speed</key>
		<string>0</string>
		<key>missiles</key>
		<string>0</string>
		<key>model</key>
		<string>new_coriolis.dat</string>
		<key>name</key>
		<string>Coriolis Station</string>
		<key>roles</key>
		<string>coriolisStationStationDefense</string>
		<key>rotating</key>
		<string>yes</string>
		<key>subentities</key>
		<array>
			<dict>
				<key>subentity_key</key>
				<string>dock-flat</string>
				<key>orientation</key>
				<array>
					<string>1</string>
					<string>0</string>
					<string>0</string>
					<string>1</string>
				</array>
				<key>position</key>
				<array>
					<string>0</string>
					<string>0</string>
					<string>500</string>
				</array>
				<key>is_dock</key>
				<string>true</string>
			</dict>
		<key>thrust</key>
		<string>100</string>
		<key>weapon_energy</key>
		<string>0</string>
	</dict>
	<key>dock-flat</key>
	<dict>
		<key>ai_type</key>
		<string>nullAI.plist</string>
		<key>model</key>
		<string>dock-flat.dat</string>
		<key>name</key>
		<string>Docking Slit (horizontal)</string>
		<key>roles</key>
		<string>docking-slit-horizontal</string>
	</dict>
</dict>
</plist>
I have both models in the Models folder, so that's not the problem. Is there a key I need to add to the plist to make the station dockable?
Last edited by Commander Xvyto on Fri Jun 01, 2012 1:14 pm, edited 2 times in total.
Currently in G1.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Re: Station Defense Minigame

Post by Commander McLane »

Commander Xvyto wrote:
or shorter:

Code: Select all

system.addShips("station", 1, Vector3D(0, 0, 2).fromCoordinateSystem("psu"), 0);
I like how short this is, but I have one question. You said that this is from the legacy scripting system. Does that mean that the code will eventually be broken?
Nope. The developers have always made sure to maintain backwards compatibility. In short: everything that worked in the previous stable release (1.65) is going to work in any new stable release (we're told that this is precisely the meaning of "stable"). Thus, while this is not advisable due to its inferiority compared to the JS-scripting system, you could even continue to script in the legacy (plist) scripting system. :wink:
Commander Xvyto wrote:
Because if so, I should probably use:

Code: Select all

var myVector = system.sun.position.subtract(system.mainPlanet.position); // this gives the vector from the planet to the sun
myVector = myVector.multiply(2); // this makes the vector longer by a factor of two
myVector = system.mainPlanet.position.add(myVector); // this gives you a position of equal distance exactly behind the sun, as seen from the planet
system.addShips("station", 1, myVector, 0); // you perhaps want it exactly in the calculated position, not randomly within a radius of 8000 meters
You can shorten that, too, if you like. By substituting the variables with the longer calculations from last line up to the first you get:

Code: Select all

system.addShips("station", 1, system.mainPlanet.position.add(system.sun.position.subtract(system.mainPlanet.position).multiply(2)), 0);
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

The slit subent needs to be marked as a dock (is_dock=1 on the subentity definition in the station shipdata), and the station as a whole needs to be marked as a station (is_carrier=1).
Thanks! The docking now is working correctly.

Is it possible to make a ship's AI so that it attacks the station, only turning on other ships if attacked? Essentially change the default pirate AI to not attack the player, but station.

Edit: found scanForNearestShipWithRole on http://wiki.alioth.net/index.php/OXP_howto_AI. However, how do I trigger this message? Is it in-script? Basically, I want to use scanForNearestShipWithRole and setDestinationToTarget to have certain ships fly towards a station with a unique role
Currently in G1.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Re: Station Defense Minigame

Post by Commander McLane »

Commander Xvyto wrote:
The slit subent needs to be marked as a dock (is_dock=1 on the subentity definition in the station shipdata), and the station as a whole needs to be marked as a station (is_carrier=1).
Thanks! The docking now is working correctly.
Alternatively to inserting the is_carrier key you can insert "station" as a role. It's the more usual way:

Code: Select all

      <key>roles</key>
      <string>station coriolisStationStationDefense</string>
Commander Xvyto wrote:
Is it possible to make a ship's AI so that it attacks the station, only turning on other ships if attacked? Essentially change the default pirate AI to not attack the player, but station.

Edit: found scanForNearestShipWithRole on http://wiki.alioth.net/index.php/OXP_howto_AI. However, how do I trigger this message? Is it in-script? Basically, I want to use scanForNearestShipWithRole and setDestinationToTarget to have certain ships fly towards a station with a unique role
It's an AI method (that's why you found it on [wiki]OXP_howto_AI[/wiki] :wink: ). Obviously this means that you have to use it inside an AI, not in a script. An AI is not a script, and a script is not an AI.

So, basically you have to create a new, custom AI.plist. In one of the AI-states it would use "scanForNearestShipWithRole: coriolisStationStationDefense" as its main scanning method. You can look into some other scanning AIs for guidance, for instance pirateAI.plist or route1patrolAI.plist. However, you cannot copy those AIs wholesale, because they are not able to guide an NPC to the place where your station is located in the first place. Therefore, if you don't spawn your attacker right next to the station to begin with, your custom AI needs a first part to lead him there, before he can begin scanning (all scanning methods are limited to scanner range = 25600m; they cannot find anything outside that range).
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

I am spawning the ships within range of the object. I just need them to attack the station above the player. So, what part of the AI does the scanForNearestShipWithRole: coriolisStationStationDefense go? ATTACK_SHIP > ENTER?
Currently in G1.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Re: Station Defense Minigame

Post by Commander McLane »

Commander Xvyto wrote:
I am spawning the ships within range of the object. I just need them to attack the station above the player. So, what part of the AI does the scanForNearestShipWithRole: coriolisStationStationDefense go? ATTACK_SHIP > ENTER?
At the end of the day that's up to you. There are usually many ways to achieve the same result.

Having said that, though, I'd suggest that the ATTACK state should handle only the attack itself, as it's the case with all other AIs. Which means that you should have another AI state dedicated to the scanning. You can name it SCAN_FOR_STATION or SCAN_FOR_TARGET. Names of AI states are totally arbitrary. You can name them whatever you want.

If your ship is reliably spawned inside scanner radius of the station, you can perform the scan in the ENTER-part of your SCAN state and get away with it. However, that would be an exception of the rule. Generally, scanning is done periodically, not just once. Thus generally it would belong in the UPDATE-part of an AI state. If the target is found, the state would be set to your ATTACK state.
User avatar
Smivs
Retired Assassin
Retired Assassin
Posts: 8408
Joined: Tue Feb 09, 2010 11:31 am
Location: Lost in space
Contact:

Re: Station Defense Minigame

Post by Smivs »

Assuming the ships are spawned within range of the station, you'll need something like

Code: Select all

{
    GLOBAL = {
         ENTER = (scanForNearestShipWithRole: coriolisStationStationDefense); 
        "TARGET_FOUND" = (setTargetToFoundTarget, "setStateTo: ATTACK_SHIP");
        "NOTHING_FOUND" = (pauseAI: 5.0, "setStateTo: GLOBAL");
        "TARGET_LOST" = (scanForNearestShipWithRole: player; "setStateTo: ATTACK_SHIP");
                   };
    "ATTACK_SHIP" = 
                   {
        ENTER = (performAttack); 
        ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP"); 
        "ENERGY_LOW" = ("setStateTo: FLEE"); 
        "INCOMING_MISSILE" = (fightOrFleeMissile, "setStateTo: FLEE"); 
        "TARGET_DESTROYED" = (scanForNearestShipWithRole: player; "setStateTo: ATTACK_SHIP"); 
        "TARGET_LOST" = (scanForNearestShipWithRole: player; "setStateTo: ATTACK_SHIP"); 
                  };
This is 'bare-bones' and will need fleshing out a bit, but should cause the ship to attack the station, or if that is destroyed or 'lost' as a target, the ship will turn on the player.
Commander Smivs, the friendliest Gourd this side of Riedquat.
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

should cause the ship to attack the station, or if that is destroyed or 'lost' as a target, the ship will turn on the player.
Will it also break from attacking the station and attack the player if the player attacks it?
Currently in G1.
User avatar
Commander McLane
---- E L I T E ----
---- E L I T E ----
Posts: 9520
Joined: Thu Dec 14, 2006 9:08 am
Location: a Hacker Outpost in a moderately remote area
Contact:

Re: Station Defense Minigame

Post by Commander McLane »

Commander Xvyto wrote:
should cause the ship to attack the station, or if that is destroyed or 'lost' as a target, the ship will turn on the player.
Will it also break from attacking the station and attack the player if the player attacks it?
Yes, that's what it says here:

Code: Select all

        ATTACKED = (setTargetToPrimaryAggressor, "setStateTo: ATTACK_SHIP"); 
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

Ok, cool. Now to test-fly.
Currently in G1.
User avatar
Commander Xvyto
Competent
Competent
Posts: 47
Joined: Mon May 28, 2012 10:52 pm
Location: Raisso

Re: Station Defense Minigame

Post by Commander Xvyto »

From my tests, the station spawns (with its ASC letter) quite well, until I add this:

Code: Select all

this.shipWillLaunchFromStation = function(station)
    {
    if(station.role=="coriolisStationStationDefense")
        {
        player.consoleMessage("Launched from research station.");
        }
    }
Is this valid code? I think that the station.role=="coriolisStationStationDefense" part is causing the problem, because without this if() control, the shipWillLaunchFromStation function works fine.
Currently in G1.
User avatar
Capt. Murphy
Commodore
Commodore
Posts: 1127
Joined: Fri Feb 25, 2011 8:46 am
Location: UK South Coast.

Re: Station Defense Minigame

Post by Capt. Murphy »

Commander Xvyto wrote:
Is this valid code? I think that the station.role=="coriolisStationStationDefense" part is causing the problem, because without this if() control, the shipWillLaunchFromStation function works fine.
Yep, role isn't a valid property as you've surmised.

Assuming that you are adding the station with that role you want.

if(station.primaryRole==="coriolisStationStationDefense")

or if it's got multiple potential roles and another might be the primary.

if(station.hasRole("coriolisStationStationDefense"))
Last edited by Capt. Murphy on Sun Jun 03, 2012 5:09 am, edited 1 time in total.
[EliteWiki] Capt. Murphy's OXPs
External JavaScript resources - W3Schools & Mozilla Developer Network
Win 7 64bit, Intel Core i5 with HD3000 (driver rev. 8.15.10.2696 - March 2012), Oolite 1.76.1
Post Reply