amending ship scripts

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

Moderators: winston, another_commander

Post Reply
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:

amending ship scripts

Post 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

Code: Select all

{
     more code
     ...
}
without replacing and therefore deleting

Code: Select all

{
     some code
     ...
}
:?:
User avatar
Thargoid
Thargoid
Thargoid
Posts: 5528
Joined: Thu Jun 12, 2008 6:55 pm

Post 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.
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 »

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.
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
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 »

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(); :lol:
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 »

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.
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:

Post 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.
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:

Post 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();
    }
}
?
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 »

Nope! :P

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! ;)
Hey, free OXPs: farsun v1.05 & tty v0.5! :0)
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:

Post 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. :shock: 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. :roll:
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 »

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. :-)
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:

Post 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.
Post Reply