Page 1 of 1

calling global function from object

Posted: Sun Oct 22, 2017 11:35 pm
by .rhavin
In the following example, the global function qpttest is called after the script loaded. However, from inside the item, I get the notification "qpttest not defined", so qpttest is nil inside onEquipItem. How can i define a function inside a script like this that I can call?

Code: Select all

print("skript loaded")
function qpttest()
	print "test called"
end
qpttest()

defineObject{
	name = "breadling",
	baseObject = "bread",
	components = {
		{
			class = "Item",
			uiName = "breadling",
			gfxIndex = 1,
			onEquipItem = function(self, champion, slot)
				hudPrint(champion:getName().."uses breadling.")
				if (qpttest ~= nil) then
					qpttest()
				else
					print("qpttest not defined")
				end
			end,
		},
	},
}

Re: calling global function from object

Posted: Sun Oct 22, 2017 11:51 pm
by minmay
Hooks get a different environment than init scripts. It's similar to the environment that ScriptComponents get.

There are three options:
1. Make it an upvalue by defining it as a local function. However, if you do this, you have to make sure to only use it in functions that don't get serialized.
2. Move it to a ScriptComponent in the dungeon. This can be annoying to maintain.
3. Put it in a table that is available in both environments, such as Config:

Code: Select all

print("skript loaded")
Config.qpttest = function()
   print "test called"
end
Config.qpttest()

defineObject{
   name = "breadling",
   baseObject = "bread",
   components = {
      {
         class = "Item",
         uiName = "breadling",
         gfxIndex = 1,
         onEquipItem = function(self, champion, slot)
            hudPrint(champion:getName().."uses breadling.")
            if (Config.qpttest ~= nil) then
               Config.qpttest()
            else
               print("qpttest not defined")
            end
         end,
      },
   },
}
This last approach is the most hacky of the three, but it's also the closest one to your desired functionality (sharing an environment between init scripts and hooks). Note that any changes made to Config (and the other "global" tables) will not be serialized, and will persist until the game is closed. This is fine for a case like this one, but it means you shouldn't try to store mutable data in it for instance.

Re: calling global function from object

Posted: Mon Oct 23, 2017 12:52 am
by Isaac
Anytime I've used Config for that, I've put it into categorized keys.

* Config.Isaac.ut.nudgeObject()
* Config.Isaac.ut.delayedCall2()
* Config.Isaac.colorTable['puce']
* Config.Isaac.gui.currentChampion
etc...

Re: calling global function from object

Posted: Mon Oct 23, 2017 3:18 am
by minmay
Yep, that's a good way to make it less bad from a code quality perspective.

Re: calling global function from object

Posted: Mon Oct 23, 2017 11:02 am
by .rhavin
Ok, comming closer ;)

Now, how do i add a hook for onDrawAttackPanel? The following code gets executed, but the actual hook never gets called:

Code: Select all

print("skript loaded")
if (Config.QDMF == nil) then
	Config.QDMF = {}
end
Config.QDMF.qpttest = function(self, champion, context, x, y)
	context.drawText("panel", 10, 10)
end
Config.QDMF.addhook = function(p,s)
	print "hook added"
	p.party:addConnector('onDrawAttackPanel', s.go.id, "Config.QDMF.qpttest")
end

defineObject{
	name = "a-test",
	baseObject = "dagger",
	components = {
		{
			class = "Item",
			uiName = "A-Test",
			gfxIndex = 10,
			gfxIndexPowerAttack = 415,
			onEquipItem = function(self, champion, slot)
				hudPrint(champion:getName().." uses A-Test.")
				Config.QDMF.addhook(party,self)
			end,
		},
	},
	tags = { "weapon" },
}

Re: calling global function from object

Posted: Mon Oct 23, 2017 2:46 pm
by Isaac
Certain Party hooks must be defined in the object, or they don't get called—despite having connectors to them.

Code: Select all

--object.lua
defineObject{
	name = "party",
	baseObject = "party", --copy/inherit object
	components = {
		{	--component changes must redefine the entire component being changed, not just the changes to it
			class = "Party",

			-- minimal dummy function to enable hook; this is all you need
			onDrawAttackPanel = function() end,   

			-- optional/ instead: defined to pass along parameters 
			onDrawAttackPanel = function(...) myScript.script.myFunction(...) end,  
		},
	}
}