Compare commits
10 Commits
b7f74ccb1a
...
76c0e35980
Author | SHA1 | Date | |
---|---|---|---|
76c0e35980 | |||
952d1d5871 | |||
026ede1023 | |||
6cc5ed68ef | |||
3a4bf205cf | |||
c873381653 | |||
2a50467a41 | |||
6ff7de5cc9 | |||
0b9af0d3b0 | |||
96b4176f8b |
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Items>
|
||||
<Item name="Flip-Flop Component" identifier="flipflopcomponent" category="Electrical" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<Item identifier="flipflopcomponent" category="Electrical" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
@@ -19,7 +19,26 @@
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
|
||||
<Item name="Counter Component" identifier="countercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<Item identifier="activeflipflopcomponent" category="Electrical" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
<Holdable selectkey="Select" pickkey="Use" aimpos="65,-10" handle1="0,0" attachable="true" aimable="true" PickingTime="5.0" slots="Any,RightHand,LeftHand" msg="ItemMsgDetachWrench">
|
||||
<RequiredItem items="wrench" type="Equipped" />
|
||||
<StatusEffect type="Always" target="This" stackable="false">
|
||||
<LuaHook name="activeflipflopcomponent.update" />
|
||||
</StatusEffect>
|
||||
</Holdable>
|
||||
<MemoryComponent canbeselected="false" MaxValueLength="1" AllowInGameEditing="false" Value="0" />
|
||||
<ConnectionPanel selectkey="Action" canbeselected="true" msg="ItemMsgRewireScrewdriver" hudpriority="10">
|
||||
<GuiFrame relativesize="0.2,0.32" minsize="400,350" maxsize="480,420" anchor="Center" style="ConnectionPanel" />
|
||||
<RequiredItem items="screwdriver" type="Equipped" />
|
||||
<input name="input" displayname="connection.input" />
|
||||
<output name="state_out" displayname="connection.state_out" />
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
|
||||
<Item identifier="countercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
@@ -39,7 +58,27 @@
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
|
||||
<item name="Reactor Controller Component" identifier="reactorcontrollercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<Item identifier="activecountercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
<Holdable selectkey="Select" pickkey="Use" aimpos="65,-10" handle1="0,0" attachable="true" aimable="true" PickingTime="5.0" slots="Any,RightHand,LeftHand" msg="ItemMsgDetachWrench">
|
||||
<RequiredItem items="wrench" type="Equipped" />
|
||||
<StatusEffect type="Always" target="This" stackable="false">
|
||||
<LuaHook name="activecountercomponent.update" />
|
||||
</StatusEffect>
|
||||
</Holdable>
|
||||
<MemoryComponent canbeselected="false" MaxValueLength="200" AllowInGameEditing="false" Value="0" />
|
||||
<AdderComponent canbeselected="false" ClampMin="0" ClampMax="100" />
|
||||
<ConnectionPanel selectkey="Action" canbeselected="true" msg="ItemMsgRewireScrewdriver" hudpriority="10">
|
||||
<GuiFrame relativesize="0.2,0.32" minsize="400,350" maxsize="480,420" anchor="Center" style="ConnectionPanel" />
|
||||
<RequiredItem items="screwdriver" type="Equipped" />
|
||||
<input name="input" displayname="connection.input" />
|
||||
<output name="state_out" displayname="connection.state_out" />
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
|
||||
<item identifier="reactorcontrollercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
@@ -63,4 +102,28 @@
|
||||
<output name="fuel_low_out" displayname="connection.fuel_low_out" />
|
||||
</ConnectionPanel>
|
||||
</item>
|
||||
|
||||
<Item identifier="enginecontrollercomponent" category="Electrical" Tags="smallitem,logic" maxstacksize="8" scale="0.5" impactsoundtag="impact_metal_light">
|
||||
<InventoryIcon texture="luacomp_inv.png" sourcerect="0,0,64,52" origin="0.5,0.5" />
|
||||
<Sprite texture="luacomp_sprite.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" />
|
||||
<Body width="32" height="24" density="30" />
|
||||
<Holdable selectkey="Select" pickkey="Use" aimpos="65,-10" handle1="0,0" attachable="true" aimable="true" PickingTime="5.0" slots="Any,RightHand,LeftHand" msg="ItemMsgDetachWrench">
|
||||
<RequiredItem items="wrench" type="Equipped" />
|
||||
<StatusEffect type="Always" target="This" stackable="false">
|
||||
<LuaHook name="enginecontrollercomponent.update" />
|
||||
</StatusEffect>
|
||||
</Holdable>
|
||||
<ConnectionPanel selectkey="Action" canbeselected="true" msg="ItemMsgRewireScrewdriver" hudpriority="10">
|
||||
<GuiFrame relativesize="0.2,0.32" minsize="400,350" maxsize="480,420" anchor="Center" style="ConnectionPanel" />
|
||||
<RequiredItem items="screwdriver" type="Equipped" />
|
||||
<input name="velocity_x_in" displayname="connection.velocity_x_in" />
|
||||
<input name="current_velocity_x_in" displayname="connection.current_velocity_x_in" />
|
||||
<input name="set_trm_target" displayname="connection.set_trm_target" />
|
||||
<input name="set_trm_aggression" displayname="connection.set_trm_aggression" />
|
||||
<input name="set_mode" displayname="connection.set_mode" />
|
||||
<input name="set_silent" displayname="connection.set_silent" />
|
||||
<output name="main_force_out" displayname="connection.force_out" />
|
||||
<output name="boost_force_out" displayname="connection.boost_force_out" />
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
</Items>
|
@@ -1,10 +1,13 @@
|
||||
local moduleNames = {
|
||||
"flipflopcomponent",
|
||||
-- "activeflipflopcomponent",
|
||||
"countercomponent",
|
||||
-- "activecountercomponent",
|
||||
"reactorcontrollercomponent",
|
||||
"enginecontrollercomponent",
|
||||
}
|
||||
|
||||
modPath = table.pack(...)[1] .. "/Lua/"
|
||||
local modPath = table.pack(...)[1] .. "/Lua/"
|
||||
|
||||
for _, moduleName in ipairs(moduleNames) do
|
||||
dofile(modPath .. moduleName .. ".lua")
|
||||
|
36
Lua/activecountercomponent.lua
Normal file
36
Lua/activecountercomponent.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
local allItems = {}
|
||||
|
||||
Hook.Add("item.created", "activecountercomponent.init", function(item)
|
||||
if item.Prefab.Identifier == "activecountercomponent" then
|
||||
allItems[item] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local signalReceived = function(signal, connection)
|
||||
local this = connection.Item
|
||||
local mem = this.Components[2]
|
||||
|
||||
if signal.value == "" then return end
|
||||
local input = tonumber(signal.value) or 1
|
||||
|
||||
if input > 0 then
|
||||
if tonumber(mem.value) >= this.Components[3].clampMax then
|
||||
mem.value = tostring(this.Components[3].clampMin)
|
||||
else
|
||||
mem.value = tostring(tonumber(mem.value) + 1)
|
||||
end
|
||||
elseif input == 0 then
|
||||
mem.value = "0"
|
||||
elseif input < 0 then
|
||||
mem.value = tostring(-input)
|
||||
end
|
||||
end
|
||||
|
||||
local think = function()
|
||||
for component, _ in pairs(allItems) do
|
||||
component.SendSignal(component.Components[2].value, "state_out")
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("think", "activecountercomponent.think", think)
|
||||
Hook.Add("signalreceived.activecountercomponent", "activecountercomponent.signalReceived", signalReceived)
|
32
Lua/activeflipflopcomponent.lua
Normal file
32
Lua/activeflipflopcomponent.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
local allItems = {}
|
||||
|
||||
Hook.Add("item.created", "activeflipflopcomponent.init", function(item)
|
||||
if item.Prefab.Identifier == "activeflipflopcomponent" then
|
||||
allItems[item] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local signalReceived = function(signal, connection)
|
||||
local this = connection.Item
|
||||
local mem = this.Components[2]
|
||||
|
||||
if signal.value == "" then return end
|
||||
local input = tonumber(signal.value) or 1
|
||||
|
||||
if input == 1 then
|
||||
if mem.value == "0" then mem.value = "1" else mem.value = "0" end
|
||||
elseif input == 0 then
|
||||
mem.value = "0"
|
||||
elseif input == -1 then
|
||||
mem.value = "1"
|
||||
end
|
||||
end
|
||||
|
||||
local think = function()
|
||||
for component, _ in pairs(allItems) do
|
||||
component.SendSignal(component.Components[2].value, "state_out")
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("think", "activeflipflopcomponent.think", think)
|
||||
Hook.Add("signalreceived.activeflipflopcomponent", "activeflipflopcomponent.signalReceived", signalReceived)
|
@@ -1,11 +1,3 @@
|
||||
local allItems = {}
|
||||
|
||||
Hook.Add("item.created", "countercomponent.init", function(item)
|
||||
if item.Prefab.Identifier == "countercomponent" then
|
||||
allItems[item] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local signalReceived = function(signal, connection)
|
||||
local this = connection.Item
|
||||
local mem = this.Components[2]
|
||||
@@ -24,13 +16,8 @@ local signalReceived = function(signal, connection)
|
||||
elseif input < 0 then
|
||||
mem.value = tostring(-input)
|
||||
end
|
||||
|
||||
this.SendSignal(mem.value, "state_out")
|
||||
end
|
||||
|
||||
local think = function()
|
||||
for component, _ in pairs(allItems) do
|
||||
component.SendSignal(component.Components[2].value, "state_out")
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("think", "countercomponent.think", think)
|
||||
Hook.Add("signalreceived.countercomponent", "countercomponent.signalReceived", signalReceived)
|
||||
|
90
Lua/enginecontrollercomponent.lua
Normal file
90
Lua/enginecontrollercomponent.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
local allItems = {}
|
||||
|
||||
local defaultTable = {
|
||||
velocity_x_in = 0,
|
||||
current_velocity_x_in = 0,
|
||||
set_trm_target = 20,
|
||||
set_trm_aggression = 200,
|
||||
set_mode = 1,
|
||||
set_silent = 0,
|
||||
previous_velocity_x_in = 0,
|
||||
acceleration = 0,
|
||||
}
|
||||
|
||||
Hook.Add("item.created", "enginecontrollercomponent.init", function(item)
|
||||
if item.Prefab.Identifier == "enginecontrollercomponent" then
|
||||
allItems[item] = {}
|
||||
for k, v in pairs(defaultTable) do
|
||||
allItems[item][k] = v
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local signalReceived = function(signal, connection)
|
||||
local this = connection.Item
|
||||
local mem = allItems[this]
|
||||
|
||||
local signalNum = tonumber(signal.value) or defaultTable[connection.Name]
|
||||
local set_mode = mem.set_mode
|
||||
|
||||
if
|
||||
mem[connection.Name] == signalNum or
|
||||
connection.Name == "current_velocity_x_in" and set_mode ~= 0
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
mem[connection.Name] = signalNum
|
||||
|
||||
local main_force_out
|
||||
local boost_force_out
|
||||
local velocity_x_in = mem.velocity_x_in
|
||||
|
||||
if set_mode == 1 then
|
||||
main_force_out = velocity_x_in
|
||||
boost_force_out = 0
|
||||
|
||||
elseif set_mode == 2 then
|
||||
main_force_out = velocity_x_in
|
||||
boost_force_out = velocity_x_in
|
||||
|
||||
elseif set_mode == 0 then
|
||||
local current_velocity_x_in = mem.current_velocity_x_in
|
||||
local set_trm_target = mem.set_trm_target
|
||||
|
||||
if connection.Name == "current_velocity_x_in" then
|
||||
mem.acceleration = (mem.previous_velocity_x_in - current_velocity_x_in)
|
||||
mem.previous_velocity_x_in = current_velocity_x_in
|
||||
end
|
||||
|
||||
local absolute_current_velocity = math.abs(current_velocity_x_in)
|
||||
if set_trm_target - 0.25 < absolute_current_velocity and velocity_x_in * current_velocity_x_in > 0 then
|
||||
local set_trm_aggression = mem.set_trm_aggression
|
||||
local target_acceleration = - (absolute_current_velocity * set_trm_aggression) + (set_trm_target * set_trm_aggression)
|
||||
|
||||
if math.abs(velocity_x_in) > math.abs(target_acceleration) then
|
||||
if current_velocity_x_in > 0 then
|
||||
main_force_out = target_acceleration
|
||||
else
|
||||
main_force_out = -target_acceleration
|
||||
end
|
||||
else
|
||||
main_force_out = velocity_x_in
|
||||
end
|
||||
else
|
||||
main_force_out = velocity_x_in
|
||||
end
|
||||
|
||||
boost_force_out = 0
|
||||
end
|
||||
|
||||
if mem.set_silent == 1 then
|
||||
main_force_out = main_force_out * 0.2
|
||||
boost_force_out = boost_force_out * 0.2
|
||||
end
|
||||
|
||||
this.SendSignal(main_force_out, "main_force_out")
|
||||
this.SendSignal(boost_force_out, "boost_force_out")
|
||||
end
|
||||
|
||||
Hook.Add("signalreceived.enginecontrollercomponent", "enginecontrollercomponent.signalReceived", signalReceived)
|
@@ -1,11 +1,3 @@
|
||||
local allItems = {}
|
||||
|
||||
Hook.Add("item.created", "flipflopcomponent.init", function(item)
|
||||
if item.Prefab.Identifier == "flipflopcomponent" then
|
||||
allItems[item] = true
|
||||
end
|
||||
end)
|
||||
|
||||
local signalReceived = function(signal, connection)
|
||||
local this = connection.Item
|
||||
local mem = this.Components[2]
|
||||
@@ -20,13 +12,8 @@ local signalReceived = function(signal, connection)
|
||||
elseif input == -1 then
|
||||
mem.value = "1"
|
||||
end
|
||||
|
||||
this.sendSignal(mem.value, "state_out")
|
||||
end
|
||||
|
||||
local think = function()
|
||||
for component, _ in pairs(allItems) do
|
||||
component.SendSignal(component.Components[2].value, "state_out")
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("think", "flipflopcomponent.think", think)
|
||||
Hook.Add("signalreceived.flipflopcomponent", "flipflopcomponent.signalReceived", signalReceived)
|
||||
|
@@ -3,10 +3,10 @@ local allItems = {}
|
||||
local defaultTable = {
|
||||
load_value_in = 0,
|
||||
fuel_in = 100,
|
||||
efficiency_in = 100,
|
||||
fission_efficiency_in = 75,
|
||||
max_power_in = 20000,
|
||||
silent_in = 0
|
||||
set_efficiency = 100,
|
||||
set_fission_efficiency = 75,
|
||||
set_max_power = 20000,
|
||||
set_silent = 0,
|
||||
}
|
||||
|
||||
Hook.Add("item.created", "reactorcontrollercomponent.init", function(item)
|
||||
@@ -23,12 +23,17 @@ local signalReceived = function(signal, connection)
|
||||
local mem = allItems[this]
|
||||
|
||||
local signalNum = tonumber(signal.value) or defaultTable[connection.Name]
|
||||
|
||||
if mem[connection.Name] == signalNum then
|
||||
return
|
||||
end
|
||||
|
||||
mem[connection.Name] = signalNum
|
||||
|
||||
local turbineoutput = (mem.load_value_in / mem.max_power_in) * mem.efficiency_in
|
||||
local fissionrate = turbineoutput / (mem.fuel_in / mem.fission_efficiency_in)
|
||||
local turbineoutput = (mem.load_value_in / mem.set_max_power) * mem.set_efficiency
|
||||
local fissionrate = turbineoutput / (mem.fuel_in / mem.set_fission_efficiency)
|
||||
|
||||
if mem.silent_in == 1 then
|
||||
if mem.set_silent == 1 then
|
||||
if turbineoutput > 10 then
|
||||
turbineoutput = 10
|
||||
end
|
||||
@@ -37,8 +42,8 @@ local signalReceived = function(signal, connection)
|
||||
end
|
||||
end
|
||||
|
||||
this.SendSignal(tostring(turbineoutput), "turbine_output_out")
|
||||
this.SendSignal(tostring(fissionrate), "fission_rate_out")
|
||||
this.SendSignal(turbineoutput, "turbine_output_out")
|
||||
this.SendSignal(fissionrate, "fission_rate_out")
|
||||
end
|
||||
|
||||
Hook.Add("signalreceived.reactorcontrollercomponent", "reactorcontrollercomponent.signalReceived", signalReceived)
|
||||
|
19
README.md
19
README.md
@@ -2,4 +2,21 @@
|
||||
|
||||
Several Lua-based wiring components for the game [Barotrauma](https://barotraumagame.com/). Requires the [Lua for Barotrauma](https://steamcommunity.com/workshop/filedetails/?id=2559634234) mod to be installed.
|
||||
|
||||
The components are mainly designed to improve the performance of an advanced custom submarine called Daedalus but can be easily adapted to other submarines.
|
||||
They are mainly designed to improve the performance of an advanced custom submarine called Daedalus by replacing large collections of vanilla components with a single Lua-based component.
|
||||
|
||||
## Design Considerations
|
||||
|
||||
You might notice some weird design decisions in the code as well as in-game. These decisions are summarized below.
|
||||
|
||||
### Usage of sub-components in item XML
|
||||
|
||||
As far as I know, Barotrauma does not have an easy way to store arbitrary variables in items. Instead, most custom component mods use a global Lua table that stores variables indexed by the item IDs they belong to. However, that comes with an important drawback: Lua tables are very slow, especially when accessed 60 times per second.
|
||||
|
||||
This is where the sub-components come in. They are used to store arbitrary values in their attributes, so editing them in-game is not recommended.
|
||||
|
||||
Specifically, the following sub-components are used depending on the stored variable type:
|
||||
|
||||
## Useful Resources
|
||||
|
||||
* [Barotrauma Modding Docs](https://regalis11.github.io/BaroModDoc/)
|
||||
* [Lua For Barotrauma Docs](https://evilfactory.github.io/LuaCsForBarotrauma/lua-docs/)
|
@@ -3,9 +3,18 @@
|
||||
<entityname.flipflopcomponent>Flip-Flop Component</entityname.flipflopcomponent>
|
||||
<entitydescription.flipflopcomponent>Switches state when receiving 1, forces state to X when receiving -X.</entitydescription.flipflopcomponent>
|
||||
|
||||
<entityname.countercomponent>Counter Component</entityname.countercomponent>\
|
||||
<entityname.activeflipflopcomponent>Flip-Flop Component (Active)</entityname.activeflipflopcomponent>
|
||||
<entitydescription.activeflipflopcomponent>Switches state when receiving 1, forces state to X when receiving -X. Constantly outputs state.</entitydescription.activeflipflopcomponent>
|
||||
|
||||
<entityname.countercomponent>Counter Component</entityname.countercomponent>
|
||||
<entitydescription.countercomponent>Counts up to ClampMax when receiving 1, resets to ClampMin when reached, forces state to X when receiving -X.</entitydescription.countercomponent>
|
||||
|
||||
<entityname.activecountercomponent>Counter Component (Active)</entityname.activecountercomponent>
|
||||
<entitydescription.activecountercomponent>Counts up to ClampMax when receiving 1, resets to ClampMin when reached, forces state to X when receiving -X. Constantly outputs state.</entitydescription.activecountercomponent>
|
||||
|
||||
<entityname.reactorcontrollercomponent>Reactor Controller Component</entityname.reactorcontrollercomponent>
|
||||
<entitydescription.reactorcontrollercomponent>Automatically sets a reactor's Fission Rate and Turbine Output.</entitydescription.reactorcontrollercomponent>
|
||||
|
||||
<entityname.enginecontrollercomponent>Engine Controller Component</entityname.enginecontrollercomponent>
|
||||
<entitydescription.enginecontrollercomponent>Sets an Engine's thrust according to the selected mode.</entitydescription.enginecontrollercomponent>
|
||||
</infotexts>
|
||||
|
@@ -6,6 +6,9 @@
|
||||
<Other file="%ModDir%/Items/luacomp_inv.png" />
|
||||
<Other file="%ModDir%/Items/luacomp_sprite.png" />
|
||||
<Other file="%ModDir%/Lua/flipflopcomponent.lua" />
|
||||
<Other file="%ModDir%/Lua/activeflipflopcomponent.lua" />
|
||||
<Other file="%ModDir%/Lua/countercomponent.lua" />
|
||||
<Other file="%ModDir%/Lua/activecountercomponent.lua" />
|
||||
<Other file="%ModDir%/Lua/reactorcontrollercomponent.lua" />
|
||||
<Other file="%ModDir%/Lua/enginecontrollercomponent.lua" />
|
||||
</contentpackage>
|
||||
|
Reference in New Issue
Block a user