Jump to content

Recommended Posts

I look at tent.lua

There 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()end

​Only 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)

​and

inst: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.

@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"] = nil

So 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 purposes

sleeper:ListenForEvent("onignite", onignite, inst)

is no different than

inst: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 by

inst: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
  • Thanks 1

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...