Jump to content

Removing task in ListenForEvent


Recommended Posts

Want to make some changes in behavior of Abigail in API way

 

there a problem, Abigail prefab have

    inst:ListenForEvent("attacked", OnAttacked)

 

where OnAttacked is local function, thats mean i cant call RemoveEventCallback, since fn is required.

 

so i invistegate what functions is actually here for event "attaked"

 

there only two - one from prefab and one from follower component, so there a question :

since i dont know which function is from follower component and which is from prefab can i just remove follower component, then empty listeners like

 

 

p = GetPlayer()abigail = TheSim:FindFirstEntityWithTag("abigail")player.event_listeners.onattacked[abigail]={}inst:RemoveComponent(follower)inst:AddComponent(follower) -- its adds again his listenerinst:ListenForEvent("attacked", MyOnAttacked)

 

or there maybe some way to detect function's source file or anything?

 

 

 

Link to comment
Share on other sites

wtf cant edit my own post :/

 

code is actually like

 

abigail = TheSim:FindFirstEntityWithTag("abigail")abigail.event_listeners.onattacked[abigail]={}abigail:RemoveComponent(follower)abigail:AddComponent(follower) -- its adds again his listenerabigail:ListenForEvent("attacked", MyOnAttacked)
Link to comment
Share on other sites

Want to make some changes in behavior of Abigail in API way

 

there a problem, Abigail prefab have

    inst:ListenForEvent("attacked", OnAttacked)

where OnAttacked is local function, thats mean i cant call RemoveEventCallback, since fn is required.

 

so i invistegate what functions is actually here for event "attaked"

 

there only two - one from prefab and one from follower component, so there a question :

since i dont know which function is from follower component and which is from prefab can i just remove follower component, then empty listeners like

p = GetPlayer()abigail = TheSim:FindFirstEntityWithTag("abigail")player.event_listeners.onattacked[abigail]={}inst:RemoveComponent(follower)inst:AddComponent(follower) -- its adds again his listenerinst:ListenForEvent("attacked", MyOnAttacked)

or there maybe some way to detect function's source file or anything?

Put different prints in both functions and see what appears in log file. Then you will know what function was executed.

For events there is some function in entityscrip.lua

local function RemoveListener(t, event, inst, fn)    if t then        local listeners = t[event]        if listeners then            local listener_fns = listeners[inst]            if listener_fns then                RemoveByValue(listener_fns, fn)                if next(listener_fns) == nil then                    listeners[inst] = nil                end            end            if next(listeners) == nil then                t[event] = nil            end        end    endend

But I don't know how to make it work, I tired few times and it was crashing my game, maybe I'm missing something.

Link to comment
Share on other sites

different prints cant help here, there can be few other functions from mods/dlc/new updated/whatever

so i need reliable method to detect function from prefab.

 

i saw entityscript.lua and saw this function, my question is not about removing, its actually pretty simple, its more about functions properties/attributes or whatever that helps to identify it

Link to comment
Share on other sites

different prints cant help here, there can be few other functions from mods/dlc/new updated/whatever

so i need reliable method to detect function from prefab.

 

i saw entityscript.lua and saw this function, my question is not about removing, its actually pretty simple, its more about functions properties/attributes or whatever that helps to identify it

You can replace prefab functions like that in modmain:

function PineconePrefabPostInit(inst)	inst.OnLoad = function(inst, data)		if data and data.growtime then			plant_mod(inst, data.growtime)		end	endendAddPrefabPostInit("pinecone", PineconePrefabPostInit)

That makes prefab to use my OnLoad function instead of its local function.

Link to comment
Share on other sites

You can replace prefab functions like that in modmain:

function PineconePrefabPostInit(inst)	inst.OnLoad = function(inst, data)		if data and data.growtime then			plant_mod(inst, data.growtime)		end	endendAddPrefabPostInit("pinecone", PineconePrefabPostInit)

That makes prefab to use my save function instead of its local function.

you cant make few Listeners for same event

in entityscript.lua you can see

 

local function AddListener(t, event, inst, fn).... skipped ....    table.insert(listener_fns, fn)end

 

that this function add new listener's functions in table instead replacing

 

in short : its dont replace prefab's local function

Link to comment
Share on other sites

its just common task, maybe guru like simplex or squeek share some LUA magic

 

someprefab.lua:

local function fn()end someglobalvariable.fn = fn

 

somemain.lua

if magicLUAfn(someglobalvariable.fn)=="someprefab" then print "Kitten saved!" end

 

question is - is it possible to make such magicLUAfn :)

Link to comment
Share on other sites

and inst.onload - you directly assign function,no questions here, easymode :-)

while listener assigns via function

Meh, just overwrite whole prefab file then, cause I don't see other way around this.

You can have more than one listener for the same event, I had it like that in some prefabs, but the code on both functions was different, not edit to the first one.

And what you want to do with Abigail?

Link to comment
Share on other sites

give her new brains and some kind of control

like different modes : attack (anything on sight), defense (she already have this) and ignore mode, when she avoid fight and dont respond on attacks.

dont think that spirit must be so dumb and dont listen Wendy for orders :-)

 

and there problem - we need to change prefab's "onattacked" to implement "ignore mode".

 

i already did same for hounds, but there was alot of changes so yes, i just rewrite prefab.

but here i want to do it in API way if possible. Who knows maybe KLEI will do something with abigail in future.

Link to comment
Share on other sites

give her new brains and some kind of control

like different modes : attack (anything on sight), defense (she already have this) and ignore mode, when she avoid fight and dont respond on attacks.

dont think that spirit must be so dumb and dont listen Wendy for orders :-)

Kill the events in prefab postinit:

inst:RemoveAllEventCallbacks()

and add your edits after that.

 

Removed events from pigman and he didn't fight back, so maybe that should work.

Link to comment
Share on other sites

its removes all events, imho not good idea. since there can be events which was added by mods before my.

You can remove just one of them:

function EntityScript:RemoveEventCallback(event, fn, source)    assert(type(fn) == "function") -- signature change, fn is new parameter and is required    source = source or self    RemoveListener(source.event_listeners, event, self, fn)    RemoveListener(self.event_listening, event, source, fn)end

Just need to make that working.

Link to comment
Share on other sites

yes, but as i said in OP problem is here:

assert(type(fn) == "function") -- signature change, fn is new parameter and is required

i cant define fn, since its local function from prefab. Its unknown for modmain.lua

You are trying to hard, don't worry about the other mods and do what must be done, don't see any Abigail mod on workshop atm.

But that thing in RemoveEventCallback should change, itsunmodable atm, doubt any LUA magic can fix it cause its local function, and if its local it don't exist for modmain.

Link to comment
Share on other sites

You are trying to hard ...  and if its local it don't exist for modmain.

Well yes, its just interesting to me, sometimes even more than game itself :grin: ( Hello, i am Rincewind and i am scriptoholic)

 

yes its local, but there difference, i have list of function's addresses, so only what i need - possibility to know which address is belong to module(prefab).

Link to comment
Share on other sites

Well yes, its just interesting to me, sometimes even more than game itself :grin: ( Hello, i am Rincewind and i am scriptoholic)

 

yes its local, but there difference, i have list of function's addresses, so only what i need - possibility to know which address is belong to module(prefab).

And that function address will be constant for every system you can run the game on?

The change was done to remove event callback, and it has to be fixed now.

Its funny how we can kill all events from modmain with just one command and can't kill one event.

Link to comment
Share on other sites

well, according to this http://stackoverflow.com/questions/17763223/lua-table-address-and-address-table
two runs of lua interpreter show same address

e$ luaLua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio> print({})table: 0x7fdaca4098c0> ^De$ luaLua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio> print({})table: 0x7fb02a4098c0> ^De$

but like in any interpreter - its not real memory address, its just emulation and for my task its doesnt matter.

Link to comment
Share on other sites

well atm i am thinking about such trick:

since there only 2 functions in list i can find function from prefab by finding address of follower's component listener

 

its like

local test = CreateEntity()test:AddComponents("follower")

and then i have to compare addresses of listerner inside test and my list. If i understand correctly address of

local function onattacked(inst,data )

inside follower component must be same for both instances

 

then i can even call RemoveEventCallback(event, fn, source)

 

will try it soon :-)

 

my guess that first in table will be function from component, second function - from prefab

all others is must be from mods

 

so my target is second one, just want to be sure.

Link to comment
Share on other sites

well atm i am thinking about such trick:

since there only 2 functions in list i can find function from prefab by finding address of follower's component listener

 

its like

local test = CreateEntity()test:AddComponents("follower")

and then i have to compare addresses of listerner inside test and my list. If i understand correctly address of

local function onattacked(inst,data )

inside follower component must be same for both instances

 

then i can even call RemoveEventCallback(event, fn, source)

 

will try it soon :-)

 

my guess that first in table will be function from component, second function - from prefab

all others is must be from mods

 

so my target is second one, just want to be sure.

There is no fn hook for that event.

It is just event pushed by combat component, by GetAttacked() function and only fn field in ther is called gethitfn or something like that.

While other RemoveEventCallback have fn fields and are called via component.

Link to comment
Share on other sites

yeah all work as i expected - there a proof via console :

70851c2c0239f97943d85fe61f68a710.jpg

there 2 abigail, bcz i spawned them via debugspawn

p is GetPlayer(). p.test - is test entity with follower component and nothing else.

but as you see functions in table have same address, so thats the way to find local function from prefab and remove it from table

 

well if made more reliable function to detect non-component listener i have to check 9 standard components.

all of them have listener for "attacked". and my life will be complete :)

Link to comment
Share on other sites

yeah all work as i expected - there a proof via console :

70851c2c0239f97943d85fe61f68a710.jpg

there 2 abigail, bcz i spawned them via debugspawn

p is GetPlayer(). p.test - is test entity with follower component and nothing else.

but as you see functions in table have same address, so thats the way to find local function from prefab and remove it from table

 

well if made more reliable function to detect non-component listener i have to check 9 standard components.

all of them have listener for "attacked". and my life will be complete :-)

Interesting, will just download that to look at the code, but still its way to much effort just to remove 1 event callback, it should be supported by mod api without all that workarounds.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...