engine/bin/data/entities/scripts/dark/io.lua

223 lines
6.7 KiB
Lua

local ent = ent
local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata")
local darkMeta = metadata["dark"] or {}
local schemaDb = darkMeta["schema_db"] or {}
local classTags = darkMeta["class_tags"] or ""
_G.DarkTargets = _G.DarkTargets or {}
if darkMeta["id"] then
_G.DarkTargets[darkMeta["id"]] = ent:uid()
end
_G.DarkScripts = _G.DarkScripts or {}
_G.DarkScripts["RelayTrap"] = function(entity, payload, dMeta)
local msg = payload.message
local eName = entity or entity:uid()
--print(string.format("%s (RelayTrap) is forwarding %s down its links...", eName, msg))
entity:callHook("link:Broadcast.%UID%", {
message = msg,
flavors = { "ControlDevice", "SwitchLink" },
caller = entity:uid(),
callerDarkID = payload.callerDarkID
})
end
_G.DarkScripts["ElevatorButton"] = _G.DarkScripts["RelayTrap"]
_G.DarkScripts["RequireAllTrap"] = function(entity, payload, dMeta)
local msg = payload.message
local callerDarkID = payload.callerDarkID
_G.RAT_States = _G.RAT_States or {}
local uid = entity:uid()
_G.RAT_States[uid] = _G.RAT_States[uid] or { inputs = {}, wasOn = false }
local state = _G.RAT_States[uid]
if callerDarkID then
state.inputs[callerDarkID] = (msg == "TurnOn")
end
local allOn = true
local incoming = dMeta["incoming_connections"] or {}
for i = 1, #incoming do
local conn = incoming[i]
if conn.flavor == "ControlDevice" or conn.flavor == "SwitchLink" then
if not state.inputs[conn.source_id] then
allOn = false
break
end
end
end
if allOn and not state.wasOn then
state.wasOn = true
--print(entity .. " (RequireAllTrap) conditions met! Broadcasting TurnOn.")
entity:callHook("link:Broadcast.%UID%", { message = "TurnOn", flavors = { "ControlDevice", "SwitchLink" }, callerDarkID = dMeta["id"], caller = uid })
elseif not allOn and state.wasOn then
state.wasOn = false
--print(entity .. " (RequireAllTrap) condition lost! Broadcasting TurnOff.")
entity:callHook("link:Broadcast.%UID%", { message = "TurnOff", flavors = { "ControlDevice", "SwitchLink" }, callerDarkID = dMeta["id"], caller = uid })
end
end
--[[
_G.DarkScripts["BaseElevator"] = function(entity, payload, dMeta)
local msg = payload.message
local eName = entity or entity:uid()
print(string.format("%s (Elevator) received command: %s", eName, msg))
if msg == "TurnOn" or msg == "TurnOff" then
print(string.format("--> Commanding Lift '%s' to move!", eName))
end
end
_G.DarkScripts["Elevator"] = _G.DarkScripts["BaseElevator"]
]]
ent:addHook("link:Message.%UID%", function(payload)
local msg = payload.message
local caller = payload.caller
local eName = ent:name() or ent:uid()
--print(string.format("Entity %s (Dark ID: %s) received message: %s from UID: %s", eName, darkMeta["id"] or "Unknown", msg, tostring(caller)))
local scripts = darkMeta["scripts"] or {}
local scriptHandled = false
for _, script in ipairs(scripts) do
if _G.DarkScripts[script] then
_G.DarkScripts[script](ent, payload, darkMeta)
scriptHandled = true
end
end
if not scriptHandled then
if eName:lower():match("filter") or eName:lower():match("trigger") then
_G.DarkScripts["RelayTrap"](ent, payload, darkMeta)
end
end
end)
local function playButtonSound()
if not classTags or classTags == "" then return end
local myDeviceType = string.match(classTags, "DeviceType%s+([^%s,]+)")
local bestMatch = nil
local bestScore = -1
for _, schema in ipairs(schemaDb) do
local sTags = schema.tags or ""
local score = 0
if myDeviceType then
local paddedTags = sTags .. ","
if string.find(paddedTags, "DeviceType%s+" .. myDeviceType .. "[,%s]") then
score = score + 10
elseif string.find(paddedTags, "DeviceType%s+Gen[,%s]") then
score = score + 5
elseif string.find(sTags, "DeviceType") then
score = score - 10
end
if score > 0 then
if string.find(sTags, "Reject") then
score = score + 5
elseif string.find(sTags, "StateChange") or string.find(sTags, "Activate") then
score = score + 5
end
end
end
if score > bestScore then
bestScore = score
bestMatch = schema
end
end
print("Button sound resolution:", ent, classTags, myDeviceType, bestMatch and bestMatch.name or "None", bestScore)
if bestMatch and bestScore > 0 and bestMatch.wavs and #bestMatch.wavs > 0 then
local pick = bestMatch.wavs[math.random(#bestMatch.wavs)]
local resolvedUrl = string.resolveURI(pick, metadata["system"]["root"])
ent:callHook("sound:Emit.%UID%", {
filename = resolvedUrl, spatial = true, volume = 1.0, maxDistance = 15.0, rolloffFactor = 1.0, unique = true
})
end
end
local connections = darkMeta["connections"]
ent:addHook("link:Broadcast.%UID%", function(payload)
local msg = payload.message
local validFlavors = payload.flavors or { "ControlDevice", "SwitchLink" }
if not connections then
return
end
for i = 1, #connections do
local conn = connections[i]
local isValid = false
for _, flav in ipairs(validFlavors) do
if conn.flavor == flav then isValid = true break end
end
if isValid then
local targetUID = _G.DarkTargets[conn.target_id]
--print(string.format("Broadcasting %s to Dark ID %s (UID: %s) via %s", msg, conn.target_id, tostring(targetUID), conn.flavor))
if targetUID then
local targetEnt = entities.get(targetUID)
if targetEnt and targetEnt:uid() then
targetEnt:callHook("link:Message." .. targetUID, {
message = msg,
caller = ent:uid(),
callerDarkID = darkMeta["id"] or payload.callerDarkID
})
end
end
end
end
end)
if darkMeta["frob"] ~= nil then
ent:addHook("entity:Use.%UID%", function(payload)
local frobWorld = darkMeta["frob"]["world"] or 0
local kFrobMove = 1 -- 1 << 0
local kFrobScript = 2 -- 1 << 1
if bit.band(frobWorld, kFrobScript) ~= 0 then
print(ent, json.encode( darkMeta ))
playButtonSound()
ent:callHook("link:Broadcast.%UID%", {
message = "TurnOn",
flavors = { "ControlDevice", "SwitchLink" },
caller = payload.user,
callerDarkID = darkMeta["id"]
})
end
if bit.band(frobWorld, kFrobMove) ~= 0 then
print("Item picked up!")
-- ent:callHook("inventory:Pickup.%UID%", { user = payload.user })
end
end)
end
ent:addHook("entity:Destroy.%UID%", function()
if darkMeta["id"] and _G.DarkTargets[darkMeta["id"]] == ent:uid() then
_G.DarkTargets[darkMeta["id"]] = nil
end
if _G.RAT_States and _G.RAT_States[ent:uid()] then
_G.RAT_States[ent:uid()] = nil
end
end)