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

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, Little Bear,

LB wants to do a check if the player had shot a mission ship. Best thing is to do that in the death_actions. With legacy script is is not possible, but in JS you can come close I think. It is worth to write this good as many other scripters, now and in the future, want to have a script that showed if it really was the player that shot the ship. If there is a working script, others could just copy it into their own source. I tried something below but really do not know if it can work. But better is even to test if the player was near and the victim was the primary target. Even better would be a check if it was the player that made the fatal shot, but that would need adding an additional check in the source-code as I think it is not stored at the moment.

Code: Select all

this.name           = "player_near_script";
this.author         = "Eric Walch";
this.copyright      = "Jan2008";
this.description    = "Untested";
this.version        = "1.00";

this.shipDied = function()
{
    this.ship.call("scanForNearestShipWithPrimaryRole:", "Player")
    if(found_target == player)
  {
   //your stuff:
   // e.g.
   //missionVariables.player_is_near = "YES"
  }
else
  {
   //your stuff 2:
   // e.g.
   //missionVariables.player_is_near = "NO"
  }
}
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, having anticipated this need, I have imbued the shipDied handler with useful parameters:

Code: Select all

this.shipDied = function(whom, why)
{
    Log("Ship was killed by " + whom + " by means of " + why)
    if (whom == player)
    {
        // player-killed-me stuff
    }
}
Currently, why can be one of the following: "energy damage", "scrape damage", "heat damage". whom should generally be useful (for instance, if a missile is the immediate cause, whom will be the ship that fired the missile, not the missile itself).
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 »

Svengali wrote:
Ok. Forget my last posts about the function lib.
Ahruman wrote:
...to trick the JS library into putting global declarations into the current script object...
After reading some more docs this was the result (without using literals). Would this work after lowering the top-level?
No, it would still be necessary to do something like worldScripts["BBFL"].BBFL_Math, since BBFL_Math would be a property of the BBFL script object.

[/code]Ahruman, you have suggested to use a suffix (_v1, _v2,...). I like this idea to be backward compatible, but is this really necessary. There is already a this.version = "1.00". So maybe a check for the correct version could (and should) be realised.[/quote]

Only one script with a given name can be found. After scripts are loaded, if more than one has a certain name, only one will remain “in play”. (As it is, it will be the last one loaded; a version check here would probably be good.) Imagine the player had OXPs with two different versions (call them 1 and 2) of your library. If version 1 was loaded after version 2 and they had the same name, anything trying to use version 2 would break. If they had different names, there wouldn't be a problem; scripts using version 1 wouldn’t care if they’re using a “full” implementation or the “transcluded” implementation as per my example.

This would be less of an issue if script name conflicts were resolved with respect to version numbers, but they currently aren’t and I can’t guarantee that they will be in future (there may be complications, I’m not sure offhand).
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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 »

Dumb question I know, but I'm trying to add a Java Script to set who killed a ship. I'm getting:-

Code: Select all

2008-01-11 19:26:56.312 oolite.exe[616] [script.javaScript.load.failed]: ***** Error loading JavaScript script AddOns/RandomHits239.oxp/Scripts/random_hits_mark_hit.js -- compilation failed
What I did was Open one of the native Java Scripts with notepad. Delete all the text from it. and C&P in my script.

Code: Select all

this.shipDied = function(whom)
{
    if (whom == player)
    {
    player.awardCargo("Gold", 90)    // killer is player
    }
    else
    {
    player.awardCargo("Gold", 45)    // killer is NPC
    }
}
(The differing cargo awards is just a test to quickly see if my script isn't messed up).

The script is in a Scripts folder and is set as the ship's script in shipdata. The problem is I'm obviously messing the file up by saving it in notepad. How do I make the Java Script file?
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 »

LB,

I have similar problems. First make sure you are having plain text. When I copy and past code from this forum, it becomes formatted text in my texteditor and won't load at all. I have to convert it first to "plain text". Apples texteditor has a menu function for that. Than the "this.name" line is mandatory. But better include al four entry lines. I wanted a similar function in UPS so I wrote next code:


Code: Select all

this.name		= "ups_boa_killed";
this.author		= "eric walch";
this.copyright		= "© 2007 the Oolite team.";
this.version		= "1.00";

this.shipDied = function(whom) 
{ 
    if (whom == player) 
    { 
       missionVariables.ups_closecontact = "YES"; 
    };
    consolemessage("I'll be back with help for revenge!!", 4.5);
    system.legacy_spawn("ups-container", 5);
    system.legacy_spawn("textilepod", 15);
    missionVariables.ups_container = "FOUND"
}
But this gives the error:

Code: Select all

 ***** JavaScript exception: SyntaxError: missing ; before statement
/Applications/Games/Oolite/AddOns/UPS-courier v1.2.2.oxp/Scripts/UPSBoaKilled.js, line 8: Ê Ê if (whom == player) 
I don't see the bug. When I leave:

Code: Select all

    if (whom == player) 
    { 
       missionVariables.ups_closecontact = "YES"; 
    };
out, it compiles OK.

But i don't see a syntax difference with the working code from within Oolite itself:

Code: Select all

	this.otherShipDocked = function(docker)
	{
		if (docker == player)
		{
			this.ship.runLegacyScriptActions(docker, this.legacy_scriptActions);
		}
	}
I think there must first be much more working code as reference material before anyone else that real programmers can make a working script.
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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 »

Ok I'll type it in rather than using any C&Ping and add the this.name etc.

A's code example has it as:-

Code: Select all

this.shipDied = function(whom, why)
So i'll try it with the why, even though I'm not doing anything dependent of the why.
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
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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 »

Trying this:-

Code: Select all

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

this.shipDied = function(whom, why)
{

Log("Random Hits Target Ship was killed by " + whom + " by means of " + why)
if (whom == player)
{
player.awardCargo("Gold", 90) // Killer was the player
}
else
{
player.awardCargo("Gold", 45) // Killer was an NPC
}

}
Oolite is reading the script but is comming up with:-

Code: Select all

2008-01-12 12:32:31.156 oolite.exe[3200] [script.javaScript.exception.144]: ***** JavaScript exception: SyntaxError: illegal character
2008-01-12 12:32:31.156 oolite.exe[3200] [script.javaScript.exception.144]:       AddOns/RandomHits241.oxp/Scripts/oolite-random-hits-killer.js, line 19: }
2008-01-12 12:32:31.156 oolite.exe[3200] [script.javaScript.load.failed]: ***** Error loading JavaScript script AddOns/RandomHits241.oxp/Scripts/oolite-random-hits-killer.js -- compilation failed
I typed it all in (no C&Ping). Its objecting to the last }. But that is the same character as the } further up! Arggh! :shock: [/code]
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
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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 »

Later:-

Got me a free JavaScript Editor from here:- http://www.freedownloadmanager.org/down ... p/free.htm

Typed the above in here and saved it. This time Oolite read the file. :)

Went and lasered the ship. And was awarded 45kg of gold. Although I did it the script seems to have acted on the else command. BTW where does the Log thing go. looked in stderr but nothing there. Stuck!
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: 6572
Joined: Wed Feb 28, 2007 7:54 am

Post by another_commander »

LB, try the LogWithClass instead of Log:

Code: Select all

LogWithClass("jstest.died", "Killed by " + whom + " by means of " + why);
This, I know for a fact, goes in your stderr.txt.
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 »

Now I have a script without error messages.:

Code: Select all

this.name		= "ups_boa_killed";
this.author		= "eric walch";
this.copyright		= "© 2008 the Oolite team.";
this.version		= "1.00";

this.shipDied = function(whom) 
{ 
//    if (whom == player) 
//    { 
//       missionVariables.ups_closecontact = "YES" 
//    }
    player.commsMessage("I'll be back with help for revenge!!", 6);
    system.legacy_spawn("ups-container", 5);
    system.legacy_spawn("textilepod", 15);
    missionVariables.ups_container_count = "0"
    missionVariables.ups_container = "FOUND";
    if (player.isCloaked) 
    { 
        system.legacy_spawn("ups-container", 5);
        player.commsMessage("Cloaking is cheating", 6)
    }
}
But it still is not working. The commented out part gives the error message mentioned in my last message. The commsMessage is not working. With "commsMessage", "consoleMessage", "player.commsMessage" nothing happens and with "player.consoleMessage" I get the error "***** JavaScript exception: ReferenceError: player is not defined"

The cloaked part is not giving errors, but also is doing nothing at all. Only thing is working are the two spawning commands and the setting of mission variables.

I for now will give up further trying until there is decent documentation on the functions. How works commsMessage and so on.
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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 »

Are you at least getting your items spawned? Mine seems to think an NPC did it when I killed him! Will try the log with class.

OK Log with Class worked by is showing:-

Code: Select all

2008-01-12 14:18:06.796 oolite.exe[1480] [js.test.died]: Killed by undefined by means of undefined
Which would explain why the script has acted on the else. Is whom broken?

This is the whole script:-

Code: Select all

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

this.shipDied = function(whom, why)
{
	LogWithClass("js.test.died", "Killed by " + whom + " by means of " + why);
	if (whom == player)
	{
		player.awardCargo("Gold", 90) // Killer was the player
	}
	else
	{
		player.awardCargo("Gold", 45) // Killer was an NPC
	}
	
}
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 »

Yes, spawning works, and setting of variables. But anything else: nop.

I copied your stuff over mine and edited it back to my original stuff. Now the error about missing ";" is gone and I get:
***** JavaScript exception: ReferenceError: player is not defined

When I use the log line I get:
***** JavaScript exception: ReferenceError: Log is not defined

When I use LogWithClass I get:
: ***** JavaScript exception: ReferenceError: LogWithClass is not defined

??? How can one program when even the example files don't work.
User avatar
LittleBear
---- E L I T E ----
---- E L I T E ----
Posts: 2868
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'm not getting any complaints from Oolite on the script. Scooping works AND detects who did it. The shipDied works and sets the death_actions but, just it doesn't detect who did it. It always goes for the else state as wether on a player or npc kill "whom" stays undefined.

Expanded it and added this:-

Code: Select all

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

this.shipDied = function(whom, why)
{
	LogWithClass("js.test.died", "Killed by " + whom + " by means of " + why);
	if (whom == player)
	{
		missionVariables.random_hits_status = "KILLED" // Killer was the player
	}
	else
	{
		missionVariables.random_hits_status = "NPCKILLED" // Killer was an NPC
	}
	
}

this.shipWasScooped = function(scooper)
{
	LogWithClass("js.test.scooped", "Scooped by " + scooper);
	if (scooper == player)
	{
		missionVariables.random_hits_status = "SCOOPING"  // Scooper was the player
	}
	else
	{
		missionVariables.random_hits_status = "NPCSCOOPING" // Scooper was an NPC
	}
	
}
My old style legacy script is acting on the setting of the variables and giving a console message "You have captured XXX YYY" if I got him or "XXX YYY has been captured and boiled alive by fierce felines" (or whatever randomly generated fate he/she befell) if an NPC scooped him. (I'm spawning a pod with the script attached with 5 scavengers within 5km). The log is confirming for the scooping with:-

Code: Select all

2008-01-12 17:10:20.062 oolite.exe[828] [js.test.scooped]: Scooped by [Player "Naval Imperial Courier" ID: 100 position: (-10745.5, 810.545, 22216.8) scanClass: CLASS_PLAYER status: STATUS_IN_FLIGHT]
This is still very handy as I can ditch all the fiddly playernear / playerfired / npcfired variable setting in AI for the pods. If it could tell the difference between a player / npc kill in the same way I could replace the entire AI checks with this two command Java. It is working and setting the death actions but either "whom" is broken or its not the right word!
[/code]
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 »

LittleBear wrote:
It is working and setting the death actions but either "whom" is broken or its not the right word!
Or maybe it never worked or was not tested. It is a copy of the eventhandler: didBecomeDead. From the wiki, eventhandlers page:

Code: Select all

this.didBecomeDead = function(whom, why)
{
     // Your code here
}
This was mend for a dying player and maybe only tested for that case.

But I am pleased at least the second part is working. The first part must be a small problem.

EDIT:
Even stranger: I just removed the comment from the logWithClass and this time no error in the log but:

Code: Select all

Oolite [js.test.died] GlobalLogWithClass (OOJSGlobal.m:174): Killed by undefined by means of undefined
This means that the has read the JS script. But my ship ejected an Q-bomb and died that way. The stange part is that he yelled a commsMessage that only was present in the death_actions and not in the JS script. And with a JS script, the death_actions should be disregarded. It did so with my previous tries.

EDIT2:
Without quitting Oolite I did spawn a second ship and killed it. This time a new line in the log, just after that of the previous ship:

Code: Select all

Oolite [js.test.died] GlobalLogWithClass (OOJSGlobal.m:174): Killed by undefined by means of undefined
Oolite [script.javaScript.exception.1] ReportJSError (OOJavaScriptEngine.m:112): ***** JavaScript exception: ReferenceError: LogWithClass is not defined
Why it recognised the command one time and without quitting or changing something it reacted different the second time?

Only thing could be that there is a problem with like_ship. I only attached the SJ to to the original as I also did with the legacy scripts.
EDIT3:
Attached the JS to all 4 "like_ships". Spawned two ships near the station. This time killing the first gave an error in the log and killing the second gave the js log, but at the same time I say the commsMessage from the legacy death_actions. ??

Code: Select all

Oolite [script.javaScript.exception.1] ReportJSError (OOJavaScriptEngine.m:112): ***** JavaScript exception: ReferenceError: LogWithClass is not defined
Oolite [script.javaScript.exception.1] ReportJSError (OOJavaScriptEngine.m:121):       /Applications/Games/Oolite/AddOns/UPS-courier v1.2.2.oxp/Scripts/UPSBoaKilled.js, line 8.
Oolite [js.test.died] GlobalLogWithClass (OOJSGlobal.m:174): Killed by undefined by means of undefined
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, it is also working for me now.

There is some bug in the scripting that the script of the second ship that is spawned gets mingled. And yesterday with testing it was always my mission script that spawned the first ship at a random location, after witch I spawned a second ship near the station with "debugMenu". Only when I gave up, went to an other system were the first missionship was not spawned and my test ship was the first, things start working. Today I repeated it. It is always the second ship that was spawned that gives errors in the script when killed, even when it is killed as first.

Whom is still unknown, but what now also is working are the next lines.

Code: Select all

    if (player.isCloaked) 
    { 
        player.commsMessage("Cloaking is cheating", 6)
    }
This is something you probably also want to know: "Is the player cloaked at the moment of killing".

My statement of yesterday that both parts of JS and the death_actions were executed was wrong. It appeared that at the end I removed a comment symbol in JS so that the on screen message was issued by the JS script and it was not unique present in the death_actions as I thought.
Post Reply