Maris Posted September 27, 2015 Share Posted September 27, 2015 I look at tent.luaThere is simple code:sleeper:ListenForEvent("onignite", onignite, inst)What it does?First of all, it take onignite function as parameter.local function onignite(inst) inst.components.sleepingbag:DoWakeUp()endOnly tent and bedroll has "sleepingbag" component. So inst is a tent instance in onignite function. But why code contains "sleeper"? Why not just "inst"? May be character will wake up on fire? I mean fire exactly on character. Okey, let's make an experiment. Go sleep in tent, then enter in console:AllPlayers[1].components.burnable:Ignite()Well, I entered this command. There was a fire near the tent. I lose some health. But character did not wake up.Of course character will wake up if I enter:thetent_inst..components.burnable:Ignite()(thetent_inst is a tent instance) So..................This event handles fire on tent, then call a function with instance of tent as paramter. And what is the association with sleeper variable?I definitely don't understand what is the difference between:sleeper:ListenForEvent("onignite", onignite, inst)andinst:ListenForEvent("onignite", onignite, inst)and even more:inst:ListenForEvent("onignite", onignite)Can someone explain me please the difference? And how ListenForEvent works? Thanks in advance. Link to comment https://forums.kleientertainment.com/forums/topic/58162-listenforevent-misunderstanding/ Share on other sites More sharing options...
DarkXero Posted September 27, 2015 Share Posted September 27, 2015 @Maris, an entity listens to the events of sources.This source can be themselves, or another one.inst:ListenForEvent("hello", function(src, data) end, src)sleeper.ListenForEvent(sleeper, "onignite", onignite, tent)EntityScript:ListenForEventself = sleeperevent = "onignite"fn = onignitesource = tentsource = tent or sleeper = tentif not tent.event_listeners then tent.event_listeners = {}end AddListener(tent.event_listeners, "onignite", sleeper, onignite) t = tent.event_listeners event = "onignite" inst = sleeper fn = onignite listeners = tent.event_listeners["onignite"] = nil if not nil then listeners = {} tent.event_listeners["onignite"] = listeners end listener_fns = listeners[sleeper] = nil if not nil then listener_fns = {} listeners[sleeper] = listener_fns end table.insert(listener_fns, onignite) -- Now you have tent.event_listeners["onignite"] = { sleeper = { onignite } }if not sleeper.event_listening then sleeper.event_listening = {}end AddListener(sleeper.event_listening, "onignite", tent, onignite) -- Now you have sleeper.event_listening["onignite"] = { tent = { onignite } }tent.ListenForEvent(tent, "onignite", onignite, tent)EntityScript:ListenForEventself = tentevent = "onignite"fn = onignitesource = tentsource = tent or tent = tent AddListener(tent.event_listeners, "onignite", tent, onignite) -- Now you have tent.event_listeners["onignite"] = { tent = { onignite } } AddListener(tent.event_listening, "onignite", tent, onignite) -- Now you have tent.event_listening["onignite"] = { tent = { onignite } } tent.ListenForEvent(tent, "onignite", onignite)EntityScript:ListenForEventself = tentevent = "onignite"fn = onignitesource = nilsource = nil or tent = tent-- Same astent.ListenForEvent(tent, "onignite", onignite, tent) -- sleeper.ListenForEvent(sleeper, "onignite", onignite, tent) tent.event_listeners["onignite"] = { sleeper = { onignite } } tent:PushEvent("onignite", data) listeners = tent.event_listeners["onignite"] for entity, fns in pairs(listeners) do for i, fn in ipairs(fns) do fn(tent, data) sleeper:PushEvent("onignite", data) listeners = sleepers.event_listeners["onignite"] = nil -- tent.ListenForEvent(tent, "onignite", onignite, tent) tent.event_listeners["onignite"] = { tent = { onignite } } tent:PushEvent("onignite", data) listeners = tent.event_listeners["onignite"] for entity, fns in pairs(listeners) do for i, fn in ipairs(fns) do fn(tent, data) sleeper:PushEvent("onignite", data) listeners = sleepers.event_listeners["onignite"] = nilSo basically, when you listen for an event, two tables get in scene.One table in a source entity, holding all the entities that listen (listeners) a certain event.One table in the listener entity, holding all the entities that is listening (sources) for a certain event. Why two tables? Because when you want to make an entity stop listening another, you can't just destroy the source. You go to the entities stored in event_listening (of sleeper) and from there you go to these source (tent) entities and make them stop running the function associated with the listener entity (sleeper). The tent is source of "onignite" events, the sleeper listens to the tent source for onignite events. For event pushing purposessleeper:ListenForEvent("onignite", onignite, inst)is no different thaninst:ListenForEvent("onignite", onignite)since they all make the DoWakeUp function of the sleeping bag component. However, using sleeper as the listener, and making him listen while sleeping (event gets listened on sleep, listener gets removed when you wake up), you end up listening for wake ups only if the tent gets on fire AND there's people sleeping on it. Optimal, instead of checking when there's no people sleeping on it. In the tent, DoWakeUp checks for self.sleeper, so if the onignite was triggered byinst:ListenForEvent("onignite", onignite)sleeper would be nil, and nothing rare would happen. The tent is a bad example, but another utility for this is the following in bearger.lua inst:ListenForEvent("ms_playerjoined", function(src, player) OnPlayerJoined(inst, player) end, TheWorld) inst:ListenForEvent("ms_playerleft", function(src, player) OnPlayerLeft(inst, player) end, TheWorld)Bearger gets mad when people steal his food.For that, he listen to the performaction event of players.However this performaction event doesn't get broadcasted somewhere globally where he could pick them up.The performaction event stays on each player. So what do we do here?We make each player listen for their performaction event, loop through Ents, and make each Bearger mad if a condition is found? Or what we can do is Bearger listen when a player enters. Such an event is pushed on the source TheWorld.Then we run a function passing inst (bearger) and player instead of source and data (player).And in this function, we make Bearger listen for the performaction event of players (new source)local function OnPlayerJoined(inst, player) for i, v in ipairs(inst._activeplayers) do if v == player then return end end inst:ListenForEvent("performaction", function(player, data) OnPlayerAction(inst, player, data) end, player) table.insert(inst._activeplayers, player)end 1 Link to comment https://forums.kleientertainment.com/forums/topic/58162-listenforevent-misunderstanding/#findComment-676345 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now