MountainSage Posted January 19, 2016 Share Posted January 19, 2016 So I've been working on a the skeletal beginnings of a mod to add books that manage trait training but I've ran into a problem I can't figure out. I'm pretty new to the language so a little green and I expect this is probably something really obvious that down the line I'll be hitting myself over not getting but I can't seem to modify the traits of a player on completion of a book. Specifically, I'm using my own version of the ISReadABook class based off the original so to handle a book to turn Illiterate into Slow Reader and so far everything works all the way up until the point the reading finishes.Then it just finishes reading and does nothing. Here's the class below that's being used. Does anyone have any idea why this might not be working?Side note: This is located in media/lua/client/TimedActions--**************************************************************************************--** Based off "ISReadABook" by ROBERT JOHNSON **--**************************************************************************************require "TimedActions/ISBaseTimedAction"TTBLearnToRead = ISBaseTimedAction:derive("TTBLearnToRead");TTBLearnToRead.pageTimer = 0;function TTBLearnToRead:isValid() return self.character:getInventory():contains(self.item) and ((self.item:getNumberOfPages() > 0 and self.item:getAlreadyReadPages() <= self.item:getNumberOfPages()) or self.item:getNumberOfPages() < 0);endfunction TTBLearnToRead:update() TTBLearnToRead.pageTimer = TTBLearnToRead.pageTimer + 1; self.item:setJobDelta(self:getJobDelta()); TTBLearnToRead.checkProgress(self); if self.item:getNumberOfPages() > 0 then local timeHours = getGameTime():getTimeOfDay() if timeHours < self.startTimeHours then timeHours = timeHours + 24 end local elapsedMins = (timeHours - self.startTimeHours) * 60 local pagesRead = math.floor(elapsedMins / self.minutesPerPage + 0.0001) if self.startPage + pagesRead > self.item:getAlreadyReadPages() then end self.item:setAlreadyReadPages(self.startPage + pagesRead); if self.item:getAlreadyReadPages() > self.item:getNumberOfPages() then self.item:setAlreadyReadPages(self.item:getNumberOfPages()); end self.character:setAlreadyReadPages(self.item:getFullType(), self.item:getAlreadyReadPages()) endend-- get how much % of the book we already read, then we apply a multiplier depending on the book read progressTTBLearnToRead.checkProgress = function(self) local readPercent = (self.item:getAlreadyReadPages() / self.item:getNumberOfPages()) * 100; if readPercent > 100 then readPercent = 100; self.character:getTraits():remove("Illiterate"); self.character:getTraits():add("SlowReader"); endendfunction TTBLearnToRead:start() self.item:setJobType(getText("ContextMenu_Read") ..' '.. self.item:getName()); self.item:setJobDelta(0.0); self.startTimeHours = getGameTime():getTimeOfDay()endfunction TTBLearnToRead:stop() ISBaseTimedAction.stop(self); if self.item:getNumberOfPages() > 0 and self.item:getAlreadyReadPages() >= self.item:getNumberOfPages() then self.item:setAlreadyReadPages(self.item:getNumberOfPages()); end self.item:setJobDelta(0.0);endfunction TTBLearnToRead:perform() self.item:getContainer():setDrawDirty(true); self.item:setJobDelta(0.0); if self.item:getAlreadyReadPages() >= self.item:getNumberOfPages() then self.item:setAlreadyReadPages(0); end ISBaseTimedAction.perform(self);endfunction TTBLearnToRead:new(character, item, time) local o = {} setmetatable(o, self) self.__index = self o.character = character; o.item = item; o.stopOnWalk = true; o.stopOnRun = true; if item:getNumberOfPages() > 0 then item:setAlreadyReadPages(character:getAlreadyReadPages(item:getFullType())) if isClient() then o.minutesPerPage = ServerOptions.getFloat("MinutesPerPage") or 1.0 if o.minutesPerPage < 0.0 then o.minutesPerPage = 1.0 end else o.minutesPerPage = 2.0 end o.startPage = item:getAlreadyReadPages() local f = 1 / getGameTime():getMinutesPerDay() / 2 time = (item:getNumberOfPages() - item:getAlreadyReadPages()) * o.minutesPerPage / f time = time + o.minutesPerPage / f -- go over the time a little so the last page is read end TTBLearnToRead.pageTimer = 0; o.ignoreHandsWounds = true; o.maxTime = time; return o;end Link to comment Share on other sites More sharing options...
ethanwdp Posted January 19, 2016 Share Posted January 19, 2016 Instead of having a modified vanilla file that will conflict if the game ever updates it, why not just add a book item?I'd imagine that the game has an event that fires once a book is read - if a book has been read and the book name is (for example) "Illiterate_To_Slowreader" and the player has the Illiterate trait, then it calls a function that removes the illiterate trait and adds the Slowreader trait. I'm not sure if it's possible to remove traits, I'll look into it. Link to comment Share on other sites More sharing options...
Svarog Posted January 19, 2016 Share Posted January 19, 2016 I'm not sure if it's possible to remove traits, I'll look into it.It is, the game does that already with traits like Athletic/Obese and Strong xpUpdate.levelPerk = function(owner, perk, level, addBuffer) -- first Strength skill, grant you some traits that gonna help you to carry more stuff, hitting harder, etc. if perk == Perks.Strength then -- we start to remove all previous Strength related traits owner:getTraits():remove("Weak"); owner:getTraits():remove("Feeble"); owner:getTraits():remove("Stout"); owner:getTraits():remove("Strong"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Weak"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Feeble"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Stout"); elseif level >= 9 then owner:getTraits():add("Strong"); end end -- then Fitness skill, grant you some traits that gonna help you to run faster, recovery faster, etc.. if perk == Perks.Fitness then -- we start to remove all previous Fitness related traits owner:getTraits():remove("Obese"); owner:getTraits():remove("Overweight"); owner:getTraits():remove("Fit"); owner:getTraits():remove("Athletic"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Obese"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Overweight"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Fit"); elseif level >= 9 then owner:getTraits():add("Athletic"); end end -- we reset the xp multiplier for this perk-- owner:getXp():getMultiplierMap():remove(perk); -- we add a "buffer" xp, so if you just get your lvl but you're still losing xp (if you've been lazy for a moment), you won't lose your lvl at the next tick if addBuffer then-- owner:getXp():AddXP(perk, 5, false); endend Link to comment Share on other sites More sharing options...
ethanwdp Posted January 19, 2016 Share Posted January 19, 2016 I'm not sure if it's possible to remove traits, I'll look into it.It is, the game does that already with traits like Athletic/Obese and Strong xpUpdate.levelPerk = function(owner, perk, level, addBuffer) -- first Strength skill, grant you some traits that gonna help you to carry more stuff, hitting harder, etc. if perk == Perks.Strength then -- we start to remove all previous Strength related traits owner:getTraits():remove("Weak"); owner:getTraits():remove("Feeble"); owner:getTraits():remove("Stout"); owner:getTraits():remove("Strong"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Weak"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Feeble"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Stout"); elseif level >= 9 then owner:getTraits():add("Strong"); end end -- then Fitness skill, grant you some traits that gonna help you to run faster, recovery faster, etc.. if perk == Perks.Fitness then -- we start to remove all previous Fitness related traits owner:getTraits():remove("Obese"); owner:getTraits():remove("Overweight"); owner:getTraits():remove("Fit"); owner:getTraits():remove("Athletic"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Obese"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Overweight"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Fit"); elseif level >= 9 then owner:getTraits():add("Athletic"); end end -- we reset the xp multiplier for this perk-- owner:getXp():getMultiplierMap():remove(perk); -- we add a "buffer" xp, so if you just get your lvl but you're still losing xp (if you've been lazy for a moment), you won't lose your lvl at the next tick if addBuffer then-- owner:getXp():AddXP(perk, 5, false); endendAh, didn't see that one. Nice find! ...Time to immediately abuse this with Cheat Menu Link to comment Share on other sites More sharing options...
MountainSage Posted January 19, 2016 Author Share Posted January 19, 2016 Instead of having a modified vanilla file that will conflict if the game ever updates it, why not just add a book item?I'd imagine that the game has an event that fires once a book is read - if a book has been read and the book name is (for example) "Illiterate_To_Slowreader" and the player has the Illiterate trait, then it calls a function that removes the illiterate trait and adds the Slowreader trait. I'm not sure if it's possible to remove traits, I'll look into it. This isn't the vanilla file, this is an entirely seperate class that is based off the vanilla one that is specifically these books. That's how I'm getting around the illiterate fail check. All that bit works fine. The only issue I'm running into is having the traits added or removed once the book is finished reading. I'm not sure if it's possible to remove traits, I'll look into it.It is, the game does that already with traits like Athletic/Obese and Strong xpUpdate.levelPerk = function(owner, perk, level, addBuffer) -- first Strength skill, grant you some traits that gonna help you to carry more stuff, hitting harder, etc. if perk == Perks.Strength then -- we start to remove all previous Strength related traits owner:getTraits():remove("Weak"); owner:getTraits():remove("Feeble"); owner:getTraits():remove("Stout"); owner:getTraits():remove("Strong"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Weak"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Feeble"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Stout"); elseif level >= 9 then owner:getTraits():add("Strong"); end end -- then Fitness skill, grant you some traits that gonna help you to run faster, recovery faster, etc.. if perk == Perks.Fitness then -- we start to remove all previous Fitness related traits owner:getTraits():remove("Obese"); owner:getTraits():remove("Overweight"); owner:getTraits():remove("Fit"); owner:getTraits():remove("Athletic"); -- now we add trait depending on your current lvl if level >= 0 and level <= 1 then owner:getTraits():add("Obese"); elseif level >= 2 and level <= 4 then owner:getTraits():add("Overweight"); elseif level >= 6 and level <= 8 then owner:getTraits():add("Fit"); elseif level >= 9 then owner:getTraits():add("Athletic"); end end -- we reset the xp multiplier for this perk-- owner:getXp():getMultiplierMap():remove(perk); -- we add a "buffer" xp, so if you just get your lvl but you're still losing xp (if you've been lazy for a moment), you won't lose your lvl at the next tick if addBuffer then-- owner:getXp():AddXP(perk, 5, false); endendAlready tried that. I tried one run of the lua file using owner: instead of self.character: like the traits for athletic/strength are handled, but that didn't seem to have an effect either. ...though that was just in my debug script. I'll try it with owner: in the book script to see if it works. Link to comment Share on other sites More sharing options...
Svarog Posted January 19, 2016 Share Posted January 19, 2016 snipowner: is probably defined somewhere with something likelocal owner = getPlayer();Try substituting owner with getPlayer(); or defining it like that yourself in your code.Edit: I mean try this getPlayer():getTraits():remove("Obese");Edit 2: Scratch that, I now believe owner refers to something else and is defnined internally by an Event firing off like OnPlayerUpdate so yeah, that might itself work depending by what causes it. Link to comment Share on other sites More sharing options...
MountainSage Posted January 19, 2016 Author Share Posted January 19, 2016 snipowner: is probably defined somewhere with something likelocal owner = getPlayer();Try substituting owner with getPlayer(); or defining it like that yourself in your code.Edit: I mean try this getPlayer():getTraits():remove("Obese");Edit 2: Scratch that, I now believe owner refers to something else and is defnined internally by an Event firing off like OnPlayerUpdate so yeah, that might itself work depending by what causes it. No luck, tried it asTTBLearnToRead.checkProgress = function(self) local readPercent = (self.item:getAlreadyReadPages() / self.item:getNumberOfPages()) * 100; if readPercent >= 100 then readPercent = 100; end if readpercent == 100 then getPlayer():getTraits():remove("Illiterate"); getPlayer():getTraits():add("SlowReader"); endendBut didn't seem to work EDIT: just noticed I'm doing an if with readpercent instead of readPercent. Going to see if fixing that has any effect. EDIT 2: Ok so it appears that this is infact doing the intended behaviour HOWEVER it is not showing the update on character info? I still see the illiterate perk but am now able to read things. Edit 3: PROGRESSSo the custom function is certainly working. Seems I just need to add a check to make sure it doesn't fire multiple times when reading the book. Then see if I can refreshing the characters info panel without needing to restart to see the updated traits. Edit 4: Got it, no more duplicate traits being added ayyyNow to sort this panel refresh issue. Edit 5: Panel refresh working. Thanks to Brybry helping me find the method needed to do it. Link to comment Share on other sites More sharing options...
Svarog Posted January 20, 2016 Share Posted January 20, 2016 Now that you worked it out, could you post the result (code that works) nad makr the thing as answered for future reference? Thanks Link to comment Share on other sites More sharing options...
MountainSage Posted January 20, 2016 Author Share Posted January 20, 2016 Now that you worked it out, could you post the result (code that works) nad makr the thing as answered for future reference? Thanks Yup here's the relevant code section with trait learning/unlearning, checks against duplicate effects and refreshing the character info panel (Provided by Brybry)TTBLearnToRead.checkProgress = function(self) local readPercent = (self.item:getAlreadyReadPages() / self.item:getNumberOfPages()) * 100; if readPercent >= 100 then readPercent = 100; end if readPercent == 100 then -- self.character:Say("DEBUG: I have read the book!") if getPlayer():HasTrait("Illiterate") then getPlayer():getTraits():remove("Illiterate"); end if not getPlayer():HasTrait("SlowReader") then getPlayer():getTraits():add("SlowReader"); end if ISCharacterInfoWindow.instance then ISCharacterInfoWindow.instance.charScreen:loadTraits(); end end end Svarog 1 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