Difference between revisions of "Lua-based equipment"
(4 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
+ | {{outdated}} | ||
As of March 2013, there's been an ongoing effort for about a year to rewrite the equipment system to be able to define and modify random pieces of equipment through Lua. | As of March 2013, there's been an ongoing effort for about a year to rewrite the equipment system to be able to define and modify random pieces of equipment through Lua. | ||
− | The resulting system is entirely Lua-based, and communicates with C++ only | + | The resulting system is entirely Lua-based, and communicates with C++ only Ship properties (as in PropertyMap) suffixed with _cap |
== From the C++ side == | == From the C++ side == | ||
Line 7: | Line 8: | ||
<pre> | <pre> | ||
− | int | + | int ecm_cap; |
− | if ( | + | ship.Properties().Get("ecm_cap", ecm_cap); // This gets you the actual value of the modifier, ie the strength of the ECM |
− | BlastAwayThisMissileWithStrength( | + | if (ecm_cap > 0) { |
+ | BlastAwayThisMissileWithStrength(ecm_cap); | ||
} | } | ||
</pre> | </pre> | ||
− | As the UI is being ported to new-ui and thus is defined in Lua, you shouldn't need to access the equipment directly. If you need more interaction with the equipment than simple modifiers | + | As the UI is being ported to new-ui and thus is defined in Lua, you shouldn't need to access the equipment directly. If you need more interaction with the equipment than simple modifiers, it might be worth it to write specific Lua interfaces that are to be called by the relevant pieces of equipment at install/uninstall time. |
TODO: A list of all the modifiers used in the C++ code. | TODO: A list of all the modifiers used in the C++ code. | ||
Line 24: | Line 26: | ||
<code>Game.player:AddEquip("HYDROGEN", 2)</code> | <code>Game.player:AddEquip("HYDROGEN", 2)</code> | ||
You'll write | You'll write | ||
− | < | + | <pre> |
+ | Equipment = import("Equipment") | ||
+ | Game.player:AddEquip(Equipment.cargo.hydrogen, 2) | ||
+ | </pre> | ||
The canonical equipment is stored in 2 tables, <code>equipment</code> and <code>cargo</code> | The canonical equipment is stored in 2 tables, <code>equipment</code> and <code>cargo</code> | ||
Line 52: | Line 57: | ||
==== The fast way ==== | ==== The fast way ==== | ||
− | You can just instantiate a new EquipType. Its only argument is a table whose only mandatory content are a <code> | + | You can just instantiate a new EquipType. Its only argument is a table whose only mandatory content are a <code>capabilities</code> table with the modifiers to apply at install time and a <code>slots</code> table/string with the name of the slots to install the piece in, stored in the array part of the table. The rest of the table content will get copied in the new object. |
Here is the creation of the basic ECM, for instance. | Here is the creation of the basic ECM, for instance. | ||
Line 61: | Line 66: | ||
}) | }) | ||
</pre> | </pre> | ||
− | Since there is only one slot to install it in, you can just use a single string instead of a full table. | + | Since there is only one slot to install it in, you can just use a single string instead of a full table, the constructor will do the smart thing. |
Please bear in mind that the object created this way will be stored as reference every time it gets installed, if you want each piece to be its own object you will have to use another method. | Please bear in mind that the object created this way will be stored as reference every time it gets installed, if you want each piece to be its own object you will have to use another method. | ||
Line 68: | Line 73: | ||
TODO: Document HyperdriveType | TODO: Document HyperdriveType | ||
+ | |||
+ | ==== The Lego™ way ==== | ||
+ | |||
+ | You can actually use any object as a piece of equipment as long as it has the following methods: | ||
+ | |||
+ | * <code>IsValidSlot(slot, ship)</code> returning <code>true</code> if the slot is valid, <code>false</code> otherwise. The <code>ship</code> argument is here for those who would want some variable behaviour, even though I don't see any use case at the moment. | ||
+ | * <code>GetDefaultSlot(ship)</code> returns a single string indicating the default slot for the piece of equipment. | ||
+ | * <code>Install(ship, num, slot)</code>. This gets called when installing the piece of equipment in the EquipSet. <code>ship</code> is obviously the targetted ship, <code>num</code> is the number of pieces planned to be installed, and <code>slot</code> is the slot it gets installed in. You don't need to check if there is enough place in the slot for the equipment, this has been sorted out already. Typically, it is in this function that the modifiers are applied to the ship. When you're done, just return the number of pieces actually installed. | ||
+ | * <code>Uninstall(ship, num, slot)</code>. It is the exact counterpart of <code>Install()</code>, just return the number of pieces actually uninstalled. |
Latest revision as of 18:38, 9 December 2020
As of March 2013, there's been an ongoing effort for about a year to rewrite the equipment system to be able to define and modify random pieces of equipment through Lua. The resulting system is entirely Lua-based, and communicates with C++ only Ship properties (as in PropertyMap) suffixed with _cap
Contents
From the C++ side
If you wish to know if there is an ECM installed on ship
, you would just do
int ecm_cap; ship.Properties().Get("ecm_cap", ecm_cap); // This gets you the actual value of the modifier, ie the strength of the ECM if (ecm_cap > 0) { BlastAwayThisMissileWithStrength(ecm_cap); }
As the UI is being ported to new-ui and thus is defined in Lua, you shouldn't need to access the equipment directly. If you need more interaction with the equipment than simple modifiers, it might be worth it to write specific Lua interfaces that are to be called by the relevant pieces of equipment at install/uninstall time.
TODO: A list of all the modifiers used in the C++ code.
From the Lua side
Accessing the equipment
The Lua interface to fetch, count, etc, the equipment hasn't changed much, I tried to keep the API changes to a minimum.
The difference is that instead of manipulating constants (well, strings) you will use straight Lua object.
For instance, instead of
Game.player:AddEquip("HYDROGEN", 2)
You'll write
Equipment = import("Equipment") Game.player:AddEquip(Equipment.cargo.hydrogen, 2)
The canonical equipment is stored in 2 tables, equipment
and cargo
The slot names are not in caps anymore, and are the following (with their default size):
* cargo=0, * engine=1, * laser_front=1, * laser_rear=0, * missile=0, * ecm=1, * scanner=1, * radar=1, * hypercloud=1, * hull_autorepair=1, * energy_booster=1, * atmo_shield=1, * cabin=50, * shield=9999, * fuel_scoop=1, * cargo_scoop=1, * laser_cooler=1, * cargo_life_support=1, * autopilot=1
Creating equipment
There are basically two ways to create a new piece of equipment for Pioneer.
The fast way
You can just instantiate a new EquipType. Its only argument is a table whose only mandatory content are a capabilities
table with the modifiers to apply at install time and a slots
table/string with the name of the slots to install the piece in, stored in the array part of the table. The rest of the table content will get copied in the new object.
Here is the creation of the basic ECM, for instance.
ecm_basic = EquipType.new({ name="Basic ECM", description="", slots="ecm", price=600000, modifiers={mass=2000, ecm_power=2} })
Since there is only one slot to install it in, you can just use a single string instead of a full table, the constructor will do the smart thing.
Please bear in mind that the object created this way will be stored as reference every time it gets installed, if you want each piece to be its own object you will have to use another method.
Note that for more specific pieces of equipment such as hyperdrives, you would use HyperdriveType instead of EquipType, with its own specifications.
TODO: Document HyperdriveType
The Lego™ way
You can actually use any object as a piece of equipment as long as it has the following methods:
IsValidSlot(slot, ship)
returningtrue
if the slot is valid,false
otherwise. Theship
argument is here for those who would want some variable behaviour, even though I don't see any use case at the moment.GetDefaultSlot(ship)
returns a single string indicating the default slot for the piece of equipment.Install(ship, num, slot)
. This gets called when installing the piece of equipment in the EquipSet.ship
is obviously the targetted ship,num
is the number of pieces planned to be installed, andslot
is the slot it gets installed in. You don't need to check if there is enough place in the slot for the equipment, this has been sorted out already. Typically, it is in this function that the modifiers are applied to the ship. When you're done, just return the number of pieces actually installed.Uninstall(ship, num, slot)
. It is the exact counterpart ofInstall()
, just return the number of pieces actually uninstalled.