Page 1 of 2

The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 8:38 pm
by NutJob
This thread is dedicated to code you think should work but it won't or throws an error and is potentially a bug. This is not for musing code theory and how to use certain aspects of the API.

This code throws an error:

Code: Select all

local o = findEntity("someItemIDthatIsEquipable")
o.item:addConnector("onEquipItem", "myScriptEntity", "mySuperAwesomeFunctionWhenEquipping")
Image

Re: The "Has anyone got this code work?" thread

Posted: Mon Nov 24, 2014 8:43 pm
by Doridion
NutJob, have you tried : o.go.item ? already got this error style when i define objects, and adding ".go." solve many problems.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 8:48 pm
by NutJob
Initialization (instantiation?) is not from a calling object so it never occurred to me (I'm directly working with the object). Also, no that doesn't work; decided to try anyway being I'm on attempt #6,209 (not really) to make it work.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 8:53 pm
by minmay
What that error is telling you is that when connectors trigger, they use some property of the triggering game object's map. A game object that is held by the mouse or in a champion's inventory or a container will have a nil map. This makes perfect sense, since it doesn't have a position in the game world, but it also prevents you from triggering any connectors from an item that's in inventory.

(Don't ask me why it looks at the map; I don't know).

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 9:01 pm
by NutJob
All right, well, I guess I'll chalk this up to "not possible" and stick with directly putting the functions in the defineObject:
SpoilerShow

Code: Select all

defineObject{
	baseObject = "base_item",
	name = "someItemWithEvents",
	components = {
		{
			class = "Item",
			onEquipItem = function(self, champion, slot) print(self, champion, slot) end,
			onUnequipItem = function(self, champion, slot) print(self, champion, slot) end,
		}
	}
}
This does work fine with no map is nil error.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 10:03 pm
by JKos
That smells like a bug to me. But if you want to set onEquip and onUnequip-hooks to all items easily you can use this function with cloneObject

Copy paste to your init.lua or clone_object.lua for example

Code: Select all

function addHooksToComponents(componentName,hooks,override)
	for name,def in pairs(defines) do
		local c = findComponent(def,componentName)
		if c then
			for hookName,method in pairs(hooks) do
				if override or c[hookName] == nil then
					c[hookName] = method
				end
			end
			defineObject(def);
		end
	end
end
then call it like this

Code: Select all

local hooks = {
		onEquipItem = function(self, champion, slot) 
			your.script.onEquipItem(self, champion, slot) 
		end,
		onUnequipItem = function(self, champion, slot) 
			your.script.onUnequipItem(self, champion, slot) 
		end
	}
addHooksToComponents('item',hooks)
This will set those hooks to all item-components. If you want to override all existing hooks you can call
addHooksToComponents('item',hooks,true)

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 10:17 pm
by QuintinStone
NutJob wrote:This thread is dedicated to code you think should work but it won't or throws an error and is potentially a bug. This is not for musing code theory and how to use certain aspects of the API.

This code throws an error:

Code: Select all

local o = findEntity("someItemIDthatIsEquipable")
o.item:addConnector("onEquipItem", "myScriptEntity", "mySuperAwesomeFunctionWhenEquipping")
Image
When is this code being called?

I've found that certain properties can't be set in a script that runs immediately when a game starts, apparently because the map has not been initialized yet.

If this is something that runs when the game starts, try triggering it off of a timer game object instead.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 10:28 pm
by NutJob
For the sake of testing I moved the whole thing to a floor_trigger partyOnly. Edit: also because all 4 of my scripts (238 functions) are loaded from a single script_entity with this amazing script loader nothing gets fired before everything else is loaded into the game. I used to have problems with spawned in objects that I literally had to move up in load order in the dungeon.lua so it would work. So I do understand why you asked that question and it's a valid problem but not with that script loader.

Aye, thanks for the possible work-around Jkos, and I do have your cloning script setup and ready to use. I'll report back if it does circumvent "whatever" is happening.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 10:49 pm
by JKos
I tested that code and at least for me it worked fine, tested save game compatibility too just in case. I wrote it for my dynamic hook framework and just happened to notice this thread so I shared it.
I think that it shouldn't be used with onThink-hook or anything which is called rapidly by multiple entities for performance reasons. onEquip and other rarely called hooks should be fine.

Re: The "Has anyone got this code to work?" thread

Posted: Mon Nov 24, 2014 11:00 pm
by NutJob
Here is the stripped down testing code that gets fired on a floor_trigger:

Code: Select all

function myTestSpawn()
	local o = spawn("rope", party.level, party.x, party.y, 0, party.elevation)
	o.item:addConnector("onEquipItem", "lib", "aaa")
	o.item:addConnector("onUnequipItem", "lib", "bbb")
end

function aaa()
	print("A")
end

function bbb()
	print("B")
end
It makes the rope, and sets it in front of the party (because they were moving north when stepping on the trigger). I can pick it up (on mouse event), no error. I can drop on a portrait (so it auto-inventories), no error. But I can't directly drop it on a slot (backpack or character slot [1, 2]).