You could quite easily add a data binding/observer like pattern to values in a table through the use of meta tables, but when it comes to properties on a game object than we need new functionality similar to what you have suggested.
You could build something that is not fully automated, but at least fairly easy to use:
observable.lua:
local M = {}
local observables = {}
--- Create an observable value
-- @param name Unique name of the value to observer to create
-- @param message_id Message id to post to observers when the value changes
function M.create(name, message_id)
observables[name] = observables[name] or { message_id = message_id, observers = {} }
end
--- Observe changes to a previously created observable value. When the value
-- changes a message will be posted to the url of the script that called this
-- function.
-- @param name Name of the value to observe. Must have been created with @{create}
function M.observe(name)
assert(observables[name], "You must create an observable before you can observe it")
table.insert(observables[name], msg.url())
end
--- Notify observers of a change to a previously created observable value
-- @param name Unique name of the value that changed
-- @param data Data to pass to all observers
function M.notify(name, data)
assert(observables[name], "You must create an observable before you can use it")
data = date or {}
local message_id = observables[name].message_id
for _,observer_url in pairs(observables[name].observers) do
msg.post(observer_url, message_id, data)
end
end
return M
hero.script:
local observable = require("observable")
local function change_hp(self, new_hp)
self.hp = new_hp
observable.notify("hp", { hp = new_hp })
end
function init(self)
self.hp = 10
observable.create("hp", hash("hp_changes"))
end
hp_bar.gui_script:
local observable = require("observable")
function init(self)
observable.observe("hp")
end
function on_message(self, message_id, message, sender)
if message_id == hash("hp_changed") then
print("new hp", message.hp)
end
end