simplex Posted October 25, 2013 Author Share Posted October 25, 2013 @simplex Any ideas on making crops planted by Winnie grow in Winter? I've looked at the related files, and it seems I need to counter MakeNotGrowableInWinter(). I'm not sure how to detect what is being planted at any given time. I suspect it has something to do with doer, however, since it involves ACTIONS.PLANT and plantables.lua. MakeNotGrowableInWinter() detects the season and eventually does item.components.pickable:DoPause(), so even if I resume it, I'm assuming that would simply pause growing again. What matters is the Crop component. The easiest way would be to change TUNING.MIN_CROP_GROW_TEMP when Winnie is being played (see Crop:DoGrow(dt) for details). Link to comment Share on other sites More sharing options...
debugman18 Posted October 25, 2013 Share Posted October 25, 2013 What matters is the Crop component. The easiest way would be to change TUNING.MIN_CROP_GROW_TEMP when Winnie is being played (see Crop:DoGrow(dt) for details).Well that was directed towards things like the berrybush, but that took care of farm plot crops. I'll see what I can do about them. Link to comment Share on other sites More sharing options...
simplex Posted October 25, 2013 Author Share Posted October 25, 2013 Well that was directed towards things like the berrybush, but that took care of farm plot crops. I'll see what I can do about them.Sorry, I thought we were just going to change farm plots. Changing things like berry bushes would have some strange implications as far as logic goes, since it wouldn't make much sense for a naturally spawning bush to have its behaviour changed (though that could be solved by checking if it was transplanted). I think changing MakeNoGrowInWinter would be the best way to do it, since its method of operation is quite hardcoded. This should do:require "standardcomponents"local oldMakeNoGrowInWinter = _G.MakeNoGrowInWinterfunction _G.MakeNoGrowInWinter(inst) -- We need to delay the actual work because spawning the player happens late. inst:DoTaskInTime(0, function(inst) if _G.GetPlayer().prefab ~= "winnie" then return oldMakeNoGrowInWinter(inst) end end)endI'm using _G instead of GLOBAL because that's the standard Lua way to reference the global environment (in the global environment, the standard variable _G just references the global environment itself) and Wicker aliases GLOBAL to it, not to mention it's shorter, so the code looks less verbose. I never quite liked the "GLOBAL" in the mod environment . but feel free to use GLOBAL if you prefer it.EDIT:To check for a player planted Pickable, the "if" should beif _G.GetPlayer().prefab ~= "winnie" or not (inst.components.pickable and inst.components.pickable.transplanted) then Link to comment Share on other sites More sharing options...
debugman18 Posted October 27, 2013 Share Posted October 27, 2013 @simplexI'm using Heavenfall's tech tree code (there's a thread here about it) but I keep getting this error. I put the code into main.lua.scripts/recipe.lua:25: attempt to index field 'level' (a number value)LUA ERROR stack traceback: scripts/recipe.lua(25,1) in function '_ctor' scripts/class.lua(28,1) =(tail call) ? ../mods/UpAndAway/scripts/upandaway/main.lua(398,1) in main chunk =[C] in function 'require' ../mods/UpAndAway/scripts/upandaway/wicker/api/core.lua(417,1) in function 'modrequire' ../mods/UpAndAway/scripts/upandaway/wicker/api/themod.lua(273,1) =(tail call) ? ../mods/UpAndAway/scripts/upandaway/wicker/api/themod.lua(111,1) in function 'Run' ../mods/UpAndAway/modmain.lua(296,1) in main chunk =[C] in function 'xpcall' ... scripts/main.lua(254,1) =[C] in function 'SetPersistentString' scripts/modindex.lua(58,1) =[C] in function 'GetPersistentString' scripts/modindex.lua(45,1) in function 'BeginStartupSequence' scripts/main.lua(253,1) in function 'callback' scripts/modindex.lua(268,1) =[C] in function 'GetPersistentString' scripts/modindex.lua(248,1) in function 'Load' scripts/main.lua(252,1) in main chunkGLOBAL.TECH.NONE.FABLE = 0for k,v in pairs(GLOBAL.TUNING.PROTOTYPER_TREES) do GLOBAL.TUNING.PROTOTYPER_TREES[k].FABLE = 0 GLOBAL.TUNING.PROTOTYPER_TREES.FABLE = {SCIENCE = 0,MAGIC = 0,ANCIENT = 0,FABLE=0}end Any idea what the issue is? Edit: Nevermind, the problem is somewhere in the recipes list... I'll probably be able to solve it. Link to comment Share on other sites More sharing options...
simplex Posted October 27, 2013 Author Share Posted October 27, 2013 @debugman18 If you attach your current main.lua code I can take a look. Link to comment Share on other sites More sharing options...
debugman18 Posted October 27, 2013 Share Posted October 27, 2013 @debugman18If you attach your current main.lua code I can take a look.The relevant section:--This adds our 'Fable' tech tree. Thanks to @[member=Heavenfall] for the code.GLOBAL.TECH.NONE.FABLE = 0for k,v in pairs(GLOBAL.TUNING.PROTOTYPER_TREES) do GLOBAL.TUNING.PROTOTYPER_TREES[k].FABLE = 0 GLOBAL.TUNING.PROTOTYPER_TREES.FABLE = {SCIENCE = 0,MAGIC = 0,ANCIENT = 0,FABLE=0}end local function enteringradiusofskeleton(inst) --entering proximity of skeletonendlocal function leavingradiusofskeleton(inst) --left proximity of skeleton local playervar = GLOBAL.GetPlayer() if playervar then playervar.components.builder.accessible_tech_trees = GLOBAL.TECH.NONE endend-- add undeadskeleton prototype type to skeletonsfunctionlocal function addfableprototype(inst) inst:AddTag("prototyper") inst:AddComponent("prototyper") inst.components.prototyper.trees = GLOBAL.TUNING.PROTOTYPER_TREES.FABLE inst.components.prototyper.onactivate = function() end inst.components.prototyper.onturnoff = leavingradiusofskeleton inst.components.prototyper.onturnon = enteringradiusofskeletonend --skeleton recipe was built end AddPrefabPostInit("research_lectern", addfableprototype)--]]local RECIPETABS = GLOBAL.RECIPETABSlocal TECH = GLOBAL.TECHlocal cotton_vest = Recipe("cotton_vest", { Ingredient("silk", 4), Ingredient("cloud_cotton", 4, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.DRESS, TECH.SCIENCE_ONE)cotton_vest.atlas = "images/inventoryimages/cloud_cotton.xml"local cotton_hat = Recipe("cotton_hat", { Ingredient("silk", 2), Ingredient("cloud_cotton", 6, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.DRESS, TECH.SCIENCE_ONE)cotton_hat.atlas = "images/inventoryimages/cloud_cotton.xml"local weather_machine = Recipe("weather_machine", { Ingredient("gears", 4), Ingredient("crystal_relic_fragment", 6, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.SCIENCE, TECH.SCIENCE_ONE)weather_machine.atlas = "images/inventoryimages/cloud_cotton.xml"local research_lectern = Recipe("research_lectern", { Ingredient("silk", 2), Ingredient("cloud_cotton", 6, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.SCIENCE, TECH.SCIENCE_TWO)research_lectern.atlas = "images/inventoryimages/cloud_cotton.xml"local cotton_candy = Recipe("cotton_candy", { Ingredient("cloud_cotton", 6, "images/inventoryimages/cloud_cotton.xml"), Ingredient("candy_fruit", 6, "images/inventoryimages/candy_fruit.xml") }, RECIPETABS.FOOD, TECH.SCIENCE_ONE)cotton_candy.atlas = "images/inventoryimages/cloud_cotton.xml"local grabber = Recipe("grabber", { Ingredient("magnet", 2, "images/inventoryimages/cloud_cotton.xml"), Ingredient("cane", 1), Ingredient("rubber", 4, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.SURVIVAL, TECH.SCIENCE_ONE)grabber.atlas = "images/inventoryimages/cloud_cotton.xml"local magnet = Recipe("magnet", { Ingredient("gears", 2), Ingredient("crystal_fragment", 3, "images/inventoryimages/cloud_cotton.xml") }, RECIPETABS.FOOD, TECH.SCIENCE_ONE)magnet.atlas = "images/inventoryimages/cloud_cotton.xml"--]] It gives me an error regarding updating the crafting tabs. I'm pretty sure it's something little. Link to comment Share on other sites More sharing options...
simplex Posted October 27, 2013 Author Share Posted October 27, 2013 @debugman18 Why can't you just upload the whole file? It's much easier to test that way, as well as match line numbers with the previous error you posted. Link to comment Share on other sites More sharing options...
debugman18 Posted October 27, 2013 Share Posted October 27, 2013 @debugman18Why can't you just upload the whole file? It's much easier to test that way, as well as match line numbers with the previous error you posted.Ah, sorry. http://www.mediafire.com/download/hjnlv13qz8c36ul/main.lua Link to comment Share on other sites More sharing options...
simplex Posted October 27, 2013 Author Share Posted October 27, 2013 Ah, sorry. http://www.mediafire.com/download/hjnlv13qz8c36ul/main.luaThe current issue was that RECIPETABS.FOOD is actually called RECIPETABS.FARM.However, that's not the same error you were getting before. That error was probably caused by the recipe level passed being nil (by an invalid index being used in TECH), since the game code in recipe.lua is actually bugged: self.level = level or 0 self.level.ANCIENT = self.level.ANCIENT or 0 self.level.MAGIC = self.level.MAGIC or 0 self.level.SCIENCE = self.level.SCIENCE or 0As you can see, using 0 as the default value for self.level is wrong, since it'll just cause a crash in the following line (precisely where you were getting the crash) because it'll try to index a number. The correct default value for self.level would be {}, an empty table.fixed_main.zip Link to comment Share on other sites More sharing options...
debugman18 Posted October 27, 2013 Share Posted October 27, 2013 The current issue was that RECIPETABS.FOOD is actually called RECIPETABS.FARM.However, that's not the same error you were getting before. That error was probably caused by the recipe level passed being nil (by an invalid index being used in TECH), since the game code in recipe.lua is actually bugged: self.level = level or 0 self.level.ANCIENT = self.level.ANCIENT or 0 self.level.MAGIC = self.level.MAGIC or 0 self.level.SCIENCE = self.level.SCIENCE or 0As you can see, using 0 as the default value for self.level is wrong, since it'll just cause a crash in the following line (precisely where you were getting the crash) because it'll try to index a number. The correct default value for self.level would be {}, an empty table. I knew it was something little. >_> As for self.level, I'm not sure if that can be fixed through the mod. Maybe with AddClassPostConstruct, but that isn't certain, and who knows if that would cause issues with other mods. I'll experiment with it later if I get a chance. Link to comment Share on other sites More sharing options...
simplex Posted October 27, 2013 Author Share Posted October 27, 2013 I knew it was something little. >_> As for self.level, I'm not sure if that can be fixed through the mod. Maybe with AddClassPostConstruct, but that isn't certain, and who knows if that would cause issues with other mods. I'll experiment with it later if I get a chance.It can be fixed by the mod, but not by a postconstruct. We'd need to implement a preconstruct by hand (which isn't hard).But I don't see much point in doing it, because the level shouldn't be optional, in my opinion. If the modder wants to use TECH.NONE, he/she should specify it, otherwise silent bugs will start creeping into mods just because a mistyped TECH specification was returning nil and being treated as TECH.NONE.EDIT: A proper "fix", in my opinion, would be doing something like:assert( type(level) == "table", "Invalid recipe level specified. If you with to use TECH.NONE, do it explicitly." ) Link to comment Share on other sites More sharing options...
debugman18 Posted November 9, 2013 Share Posted November 9, 2013 @simplexI pushed the jellyshroom textures, and a little bit of work on the crystal lamps. Any idea why my code doesn't work consistently? Sometimes it does exactly what I wrote it for, and other times it's like, nope, not even going to try. local function onLight(inst) local partner = GLOBAL.GetClosestInstWithTag("crystal_lamp", inst, 100) inst.Light:Enable(true) if partner and not partner.components.machine.ison then partner.components.machine.turnonfn = onLight partner:DoTaskInTime(0.3, function(inst, data) partner.components.machine:TurnOn() end) print "Partner lamp lit." end end Basically, it finds the closest crystal lamp to itself, and lights it up. It then does the same thing. Sometimes it does do that, sometimes it just stops after one or two lamps. Link to comment Share on other sites More sharing options...
simplex Posted November 9, 2013 Author Share Posted November 9, 2013 @debugman18 GetClosestInstWithTag is bugged. If you check it's definition in simutil.lua, you'll see it's not determining the closest entity at all, it's just returning some entity. EDIT: Though the actual error cause is probably that you're getting back a lamp that's already been turned on, breaking the chain. So the way to do it would be to get the list of all lamps within the radius and determine the closest one, but excluding those that are already lit. Link to comment Share on other sites More sharing options...
debugman18 Posted November 9, 2013 Share Posted November 9, 2013 @debugman18GetClosestInstWithTag is bugged. If you check it's definition in simutil.lua, you'll see it's not determining the closest entity at all, it's just returning some entity.If you put them in a line, it'll start with the closest one, and move further to the last. That aside though, would using TheSim:FindEntities work better for this purpose? I like the appearance of it doing one at a time until the last one is lit. Link to comment Share on other sites More sharing options...
simplex Posted November 9, 2013 Author Share Posted November 9, 2013 If you put them in a line, it'll start with the closest one, and move further to the last. If it does, that's coincidental. Even if TheSim:FindEntities() returns entities in sorted order regarding distance, GetClosestInstWithTag iterates through it using pairs(), not ipairs(), so the order of the transversal is not guaranteed. But anyway, see my previous edit for the probable actual cause of the issue you're having (though you still shouldn't use GetClosestInstWithTag* ;P). * And it wouldn't work under this more general setting anyway. I just uploaded a mod doing something like this, you could copy-paste some of it, but it's not hard to do it by hand anyway. Link to comment Share on other sites More sharing options...
simplex Posted November 9, 2013 Author Share Posted November 9, 2013 @debugman18Actually, wicker has a function for that. Try this:local game = wickerrequire "utils.game"local function onLight(inst) local partner = game.FindClosestEntity(inst, 100, function(e) return e.components.machine and not e.components.machine:IsOn() end, {"crystal_lamp"}) inst.Light:Enable(true) if partner and not partner.components.machine.ison then partner.components.machine.turnonfn = onLight partner:DoTaskInTime(0.3, function(inst, data) partner.components.machine:TurnOn() end) print "Partner lamp lit." end endEDIT:All the wicker functions for finding entities (see wicker/utils/game.lua) receive a standard sequence of parameters:center, radius, fn, tagscenter is of course the center of the search, but it can be given either as an entity or as a Point (equivalently, as a Vector3). radius is the radius (duh). fn is an (optional, you may give nil) function applied to each entity, and only those for which it returns true are taken into account. tags is a (optional) table (array) of tags, like in TheSim:FindEntities().Also, the wicker searching functions already exclude entities which are invalid (i.e., for which inst:IsValid() returns false) or that are not are "in limbo" (i.e., for which inst:IsInLimbo() returns true). Link to comment Share on other sites More sharing options...
debugman18 Posted November 10, 2013 Share Posted November 10, 2013 @debugman18Actually, wicker has a function for that. Try this:local game = wickerrequire "utils.game"local function onLight(inst) local partner = game.FindClosestEntity(inst, 100, function(e) return e.components.machine and not e.components.machine:IsOn() end, {"crystal_lamp"}) inst.Light:Enable(true) if partner and not partner.components.machine.ison then partner.components.machine.turnonfn = onLight partner:DoTaskInTime(0.3, function(inst, data) partner.components.machine:TurnOn() end) print "Partner lamp lit." end endEDIT:All the wicker functions for finding entities (see wicker/utils/game.lua) receive a standard sequence of parameters:center, radius, fn, tagscenter is of course the center of the search, but it can be given either as an entity or as a Point (equivalently, as a Vector3). radius is the radius (duh). fn is an (optional, you may give nil) function applied to each entity, and only those for which it returns true are taken into account. tags is a (optional) table (array) of tags, like in TheSim:FindEntities().Also, the wicker searching functions already exclude entities which are invalid (i.e., for which inst:IsValid() returns false) or that are not are "in limbo" (i.e., for which inst:IsInLimbo() returns true). Ah, I'm glad Wicker had the same functionality I was hoping for. However, it's crashing for me with an arithmetic error.scripts/util.lua:260: attempt to perform arithmetic on a nil valueLUA ERROR stack traceback: scripts/util.lua(260,1) in function 'distsq' ../mods/UpAndAway/scripts/upandaway/wicker/utils/game.lua(87,1) in function 'folder' ../mods/UpAndAway/scripts/upandaway/wicker/paradigms/functional.lua(685,1) in function 'g' ../mods/UpAndAway/scripts/upandaway/wicker/paradigms/functional.lua(106,1) in function 'p' ../mods/UpAndAway/scripts/upandaway/wicker/paradigms/functional.lua(531,1) =(tail call) ? ../mods/UpAndAway/scripts/upandaway/wicker/paradigms/functional.lua(684,1) in function 'Fold' ../mods/UpAndAway/scripts/upandaway/wicker/utils/game.lua(95,1) in function 'FindClosestEntity' ../mods/UpAndAway/scripts/upandaway/prefabs/crystal_lamp.lua(14,1) in function 'turnonfn' scripts/components/machine.lua(32,1) in function 'TurnOn' scripts/components/machine.lua(20,1) in function 'OnLoad' ... =[C] in function 'GetPersistentString' scripts/saveindex.lua(67,1) in function 'Load' scripts/gamelogic.lua(1069,1) in function 'callback' scripts/playerprofile.lua(378,1) in function 'Set' scripts/playerprofile.lua(278,1) =[C] in function 'GetPersistentString' scripts/playerprofile.lua(276,1) in function 'Load' scripts/gamelogic.lua(1068,1) in main chunk =[C] in function 'require' scripts/mainfunctions.lua(601,1) Link to comment Share on other sites More sharing options...
simplex Posted November 10, 2013 Author Share Posted November 10, 2013 @debugman18 Sorry about that, there was a bug in FindClosestEntity. I just fixed it, pushed the revision to the wicker repository, pulled the wicker repository into the U&A one and pushed it into GitHub. Link to comment Share on other sites More sharing options...
debugman18 Posted November 10, 2013 Share Posted November 10, 2013 @debugman18Sorry about that, there was a bug in FindClosestEntity. I just fixed it, pushed the revision to the wicker repository, pulled the wicker repository into the U&A one and pushed it into GitHub. They still get confused if there's a bunch hobbled together, but that's not really an issue. It's working more consistently than the previous code did. Link to comment Share on other sites More sharing options...
simplex Posted November 10, 2013 Author Share Posted November 10, 2013 They still get confused if there's a bunch hobbled together, but that's not really an issue. It's working more consistently than the previous code did.What do you mean by "confused"?And oh, the previous code wasn't checking for the entity being different than the "center" entity. Use this instead:local game = wickerrequire "utils.game"local function onLight(inst) local partner = game.FindClosestEntity(inst, 100, function(e) return e ~= inst and e.components.machine and not e.components.machine:IsOn() end, {"crystal_lamp"}) inst.Light:Enable(true) if partner and not partner.components.machine.ison then partner.components.machine.turnonfn = onLight partner:DoTaskInTime(0.3, function(inst, data) partner.components.machine:TurnOn() end) print "Partner lamp lit." end endEDIT:Also, instead of using print(), consider usingTheMod:DebugSay "Partner lamp lit."That way, if DEBUG is set to false in rc.lua nothing will be written. The message prefix in the log is also cleaner.When a class (for example a component) inherits from Debuggable (wickerrequire "adjectives.debuggable") then you can use self:DebugSay() instead, which is better because it allows toggling debugging at a class level to avoid extra messages even when global debugging is on, but in a prefab case there's not much choice.EDIT 2:DebugSay() will also turn its arguments into strings (and concatenate them with nothing in between, so you can give it pieces), so you can pass the entity itself to help with debugging, for example:TheMod:DebugSay("Partner lamp [", partner, "] lit.")EDIT 3:TheMod:Say() works the same way, except it always prints, regardless of debugging. Also, TheMod:Debug() returns true or false according to whether debugging is on or off. Any class inheriting from Debuggable has those methods. Link to comment Share on other sites More sharing options...
debugman18 Posted November 10, 2013 Share Posted November 10, 2013 What do you mean by "confused"?And oh, the previous code wasn't checking for the entity being different than the "center" entity. Use this instead:local game = wickerrequire "utils.game"local function onLight(inst) local partner = game.FindClosestEntity(inst, 100, function(e) return e ~= inst and e.components.machine and not e.components.machine:IsOn() end, {"crystal_lamp"}) inst.Light:Enable(true) if partner and not partner.components.machine.ison then partner.components.machine.turnonfn = onLight partner:DoTaskInTime(0.3, function(inst, data) partner.components.machine:TurnOn() end) print "Partner lamp lit." end endEDIT:Also, instead of using print(), consider usingTheMod:DebugSay "Partner lamp lit."That way, if DEBUG is set to false in rc.lua nothing will be written. The message prefix in the log is also cleaner.When a class (for example a component) inherits from Debuggable (wickerrequire "adjectives.debuggable") then you can use self:DebugSay() instead, which is better because it allows toggling debugging at a class level to avoid extra messages even when global debugging is on, but in a prefab case there's not much choice.EDIT 2:DebugSay() will also turn its arguments into strings (and concatenate them with nothing in between, so you can give it pieces), so you can pass the entity itself to help with debugging, for example:TheMod:DebugSay("Partner lamp [", partner, "] lit.")EDIT 3:TheMod:Say() works the same way, except it always prints, regardless of debugging. Also, TheMod:Debug() returns true or false according to whether debugging is on or off. Any class inheriting from Debuggable has those methods. By 'confused' I mean that in a large group they will not always light up all of the available lights. That's fixed with that, though. Link to comment Share on other sites More sharing options...
simplex Posted November 10, 2013 Author Share Posted November 10, 2013 By 'confused' I mean that in a large group they will not always light up all of the available lights. That's fixed with that, though. Hmm, well, by always getting the closest one it is possible for some lamps to not be lit up (the path of closest lamps could lead away from a group of nearby lamps). We could light up all the close lamps, though, instead of just the closest one. The corresponding function in wicker is FindAllEntities (same parameters), returning a table. Link to comment Share on other sites More sharing options...
debugman18 Posted November 10, 2013 Share Posted November 10, 2013 Hmm, well, by always getting the closest one it is possible for some lamps to not be lit up (the path of closest lamps could lead away from a group of nearby lamps).We could light up all the close lamps, though, instead of just the closest one. The corresponding function in wicker is FindAllEntities (same parameters), returning a table.Well, it lights them all up, given they're in the correct range. It works quite nicely, in my opinion. Link to comment Share on other sites More sharing options...
simplex Posted November 10, 2013 Author Share Posted November 10, 2013 Well, it lights them all up, given they're in the correct range. It works quite nicely, in my opinion. But if you arrange them in a (big enough) cross it won't work. It doesn't even need to be a cross, starting from the middle of a (big enough) line would do it, the cross pattern just ensures it won't work regardless of the starting point. Link to comment Share on other sites More sharing options...
simplex Posted November 10, 2013 Author Share Posted November 10, 2013 It is possible to determine a sequence of which lamps to light up such that each "jump" happens within the specified radius, with all valid* lamps being covered. However, calculating such path is both slow and hard to implement. * This depends on how you define "valid", though. ;P Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.
Please be aware that the content of this thread may be outdated and no longer applicable.