Tiafu Posted January 19, 2019 Share Posted January 19, 2019 Hi! name's Ti and I'm making my first mod, I'm kind of a programmer so I have a little bit of code understanding yet .lua is absolutely new to me and the way to address things in-game has been really difficult to understand, so I'm leaving aside my stubbornness about never asking for help and.. well... asking for help ;-; I'm making a character mod and so far everything is working fine, the only problem I have are the perks I'm trying to give to the character... I know what I want to do but can't figure out how to do it with the knowledge I have of .lua as programming language... so basically there are two perks I'm trying to make (besides a custom item that I haven't quite added yet) and those are -if the character is idle for a certain amount of time, they start losing sanity (I have figured out the time and how to calculate it, what I can't actually program is how to find the character's position and if they moved or not) -time to time the character is supposed to "forget" recipes from the crafting tab, so they should get locked again, making it impossible to craft unless there's a science machine/alchemy engine.(as if they've never learned it) If anyone has an idea of how to do this or point me to a guide that can help me understand the game programming more I'd really appreciate it... Link to comment Share on other sites More sharing options...
Ultroman Posted January 19, 2019 Share Posted January 19, 2019 (edited) For checking whether the character is standing still, there are a couple of ways. This first one looks at the actual motorspeed of the character, which means if the character is moved without input from the player, like when pushed by an AoE or something, the motorspeed is going to be not 0. The following code keeps updating a variable called LastMovementTime on the player instance, which holds the last time any movement of the character was detected. inst.LastMovementTime = -100 -- just setting a starting value to something ridiculously low, so it isn't nil inst:DoPeriodicTask(0.2, function(inst) if inst.Physics:GetMotorSpeed() ~= 0 then inst.LastMovementTime = GLOBAL.GetTime() end end You can then check against the current time, to see if enough time has passed to apply the sanity loss. The following example already has the code from the snippet above, so you don't need both. inst.LastMovementTime = -100 -- just setting a starting value to something ridiculously low, so it isn't nil local sanityLossPerSecond = 0.5 local periodicTaskInterval = 0.2 -- keep this below 1.0, so there isn't too large a period between updating. It'll reduce the margin of error for the edgecases. inst:DoPeriodicTask(periodicTaskInterval, function(inst) if inst.Physics:GetMotorSpeed() ~= 0 then inst.LastMovementTime = GLOBAL.GetTime() end if GLOBAL.GetTime() - inst.LastMovementTime > delayBeforeLosingSanity then -- remove sanity inst.components.sanity:DoDelta(sanityLossPerSecond * periodicTaskInterval) end end I'm not 100% sure, but I think this next example will react only to voluntary movement, so if the character is pushed/moved by some physics-stuff, it will still count as standing still. inst.LastMovementTime = -100 -- just setting a starting value to something ridiculously low, so it isn't nil local sanityLossPerSecond = 0.5 local periodicTaskInterval = 0.2 -- keep this below 1.0, so there isn't too large a period between updating. It'll reduce the margin of error for the edgecases. inst:DoPeriodicTask(periodicTaskInterval, function(inst) if inst.components.locomotor.isrunning then inst.LastMovementTime = GLOBAL.GetTime() end if GLOBAL.GetTime() - inst.LastMovementTime > delayBeforeLosingSanity then -- remove sanity inst.components.sanity:DoDelta(sanityLossPerSecond * periodicTaskInterval) end end This code should go at the bottom of your character's fn() or post-init function. Also, you will help yourself A LOT if you just took a short course in LUA. Here's a crash course, and I advise you to take more. About forgetting recipes, that is pretty complex, due to the complexity of the whole recipe-system. There are functions for learning recipes, but not for removing them. There is a similar topic on the forum here, where someone wanted to do exactly that. Search around and you should find it. Not sure if they ever figured it out, though. Edited January 19, 2019 by Ultroman Link to comment Share on other sites More sharing options...
Tiafu Posted January 19, 2019 Author Share Posted January 19, 2019 Thank you! @Ultroman that was really helpful!! tho the GLOBAL variable doesn't really work outside modmain.lua, in <character>.lua is not necessary. I was in the right tracks but couldn't figure out how to actually write down what I needed. DoDelta is also not a great visual so I changed the code a to sanity.dapperness and added a few things and now is working perfectly! exactly how I wanted it to be! thank you for linking the lua tutorial too! but my problem is not with lua itself but some of the games' way to use it, your example though was extremely helpful!! As for the second perk I did see the thread about someone else trying to do the same thing, but I didn't see any concrete answer, some methods that didn't really worked or had some visual issues, though I think I can implement what I'm looking for in a different way Again, Thank you for your reply! it was really helpful and I got it working in no time ! Link to comment Share on other sites More sharing options...
Ultroman Posted January 19, 2019 Share Posted January 19, 2019 Oh yeah, in a character's LUA, you shouldn't have the GLOBAL. in from of the global variables/functions. All my code is usually in the modmain, that's why Link to comment Share on other sites More sharing options...
IronHunter Posted January 19, 2019 Share Posted January 19, 2019 Well I got a solution for forgetting things overtime. Spoiler AddComponentPostInit("builder", function(self) self.RemoveRecipe = function(self, recname) if table.contains(self.recipes, recname) then for k, v in ipairs(self.recipes) do if v == recname then table.remove(self.recipes, k) break end end end self.inst.replica.builder:RemoveRecipe(recname)--already exists end self.LockRecipe= function(self, recname) local recipe = GLOBAL.GetValidRecipe(recname) if recipe ~= nil and not recipe.nounlock then --print("Locking: ", recname) self:RemoveRecipe(recname) self.inst:PushEvent("lockrecipe", { recipe = recname }) end end end) This needs to go into modmain To forget random ones we need to Spoiler local function forget(inst)--goes above the Postinit if inst.components.builder then local size = #inst.components.builder.recipes if size > 0 then local rand = math.random(1,size) inst.components.builder:LockRecipe(inst.components.builder.recipes[rand]) end end end --Common Postinit --Master Postinit inst.forgetful = inst:DoPeriodicTask(10, forget)--adjust to your liking This goes into your character's prefab file If you want to lose sanity or do other things whenever you forget you can inst:ListenForEvent("lockrecipe", yourfunction) with your function being a -dodelta to sanity etc. Link to comment Share on other sites More sharing options...
Ultroman Posted January 19, 2019 Share Posted January 19, 2019 (edited) 2 hours ago, Tiafu said: DoDelta is also not a great visual so I changed the code a to sanity.dapperness and added a few things and now is working perfectly! What do you mean DoDelta is not a great visual? You can add a value to the "overtime" parameter, to control whether you want it to pulse (and make the noise) when regenerating. Adding "false" after the number lets it pulse and make noise (this is default behavior if you do not add the parameter, so this was what you had with my code), and if you don't want it to give the pulse and noise, you just put in "true". inst.components.sanity:DoDelta(sanityLossPerSecond * periodicTaskInterval, true) The problem with using the sanity.dapperness value, is that everyone else uses it, so you can't really trust its value over time, so you can't save it, and reset it later. All you can do is add your specific value to it, and when you want to remove it again, subtract your specific value from it. Otherwise, you might mess up something that another mod is doing to it. Edited January 19, 2019 by Ultroman Link to comment Share on other sites More sharing options...
Tiafu Posted January 19, 2019 Author Share Posted January 19, 2019 @IronHunter OH GOSH THANK YOU!!!! That works PERFECTLY AAHH!!! THANK YOU SO MUCH!!!!!! 1 hour ago, Ultroman said: The problem with using the sanity.dapperness value, is that everyone else uses it, so you can't really trust its value over time, so you can't save it, and reset it later. All you can do is add your specific value to it, and when you want to remove it again, subtract your specific value from it. Otherwise, you might mess up something that another mod is doing to it. wait does that mean that if if something else is causing a drop/gain in sanity with sanity.dapperness it'll mess up? I haven't tested the mod enough but I'm doing it right now. I'm not super clear on what kind of problems it can cause... Link to comment Share on other sites More sharing options...
Ultroman Posted January 20, 2019 Share Posted January 20, 2019 (edited) 14 hours ago, Tiafu said: wait does that mean that if if something else is causing a drop/gain in sanity with sanity.dapperness it'll mess up? 5 5 It depends on how you use it. As I said, if you have one specific value, which you add or subtract to/from dapperness at one point, and then do the reverse (add or subtract the value) after a while, you should be fine. You just can't trust saving the "current" dapperness, then change it, and then later reset it to the saved value, because it might have changed in between. Edited January 20, 2019 by Ultroman 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