RAINBOW Posted April 13, 2014 Share Posted April 13, 2014 I've reached a point in modding, where I need to learn what this function: ISTimedActionQueue Does. What I have learned from delving into PZ modding, is that lua calls require knowing what is going on here. I'm assuming this is the handler for all the action "bar" related things that go on in PZ. Such as eating a "Ham" item in my example. ("Jambon" if you are Robert Johnson ) so booleans like "Finished" and "Started" are all there in the documentation (as you would expect). My example pertains to the following piece of code I have copied out of the lua file which deals extensively with the inventory panel (You can find the example files in "Steam/SteamApps/Media/lua" incidentally!) -- alot of stuff here before -- Then eat it. ISTimedActionQueue.add(ISEatFoodAction:new(player, item, 240)); I decided to debug with a few print statements before I got stuck into it- Heres what I did to debug, basically just see what printed in console: -- Then eat it. ISTimedActionQueue.add(ISEatFoodAction:new(player, item, 240));--debugprint(getItemText(item:getName()));print(item);print(player, item);print(item:getName());The answer, quizzically, was none of the print statements worked! Interesting isn't it! The method defined "item" here: "ISInventoryPaneContextMenu.eatItem = function(item, player)" My suspicions lie entirely with the ActionQueue functions. Does anyone know what is going on here? Link to comment Share on other sites More sharing options...
RoboMat Posted April 13, 2014 Share Posted April 13, 2014 I documented the TA I use for Unpack Bags, so maybe this'll help you: -- =============================================================================-- Unpack Bags-- by RoboMat---- Created: 23.08.13 - 10:39-- =============================================================================require'TimedActions/ISBaseTimedAction';-- -------------------------------------------------- Global Variables-- ------------------------------------------------TAUnpackBag = ISBaseTimedAction:derive("TAUnpackBag");-- -------------------------------------------------- Functions-- ----------------------------------------------------- The condition which tells if the timed action is still valid.--function TAUnpackBag:isValid() return true;end----- Stops the Timed Action.--function TAUnpackBag:stop() ISBaseTimedAction.stop(self);end----- Is called on start of the Timed Action.--function TAUnpackBag:start()end----- Is called when the time has passed.--function TAUnpackBag:perform() local player = self.character; local bag = self.bag; local inventory = bag:getInventory(); -- Get the bag's inventory. local container = bag:getContainer(); -- Get the container in which the bag itself is contained. -- Remove all items from the baggage container. inventory:removeAllItems(); -- Now we move all the items from the bag to the container. container:setDrawDirty(true); for _, item in ipairs(self.itemsInBag) do if item then -- If the floor is selected add the items to the ground. if container:getType() == "floor" then player:getCurrentSquare():AddWorldInventoryItem(item, 0.0, 0.0, 0.0); else container:AddItem(item); end end end -- Make sure we refresh the inventory so the items show up. local pdata = getPlayerData(player:getPlayerNum()); if pdata then pdata.playerInventory:refreshBackpacks(); pdata.lootInventory:refreshBackpacks(); end -- Remove Timed Action from stack. ISBaseTimedAction.perform(self);end----- Constructor-- @param _character - The character who performs the action.-- @param _table - The table containing all items in the bag.-- @param _bag - The container / bag itself.-- @param _time - The time to complete the action.--function TAUnpackBag:new(_character, _table, _bag, _time) local o = {}; setmetatable(o, self); self.__index = self; o.character = _character; o.bag = _bag; o.itemsInBag = _table; o.stopOnWalk = false; o.stopOnRun = false; o.maxTime = _time; return o;end and yeah just like you thought you'll have to add it to the queue some time: ISTimedActionQueue.add(TAUnpackBag:new(_player, _itemsInContainer, bag, 50));That's all you need Link to comment Share on other sites More sharing options...
RAINBOW Posted April 13, 2014 Author Share Posted April 13, 2014 RoboMat, you are an absolute legend. I owe you a coke. Link to comment Share on other sites More sharing options...
RAINBOW Posted April 16, 2014 Author Share Posted April 16, 2014 Hmm.. This is all well and good, but what about when you are wanting to "Check" on the progress of a timed action? Here's what I mean in code, the example is called from an overridden base lua file in my mod folder, and is working in the 'traditional sense' of throwing errors: --Lots of stuff came before here.... -- Then eat it.ISTimedActionQueue.add(ISEatFoodAction:new(player, item, 240)); --------------------------------------------------------------- --+Debug+-- "The statement AAAAAA will print fine, just after this action queue has been called here in my--overrided base lua. But BBBBB will not execute."player:Say("AAAAAA");---------------------------------------------------------------if ISTimedActionQueue.finish(ISEatFoodAction) == true thenplayer:Say("BBBBB"); end --------------------------------------------------------------- The code throws a "Called T nil" error, and "BBBBB" is never printed! I double checked that "finish" is an acceptable boolean here. I looked for examples of checking for a finished action queue, and have last resorted to this post. Cheers in advance! Raenbow Link to comment Share on other sites More sharing options...
RAINBOW Posted April 16, 2014 Author Share Posted April 16, 2014 Ah ha! I've been editing code where I shouldn't be, haven't I? I've been editing the "Right Click Inventory Panel" lua, when I needed to be in the "ISEatFoodAction.lua"! it's no wonder I've been unable to find a finish option! Link to comment Share on other sites More sharing options...
EnigmaGrey Posted April 16, 2014 Share Posted April 16, 2014 Going out on a limb, but I'd assume it's because you're testing whether a uninitialized action is complete -- something that'd never happen, it not existing.Tryo = ISEatFoodAction:new(player, item, 240) ISTimedActionQueue.add(o)...if ISTimedActionQueue.finish(o) == true thenplayer:Say("BBBBB"); end Link to comment Share on other sites More sharing options...
RoboMat Posted April 17, 2014 Share Posted April 17, 2014 You could also hook into the perform() function of the timed action as that one is performed after the "progress bar" is full. function ISFooBarAction:perform() -- do fun code stuff here player:Say('Never Gonna Give You Up');end Unless I misunderstood what you want to do. Link to comment Share on other sites More sharing options...
RAINBOW Posted April 21, 2014 Author Share Posted April 21, 2014 The problem I have discovered, is I can hook into the Event fired in the "Right Click Inventory Panel" which is found here: C:\Program Files (x86)\Steam\SteamApps\common\ProjectZomboid\media\lua\ISUI\ISInventoryPaneContextMenu.lua" here's some sample code that fires okay from right clicking in game: --The player has right clicked the menu. function RClickMenu.init(player, context, items) --debugplayer:Say("AAAAAAAA"); end Events.OnFillInventoryObjectContextMenu.Add(RClickMenu.init);But! what about when I want to access the code within, in particular, the "ISEatFoodAction.perform"? Link to comment Share on other sites More sharing options...
RoboMat Posted April 21, 2014 Share Posted April 21, 2014 Why would you want to create an Inventory Context Menu when the player has finished eating stuff? Link to comment Share on other sites More sharing options...
RAINBOW Posted April 21, 2014 Author Share Posted April 21, 2014 I don't! There's just no "Event" in the "ISEatFoodAction.lua" for me to hook into Link to comment Share on other sites More sharing options...
RoboMat Posted April 21, 2014 Share Posted April 21, 2014 I'm confused then. What exactly are you trying to do? Link to comment Share on other sites More sharing options...
RAINBOW Posted April 21, 2014 Author Share Posted April 21, 2014 Agh! Nevermind, I went back to it after a cup of tea, was calling a bloody nil table for the 1000th time, if anyone reading this ever see's the error "Called T nil table" or whatever it is, it is because one of your vars is undeclared. thing is working perfectly now. lol ! Sorry I bloody wasted everyones time. Here's some working code: RClickMenu = {}; --The player has right clicked the menu. If shit happens, do shit.function RClickMenu.init(player, context, items) --custom SANCTUARY here:function ISEatFoodAction:perform()-- do fun code stuff hereself.character:Say('Never Gonna Give You Up');endend Events.OnFillInventoryObjectContextMenu.Add(RClickMenu.init);Fixed code-tags. -RM Link to comment Share on other sites More sharing options...
RoboMat Posted April 21, 2014 Share Posted April 21, 2014 I don't want to sound like a dick, but that's totally wrong RAINBOW ^^ Here is example code from my unpack bags mod. It does what you are trying to do (I think) which is starting a timed action once the player has clicked a context menu in the inventory. Timed Action-- =============================================================================-- Unpack Bags-- by RoboMat---- Created: 23.08.13 - 10:39-- =============================================================================require'TimedActions/ISBaseTimedAction';-- -------------------------------------------------- Global Variables-- ------------------------------------------------TAUnpackBag = ISBaseTimedAction:derive("TAUnpackBag");-- -------------------------------------------------- Functions-- ----------------------------------------------------- The condition which tells the timed action if it-- is still valid.--function TAUnpackBag:isValid() return true;end----- Stops the Timed Action.--function TAUnpackBag:stop() ISBaseTimedAction.stop(self);end----- Starts the Timed Action.--function TAUnpackBag:start()end----- Is called when the time has passed.--function TAUnpackBag:perform() local player = self.character; local bag = self.bag; local inventory = bag:getInventory(); -- Get the bag's inventory. local container = bag:getContainer(); -- Get the container in which the bag itself is contained. -- Remove all items from the baggage container. inventory:removeAllItems(); -- Now we move all the items from the bag to the container. container:setDrawDirty(true); for _, item in ipairs(self.itemsInBag) do if item then -- If the floor is selected add the items to the ground. if container:getType() == "floor" then player:getCurrentSquare():AddWorldInventoryItem(item, 0.0, 0.0, 0.0); else container:AddItem(item); end end end -- Make sure we refresh the inventory so the items show up. local pdata = getPlayerData(player:getPlayerNum()); if pdata then pdata.playerInventory:refreshBackpacks(); pdata.lootInventory:refreshBackpacks(); end -- Remove Timed Action from stack. ISBaseTimedAction.perform(self);end----- Constructor-- @param _character - The character who performs the action.-- @param _table - The table containing all items in the bag.-- @param _bag - The container / bag itself.-- @param _time - The time to complete the action.--function TAUnpackBag:new(_character, _table, _bag, _time) local o = {}; setmetatable(o, self); self.__index = self; o.character = _character; o.bag = _bag; o.itemsInBag = _table; o.stopOnWalk = false; o.stopOnRun = false; o.maxTime = _time; return o;end Inventory-- =============================================================================-- Unpack Bags-- by RoboMat---- Created: 22.08.13 - 12:00-- =============================================================================require'Mods/UnpackBags/TimedActions/TAUnpackBag';require'TimedActions/ISTimedActionQueue';-- -------------------------------------------------- Local Variables-- ------------------------------------------------local zomboid = zomboid;local table = table;-- -------------------------------------------------- Local Functions-- ----------------------------------------------------- Creates the timed action which empties the bag.-- @param _items - A table containing the clicked items / stack.-- @param _player - The player who clicked the menu.-- @param _itemsInContainer - The items contained in the bag.-- @param _bag - The bag to unpack.--local function onUnpackBag(_items, _player, _itemsInContainer, _bag) local bag = _bag; local bagWeight = bag:getInventory():getCapacityWeight(); local container = bag:getContainer(); local conWeight = bag:getContainer():getCapacityWeight(); -- We check if the target bag has enough free capacity to hold the items. if container:getCapacity() < (bagWeight + conWeight) then zomboid.okModal("There is not enough space to unpack the bag here.", true); return; end ISTimedActionQueue.add(TAUnpackBag:new(_player, _itemsInContainer, bag, 50));end----- Creates a context menu entry when the player selects-- an inventory container (e.g. hiking bag).-- @param _player - The player who clicked the menu.-- @param _context - The context menu to add a new option to.-- @param _items - A table containing the clicked items / stack.--local function createMenu(_player, _context, _items) local itemTable = _items; -- The table containing the clicked items. local context = _context; local player = getSpecificPlayer(_player); -- We iterate through the table of clicked items. We have -- to seperate between single items, stacks and expanded -- stacks. for i1 = 1, #itemTable do local item = itemTable[i1]; if instanceof(item, "InventoryItem") and instanceof(item, "InventoryContainer") then local bag = item; -- Store the clicked bag. local itemsInContainer = table.convertArrayList(bag:getInventory():getItems()); -- Get its contents. -- Only create a menu entry if the bag contains an item. if #itemsInContainer > 0 then context:addOption("Unpack (" .. #itemsInContainer .. " Items)", itemTable, onUnpackBag, player, itemsInContainer, bag); end elseif type(itemTable[i1]) == "table" then -- We start to iterate at the second index to jump over the dummy -- item that is contained in the item-table. for i2 = 2, #itemTable[i1].items do local item = itemTable[i1].items[i2]; if instanceof(item, "InventoryItem") and instanceof(item, "InventoryContainer") then local bag = item; local itemsInContainer = table.convertArrayList(bag:getInventory():getItems()); if #itemsInContainer > 0 then context:addOption("Unpack (" .. #itemsInContainer .. " Items)", itemTable, onUnpackBag, player, itemsInContainer, bag); end end end end endend-- -------------------------------------------------- Game Hooks-- ------------------------------------------------Events.OnPreFillInventoryObjectContextMenu.Add(createMenu); You never directly call a timed action's functions since they are called automatically by the engine. You only add them to the queue:local function onUnpackBag(_items, _player, _itemsInContainer, _bag) -- <snip> -- this is all you will ever need to call for a timed action ISTimedActionQueue.add(TAUnpackBag:new(_player, _itemsInContainer, bag, 50));end Link to comment Share on other sites More sharing options...
RoboMat Posted April 21, 2014 Share Posted April 21, 2014 To elaborate: ISEatFoodAction can be compared to a class that you'd have in an OOP language. The ...new() function is a constructor which creates a new object (through metatable-wizardy and magic) and returns it.So you could rewrite the above example like this: -- Create a new instance of the timed action.local TAobject = TAUnpackBag:new(_player, _itemsInContainer, bag, -- Add it to the queue for timed actions.ISTimedActionQueue.add(TAobject); Of course you could now call the methods of the created objects outside of the timed action queue (albeit I never tried that, because I never needed it^^) like this: TAObject:perform() If you'd try to call TAUnpackBAgs:perform() you'd try to call a function and since perform() internally tries to access variables that are only initialised via a constructor you'll get "tried to call nil" exceptions a lot. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now