Author Topic: Customizing ship plugins for NanoFXv2Beta features  (Read 2083 times)

Offline MLeo

  • Retired Staff
  • Posts: 3636
  • Cookies: 833
  • Software Simian
    • the Programming Pantheon
Customizing ship plugins for NanoFXv2Beta features
« on: April 17, 2008, 07:19:52 PM »
A little rundown on the customization features of NanoFXv2Beta.
Most of these are based on the ship plugin (so the files in scripts/Custom/Ships) and you will need to add things to the ship "instance" (usually the part before the = Foundation.<<Something>>ShipDef(.......)), there are a couple of built in predefines, but they can be override on a per ship or a per "race" basis. I'll cover both.

I'll use this simple ship plugin as an example:
Code: [Select]
import Foundation

Foundation.ShipDef.TestBedShip = Foundation.DominionShipDef("squater", SQUATER_SPECIES, {extra stuff})

I suppose it's a good idea to enumerate all possible things we can change on a per ship (or on a per "race" basis):
  • Explosion colour;
  • Plasma colour;
  • Warp Flash colour;
  • Weapon Flash colour (projectile only);
  • Warp entry sound (race only);
  • Warp exit sound (race only).

The only 3 odd ones are the weapon flash, and the 2 sounds. So we'll handle those at the end. The weapon flash (when a projectile is fired) is by default white.

Back to our example:
Out of the box this will produce the following results, all colours are in rgb format:
Explosion, plasma and warp flash colours are all 182.0, 0.0, 201.0.
The sound named DominionEntryWarp is played on entering warp, and the aptly named DominionExitWarp on exiting warp.


Now, how did I derive at these values?

The entry and exit sound is a naming convention used by NanoFX, the race name + EnterWarp and the race name + ExitWarp if no sound is found with that name (remember the sound packs) then no sound is played.

As for the colours, here is the race lookup table:
Code: [Select]
"Federation" : ( 55.0, 120.0, 255.0)
"Klingon"    : (255.0,  20.0,   0.0)
"Romulan"    : (  0.0, 248.0, 130.0)
"Cardassian" : (255.0, 200.0,   0.0)
"Ferengi"    : (255.0, 180.0,   0.0)
"Kessok"     : (182.0,   0.0, 201.0)
"Dominion"   : (182.0,   0.0, 201.0)
"Borg"       : (  0.0, 248.0, 150.0)
If the race used isn't found (remember this when you read about ShipDef in little bit below), and no override is provided then the default colour is used, being: (155.0, 120.0, 255.0).

Now, I mentioned ship specific overrides.
They are added through adding functions to the ship instance (I'll also cover adding them to multiple ships at the same time).

All functions are like this:
Code: [Select]
def FunctionName(self):
    return (<r>, <g>, <b>)
Where r, g, and b are values between 0 and 1, all 0 is black, all 1 is white.
A way to convert a 255 based value is through this:
<value>/255.0 and placing that at each r, g and b, for example:
Code: [Select]
128.0/255.0, 0.0, 255/255.0That produces a purplish colour, more blue than red.

To add this function to the ship instance, you do this after you created the function (did you remember the important part I mentioned at the beginning?):
Code: [Select]
Foundation.ShipDef.TestBedShip.FunctionName = FunctionName
Resulting in this total example code:
Code: [Select]
import Foundation

Foundation.ShipDef.TestBedShip = Foundation.DominionShipDef("squater", SQUATER_SPECIES, {extra stuff})

def FunctionName(self):
    return (0.5, 0, 255.0/255.0)
Foundation.ShipDef.TestBedShip.FunctionName = FunctionName

Now, both order of the lines and all the capitalization is important.
a does not match A. So apples does not match Apples nor aPpLeS.

Why is the order important?
The first line only depends on Python (the environment) to function properly.
The second line depends on the first line because it introduces the Foundation "name" to the file.
The third line doesn't depend on anything, and could be placed randomly anywhere before this point.
The fourth line depends on both the second line and the third line (and in effect the first line), and must be placed after all those lines to function.


Now, there are a couple naming conventions (otherwise, how does NanoFX know what to call?).
They are these:
For the explosion colour:
OverrideExpFXColor
For Warp flash colour:
OverrideWarpFXColor
And for the plasma colour:
OverridePlasmaFXColor

With these functions you can customize each aspect on a per ship basis. Just replace the FunctionName with one of the above.

Say, considering this aw-god of powerfull Squater ship class, would use a yellow warp flash, and a deep red plasma colour, what would I have to do?
This is the result:
Code: [Select]
import Foundation

Foundation.ShipDef.TestBedShip = Foundation.DominionShipDef("squater", SQUATER_SPECIES, {extra stuff})

def OverrideWarpFXColor(self):
    return (1.0, 1.0, 0.0)
Foundation.ShipDef.TestBedShip.OverrideWarpFXColor = OverrideWarpFXColor

def OverridePlasmaFXColor(self):
    return (0.64, 0.0, 0.0)
Foundation.ShipDef.TestBedShip.OverridePlasmaFXColor = OverridePlasmaFXColor


Now, how does NanoFX match race to ship?
Through the class that creates the ship instance.
In this case we used the predefined (by Foundation, not NanoFX, unless you are using a pre Foundation version of Foundation, then you have these installed) ShipDef "class" called DominionShipDef, which is, of course, for dominion ships.
This is the list of all the ShipDef classes (minus stations, but they also have some stuff) and there related races:
FedShipDef -> Federation
 GalaxyDef -> Federation
 SovereignDef -> Federation
CardShipDef -> Cardassian
RomulanShipDef -> Romulan
KlingonShipDef -> Klingon
KessokShipDef -> Kessok
FerengiShipDef -> Ferengi
DominionShipDef -> Dominion
BorgShipDef -> Borg

But that still doesn't tell us how it maps this, since, for example, we also have GalaxyDef and SovereignDef.
What ShipDefs are actually used for by Foundation is mainly for AI (yes, you can have your custom AI loaded through this) and sounds (actually for Enemy Akira Destroyed and such, so yes, you can have your own sound, it just won't sound as good).
What it also holds, is a reference to a "race" instance.

These are all the races predined:
Federation
Cardassian
Klingon
Romulan
Ferengi
Kessok
Dominion
Breen
Borg

You may notice the Breen here, that's right, there isn't a predefined BreenShipDef, and there isn't a default entry in that table.
But we would really like an uniform Breen feel among all the breen ships in our mod, and we don't like copy'n'pasting because it defeats the DRY principle.
Now, how do we do this without breaking anything?

Well, create a new file, and put it in scripts/Custom/Ships called BreenDef.py
This has a reason, as it is now, when mods are first loaded, the scripts/Custom/Ships is first loaded, and then scripts/Custom/Autoload this means we can't add our new ShipDef to Autoload, which would have been prefered, anyway.

In this file we first put import Foundation in it on the first line.

Then, we do the following:
Code: [Select]
class BreenShipDef(Foundation.ShipDef):
    def __init__(self, abbrev, species, dict):
        dict['race'] = Foundation.Breen
        Foundation.ShipDef.__init__(self, abbrev, species, dict)

Resulting in this:
Code: [Select]
import Foundation

class BreenShipDef(Foundation.ShipDef):
    def __init__(self, abbrev, species, dict):
        dict['race'] = Foundation.Breen
        Foundation.ShipDef.__init__(self, abbrev, species, dict)

Now, in each Breen ship we have to do the following (put this after the import Foundation line):
Code: [Select]
from Custom.Ships.BreenDef import BreenShipDef
Afterwards you create your ship instance with:
Code: [Select]
Foundation.ShipDef.YourBreenShip = BreenShipDef("YourBreenShip", BREEN_SHIP_SPECIES, {extra stuff})
Running this gives you a ship with no warp sounds (you just have to create a sound pack for this, but that's a topic for another day, and one covered in the modding forum a couple of times) and the default colours.
So, how to change this?
Well, we could add it to each ship individually, but why did we create the BreenShipDef then for?

The reason is this, we can add it to that.

Say, something like this:

Code: [Select]
import Foundation

class BreenShipDef(Foundation.ShipDef):
    def __init__(self, abbrev, species, dict):
        dict['race'] = Foundation.Breen
        Foundation.ShipDef.__init__(self, abbrev, species, dict)

    def OverrideExpFXColor(self):
        return (0, 1.0, 0)
Resulting in a green explosion.

As you can see, indentation is really important, try to keep it consistent!
The extra function, OverrideExpFXColor, uses the same naming as in the previous examples, so those other names also work.

In fact, (you may skip this if you aren't interrested in programming,) what this results in is in a way the same thing that we did before. This simply "pre"-adds it to our ship instance. Another nice thing with this, is that you can base your new ShipDef on an existing race and still expand on it.

One note of caution, you _have_ to include this file with every mod using this, otherwise you get a nice black screen with a yellow cursor when you try to start BC.

You might also be interrested in creating your own race (for the warp sounds).
This is done by (I'll use the breen example, as if there was no breen race defined) doing the following (I'll put it in the same file as above):
Code: [Select]
import Foundation# You only need this once per file

Then you can use it like this:
Code: [Select]
import Foundation
MyBreen = Foundation.RaceDef("Breen", "BRN")

class BreenShipDef(Foundation.ShipDef):
    def __init__(self, abbrev, species, dict):
        dict['race'] = MyBreen
        Foundation.ShipDef.__init__(self, abbrev, species, dict)

    def OverrideExpFXColor(self):
        return (0, 1.0, 0)

This will cause it to look for the BreenEnterWarp and BreenExitWarp.


About Weapon flashes:
These are determined per projectile, you basicly add a function to your projectile file with no arguments (example follows) that returns a colour (in the same format as in previous examples) called GetFlashColor


I hope I didn't miss anything, but if I did, let me know and I'll see if I can add it.

Now, lets see some changed ships out there!
I still can't read peoples minds, nor can I read peoples computers, even worse, I can't combine the two to read what is going wrong with your BC install...

"It was filed under 'B' for blackmail." - Morse, Inspector Morse - The dead of Jericho.