216 lines
5.5 KiB
Lua
216 lines
5.5 KiB
Lua
AddCSLuaFile()
|
|
DEFINE_BASECLASS( "base_wire_entity" )
|
|
ENT.PrintName = "Wire Gate"
|
|
ENT.WireDebugName = "Gate"
|
|
|
|
if CLIENT then return end -- No more client
|
|
|
|
local Wire_EnableGateInputValues = CreateConVar("Wire_EnableGateInputValues", 1, FCVAR_ARCHIVE)
|
|
|
|
function ENT:Initialize()
|
|
self:PhysicsInit( SOLID_VPHYSICS )
|
|
self:SetMoveType( MOVETYPE_VPHYSICS )
|
|
self:SetSolid( SOLID_VPHYSICS )
|
|
|
|
self.Inputs = {}
|
|
self.Outputs = {}
|
|
end
|
|
|
|
function ENT:Setup( action, noclip )
|
|
local gate = GateActions[action]
|
|
if not gate then return end
|
|
if GateActions[action].is_banned then return end
|
|
|
|
self.Updating = true
|
|
|
|
self.action = action
|
|
|
|
self.WireDebugName = gate.name
|
|
|
|
WireLib.AdjustSpecialInputs(self, gate.inputs, gate.inputtypes )
|
|
if (gate.outputs) then
|
|
WireLib.AdjustSpecialOutputs(self, gate.outputs, gate.outputtypes)
|
|
else
|
|
--Wire_AdjustOutputs(self, { "Out" })
|
|
WireLib.AdjustSpecialOutputs(self, { "Out" }, gate.outputtypes)
|
|
end
|
|
|
|
if (gate.reset) then
|
|
gate.reset(self)
|
|
end
|
|
|
|
local ReadCell = gate.ReadCell
|
|
if ReadCell then
|
|
function self:ReadCell(Address)
|
|
return ReadCell(gate,self,Address)
|
|
end
|
|
else
|
|
self.ReadCell = nil
|
|
end
|
|
|
|
local WriteCell = gate.WriteCell
|
|
if WriteCell then
|
|
function self:WriteCell(Address,value)
|
|
return WriteCell(gate,self,Address,value)
|
|
end
|
|
else
|
|
self.WriteCell = nil
|
|
end
|
|
|
|
if (noclip) then
|
|
self:SetCollisionGroup( COLLISION_GROUP_WORLD )
|
|
end
|
|
self.noclip = noclip
|
|
|
|
self.Action = gate
|
|
self.PrevValue = nil
|
|
|
|
--self.Action.inputtypes = self.Action.inputtypes or {}
|
|
|
|
self.Updating = nil
|
|
|
|
self:CalcOutput()
|
|
self:ShowOutput()
|
|
end
|
|
|
|
|
|
function ENT:OnInputWireLink(iname, itype, src, oname, otype)
|
|
if (self.Action) and (self.Action.OnInputWireLink) then
|
|
self.Action.OnInputWireLink(self, iname, itype, src, oname, otype)
|
|
end
|
|
end
|
|
|
|
function ENT:OnOutputWireLink(oname, otype, dst, iname, itype)
|
|
if (self.Action) and (self.Action.OnOutputWireLink) then
|
|
self.Action.OnOutputWireLink(self, oname, otype, dst, iname, itype)
|
|
end
|
|
end
|
|
|
|
function ENT:TriggerInput(iname, value, iter)
|
|
if self.Updating then return end
|
|
if (self.Action) and (not self.Action.timed) then
|
|
self:CalcOutput(iter)
|
|
self:ShowOutput()
|
|
end
|
|
end
|
|
|
|
function ENT:Think()
|
|
BaseClass.Think(self)
|
|
|
|
if (self.Action) and (self.Action.timed) then
|
|
self:CalcOutput()
|
|
self:ShowOutput()
|
|
|
|
self:NextThink(CurTime()+0.02)
|
|
return true
|
|
end
|
|
end
|
|
|
|
|
|
function ENT:CalcOutput(iter)
|
|
if (self.Action) and (self.Action.output) then
|
|
if (self.Action.outputs) then
|
|
local result = { self.Action.output(self, unpack(self:GetActionInputs(), 1, #self.Action.inputs)) }
|
|
|
|
for k,v in ipairs(self.Action.outputs) do
|
|
Wire_TriggerOutput(self, v, result[k] or WireLib.DT[ self.Outputs[v].Type ].Zero, iter)
|
|
end
|
|
else
|
|
local value = self.Action.output(self, unpack(self:GetActionInputs(), 1, #self.Action.inputs)) or WireLib.DT[ self.Outputs.Out.Type ].Zero
|
|
|
|
Wire_TriggerOutput(self, "Out", value, iter)
|
|
end
|
|
end
|
|
end
|
|
|
|
function ENT:ShowOutput()
|
|
local txt
|
|
|
|
if (self.Action) then
|
|
txt = (self.Action.name or "No Name")
|
|
if (self.Action.label) then
|
|
txt = txt.."\n"..self.Action.label(self:GetActionOutputs(), unpack(self:GetActionInputs(Wire_EnableGateInputValues:GetBool()), 1, #self.Action.inputs))
|
|
end
|
|
else
|
|
txt = "Invalid gate!"
|
|
end
|
|
|
|
self:SetOverlayText(txt)
|
|
end
|
|
|
|
|
|
function ENT:OnRestore()
|
|
self.Action = GateActions[self.action]
|
|
|
|
BaseClass.OnRestore(self)
|
|
end
|
|
|
|
|
|
function ENT:GetActionInputs(as_names)
|
|
local Args = {}
|
|
|
|
if (self.Action.compact_inputs) then
|
|
-- If a gate has compact inputs (like Arithmetic - Add), nil inputs are truncated so {0, nil, nil, 5, nil, 1} becomes {0, 5, 1}
|
|
for k,v in ipairs(self.Action.inputs) do
|
|
local input = self.Inputs[v]
|
|
if (not input) then
|
|
ErrorNoHalt("Wire Gate ("..self.action..") error: Missing input! ("..k..","..v..")\n")
|
|
return {}
|
|
end
|
|
|
|
if IsValid(input.Src) then
|
|
if (as_names) then
|
|
table.insert(Args, input.Src.WireName or input.Src.WireDebugName or v)
|
|
else
|
|
table.insert(Args, input.Value)
|
|
end
|
|
end
|
|
end
|
|
|
|
while (#Args < self.Action.compact_inputs) do
|
|
if (as_names) then
|
|
table.insert(Args, self.Action.inputs[#Args+1] or "*Not enough inputs*")
|
|
else
|
|
--table.insert( Args, WireLib.DT[ (self.Action.inputtypes[#Args+1] or "NORMAL") ].Zero )
|
|
table.insert( Args, WireLib.DT[ self.Inputs[ self.Action.inputs[#Args+1] ].Type ].Zero )
|
|
end
|
|
end
|
|
else
|
|
for k,v in ipairs(self.Action.inputs) do
|
|
local input = self.Inputs[v]
|
|
if (not input) then
|
|
ErrorNoHalt("Wire Gate ("..self.action..") error: Missing input! ("..k..","..v..")\n")
|
|
return {}
|
|
end
|
|
|
|
if (as_names) then
|
|
Args[k] = IsValid(input.Src) and (input.Src.WireName or input.Src.WireDebugName) or v
|
|
else
|
|
Args[k] = IsValid(input.Src) and input.Value or WireLib.DT[ self.Inputs[v].Type ].Zero
|
|
end
|
|
end
|
|
end
|
|
|
|
return Args
|
|
end
|
|
|
|
function ENT:GetActionOutputs()
|
|
if (self.Action.outputs) then
|
|
local result = {}
|
|
for _,v in ipairs(self.Action.outputs) do
|
|
result[v] = self.Outputs[v].Value or WireLib.DT[ self.Outputs[v].Type ].Zero
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
return self.Outputs.Out.Value or WireLib.DT[ self.Outputs.Out.Type ].Zero
|
|
end
|
|
|
|
function WireLib.MakeWireGate(pl, Pos, Ang, model, action, noclip, frozen, nocollide)
|
|
if not GateActions[action] then return end
|
|
if GateActions[action].is_banned then return end
|
|
|
|
return WireLib.MakeWireEnt(pl, { Class = "gmod_wire_gate", Pos=Pos, Angle=Ang, Model=model }, action, noclip)
|
|
end
|
|
duplicator.RegisterEntityClass("gmod_wire_gate", WireLib.MakeWireGate, "Pos", "Ang", "Model", "action", "noclip")
|