Page 1 of 1
amending ship scripts
Posted: Thu Nov 19, 2009 11:50 am
by Commander McLane
Is it possible to
amend a ship script on the fly rather than
replace it?
More specifically: If a ship has already let's say
Code: Select all
this.shipBeingAttacked = function()
{
some code
...
}
in its script, can I somehow add
without replacing and therefore deleting
Posted: Thu Nov 19, 2009 11:55 am
by Thargoid
It sounds like a risky thing to do, unless you know exactly what each of the code sections are going to do. One may for example perform a return, or send the script to a different function, at which point the subsequent code would get ignored completely.
But if it were me I would probably copy the existing function into a new one (<scriptname>.shipBeingAttacked = <scriptname>.originalShipBeingAttacked or somesuch), add your code as newShipBeingAttacked and then replace the original function with one that simply calls the two new functions in turn.
Posted: Thu Nov 19, 2009 12:08 pm
by Kaks
This should more or less do what you asked:
Code: Select all
P.target.script.originalAttacked = P.target.script.beingAttacked;
P.target.script.beingAttacked = function(){
new stuff
this.originalAttacked();
more new stuff
};
I'd check both name and version of the particular ship script to get some idea of what was inside the original beingAttacked() function.
Of course, name & version could be lies: as a general software thing, changing version numbers tends to be forgotten when making changes to the actual code.
Posted: Thu Nov 19, 2009 2:47 pm
by Eric Walch
That should work. But to be completely at the save side I would not use
this.originalAttacked(); but
this.mcLaneAttacked();, (or any other unique name) just for the case there was another oxp that already had changed the script and also used the name
this.originalAttacked();
Posted: Thu Nov 19, 2009 3:29 pm
by JensAyton
You can actually do this (it’s often called monkey patching) without adding a new property to the target, thus removing the risk of name conflicts:
Code: Select all
this.patchTarget = function()
{
var originalAttacked = player.ship.target.beingAttacked;
player.ship.target.beingAttacked = function()
{
// Do stuff
originalAttacked();
}
}
Or, more generally:
Code: Select all
this.applyHeadPatch = function(target, property, patch)
{
var original = target[property];
target[property] = function()
{
// Depending on what you’re doing you might want to swap the order,
// in which case it’s a tail patch.
patch.apply(this, arguments);
original.apply(this, arguments);
}
}
...
this.patchTarget = function()
{
this.applyHeadPatch(player.target.script, "beingAttacked", function()
{
// Do stuff
});
}
Documentation:
Function.apply(),
arguments
Oh, and don’t use P as a shortcut for player in scripts! It’s only defined when the debug console is in use.
Posted: Fri Nov 20, 2009 7:13 am
by Commander McLane
Thanks all! Will try how it works. And if it seems that it may break things, I will of course not use it.
What I want is to simulate a requested-but-not-yet-existing shipHittingOther event handler for an NPC by inserting a script line into the ship script of the opponent, which will call the shipHittingOther function when it gets hit itself, therefore I need to access the shipBeingAttacked function in the opponent's script, without completely overwriting it.
Posted: Thu Nov 26, 2009 8:16 am
by Commander McLane
Ahruman wrote:You can actually do this (it’s often called monkey patching) without adding a new property to the target, thus removing the risk of name conflicts:
Code: Select all
this.patchTarget = function()
{
var originalAttacked = player.ship.target.beingAttacked;
player.ship.target.beingAttacked = function()
{
// Do stuff
originalAttacked();
}
}
Shouldn't that be
Code: Select all
this.patchTarget = function()
{
var originalAttacked = player.ship.target.beingAttacked;
player.ship.target.script.beingAttacked = function()
{
// Do stuff
originalAttacked();
}
}
?
Posted: Thu Nov 26, 2009 9:43 am
by Kaks
Nope!
It's actually more likely to work if it's
Code: Select all
this.patchTarget = function()
{
var originalAttacked = player.ship.target.script.beingAttacked;
player.ship.target.script.beingAttacked = function()
{
// Do stuff
if (originalAttacked) originalAttacked();
}
}
In the versions you & Ahruman wrote originalAttacked would always be
undefined, and - thinking about it - some ships' scripts might not have a .beingAttacked function to begin with!
Posted: Thu Nov 26, 2009 10:59 am
by Commander McLane
I had the problem with the undefined again, because I wanted to amend the world script shipWillDockWithStation from a ship script, when an escape pod was scooped. Of course originalShipWillDockWithStation was always undefined when I actually docked, because at this point the escape pod with the ship script had of course seized to exist.
So I had to define worldScripts.personalities.originalShipWillDockWithStation, and now it's working fine.
By the way: this is quite a complicated workaround for giving a ship two different specific escape pods, which both have to be spawned.
Posted: Thu Nov 26, 2009 1:59 pm
by JensAyton
Commander McLane wrote:I had the problem with the undefined again, because I wanted to amend the world script shipWillDockWithStation from a ship script, when an escape pod was scooped.
Wouldn’t it be easier to just have a world script check a condition and do what you need when it’s appropriate? You could then set a flag like:
Code: Select all
worldScripts["my-super-duper-script"].doInterestingStuff = true;
In general, patching should be your last resort, not your first. :-)
Posted: Thu Nov 26, 2009 2:33 pm
by Commander McLane
Generally I agree. But in this case a ship script of a personalities ship in set A has to access the world script, which will be shipped with the original OXP. While I of course could put it in the world script, I won't be able to do so with upcoming new sets of characters. I don't want to re-distribute the original OXP, because of a small change in its script.
But it will all stay in the family. I have no intention to amend something outside the personalities OXPs.