calling global function from object

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!

calling global function from object

Postby .rhavin » Sun Oct 22, 2017 11:35 pm

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,
      },
   },
}
User avatar
.rhavin
 
Posts: 23
Joined: Fri Oct 13, 2017 1:10 pm
Location: Berlin

Re: calling global function from object

Postby minmay » Sun Oct 22, 2017 11:51 pm

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.
minmay
 
Posts: 2337
Joined: Mon Sep 23, 2013 2:24 am

Re: calling global function from object

Postby Isaac » Mon Oct 23, 2017 12:52 am

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...
User avatar
Isaac
 
Posts: 2491
Joined: Fri Mar 02, 2012 10:02 pm

Re: calling global function from object

Postby minmay » Mon Oct 23, 2017 3:18 am

Yep, that's a good way to make it less bad from a code quality perspective.
minmay
 
Posts: 2337
Joined: Mon Sep 23, 2013 2:24 am

Re: calling global function from object

Postby .rhavin » Mon Oct 23, 2017 11:02 am

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" },
}
User avatar
.rhavin
 
Posts: 23
Joined: Fri Oct 13, 2017 1:10 pm
Location: Berlin

Re: calling global function from object

Postby Isaac » Mon Oct 23, 2017 2:46 pm

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, 
      },
   }
}
User avatar
Isaac
 
Posts: 2491
Joined: Fri Mar 02, 2012 10:02 pm


Return to Mod Creation

Who is online

Users browsing this forum: No registered users and 5 guests