Not a member yet? Why not Sign up today
Create an account  

  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Guide to mod the vehicles (plugins only)

Until now, it was only possible to mod the items and blocks.
Now it's also possible to mod the vehicles themselves.

Some background before we begin:
Each construct is divided in a 'MainConstruct' and possibly some 'SubConstruct' (on the turrets, SpinBlocks and pistons).
The 'MainConstruct' and 'SubConstruct' classes inherit from 'AllConstruct'.
There are behaviours that are attached to the constructs (either 'MainConstruct' or 'AllConstruct', they are called 'Modules'.

How to add modules?
It is now possible to add modules, or even replace existing modules.
In order to add a new module, you need to inherit from 'MainConstructModule' or 'AllConstructModule' (depending if you want to add it to the 'MainConstruct' or the 'AllConstruct').
You also need to add the '[ConstructModule]' attribute to your class.

How to replace existing modules?
If a module name (the name of its class) is the same than an existing module, then it will replace the original one.
Be careful when replacing a module as they need to either implement a specific interface or to inherit from the original module.
Currently, this is an experimental feature, so it's not yet possible to replace everything.
The goal would be to have only interfaces, or to add a lot of 'virtual' and 'protected', but for now it's not completely done.
Also, it may be possible that at some place in the code an interface is cast back to the original type of the module, which will cause a casting exception if the module has been replaced, we can fix it if we're told about the specific problem.

How to get a module?
In order to get a module, just use:
Where 'T' is the type of the module.

The modules list:
Rather than having an incomplete list here, I think it's better to tell you to use ILSpy (or an equivalent).
All the replaceable modules have the 'ConstructModuleAttribute' attribute, ILSpy will provide you the list.
In the 'AllConstruct' and 'MainConstruct' constructors you'll find them affected to some internal variables (for fast access).
The type of these variables will indicate you what interface you must implement or if you have to inherit from a specific class.

How does the modules work?
The modules are created automatically when a new vehicle (or fortress or structure or SubConstruct) is constructed.
The '_construct' field contains the associated 'Construct' or 'MainConstruct'.
In the case of a MainConstruct, the methods of the 'AllConstruct' modules will be called just before the ones of the modules of the 'MainConstruct' (because of the inheritance).
The initialization sequence is:
- Constructor (not that the constructor must take the Construct or MainConstruct as a parameter)
- LinkUpExternallyPriorToBlocksInitialising()
- LinkUpExternallyAfterBlocksInitialising()

- BlockAdded() Called when a block is added
- BlockRemoved() Called when a block is removed

- CleanUpOnDestroy() Called when the associated construct is destroyed

MainConstruct modules only:
- EverythingLinkedUp() When the blueprint is fully loaded
- AfterEverythingLinkedUp() When the blueprint is fully loaded (when all the modules have executed 'EverythingLinkedUp()')

The usual way to use the modules is to do their initialization in 'LinkUpExternallyPriorToBlocksInitialising()' and/or 'LinkUpExternallyAfterBlocksInitialising()' depending on the specific needs.
It is also very useful to add some calls to the 'Scheduler' in order to execute some code at some given intervals.

Here is an example of the replacement of the resource module:
using System;

using BrilliantSkies.FromTheDepths.Planets;

/// <summary>
/// Resources optimization
/// </summary>
class MainConstructResourceStorage : MainConstructModule, IConstructResourceStorage
    /// <summary>The materials</summary>
    public ConsumablesModule Material { get { return m_Material; } }
    private ConsumablesModule m_Material = null;

    /// <summary>The cached resources store</summary>
    private ResourceStoreAbstract m_ResourceStore = null;

    /// <summary>
    /// Standard constructor
    /// </summary>
    /// <param name="C">The MainConstruct</param>
    public MainConstructResourceStorage(MainConstruct C) : base(C)
        m_Material = new ConsumablesModule();
        Material.LP = new Vector3i(-1000, -1000, 1);

    /// <summary>
    /// Called just before the intitialization of the blocks
    /// </summary>
    public override void LinkUpExternallyPriorToBlocksInitialising()
        m_ResourceStore = new MainConstructResourceWrapper(_construct.GetTeam());

    /// <summary>
    /// Get the resources relative to the current storage
    /// </summary>
    /// <param name="forceLocal">Indicates if it will be a local resource despite the current mode</param>
    /// <returns>The resources</returns>
    public IResourceStore GetResourceStore(Boolean forceLocal=false)
        ResourceStoreAbstract resourceStore;

        if (InstanceSpecification.i.Header.CommonSettings.LocalisedResourceMode == LocalisedResourceMode.UseCentralStore && !forceLocal)
            resourceStore = ResourceManager.GetResourceStore(_construct.GetTeam());
            resourceStore.iAmmo = _construct.iAmmo.Ammo;
            resourceStore.iFuel = _construct.iPowerUsageCreationAndFuel.Fuel;
            resourceStore.iEnergy = _construct.iPowerUsageCreationAndFuel.Energy;
            resourceStore = m_ResourceStore;
            resourceStore.TeamId = _construct.GetTeam();
            resourceStore.iMaterial = Material;
            resourceStore.iAmmo = _construct.iAmmo.Ammo;
            resourceStore.iFuel = _construct.iPowerUsageCreationAndFuel.Fuel;
            resourceStore.iEnergy = _construct.iPowerUsageCreationAndFuel.Energy;

        return resourceStore;

Forum Jump:

Users browsing this thread:
1 Guest(s)