-
Notifications
You must be signed in to change notification settings - Fork 2
Usage instructions
- Using the framework in Galactic Conquest
- Using the framework with a game object script
- Creating a plugin definition
- Implementing a plugin object
- Using the events from the GalacticConquest object
- Defining a plugin with dependencies
A single story plot in a GC should be set as the container for the EawX Framework. A high ServiceRate
must be set (we use 0.1) in order to ensure that all plugins will receive updates at the correct time. Calling deepcore:galactic
will load plugins from the folder specified in the configuration table and return a plugin runner that is responsible for continuously updating your plugins. Additionally a context
table that can include variables you want to pass to every plugin init()
function and a list of plugin folders may be provided inside the configuration table. If no plugin folder list is given the plugin system will load the file InstalledPlugins.lua
from the specified plugin folder.
require("PGDebug")
require("PGStateMachine")
require("PGStoryMode")
require("deepcore/std/deepcore")
function Definitions()
DebugMessage("%s -- In Definitions", tostring(Script))
ServiceRate = 0.1
StoryModeEvents = {Universal_Story_Start = Begin_GC}
end
function Begin_GC(message)
if message == OnEnter then
-- The context table allows you to pass variables to
-- the init() function of your plugins
local context = {}
DeepCoreRunner = deepcore:galactic {
context = context,
plugin_folder = "eawx-plugins/galactic"
}
elseif message == OnUpdate then
DeepCoreRunner:update()
end
end
The framework isn't limited to Galactic Conquest. You can also use it from a game object script. Similar to galactic mode you can call deepcore:game_object()
with a configuration table to load plugins and create a plugin runner. Just like deepcore:galactic()
you can provide optional context
and plugins
tables. It is intended to be used during tactical mode only.
require("PGCommands")
require("PGStateMachine")
require("deepcore/std/deepcore")
function Definitions()
DebugMessage("%s -- In Definitions", tostring(Script))
Define_State("State_Init", State_Init)
end
function State_Init(message)
if message == OnEnter then
if Get_Game_Mode() ~= "Space" then
ScriptExit()
end
DeepCoreRunner = deepcore:game_object {
context = {},
plugin_folder = "eawx-plugins/gameobject/space",
plugins = { "microjump" }
}
elseif message == OnUpdate then
DeepCoreRunner:update()
end
end
A plugin consists of a folder containing at least a file called init.lua
. It is used to configure and create the plugin object. The init.lua
must return a table with both target
and init
keys. The target
specifies when or how often a plugin gets updated. The targets are defined in plugintargets.lua
and can be extended with new targets if needed. init
refers to a function that must at least be able to receive the self
argument. Its second argument is the plugin context
(ctx
) table that was defined in the main GC or game object Lua function (see Using the framework in Galactic Conquest and Using the framework with a game object script). If you're defining a galactic conquest plugin the ctx
table contains the GalacticConquest
object in ctx.galactic_conquest
. See The GalacticConquest class for more information on what functions it provides. The init
function must return a plugin object with an update
function (unless the target is never()
).
Galactic conquest plugins can set the requires_planets
to true
. In that case the plugin's update function will be called with one planet at a time.
The code snippet below demonstrates the structure of the init.lua
file.
require("deepcore/std/plugintargets")
require("eawx-plugins/galactic/production-listener/ProductionFinishedListener")
return {
target = PluginTargets.never(),
requires_planets = false,
init = function(self, ctx)
---@type GalacticConquest
local galactic_conquest = ctx.galactic_conquest
return ProductionFinishedListener(galactic_conquest)
end
}
The framework comes with the following plugin targets out of the box:
Name | Parameters | Description |
---|---|---|
always | - | Allows a plugin to be updated every frame |
never | - | Never allows updates. Use this if you want to react to observable events only |
interval | number | Updates the plugin every X seconds |
story_flag | string, PlayerWrapper | Uses Check_Story_Flag to determine if an update is allowed |
As specified in the previous section most plugin objects require an update
function. Plugin objects can be created using a simple table inside the plugin definition:
require("deepcore/std/plugintargets")
return {
target = PluginTargets.interval(45)
init = function(self, ctx)
return {
update = function(self)
-- do something
end
}
end
}
They can also be objects located in another file like the ProductionFinishedListener
from the previous section. The next section about events will show its code in more detail. To enhance readability and code structure it is recommended to place plugin objects in separate files.
The following example demonstrates how to listen to the events defined in the GalacticConquest
object. As explained in the first plugin definition, the GalacticConquest
object gets passed to a plugin's init()
function via the context
table. From there it can be accessed with ctx.galactic_conquest
. The events are defined inside a sub-table of the object and can be accessed with ctx.galactic_conquest.Events
. The production-listener
plugin uses the GalacticProductionFinished
event to count the total amount of objects produced by the player and return the build cost of the produced object. To do that it attaches its own function on_production_finished
with the additional argument self
to the event via attach_listener()
.
require("deepcore/std/class")
---@class ProductionFinishedListener
ProductionFinishedListener = class()
---@param galactic_conquest GalacticConquest
function ProductionFinishedListener:new(galactic_conquest)
self.human_player = galactic_conquest.HumanPlayer
self.total_amount_of_objects = 0
galactic_conquest.Events.GalacticProductionFinished:attach_listener(self.on_production_finished, self)
end
---We don't like to lose money, so we return it to the player on build completion
---@param planet Planet
---@param object_type_name string
function ProductionFinishedListener:on_production_finished(planet, object_type_name)
if not planet:get_owner().Is_Human() then
return
end
self.total_amount_of_objects = self.total_amount_of_objects + 1
local object_type = Find_Object_Type(object_type_name)
if object_type then
local cost = object_type.Get_Build_Cost()
self.human_player.Give_Money(cost)
end
end
Dependencies can be added to a plugin by providing a dependencies
table in the plugin definition. The table contains a list of plugin folder names.
The plugin in the example below depends on the previously defined production-listener
plugin. The plugin loader will initialise the dependencies of a plugin first and then pass the initialised dependencies to the plugin's init()
function in the same order as specified in the dependencies
table. In this case this means the init()
function will receive an instance of ProductionFinishedListener
.
Important: Plugin dependencies must not be cyclic. If a plugin A
depends on plugin B
, B
depends on C
and C
depends on A
the plugin loader will stop loading and likely break the GC script.
weekly-game-message-service/init.lua
:
require("deepcore/std/plugintargets")
require("eawx-plugins/galactic/weekly-game-message-service/GameMessageService")
return {
target = PluginTargets.interval(45),
-- We can specify plugin dependencies in this table
dependencies = {"production-listener"},
-- The plugins we specified in the dependencies table will be passed to the init function in order
init = function(self, ctx, production_finished_listener)
return GameMessageService(production_finished_listener)
end
}
weekly-game-message-service/GameMessageService.lua
:
require("deepcore/std/class")
---@class GameMessageService
GameMessageService = class()
---@param production_finished_listener ProductionFinishedListener
function GameMessageService:new(production_finished_listener)
self.production_finished_listener = production_finished_listener
end
-- We'll show a Game_Message for every produced object
function GameMessageService:update()
local objects_produced = self.production_finished_listener.total_amount_of_objects
for i = 1, objects_produced do
Game_Message("TEXT_FACTION_EMPIRE")
end
end