Hey all,
This is a technical post, but it's a milestone for UoN and I wanted to share.
One of the most difficult to implement features of a complex game is a modding API, the ability to inject custom code into the game. The reason it is difficult is because the game has to be structured to suit code injection, the ability to use code that was not written as part of the game. Luckily I planned for a modding API from the start, but I still had a lot of work to do to actually implement it.
I added the ability to use custom assets (textures, models, UIs), and config files (for entities in the game, spaceships, equipment) into the game last year, but put off the modding API until recently. Thankfully that work is now complete, UoN now has a full modding API where all of the systems in the game are accessible to, and can use, custom code.
Here is an example of code from the base mod (UNION uses a base mod for all of the game's content). This is the main spaceship process, which manages Heat and Instability. This file is saved as a .CS file in the mod folder.
using System;
using UON.Common;
using UON.ModdingAPI;
namespace UON.BaseMod
{
public class StandardSpaceshipExtension : ISpaceshipExtension
{
private float m_nextUpdatePassiveHeatTime;
private ISpaceshipComponent m_spaceshipComponent;
private IEquipmentComponent m_equipmentComponent;
public void OnServerEntityUpdate(float deltaTime, IKotarEntity entity)
{
m_spaceshipComponent = entity.GetComponent<SpaceshipComponent>(ComponentIds.Spaceship);
m_equipmentComponent = entity.GetComponent<EquipmentComponent>(ComponentIds.Equipment);
for (byte systemIndex = 0; systemIndex < m_spaceshipComponent.Template.Systems.Count; systemIndex++)
{
float actualPassiveHeatLevel = 0.0f;
if (m_equipmentComponent[systemIndex].OperatingPowerLevel >= m_equipmentComponent[systemIndex].Template.Class.MinOperatingPower)
{
actualPassiveHeatLevel = m_equipmentComponent[systemIndex].OperatingPowerLevel * m_equipmentComponent[systemIndex].Template.PassiveHeatCoefficient;
}
if (actualPassiveHeatLevel == 0.0f)
{
m_equipmentComponent[systemIndex].PassiveOperatingHeat = actualPassiveHeatLevel;
}
else if (UONGame.Instance.PlayTime.TotalTime.TotalSeconds > m_nextUpdatePassiveHeatTime)
{
m_equipmentComponent[systemIndex].PassiveOperatingHeat = actualPassiveHeatLevel + (((float)UONGame.Instance.Random.NextDouble() * 20.0f) - 10.0f);
}
if (m_equipmentComponent[systemIndex].Heat > m_equipmentComponent[systemIndex].PassiveOperatingHeat)
{
float excessHeat = m_equipmentComponent[systemIndex].Heat - m_equipmentComponent[systemIndex].Template.HeatsinkCapacity;
if (excessHeat > 0.0f)
{
m_equipmentComponent[systemIndex].Instability += (excessHeat * m_equipmentComponent[systemIndex].Template.OverheatToInstabilityRate);
m_equipmentComponent[systemIndex].Heat -= excessHeat;
}
m_equipmentComponent[systemIndex].Heat -= ((m_equipmentComponent[systemIndex].Template.HeatDissipationAmountPerSecond * 0.5f) + (m_equipmentComponent[systemIndex].Template.HeatDissipationAmountPerSecond * 0.5f * (m_equipmentComponent[systemIndex].PercentageIntegrity / 100))) * deltaTime;
}
if (m_equipmentComponent[systemIndex].Heat < m_equipmentComponent[systemIndex].PassiveOperatingHeat)
{
m_equipmentComponent[systemIndex].Heat = Math.Min(m_equipmentComponent[systemIndex].Heat + (4.0f * deltaTime), m_equipmentComponent[systemIndex].PassiveOperatingHeat); // Add heat up to the current PassiveOperatingHeat, 4.0f is just a sample number
}
if (UONGame.Instance.PlayTime.TotalTime.TotalSeconds > m_nextUpdatePassiveHeatTime)
{
m_nextUpdatePassiveHeatTime = (float)UONGame.Instance.PlayTime.TotalTime.TotalSeconds + 0.75f + ((float)UONGame.Instance.Random.NextDouble() * 0.75f);
}
}
}
}
}
To use this code, all that is required is setting the class name
StandardSpaceshipExtension in the
SpaceshipExtensionCodePath entry on the spaceship config file:
/* UNION Spaceship Template v0.01a */
{
"Key": "Albatross",
"IsEnabled": true,
"Data": {
"TypeKey": "Spaceship",
"FactionKey": "UNION",
"IsPlayerSelectable": true,
"ClassType": "Frigate",
"EntityPath": "UNIONBase/Entity/Albatross",
"SpaceshipExtensionCodePath": "UNIONBase/Code/StandardSpaceshipExtension"
}
}
Now that the modding API has been completed I will, over time, be moving a lot of code out of the compiled game and into the base mod. Anyone can then modify the code and put it into their own mods.
Thanks for reading!
Mark