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

Scripters cove

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

Moderators: winston, another_commander

another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6573
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

LB, I cannot tell at the moment why you cannot seem to get whom to work. Using the standard example script, if I launch at Lave, turn 180 and ram the station, this is what I get in the log:

Code: Select all

008-01-13 10:54:59.129 oolite.exe[10672] [jstest.died]: Player has suffered an existence failure.
2008-01-13 10:54:59.129 oolite.exe[10672] [jstest.died]: Killed by [Station "Coriolis Station" "Coriolis Station" ID: 105 position: (-49515.3, 60769.4, 592262) scanClass: CLASS_STATION status: STATUS_ACTIVE] by means of scrape damage
Whom is working fine apparently, at least when it is checking who killed the player. Are you giving the ships you want to check against killing a script at initialization? I think it should be on that script that all checks are done. Not entirely sure, though, will have to check the code.
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2869
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 »

I dunno if this makes a difference A_C. but I'm attaching the script to the ship in shipdata like this:-

Code: Select all

<key>random_hits_pod1</key>
<dict>
<key>beacon</key>
<string>P-Pod</string>
<key>script</key>
<string>oolite-random-hits-pods.js</string>
<key>like_ship</key>
<string>escape-capsule</string>
<key>name</key>
<string>Escape Capsule (Target Aboard)</string>
<key>roles</key>
<string>random_hits_pod1</string>
<key>ai_type</key>
<string>randomhitshomeAI.plist</string>
<key>cargo_type</key>
<string>CARGO_SCRIPTED_ITEM</string>
<key>unpiloted</key>
<false/>
<key>has_escape_pod</key>
<real>0.0</real>
<key>has_fuel_injection</key>
<real>0.34</real>
<key>fuel</key>
<integer>17</integer>
</dict>
In a random hits mission, a pod would only appear (% chance) on the death of a mission ship. If no pod is spawned the OXP goes straight to the status variable being set to KILLED. If its it then it goes to PODDED. The "scooper" function in the Java Script work fine on the same ship though, setting the variable to NPCSCOOPED / SCOOPED depending on who scooped him. When scooped I get the correct log message:-

Code: Select all

2008-01-12 20:50:52.218 oolite.exe[1196] [js.test.scooped]: Scooped by [Ship "Cobra Mark I" ID: 307 position: (-7977.48, -1555.82, 6524.54) scanClass: CLASS_NEUTRAL status: STATUS_IN_FLIGHT]
But when killed, although its run the Java death actions, I always get:-

Code: Select all

2008-01-13 13:50:46.142 oolite.exe[2520] [js.test.died]: Killed by undefined by means of undefined
The variable is set to NPCKILLED even if I did it, as although the death_action worked, whom = undefined rather than player, so it executes the else command.

The Java script for the death of the ship is working, but however he's killed (I ramed him, lasered him, missiled him, e-bombed him q-mined him and let him be killed by NPCs - for testing I'm spawning podkillers (- have a simple AI to find the pod and kill it). I always get the log message of "Killed by undefined by means of undefined" whoever got him. To save me having to take a mission to check it. I just have a simple testship.oxp installed that just says this in script:-

Code: Select all

<dict> 
   <key>testship</key> 
   <array> 
      <dict> 
         <key>conditions</key> 
         <array> 
            <string>status_string equal STATUS_EXITING_WITCHSPACE</string>
         </array> 
         <key>do</key> 
         <array> 
	   <string>addShipsWithinRadius: random_hits_pod1 1 wpm 0 0 4000 10000</string>
	   <string>addShipsWithinRadius: random_hits_spacebar23 1 wpm 0 0 4000 10000</string>
	   <string>addShipsWithinRadius: scavenger 5 wpm 0 0 4000 10000</string>
         </array> 
      </dict> 
   </array> 

</dict> 
</plist>

I haven't tested the "whom" on the player, but it looks like it doesn't work on an NPC ship. BTW What is the equivilant of "launch_actions" in Java? Once I attach a Java Script to the ship it won't read any death_actions / launch_actions that are in the shipdata entry.
Last edited by LittleBear on Sun Jan 13, 2008 1:53 pm, edited 2 times in total.
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 »

BTW What is the equivilant of "launch_actions" in Java? Once I attach a Java Script to the ship it won't read any death_actions / launch_actions that are in the shipdata entry.
See for example the newest "military Fiasco" I uploaded. There is one in and working:

Code: Select all

this.name           = "leviathanEscort";
this.author         = "Eric Walch";
this.copyright      = "Dec2007";
this.description    = "bugFix";
this.version        = "1.00";

this.shipSpawned = function()
{
  this.ship.primaryRole = "escort";
  this.ship.call("switchAITo:", "militariFiascoEscortAI.plist")
  delete this.didSpawn;
}
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 »

LB,

as another_commander wrote in the bugs section, is the whom with shipDied not yet implemented. that means it will not work until the 1.71 release. For the time being I think you can do with:

Code: Select all

this.beingAttacked = function(whom)
{ 
    if(whom == player) 
    {
      missionVariables.ups_closecontact = "YES" // Shooter was the player 
       if (player.isCloaked) 
       { 
        missionVariables.ups_closecontact = "NO" // don't honour a cloaked shot 
       }
    }
    else
    {
      missionVariables.ups_closecontact = "NO" // Shooter was NPC ship 
    }
}
The variable names are for my OXP, but it will work for random_hits under 1.70. "closecontact" stores the identity of the last shooter. (Most likely also the killer). As extra a cloaked shot is not awarded to the shooter. With this code you can at least issue a better working of random hits. And when 1.71 comes out, you can always upgrade it to shipDied = function(whom)
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2869
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 »

Hey Hey! Looks good. Whole script is now this:-

Code: Select all

this.name = "oolite-random-hits-pod1";
this.author = "LittleBear";
this.copyright = "2008 - But do what you like with it!";
this.version = "1.1";

this.shipSpawned = function ()
{
	missionVariables.random_hits_store_showship = "random_hits_pod1"
}

this.shipDied = function(whom)
{
	LogWithClass("js.test.died", "Random Hits Pod Killed by " + whom);
	if (whom == player)
	{
		missionVariables.random_hits_status = "KILLED" // Killer was the player - Doesn't work yet so death is tested with the next command.
	}
	else
	{
		missionVariables.random_hits_status = "KILLED" // Killer was an NPC - Doesn't work yet so death is tested with the next command.
	}
	
}

this.beingAttacked = function(whom)
{
	LogWithClass("js.test.shoot", "Random Hits Pod Shot at by " + whom);
    if(whom == player)
    {
      missionVariables.random_hits_whoshot = "PLAYER_ATTACK" // Shooter was the player and he did it in fair combat Uncloaked!
       if (player.isCloaked)
       {
     missionVariables.random_hits_whoshot = "PLAYER_ATTACK_CLOAKED" // Shooter was the player, but he's a cowardly Cloaked backstaber!
       }
    }
    else
    {
     missionVariables.random_hits_whoshot = "NPC_ATTACK" // Shooter was NPC ship.
    }
}

this.shipWasScooped = function(scooper)
{
	LogWithClass("js.test.scooped", "Random Hits Pod Scooped by " + scooper);
	if (scooper == player)
	{
		missionVariables.random_hits_whoscooped = "PLAYER"  // Scooper was the player.
	}
	else
	{
		missionVariables.random_hits_whoscooped = "NPC" // Scooper was an NPC.
	}
	
}
Lasered the test pod. Worked! :-

Code: Select all

2008-01-21 18:59:24.812 oolite.exe[3496] [js.test.shoot]: Random Hits Pod Shot at by [Player "Naval Imperial Courier" ID: 100 position: (-5769.45, 9866.71, 7725.13) scanClass: CLASS_PLAYER status: STATUS_IN_FLIGHT]
2008-01-21 18:59:24.968 oolite.exe[3496] [js.test.died]: Random Hits Pod Killed by undefined
Now to test all the other permutations!....[/code]

LATER:-

NPC kill logged perfectly too:-

Code: Select all

2008-01-21 20:30:41.062 oolite.exe[3960] [js.test.shoot]: Random Hits Pod Shot at by [Ship "Asp Mark I (Bailiff)" ID: 323 position: (-14094.7, -1547.74, 11119.9) scanClass: CLASS_NEUTRAL status: STATUS_IN_FLIGHT]
If the player kills him by a Q-mine E-bomb or Missile without EVER hitting him with a laser beam, the status stays undefined. However for Random Hits this method will be perfect. The variable stores the last Attack immedatley before the marks death. If I shoot him, but an NPC fires the fatal shot the NPC gets the credit for the kill - which is what I want. If I kill him without ever hitting him with a laser (ie I just q-mine / e-bomb or missile him). The status is undefined. I can use undefined to give the player the credit for the kill, but with a fine for breaking the Terms of the Contract that mass-destruction weapons are not used. This would create the slight odd situation that if you just ram the mark to death then you are penalised. Hey, those are the rules though.

The hit must be made with Lasers. I fine is imposed for not having the guts to go into a straight dogfight. In reality I don't think it would be possible to kill a mark without lasering him (unless you just press tab and then you deserve your fine!), as they'll witch out or injector away from a q-mine, the small ships have injectors so will outrun a missile and the big ones have enough shields to take a single missile hit.

Probley get a V1.1 up at the weekend.

EDIT:-

Actually the this.beingAttacked has exactly the same result as the this.shipDied would have if the whom worked. As the variable is set and reset as different ships it him, the attacking ship on his death is always the same as the ship that killed him. Tested it here:-

Code: Select all

2008-01-22 00:16:42.281 oolite.exe[3744] [js.test.shoot]: Random Hits Pod Shot at by [Ship "Asp Mark I (Bailiff)" ID: 350 position: (-16323.8, 5270.93, 2671.05) scanClass: CLASS_NEUTRAL status: STATUS_IN_FLIGHT]
2008-01-22 00:16:51.218 oolite.exe[3744] [js.test.shoot]: Random Hits Pod Shot at by [Ship "Asp Mark I (Bailiff)" ID: 348 position: (-8694.16, -3402.47, 591.692) scanClass: CLASS_NEUTRAL status: STATUS_IN_FLIGHT]
2008-01-22 00:16:54.203 oolite.exe[3744] [js.test.shoot]: Random Hits Pod Shot at by [Ship "Asp Mark I (Bailiff)" ID: 346 position: (-5184.18, 1267.37, 10758) scanClass: CLASS_NEUTRAL status: STATUS_IN_FLIGHT]
2008-01-22 00:17:18.640 oolite.exe[3744] [js.test.shoot]: Random Hits Pod Shot at by [Player "Naval Imperial Courier" ID: 100 position: (-9509.27, 3747.81, 6226.41) scanClass: CLASS_PLAYER status: STATUS_IN_FLIGHT]
Here although NPCs hit him I nailed him. My save file shows the variable correctly set as:-

Code: Select all

	<key>mission_random_hits_whoshot</key>
	<string>PLAYER_ATTACK</string>
So the script acts correctly on a kill by the player (uncloaked).

EDIT:-

Present script does not detect a cloaked kill. I think it needs to be if (player.isCloaked == true). Also it won't detected it under attacked, as the ship seems to not regard a laser blast from a cloaked attacked ship as an Attack, so this.beingAttacked never gets run. Should work though if I do it under this.shipDied.

Now to test using A_C's new build with the whom in this.shipDied fixed.
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 »

The past days I started to play with JS. I converted my whole ups.solar missions into JS. This has the shortest code in ups. I noticed that the transformation is straight forward. "Conditions/do/else" translate easy into "if(){}else{}

I got my first offer working and the destination and description are set proper. On translating every function I discovered that some are still missing on the wiki (Or did I search on the wrong place?) Those missing functions I looked up in the code itself. (eg markSystem() and unmarkSystem()). Most functions translate 1 tot 1.

But detection on solar station is not working. I don't know how to detect a station other than the main station. I have a station with name: "Sun Research Station Alpha". The code below didn't work, but I also believe that with spaces in the name it won't work. (I did not try (EDIT did now try but gave errors as expected)). according to the wiki it must be: player.dockedStation.stationname

Anybody a suggestion?

Code: Select all

    if (player.dockedStation.isMainStation)
    {LogWithClass("ups.sun", "at main station with missionstatus: " + missionVariables.ups_sun)
......
    if (player.dockedStation.Sun_Research_Station_Alpha)
    {LogWithClass("ups.sun", "Docked at : Sun_Research_Station_Alpha")
for info:
For scripting JS on the Mac I noticed that the "Project Builder" works very well. This program is part of the developers package that is on the installation disk.

It is basically a text-editor, but does a lot more. You can easy indent large code blocks and it warns you for non-maching brackets {} with colour coding.

Also strings and numbers get their own colours while typing. This makes things easy and it is available on every Mac when you instal the developers package.


EDIT: Above was yesterday late. This morning I realised that it should have been: if (player.dockedStation.shipDescription == "Sun Research Station Alpha")

Not tested yet, but I am sure it will work.

EDIT2: JS looks a lot a C. I think the wiki needs an explanation of how the variable structures work. Specially for the non programmers like me it would be helpfull. (I'll make a start next week)

- dockedStation is the name of the variable. Or better of the structure that contains the variables.

- player is the entity for which we want to know the status.

- shipDescription is the entry within the dockedStation structure were the name is stored as string.

For addressing it as whole we need: player.dockedStation.shipDescription

When logging "player.dockedStation" we get in the log several parts of the structure: "[Station "Icosahedron Station" "Icosahedron Station" ID: 171 position: (16450.3, 52909.6, 356990) scanClass: CLASS_STATION status: STATUS_ACTIVE]"

When logging "player.dockedStation.shipDescription" we get in the log just the name: "Icosahedron Station"
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2869
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 »

Hi A_C, I've been testing the modded build you sent me. Sorry about the delay in getting back to you, had quite a bit of RL stuff to do last week!

I've put the Java Scripts I've used at the end of this post and also put the post on the Scripters Cover thread.

I'm using both thisBeingAttacked and thisShipDied. These are the results:-

thisShipDied on the new build works perfectly. It records who killed, however the ship died. Even if the player hit the ship with an e-bomb / missile / q-bomb "whom" is recorded as the player rather than the e-bomb / missile / q-bomb. Even if the death is caused by the player ramming the ship, the killer is still recorded as the player. It also works for recording a kill by an NPC even if the NPC used a missile. :D

thisBeingAttacked does not work quite as well. It regards a laser blast as an attack, but does not record a missile / e-bomb / q-mine or collison as an attack. If the ship is killed by these means the variable remains undefined. For 1.1 of Random Hits I'll use the thisBeingAttacked to test the killer. It works as well as thisShipDied because I'm reseting the variable every time the ship is hit. It therefore records the last ship to shoot the target before its death (which is the same as who killed it). I then use the undefined status to test for a e-bomb / q-mine kill.

One oddity on both build has been touched on by Eric above. The game will not read a Java Script attached to the second ship to be added with the spawn command. It always reads a script attached to a ship if the ship has been added with addSystemShips. On the death of the target ship (on a dice role) I spawn his pod. This works fine the first time by the second time (in the same game session) I spawn a ship, I get this error log:-

Code: Select all

2008-01-26 12:24:10.703 oolite.exe[600] [js.test.died]: RandomHits.OXP Pod Killed by [Player "Naval Imperial Courier" ID: 100 position: (-6063.97, 4209.98, 7157.24) scanClass: CLASS_PLAYER status: STATUS_IN_FLIGHT]. Command does not work on 1.70 or lower so I detect who killed him by using the last ship to shoot at the Pod before it died!
2008-01-26 12:25:05.593 oolite.exe[600] [script.debug.onOff]: SCRIPT debug messages ON
2008-01-26 12:25:05.609 oolite.exe[600] [script.debug.onOff]: SCRIPT debug messages OFF
2008-01-26 12:25:27.171 oolite.exe[600] [js.test.died]: RandomHits.OXP Pod Killed by [Player "Naval Imperial Courier" ID: 100 position: (10840.9, -4442.25, 4578.56) scanClass: CLASS_PLAYER status: STATUS_IN_FLIGHT]. Command does not work on 1.70 or lower so I detect who killed him by using the last ship to shoot at the Pod before it died!
2008-01-26 12:25:27.343 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: missionVariables is not defined
2008-01-26 12:25:27.343 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 9.
2008-01-26 12:25:46.718 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:46.718 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 30.
2008-01-26 12:25:46.875 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:46.875 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 30.
2008-01-26 12:25:47.015 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:47.015 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 30.
2008-01-26 12:25:47.156 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:47.156 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 30.
2008-01-26 12:25:47.296 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:47.296 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 30.
2008-01-26 12:25:47.421 oolite.exe[600] [script.javaScript.exception.1]: ***** JavaScript exception: ReferenceError: player is not defined
2008-01-26 12:25:47.421 oolite.exe[600] [script.javaScript.exception.1]:       AddOns/RandomHits251.oxp/Scripts/oolite-random-hits-pod1.js, line 15.
2008-01-26 12:25:50.906 oolite.exe[600] [unclassified.MyOpenGLView]: Found mode {Height = 768; RefreshRate = 0; Width = 1024; }
2008-01-26 12:25:51.906 oolite.exe[600] [gameController.exitApp]: .GNUstepDefaults synchronized. Exiting.
On the first kill the pod's scipt worked fine. For testing I'm adding a victim ship by the w/s beacon on every Jump. When I jump and kill the ship for the second time. The SHIP's script works fine (as it was added with addShips), but as the pod is spawned, the SECOND time its spawned the error comes up. If I save and restart Oolite however then the next ship spawned works fine. It looks like you can only SPAWN (as opposed to ADD) one ship with a JS attached in the same game session.

In play this won't matter too much, as it would only arrise if the player took a random hits mission AND the mark podded AND he then took another one AND killed the next victim AND the second victim also podded. As long as the player took a break and restarted Oolite after completing the first mission then there would be no problem. Still odd though. Other than that though the JS and "who" seem to be working fine.

This is the Script for the Target Ship:-

Code: Select all

this.name = "oolite-random-hits-mark2";
this.author = "LittleBear";
this.copyright = "2008 - But do what you like with it in your OXPs!";
this.description	= "Tests who killed a RandomHits OXP Victim Ship and how they did it. The main script acts on the setting of variables."
this.version = "1.1";

this.shipDied = function(whom)
{
	LogWithClass("js.test.died", "RandomHits.OXP Pod Killed by " + whom +". Command does not work on 1.70 or lower so I detect who killed him by using the last ship to shoot at the Pod before it died!");
		    if(Math.random() < 0.99) // Role the Dice to see if the Victim made it to his Pod.
	{
		missionVariables.random_hits_status = "PODED" // Victim made it to his Pod! Set the variable to reflect that the player still needs to kill or scoop the Pod!
		system.legacy_spawn("random_hits_pod3", 1); // Spawn a Pod. Any shooting or scooping of the Pod is handled by the Pod's own Script.
		delete this.shipDied
	}
	else
	{	
		missionVariables.random_hits_status = "KILLED" // Victim died with his ship. Set the variable to reflect this.
		system.legacy_spawn("random_hits_qbomb", 1); // Spawn a Q-Mine which taunts the player before exploding! Nasty!
		delete this.shipDied
	}
	
}

this.beingAttacked = function(whom)
{
    if(whom == player)
    {
      missionVariables.random_hits_whoshot = "PLAYER_ATTACK" // Shooter was the player not using an e-bomb, q-mine or cloak. The variable remains undefined if the player e-bombs, q-mines or kills the victim whilst cloaked as thisBeingAttacked does not get run. The main script then awards the player the credit for the kill, but fines him for dishonerable conduct!
	delete this.beingAttacked
    }
    else
    {
     missionVariables.random_hits_whoshot = "NPC_ATTACK" // Shooter was NPC ship. Every time the victim is hit, the variable is reset. Once he's dead the variable is not longer reset. So the last ship to hit him was also the killer!
	delete this.beingAttacked
    }
}

This is the script for the Target Ship's Pod:-

Code: Select all


this.name = "oolite-random-hits-pod1";
this.author = "LittleBear";
this.copyright = "2008 - But do what you like with it in your OXPs!";
this.description	= "Tests who killed or scooped a RandomHits OXP Escape Pod carring the mission target and how they did it. The main script acts on the setting of variables."
this.version = "1.1";

this.shipSpawned = function ()
{
	missionVariables.random_hits_store_showship = "random_hits_pod1" // The ship the victim is flying is shown on mission briefing screens. So I switch the ship to a Pod as he's now abandoned ship.
	delete this.shipSpawned
}

this.shipDied = function(whom)
{
	    if(whom == player)
	{
		missionVariables.random_hits_status = "KILLED" // Record the fact that the Pod has died! If whom worked on this.ShipDied I'd set the variable directly here to COMPLETE.
		delete this.shipDied
	}
	else
	{	
		missionVariables.random_hits_status = "KILLED" // Record the fact that the Pod has died! If whom worked on this.ShipDied I'd set the variable directly here to NPCKILL.
		delete this.shipDied
	}
	
}

this.beingAttacked = function(whom)
{
    if(whom == player)
    {
      missionVariables.random_hits_whoshot = "PLAYER_ATTACK" // Shooter was the player not using an e-bomb, q-mine or cloak. The variable remains undefined if the player e-bombs, q-mines or kills the victim whilst cloaked as thisBeingAttacked does not get run. The main script then awards the player the credit for the kill, but fines him for dishonerable conduct!
	delete this.beingAttacked
    }
    else
    {
     missionVariables.random_hits_whoshot = "NPC_ATTACK" // Shooter was NPC ship. Every time the victim is hit, the variable is reset. Once he's dead the variable is not longer reset. So the last ship to hit him was also the killer!
	delete this.beingAttacked	
    }
}

this.shipWasScooped = function(scooper)
{
	if (scooper == player)
	{
		missionVariables.random_hits_whoscooped = "PLAYER"  // Scooper was the player.
		delete this.shipWasScooped
	}
	else
	{
		missionVariables.random_hits_whoscooped = "NPC" // Scooper was an NPC.
		delete this.shipWasScooped
	}
	
}

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.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6573
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

Just a quick clarification I need: Is the this.beingAttacked behaving the same on both vanilla 1.70 and the modded build or is it only on the modded one that it does not perform as expected?
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2869
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 »

Its on both, but I think this is normal. I'd noticed when doing the AIs that an E-bomb which kills a ship outright is not regarded as "ATTACKED" in the AI, nor is the fireing of a missile (although this can be detected in AI obviously with INCOMING_MISSILE). If the ship has enough energy to survive an e-bomb THEN the ATTCKED in AI is recognised and the ship will act on it.

Should also add that a laser blast fired by a Cloaked Player is not recognised as an ATTACK (either in AI or with beingAttacked) - also on both builds. For Random Hits however, this is rather handy as the death of the ship still sets the variable to KILLED and I know that if the ship is dead and whoshot is undefined then the kill was made by e-bomb / q-mine / cloaked player, so it give me an easy way to detect a "dishonerable kill".

I'm testing the variables set by the Java Script in a legacy script like this:-

Code: Select all


<!-- If the mark was destroyed but launched a pod, set the mission description to tell the player to destroy the pod  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status equal PODED</string>
            </array>
            <key>do</key>
            <array>
	       <string>setMissionDescription: random_hits_shortdescription4</string>
	       <string>set: mission_random_hits_status PODEDOUT</string>
	       <string>consoleMessage6s: [random_hits_poded]</string>
            </array>
         </dict>

<!-- If the mark jumped out of the system, set the mission description to tell the player to follow him.  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status equal JUMPING</string>
            </array>
            <key>do</key>
            <array>
	       <string>setMissionDescription: random_hits_shortdescription7</string>
	       <string>set: mission_random_hits_status JUMPED</string>
               <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>consoleMessage6s: [random_hits_jumped_comms]</string>
            </array>
         </dict>

<!-- If the player jumps out leaving a launched pod alive, give a mission failed message and reset the short description.  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status oneof PODED, PODEDOUT</string>
	       <string>status_string equal STATUS_EXITING_WITCHSPACE</string>
            </array>
            <key>do</key>
            <array>
	       <string>setMissionDescription: random_hits_shortdescription5</string>
	       <string>consoleMessage6s: [random_hits_failed]</string>
	       <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
               <string>reset: mission_random_hits_whoscooped</string>
               <string>reset: mission_random_hits_whoshot</string>
	       <string>set: mission_random_hits_status FAILED</string>
            </array>
         </dict>

<!-- If the player scoops up the mark's escape pod, set the short description to tell him to take him to the station. Award an extra point for scooping him!  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status oneof PODED, PODEDOUT</string>
	       <string>mission_random_hits_whoscooped equal PLAYER</string>
            </array>
            <key>do</key>
            <array>
	       <string>setMissionDescription: random_hits_shortdescription8</string>
	       <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>consoleMessage6s: [random_hits_scooped_comms]</string>
               <string>reset: mission_random_hits_whoscooped</string>
               <string>reset: mission_random_hits_whoshot</string>
	       <string>reset: mission_random_hits_whoscooped</string>
	       <string>set: mission_random_hits_status SCOOPED</string>
	       <string>add: mission_random_hits_store_skill 1</string>
            </array>
         </dict>

<!-- If an NPC scoops up the mark's escape pod, give mission failed message.  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status oneof PODED, PODEDOUT</string>
	       <string>mission_random_hits_whoscooped equal NPC</string>
            </array>
            <key>do</key>
            <array>
               <string>set: mission_random_hits_status NPCKILL</string>
               <string>set: mission_random_hits_npcdays [clock_days_number]</string>
               <string>set: mission_random_hits_deathcause [random_hits_deathcause_scoop]</string>
               <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>setMissionDescription: random_hits_shortdescription6</string>
	       <string>consoleMessage6s: [random_hits_npckill]</string>
	       <string>reset: mission_random_hits_whoscooped</string>
		   <string>reset: mission_random_hits_whoshot</string>
            </array>
         </dict>

<!-- If the player killed the mark and no escape pod was launched or the player destroyed the pod, reset the short description and send a congratulations message.  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status equal KILLED</string>
	       <string>mission_random_hits_whoshot equal PLAYER_ATTACK</string>
            </array>
            <key>do</key>
            <array>
               <string>set: mission_random_hits_status COMPLETE</string>
               <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>setMissionDescription: random_hits_shortdescription2</string>
	       <string>consoleMessage6s: [random_hits_complete_comms]</string>
		   <string>reset: mission_random_hits_whoscooped</string>
           <string>reset: mission_random_hits_whoshot</string>
            </array>
         </dict>
		 
<!-- In the event that an NPC killed the mark, set the status to reflect an NPC kill, send comms message and set short description  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status equal KILLED</string>
               <string>mission_random_hits_whoshot equal NPC_ATTACK</string>
            </array>
            <key>do</key>
            <array>
               <string>set: mission_random_hits_status NPCKILL</string>
               <string>set: mission_random_hits_npcdays [clock_days_number]</string>
               <string>set: mission_random_hits_deathcause [random_hits_deathcause]</string>
               <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>setMissionDescription: random_hits_shortdescription6</string>
	       <string>consoleMessage6s: [random_hits_npckill]</string>
		   <string>reset: mission_random_hits_whoscooped</string>
           <string>reset: mission_random_hits_whoshot</string>
            </array>
         </dict>

<!-- The Game does not regard e-bombing q-mining or lasering whilst cloaked as an attack. Thus if whoshot is undefined and the Mark is dead, he's been got in a dishonerable way by the player!  -->
<!-- The Player is credited with the kill, but as he's a cowardly custard he is fined and he won't earn any points for completing this hit!  -->

	 <dict>
            <key>conditions</key>
            <array>
	       <string>mission_random_hits_status equal KILLED</string>
               <string>mission_random_hits_whoshot undefined</string>
            </array>
            <key>do</key>
            <array>
               <string>set: mission_random_hits_status COMPLETE</string>
               <string>awardCredits: -[mission_random_hits_fine]</string>
               <string>removeMissionDestination: [mission_random_hits_planetnumber]</string>
	       <string>setMissionDescription: random_hits_shortdescription2</string>
	       <string>consoleMessage6s: [random_hits_complete_ebomb]</string>
	       <string>set: mission_random_hits_store_skill 0</string>
		   <string>reset: mission_random_hits_whoscooped</string>
           <string>reset: mission_random_hits_whoshot</string>
            </array>
         </dict>

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.
another_commander
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 6573
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

I had a look at the code for beingAttacked. Apparently, the engine does not register a beingAttacked, until energy damage has been caused. This is why only lasers seem to work fine. A missile will have to travel all the way to its target to cause damage and have a beingAttacked broadcasted to scripts. I think, at least in the case of a missile, a beingAttacked should be sent upon launch. The AI reacts to missile launch anyway, so might as well notify the scripts that an attack is taking place.
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 »

Little Bear wrote:
Present script does not detect a cloaked kill. I think it needs to be if (player.isCloaked == true). Also it won't detected it under attacked, as the ship seems to not regard a laser blast from a cloaked attacked ship as an Attack, so this.beingAttacked never gets run. Should work though if I do it under this.shipDied.
The last is true. A cloaked attack is not registered so the check for cloaked does not take place. Putting it in this.shipDied will work.

if (player.isCloaked) is correct. This is a boolean variable that is false or true. So it does not need a further check for false or true.

--
On the issue of not proper working "spawn" function in 1.70.: The C-code knows the function: launchEscapeCapsule

the C code for this routine is;

Code: Select all

	pod = [UNIVERSE newShipWithRole:[shipinfoDictionary stringForKey:@"escape_pod_model" defaultValue:@"escape-capsule"]];
	mainPod = pod;
This meant that when you have defined a capsule with role "escape_pod_model". It will be ejected automatically. This function is already called by the system itself. So in normal cases the script does not need to spawn the capsule.

Only with week ships you sometimes shoot them so fast they don't have time to eject a capsule. (But your marks probably are strong enough to last that long before dying.)

I think the function could also be activated with the JS call:

this.ship.call("launchEscapeCapsule") //not tested and probably not needed.
-----
EDIT:
deleting structures that are not used anymore is a good thing, but the command delete this.beingAttacked is wrong. This one should stay active until the ship dies.
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 »

I am quite exited with debugMenu. Online changing of mission variables makes oxp testing much easier and faster. Just change the variables during flight and go on with testing. It is called JS console so I never tried this part for legacy scripting, but even with legacy scripting it is just as useful for online variable changing. (Provided you use the JS syntax in the console)

Than a tiny problem I ran into.

For adding ships I always did it in a "condition = (status_string oneof STATUS_LAUNCHING, STATUS_EXITTING_WITCHSPACE"). Otherwise you had to duplicate your code.

I tried it is JS but I see noting similar. "this.shipExitedWitchspace = this.shipLaunchedFromStation = function()" seems to work, but is erases a preceding "this.shipLaunchedFromStation = function()" and "this.shipExitedWitchspace = function()".

Am I right I have to duplicate code here? Or is it better to define a new function and call it from both places?
User avatar
Kaks
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 3009
Joined: Mon Jan 21, 2008 11:41 pm
Location: The Big Smoke

Post by Kaks »

From a programming point of view it would be better to define a common function & call it from the two places. That way if you have to make a change, you don't have to make it twice.

It will have to be a unique name, though.

There's a problem with the javascript namespace: if there's two functions with the same name in different scripts, the last function to be loaded will override the first.

There's a couple of javascript techniques that can be used to use the same function names without conflicts. I'm going to test one of them, and I'll report back on my findings!

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 »

Kaks wrote:
There's a problem with the javascript namespace: if there's two functions with the same name in different scripts, the last function to be loaded will override the first.
Yes. For this reason, every function should be declared as a method of the script object (i.e., this.Foo = function()…), even if it’s not a method that’s called by Oolite. It may be possible to subvert the JS runtime to avoid this problem.

Since functions are objects, you can assign them to more than one attribute, just as Eric did with his “this.shipExitedWitchspace = this.shipLaunchedFromStation = function()…”. This will indeed replace any previous this.shipExitedWitchspace and this.shipLaunchedFromStation, but if you actually want them to be the same function, what’s the problem?

If you want to do the same thing in those event handlers, but also do other stuff, a third function is indeed the way to go.

Code: Select all

this.launchedOrEnteredSystem = function()
{
    // Stuff to do in either case goes here
}

this.shipLaunchedFromStation = function()
{
    this.launchedOrEnteredSystem();
    // Other stuff goes here
}

this.shipExitedWitchspace = function()
{
    this.launchedOrEnteredSystem();
    // Other stuff goes 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 »

Ahruman wrote:
Yes. For this reason, every function should be declared as a method of the script object (i.e., this.Foo = function()…), even if it’s not a method that’s called by Oolite. It may be possible to subvert the JS runtime to avoid this problem.
I did read this to late and found it out the hard way. I declared in two scripts the function setUpShips() and noticed one was not working. With unique names the problem was over. But I understand with this. it will become local to the script. Maybe very obvious for one that knows JS but not for me. So we need proper programmed examples as reference. Ill try to release my UPS script within a week so experts can comment on the used programming methods.
Post Reply