Author Topic: Creating a basic autoload script  (Read 623 times)

Offline Mario

  • Senior Software Developer
  • Administrator
  • Posts: 2186
  • Cookies: 1706
  • Life is life
Creating a basic autoload script
« on: August 12, 2012, 09:11:41 AM »
Intro

I promised almost 1.5 years ago to write a follow up article on Becoming a scripter 101. So finally here it is. To make sure you can understand this tutorial, make sure you understand these python basics. This article is aimed at beginner scripters with a basic understanding of Python and OOP.

BC Introduction

Now, let's go over some short general information about BCs engine and python. As you may or may not know BC uses now an ancient 1.52 python version. So get ready for some retro programming. Game engine it uses is called NetImmerse which in turn was written in C++. Both of these are connected using Simplified Wrapper and Interface Generator aka SWIG (for more info click here).

Bridge Commander was not always mod friendly, it allowed a great deal of modability but it had a lot of static indexes. Foundation changed this, it replaced static indexes with dynamic structures. That made the Foundation the most important piece of software ever written in Bridge Commander history. This is a fact we tend to forget a decade later.

Foundation Folder Structure

scripts\Custom\Autoload: This is the directory which Foundation uses to autoload scripts. This is where you put your Foundation compliant scripts which use the TriggerDef or SoundDef system.

   * SoundDef: These allow you to "inject" custom sounds in the Bridge Commander.            

   * TrigerDef: TriggerDef allows you to register your event handlers. Most of the time your requirement will be only to react to a certain event, while there are other types of scripts one can do. However we'll talk about that in another article.

scripts\Custom\Ships: Plainly and simply this is where your ShipDefs go and is used to "inject" new custom ships into the game. There will be times when you will want to add a new tech into the game, in these scenarios these techs will most likely be defined in a ship plugin file. However this is beyond the scope of this article and will be explained in another article.
   
Defining a TriggerDef

To define your TriggerDef you need to define a class structure which inherits Foundation.TriggerDef.
Code: [Select]
class MyTrigger(Foundation.TriggerDef):

Next we define the constructor and initialize the base class:
Code: [Select]
def __init__(self, name, eventKey, dict = {}):
Foundation.TriggerDef.__init__(self, name, eventKey, dict)

Next method is the __call__ method which causes class instances to become callables which means they can be called as functions.

A crude demonstration can be found below:
Code: [Select]
class notCallableClass:
        def __init__(self):
                pass
        def sayHello(self):
                print 'hello from non callable class'

t = notCallableClass()
t.sayHello()


class callableClass:
        def __init__(self):
                pass
        def __call__(self):
                print 'hello from callable class'

t = callableClass()
t()

This is also where our code goes to handle event calls. Now let's write the code:

Code: [Select]
def __call__(self, pObject, pEvent, dict = {}):
pShip = App.ShipClass_Cast(pEvent.GetDestination())
if pShip:
# do our magic here
pass
if pObject and pEvent:
pObject.CallNextHandler(pEvent)

In the end we need to initialize our class
Code: [Select]
MyTrigger('My trigger', App.ET_ENTERED_SET, dict = { 'modes': [ mode ] } )

First parameter is the name of your trigger, 2nd one is which event you want to handle and final is the MutatorDef.

To define MutatorDef you would use the following code:
Code: [Select]
mode = Foundation.MutatorDef("My Trigger")

You can attach your script to an external MutatorDef or define your own (which is highly recommended).

Full Code
So the in the end this is how our autoload script looks like:

Code: [Select]
import Foundation
import App

mode = Foundation.MutatorDef("My Trigger")

class MyTrigger(Foundation.TriggerDef):
        def __init__(self, name, eventKey, dict = {}):
                Foundation.TriggerDef.__init__(self, name, eventKey, dict)

        def __call__(self, pObject, pEvent, dict = {}):            
pShip = App.ShipClass_Cast(pEvent.GetDestination())
if pShip:
# do our magic here
pass
                if pObject and pEvent:
                        pObject.CallNextHandler(pEvent)

MyTrigger('My trigger', App.ET_ENTERED_SET, dict = { 'modes': [ mode ] } )

Conclusion

This is a very basic article in which I tried to simplify much of the technical terms and it tries to explain the steps needed to create a basic autoload script. There are modules out there such as QBAutostart which allow you to bypass the following procedure, but there will be times when you will not want to utilize QBAutostart.

Not bad for a quickly written article, eh? Anyway, there will probably be questions so please post them here.
Acta, non verba.
aka USS Sovereign