Helwdrokin Posted September 23, 2021 Share Posted September 23, 2021 (edited) so i'm trying to make a mod that checks how many souls wortox has, and when it reaches a certain number, it will drop the excess soul to avoid getting more than 20 souls, and losing sanity due to soul overload. that my code local _G = GLOBAL local MAX = GetModConfigData("MAXSOULS") local function IsSoul(item) return item.prefab == "wortox_soul" end local function GetStackSize(item) return item.components.stackable ~= nil and item.components.stackable:StackSize() or 1 end local function TheDrop(parent) local souls = parent.components.inventory:FindItems(IsSoul) local count = 0 for i, v in pairs(_G.ThePlayer.replica.inventory:GetItems(IsSoul)) do if v ~= nil and v.prefab == "wortox_soul" then for i, v in ipairs(souls) do count = count + GetStackSize(v) end if count > MAX then _G.ThePlayer.replica.inventory:DropItemFromInvTile(v) end end end end AddPlayerPostInit(function(inst) inst:DoPeriodicTask(0.5, function() if 1==1 then TheDrop(inst) end end) end) it works fine in local worlds, but when i add caves or go to a server the games crashes thats the log [00:28:15]: [string "../mods/_Wortox Souls Droping/modmain.lua"]:16: attempt to index field 'inventory' (a nil value) LUA ERROR stack traceback: ../mods/_Wortox Souls Droping/modmain.lua:16 in (upvalue) TheDrop (Lua) <15-29> ../mods/_Wortox Souls Droping/modmain.lua:34 in (field) fn (Lua) <32-36> scripts/scheduler.lua:177 in (method) OnTick (Lua) <155-207> scripts/scheduler.lua:371 in (global) RunScheduler (Lua) <369-377> scripts/update.lua:191 in () ? (Lua) <170-249> this is my first forum post, so sorry if i did something wrong, and ty for you time Edited September 23, 2021 by Helwdrokin Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/ Share on other sites More sharing options...
Nelzanger Posted September 23, 2021 Share Posted September 23, 2021 I'm not sure at 100% but I don't think the inventory gameplay wise is managed client-side (the UI is however). I think you should try to get your content from the inventory replica to see if it solves your issue. Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/#findComment-1497697 Share on other sites More sharing options...
Helwdrokin Posted September 24, 2021 Author Share Posted September 24, 2021 is i tried to search for a function that could replace FindItems() but i couldn't find one i really don't know what to do, i think only if make a function that could replace finditems but idk what self (in inventory.lua) and inst (in general) exactly do Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/#findComment-1497969 Share on other sites More sharing options...
Nelzanger Posted September 24, 2021 Share Posted September 24, 2021 (edited) First, some coding context, if you are interested. Spoiler Lua is lenient on "typing" your variables, aka weakly-typed, meaning that you don't need to declare what type your variable is. This is both a blessing and a curse, because you can use this at your advantage for tricky (and unsafe) parts, but you also don't know what you are manipulating. Knowing the context in where the code is used (what method was called, what are the parameters given, etc.), is important because if you do something wrong, the game will crash, and crashes, along with the logs, are the only thing you can rely on for debugging and understanding what went wrong. Consider this definition in C#, with a strong-typed signature : public List<Entity> FindFoodEntities(List<Enity> entities, bool mode) This code tells you what you are manipulating just by looking at types : public List<Entity> says that your method can be called by an instance of your object and will return a list of objects named "Entity" ; List<Enity> entities says that your first parameter is a list of entities, probably the one you wish to loop on to find the food related ones ; bool mode says that you have a toggle, true or false, for a special processing, for example, finding all the food, or only those who are not spoiled. Consider the same method definition in Lua, which is weakly-typed : local function FindFoodEntities(inst, entities, mode) You can't know what your parameters are, and you don't know what is the return type. You also have an additional parameter, which is "inst". This is how lua works. You just know by looking at it that it will "find entities". To understand what your method is doing, you are obliged to see where this method is used in a practical situation. And yet, you may still need to check further to know what the parameters are made from ! All this to say that in Lua, context is important in order to understand how the code works, because it is not explicitly shown. You will need to dig in lots of files to get a grasp on how things are called and used. And also, why the additional inst ? In Lua, you need to give your own instance as parameter to make effective changes on it. Otherwise, changes will not be applied. Then, onto your question about Inventory.self and inst in general : Inventory is a class. But Lua does not have classes, that's why Klei had the need to emulate its behavior by making class.lua. A class, when created, will reference its own instance, often with a keyword, like "this" in C#, or for our context, "self". With Klei's class, "self" is a variable that contains the instance of the class you created. So when applied to inventory, "self" will reference the instance of the inventory itself. That allows to call methods, or set variables on your own object in other methods without the need to give the instance as a parameter ; "inst" in general, is the instance of an object you are manipulating. In Lua, if your object does not behavior like a class, you need to give the instance as a parameter if you want your changes to be effective on the said instance, otherwise, your changes will not be applied. Finally, I don't think you need to make new functions. You can hook the one that manages the soul drop when going over 20 souls. Let's check how it's managed in wortox.lua : --prefabs/wortox.lua local function CheckSoulsAdded(inst) inst._checksoulstask = nil local souls = inst.components.inventory:FindItems(IsSoul) -- Find souls in the inventory local count = 0 -- Compute how many souls you have in the inventory for i, v in ipairs(souls) do count = count + GetStackSize(v) end -- If you have reached the threshold, then you drop souls if count > TUNING.WORTOX_MAX_SOULS then --convert count to drop count count = count - math.floor(TUNING.WORTOX_MAX_SOULS / 2) + math.random(0, 2) - 1 table.sort(souls, SortByStackSize) local pos = inst:GetPosition() -- Drop X souls at pos for i, v in ipairs(souls) do local vcount = GetStackSize(v) if vcount < count then inst.components.inventory:DropItem(v, true, true, pos) count = count - vcount else if vcount == count then inst.components.inventory:DropItem(v, true, true, pos) else v = v.components.stackable:Get(count) v.Transform:SetPosition(pos:Get()) v.components.inventoryitem:OnDropped(true) end break end end -- Sanity penalty inst.components.sanity:DoDelta(-TUNING.SANITY_MEDLARGE) inst:PushEvent("souloverload") -- If you have 80% of souls on your max allowed, push the event that will probably make Wortox says that he has enough elseif count > TUNING.WORTOX_MAX_SOULS * .8 then inst:PushEvent("soultoomany") end end You can see the part where wortox drops souls if he goes above a specific amount. All you need would be to "hook" this function and redefine its behavior into what you want. Edited September 24, 2021 by Nelzanger Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/#findComment-1497992 Share on other sites More sharing options...
Monti18 Posted September 24, 2021 Share Posted September 24, 2021 5 hours ago, Nelzanger said: You can see the part where wortox drops souls if he goes above a specific amount. All you need would be to "hook" this function and redefine its behavior into what you want. The problem is that this should be a client side mod, but the changes you propose make it an server mod. local _G = GLOBAL local MAX = GetModConfigData("MAXSOULS") local function GetStackSize(item) return item.replica.stackable ~= nil and item.replica.stackable:StackSize() or 1 end local function TheDrop(inst) local count = 0 for i, v in pairs(inst.replica.inventory:GetItems()) do if v ~= nil and v.prefab == "wortox_soul" then count = count + GetStackSize(v) end if count > MAX then inst.replica.inventory:DropItemFromInvTile(v) end end end end Something like this should be able to run completely on the client side without needing to add your own code on the server. 2 Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/#findComment-1498082 Share on other sites More sharing options...
Helwdrokin Posted September 24, 2021 Author Share Posted September 24, 2021 it worked Monti18, I just had to use an if statement to check which inventory slot the soul was in before dropping it, otherwise the character would end up dropping the last item in the inventory i am realy glad for the help ty Monti18 and ty Nelzanger you realy helped me understand how lua works 1 1 Link to comment https://forums.kleientertainment.com/forums/topic/133877-help-with-a-clientside-mod/#findComment-1498137 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