[Code] A Thread On Lambdas And Other Epsilons


simplex

Recommended Posts

Well, I reference this usually, if I need clarification on something:

http://www.lua.org/pil/contents.html

Alright, got that already. ^ ^

 

 

 

 

For Don't Starve specific Lua usage, I recommend http://forums.kleientertainment.com/files/file/202-sample-mods/

 

Using that hand-in-hand with vanilla scripts will help you solidify your ability to understand Lua. Those are in prefabs/ in the Don't Starve data/ directory. You could also tear open U&A and look at our prefabs. Those are in code/prefabs/ in the mod directory.

 

Ok, I will look into that, too.

Many thankees!

Link to comment
Share on other sites

Question,

I really want to expand my knowledge of this upon more than just art and atlases. Not only to contribute better to our cause but because I'm shifting my education in this direction.

 

Also it only can help with spriter and also anim.files  to get a better result in our work here. I know there are tutorials and stuff. Since you are already into it could you perhaps point out the ones you find best for me? ^ ^

I've downloaded Lua 5.1 from the official page to get a look onto it.

 

Incidentally I'm looking into coding in general too and I'm intensifying to train my art skills.

As debugman mentioned, the book Programming in Lua is very good (and allows cherry picking topics once you covered the basics). The edition freely available is for Lua 5.0, but it is still largely relevant. The Lua users tutorial is also a pretty good resource.

Link to comment
Share on other sites

@debugman18

Do we still want to spawn the Shopkeeper randomly along the road? Because I just figured out how to do so, and implemented some things in wicker to that effect.

Doing

local gametopo = wickerrequire "game.topology"print( gametopo.TheRoad(0), " ", gametopo.TheRoad(1) )
will print the extremities of the road, and for any t between 0 and 1 gametopo.TheRoad(t) will give the point inside the road with a distance to gametopo.TheRoad(0) proportional to t (i.e., gametopo.TheRoad(0.5) gives the midpoint of the road, gametopo.TheRoad(1/4) the point at the first quarter, etc.). Therefore, gametopo.TheRoad(math.random()) gives a random point in the road uniformly distributed with respect to road length, and we can use this to randomly place the Shopkeeper along the road.

It took some work to build that because the game does not expose road information. However, this engine-level info is stored in the savedata, so I'm fetching it directly from that through an AddGamePostInit. Since I get that info through a game post init, it is safe to use it inside a Sim post init, since those run after game post inits.

I'm still finishing the details, but I'll push the changes to wicker (and then pull them into the mod) shortly.

Link to comment
Share on other sites

@debugman18

Do we still want to spawn the Shopkeeper randomly along the road? Because I just figured out how to do so, and implemented some things in wicker to that effect.

Doing

local gametopo = wickerrequire "game.topology"print( gametopo.TheRoad(0), " ", gametopo.TheRoad(1) )
will print the extremities of the road, and for any t between 0 and 1 gametopo.TheRoad(t) will give the point inside the road with a distance to gametopo.TheRoad(0) proportional to t (i.e., gametopo.TheRoad(0.5) gives the midpoint of the road, gametopo.TheRoad(1/4) the point at the first quarter, etc.). Therefore, gametopo.TheRoad(math.random()) gives a random point in the road uniformly distributed with respect to road length, and we can use this to randomly place the Shopkeeper along the road.

It took some work to build that because the game does not expose road information. However, this engine-level info is stored in the savedata, so I'm fetching it directly from that through an AddGamePostInit. Since I get that info through a game post init, it is safe to use it inside a Sim post init, since those run after game post inits.

I'm still finishing the details, but I'll push the changes to wicker (and then pull them into the mod) shortly.

 

Actually, yes. I'm surprised you were able to figure a way out to do that. So we won't have to rely on the pig king room for the shopkeeper to be a guaranteed spawn (because even that sometimes doesn't spawn.) :p

 

I also looked at saveindex.lua again, trying to find a way to change the save names, but it seems we'd have to rewrite a notable chunk of it to do so (which would not be very mod or update friendly.) It's not a big deal, but it's an aesthetic issue. Maybe they'll revisit the API in the future. Honestly I'm pretty doubtful, but one can hope.

 

Also, it seems that it may not have been ktech that stretched the converted animations. It seems actually that the version of Spriter used has something to do with it, as it forms the scml file differently.

Link to comment
Share on other sites

I also looked at saveindex.lua again, trying to find a way to change the save names, but it seems we'd have to rewrite a notable chunk of it to do so (which would not be very mod or update friendly.) It's not a big deal, but it's an aesthetic issue. Maybe they'll revisit the API in the future. Honestly I'm pretty doubtful, but one can hope.

Wouldn't just changing SaveIndex.GetSaveGameName through a postinit do the trick, since it is used both for fetching and storing the savedata? As long as it contains a substring of the form "cave_(%d+)_", where "(%d+)" denotes the cave number, I don't see what would go wrong (I haven't tested it, though). But it would be a pain to detect when a cave number refers to a cloud realm externally, so that we can change the file name accordingly.

But I don't see how it is an aesthetic issue. Regular players won't peek around their save files :razz:. The main motivation for this is that with a renamed save file, if the player loads a save which was in the cloud realm, but with U&A disabled, then the savedata won't be lost, and the player will spawn into a cave. However, if the player goes back to the surface the corresponding beanstalk will disappear.

 

Also, it seems that it may not have been ktech that stretched the converted animations. It seems actually that the version of Spriter used has something to do with it, as it forms the scml file differently.

That's good to know, thanks for letting me know. Is this Spriter version also used in Windows, or does this happen only in Linux (and possibly Mac)?

 

Actually, yes. I'm surprised you were able to figure a way out to do that. So we won't have to rely on the pig king room for the shopkeeper to be a guaranteed spawn (because even that sometimes doesn't spawn.) :razz:

Well, it happened that I was working on geometry stuff to use in the balloon hound spawning. Since balloon hounds would take some time falling down and they don't chase the player, simply spawning them along a circle around the player wouldn't be ideal, since if the player is running he'll miss most of them. So I was working on some geometry and probability stuff to have the hounds spawn along the direction the player is facing if he is running (either along a circular arc or a disk sector, I'm still not sure). As I tend to do, I wrote code much more generic (and consequently more complicated :razz:) than was required for the task, and then I realised some of that code would be a perfect fit for spawning the Shopkeeper along the road. So I just had to figure out how to get the geometry of the road. I'll explain how it works below, for reference.

Internally, the road is a polygonal path (though the game slightly distorts it to make it look more organic). The road is built by the engine through the RoadManager, which has methods for receiving road information from the savedata, but not for returning them. So I had to grab that from the savedata. From now on, suppose "savedata" is a variable holding the table with the savedata.

The road information is stored in savedata.map.roads, which is a table where each value is the data for a single road or trail (I haven't checked what the keys are or even if they are numerical, since the savedata handling seems to show they are not important). Each value road_data in savedata.map.roads is an array (table with numerical indices). road_data[1] is the weight of the road, which is 3 for proper roads and 1 or 2 for trails. The remaining entries (starting from road_data[2]) are the vertices of the road, which is the polygonal path connecting them. They are represented as pairs, i.e. road_data[2][1] is the x coordinate and road_data[2][2] is the z coordinate.

I'm "glueing" together all the proper roads when building gametopo.TheRoad, so if there is more than one starting from some value t gametopo.TheRoad(t) will jump from one road to another. I did it this way because firstly survival maps just have one road anyway (I think multiple roads only appear in maps with more than one island), and secondly if there is more than one road this is ideal for our current purposes, since gametopo.TheRoad(math.random()) will then give a random point in any road. I'm not processing trails since we have no use for them right now, but doing so would take just a couple more lines of code.

Link to comment
Share on other sites

Wouldn't just changing SaveIndex.GetSaveGameName through a postinit do the trick, since it is used both for fetching and storing the savedata? As long as it contains a substring of the form "cave_(%d+)_", where "(%d+)" denotes the cave number, I don't see what would go wrong (I haven't tested it, though). But it would be a pain to detect when a cave number refers to a cloud realm externally, so that we can change the file name accordingly.

But I don't see how it is an aesthetic issue. Regular players won't peek around their save files :razz:. The main motivation for this is that with a renamed save file, if the player loads a save which was in the cloud realm, but with U&A disabled, then the savedata won't be lost, and the player will spawn into a cave. However, if the player goes back to the surface the corresponding beanstalk will disappear.

That's good to know, thanks for letting me know. Is this Spriter version also used in Windows, or does this happen only in Linux (and possibly Mac)?

Well, it happened that I was working on geometry stuff to use in the balloon hound spawning. Since balloon hounds would take some time falling down and they don't chase the player, simply spawning them along a circle around the player wouldn't be ideal, since if the player is running he'll miss most of them. So I was working on some geometry and probability stuff to have the hounds spawn along the direction the player is facing if he is running (either along a circular arc or a disk sector, I'm still not sure). As I tend to do, I wrote code much more generic (and consequently more complicated :razz:) than was required for the task, and then I realised some of that code would be a perfect fit for spawning the Shopkeeper along the road. So I just had to figure out how to get the geometry of the road. I'll explain how it works below, for reference.

Internally, the road is a polygonal path (though the game slightly distorts it to make it look more organic). The road is built by the engine through the RoadManager, which has methods for receiving road information from the savedata, but not for returning them. So I had to grab that from the savedata. From now on, suppose "savedata" is a variable holding the table with the savedata.

The road information is stored in savedata.map.roads, which is a table where each value is the data for a single road or trail (I haven't checked what the keys are or even if they are numerical, since the savedata handling seems to show they are not important). Each value road_data in savedata.map.roads is an array (table with numerical indices). road_data[1] is the weight of the road, which is 3 for proper roads and 1 or 2 for trails. The remaining entries (starting from road_data[2]) are the vertices of the road, which is the polygonal path connecting them. They are represented as pairs, i.e. road_data[2][1] is the x coordinate and road_data[2][2] is the z coordinate.

 

I'm not sure about the postinit, but I suppose that would do the trick. It's just silly looking at save names like Cave Depth -1. I'll see if I can't get it to work without causing other issues.

 

Well, it happens because the version of Spriter that comes with the mod tools is bv5, while the one I'm using on Linux is bv6.1. As for Mac, I'm not sure, but I bet the same issue occurs. For comparison, here's a working scml, and a non-working scml.

 

Working

<pre><?xml version="1.0" encoding="UTF-8"?><spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="b5">    <folder id="0">        <file id="0" name="cloud_algae.png" width="117" height="177" pivot_x="0" pivot_y="1"/>    </folder>    <entity id="0" name="cloud_algae">        <animation id="0" name="idle" length="1000">            <mainline>                <key id="0">                    <object_ref id="0" name="cloud_algae" folder="0" file="0" abs_x="-143.923939" abs_y="396.003222" abs_pivot_x="0" abs_pivot_y="1" abs_angle="0" abs_scale_x="2.42752" abs_scale_y="2.436543" abs_a="1" timeline="0" key="0" z_index="0"/>                </key>            </mainline>            <timeline id="0" name="cloud_algae">                <key id="0" spin="0">                    <object folder="0" file="0" x="-143.923939" y="396.003222" angle="0" scale_x="2.42752" scale_y="2.436543"/>                </key>            </timeline>        </animation>    </entity></spriter_data></pre>

 

Non-Working

<pre><?xml version="1.0" encoding="UTF-8"?><spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="b6.1">    <folder id="0">        <file id="0" name="cloud_algae.png" width="117" height="177" pivot_x="0" pivot_y="1"/>    </folder>    <entity id="0" name="cloud_algae">        <animation id="0" name="idle" length="1000">            <mainline>                <key id="0">                    <object_ref id="0" timeline="0" key="0" z_index="0"/>                </key>            </mainline>            <timeline id="0" name="cloud_algae">                <key id="0" spin="0">                    <object folder="0" file="0" x="-143.923939" y="396.003222" angle="0" scale_x="2.42752" scale_y="2.436543"/>                </key>            </timeline>        </animation>    </entity></spriter_data></pre>

 

As you can see, the mainline bit is not written correctly in bv6.1. It doesn't say where the parts actually are.

Link to comment
Share on other sites

I'm not sure about the postinit, but I suppose that would do the trick. It's just silly looking at save names like Cave Depth -1. I'll see if I can't get it to work without causing other issues.

Oh, you mean the save name in the selection screen. Changing SaveIndex:GetSaveGameName() won't help with that. The code that sets it is the following, in loadgamescreen.lua:

elseif mode == "cave" then	local level = SaveGameIndex:GetCurrentCaveLevel(slotnum)	widget.text:SetString(string.format("%s %d",STRINGS.UI.LOADGAMESCREEN.CAVE, level))else	--This should only happen if the user has run a mod that created a new type of game mode.	widget.text:SetString(STRINGS.UI.LOADGAMESCREEN.MODDED)end
so it's quite hardcoded. Though using a custom level type would show the "Modded" string instead (which I still wish we could customise).

 

Well, it happens because the version of Spriter that comes with the mod tools is bv5, while the one I'm using on Linux is bv6.1. As for Mac, I'm not sure, but I bet the same issue occurs. For comparison, here's a working scml, and a non-working scml.

 

Working

<pre><?xml version="1.0" encoding="UTF-8"?><spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="b5">    <folder id="0">        <file id="0" name="cloud_algae.png" width="117" height="177" pivot_x="0" pivot_y="1"/>    </folder>    <entity id="0" name="cloud_algae">        <animation id="0" name="idle" length="1000">            <mainline>                <key id="0">                    <object_ref id="0" name="cloud_algae" folder="0" file="0" abs_x="-143.923939" abs_y="396.003222" abs_pivot_x="0" abs_pivot_y="1" abs_angle="0" abs_scale_x="2.42752" abs_scale_y="2.436543" abs_a="1" timeline="0" key="0" z_index="0"/>                </key>            </mainline>            <timeline id="0" name="cloud_algae">                <key id="0" spin="0">                    <object folder="0" file="0" x="-143.923939" y="396.003222" angle="0" scale_x="2.42752" scale_y="2.436543"/>                </key>            </timeline>        </animation>    </entity></spriter_data></pre>

 

Non-Working

<pre><?xml version="1.0" encoding="UTF-8"?><spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="b6.1">    <folder id="0">        <file id="0" name="cloud_algae.png" width="117" height="177" pivot_x="0" pivot_y="1"/>    </folder>    <entity id="0" name="cloud_algae">        <animation id="0" name="idle" length="1000">            <mainline>                <key id="0">                    <object_ref id="0" timeline="0" key="0" z_index="0"/>                </key>            </mainline>            <timeline id="0" name="cloud_algae">                <key id="0" spin="0">                    <object folder="0" file="0" x="-143.923939" y="396.003222" angle="0" scale_x="2.42752" scale_y="2.436543"/>                </key>            </timeline>        </animation>    </entity></spriter_data></pre>

 

As you can see, the mainline bit is not written correctly in bv6.1. It doesn't say where the parts actually are.

That's odd. Did you get this by loading a 5.0 scml in 6.1? I'm guessing the format was changed slightly, and so some information is being discarded on load.

Link to comment
Share on other sites

Oh, you mean the save name in the selection screen. Changing SaveIndex:GetSaveGameName() won't help with that. The code that sets it is the following, in loadgamescreen.lua:

elseif mode == "cave" then	local level = SaveGameIndex:GetCurrentCaveLevel(slotnum)	widget.text:SetString(string.format("%s %d",STRINGS.UI.LOADGAMESCREEN.CAVE, level))else	--This should only happen if the user has run a mod that created a new type of game mode.	widget.text:SetString(STRINGS.UI.LOADGAMESCREEN.MODDED)end
so it's quite hardcoded. Though using a custom level type would show the "Modded" string instead (which I still wish we could customise).

 

That's odd. Did you get this by loading a 5.0 scml in 6.1? I'm guessing the format was changed slightly, and so some information is being discarded on load.

 

So short of modifying the file itself (which lets me easily enable this) there's no way to do it? I'm going to tinker, perhaps there is a hackish way of doing it. The way I did it in the file itself is simple, I only had to add an extra if and else statement:

    elseif mode == "cave" then        local level = SaveGameIndex:GetCurrentCaveLevel(slotnum)        if level == -1 then            local cloudlevel = level * -1            widget.text:SetString(string.format("%s %d","Cloudrealm", cloudlevel))        else                widget.text:SetString(string.format("%s %d",STRINGS.UI.LOADGAMESCREEN.CAVE, level))        end        else

A similar thing can be done to slotdetailscreen. A quirk with this however, is that it doesn't seem to display the day.

 

If I can find a way to do that in the mod, it'd be fantastic. Considering it's a widget within a screen, it seems possible to me, unless there's a reason I'm not following.

 

As for the scml issue, I loaded up the same scml files in a Windows version of Spriter (the mod tools version) and resaved the scml. Converting them without doing that still produced the issue. (Albeit slightly differently.)

Link to comment
Share on other sites

So short of modifying the file itself (which lets me easily enable this) there's no way to do it? I'm going to tinker, perhaps there is a hackish way of doing it.

Actually it shouldn't be hard at all. I'm thinking a class post construct on screens/loadgamescreen patching MakeSaveTile should do it. I'll try that in a few minutes.

Link to comment
Share on other sites

Actually it shouldn't be hard at all. I'm thinking a class post construct on screens/loadgamescreen patching MakeSaveTile should do it. I'll try that in a few minutes.

Well I fought with it using a post construct already, but I think widget being local is a problem, since I'm changing widget.text's string. I'm curious why it isn't self.widget. If you get it, though, do tell how you managed it. :p

Link to comment
Share on other sites

Well I fought with it using a post construct already, but I think widget being local is a problem, since I'm changing widget.text's string. I'm curious why it isn't self.widget. If you get it, though, do tell how you managed it. :razz:

Done.

local Climbing = modrequire "lib.climbing"TheMod:AddClassPostConstruct("screens/loadgamescreen", function(self)	self.MakeSaveTile = (function()		local MakeSaveTile = self.MakeSaveTile		return function(self, slotnum, ...)			local tile = MakeSaveTile(self, slotnum, ...)			local h = Climbing.GetLevelHeight(slotnum)			if h > 0 then				tile.text:SetString(("Cloudrealm %d"):format(h))			end			return tile		end	end)()end)TheMod:AddClassPostConstruct("screens/slotdetailsscreen", function(self)	self.BuildMenu = (function()		local BuildMenu = self.BuildMenu		return function(self, ...)			BuildMenu(self, ...)			local slotnum = self.saveslot			local h = Climbing.GetLevelHeight(slotnum)			if h > 0 then				local day = SaveGameIndex:GetSlotDay(slotnum)				self.text:SetString(("Cloudrealm %d-%d"):format(h, day))			end		end	end)()end)

I also had to change screens/slotdetailsscreen, otherwise when clicking on the slot the opened screen would show cave strings. The above code is the whole content of code/postinits/saveselection.lua. I already pushed the changes.

Note that we don't need to check if the game mode is "cave", since otherwise the level height is 0 (in fact, if you check lib/climbing.lua you'll see I explicitly do this test and then return 0 if the mode is not "cave").

Link to comment
Share on other sites

@debugman18

I have some general comments on things I've seen in the code lately (most of them being suggestions, not really that important).

  • When you want to check if a global variable "some_var" exists, you can't simply do

    _G.some_var ~= nil
    That's because the global environment runs in "strict mode". This is done (through vanilla's strict.lua) by attaching a metatable to the global environment that raises an error if a nondeclared global variable is accessed. A variable is considered declared if something was set to it (even nil), but only if this is done through code running outside any function (i.e., at the "top level" of a file); trying to set something inside a function to an undeclared global variable also raises an error. To check if a global variable exists, you can do either of the following

    rawget(_G, "some_var") ~= nilVarExists("some_var")
    The first one uses the standard Lua function rawget, which indexes a table without invoking metamethods. The second one is a wicker function that is a bit more robust (working even if some mod is patching the global metatable for some shenanigans, even though this would be odd).
  • Calling the function string.len is just excessive typing. The length operator does the same thing, in a shorter and cleaner way, though literal strings need to be enclosed in parentheses.

    local str = "Hello world!"assert( #str == string.len(str) )assert( #str == #("Hello world!") )
    Moreover, all function in the string table can be called as methods on strings (though, once again, literal strings need to be enclosed in parentheses).

    assert( #("Hello world!") == ("Hello world!"):len() )
  • The GROUND table is already preloaded in the wicker environment.
Link to comment
Share on other sites

@debugman18

I have some general comments on things I've seen in the code lately (most of them being suggestions, not really that important).

  • When you want to check if a global variable "some_var" exists, you can't simply do

    _G.some_var ~= nil
    That's because the global environment runs in "strict mode". This is done (through vanilla's strict.lua) by attaching a metatable to the global environment that raises an error if a nondeclared global variable is accessed. A variable is considered declared if something was set to it (even nil), but only if this is done through code running outside any function (i.e., at the "top level" of a file); trying to set something inside a function to an undeclared global variable also raises an error. To check if a global variable exists, you can do either of the following

    rawget(_G, "some_var")VarExists("some_var")
    The first one is uses the standard Lua function rawget, which indexes a table without invoking metamethods. The second one is a wicker function that is a bit more robust (working even if some mod is patching the global metatable for some shenanigans, even though this would be odd).
  • Calling the function string.len is just excessive typing. The length operator does the same thing, in a shorter and cleaner way, though literal strings need to be enclosed in parentheses.

    local str = "Hello world!"assert( #str == string.len(str) )assert( #str == #("Hello world!") )
    Moreover, all function in the string table can be called as methods on strings (though, once again, literal strings need to be enclosed in parentheses).

    assert( #("Hello world!") == ("Hello world!"):len() )
  • The GROUND table is already preloaded in the wicker environment.

 

I actually noticed the VarExists function yesterday, but I haven't had an opportunity to use it.

 

As for the rest, noted. Where are those being used? I don't recall using string.len anywhere.

Link to comment
Share on other sites

As for the rest, noted. Where are those being used? I don't recall using string.len anywhere.

string.len was being used in the U&A menu screen (and so was the nil checking for global variables, when determining if the function IsDLCEnabled exists). Though that might be a result of copy pasting code from vanilla (older DS code looks quite ugly compared to newer code; Kevin mentioned he didn't know Lua when he started developing DS, and I'm guessing this was also the case for other devs, so it's understandable that older code tended to not be all that elegant :razz:). The GROUND table was being imported in code/main.lua to add the shopkeeper stall; but this is a really minor detail, since it's often easier to just import stuff instead of checking what is and isn't already in the environment.

Link to comment
Share on other sites

@debugman18

To make testing easier, now the U&A environment (more precisely, the environment of the file code/debugtools.lua) is accessible via the console in the variable UA (but only if the DEBUG option of the mod is set to true). So you can do things like this from the console:

UA.TheMod:Say "hello there"Climbing = UA.modrequire "lib.climbing"
I also made all wicker functions looking for entities (FindAllEntities, FindSomeEntity, etc.) also accept a string in place of the "fn" testing function. This string represents a prefab name, and translates into the condition "the entity should have this prefab". This is generally handy, but especially so in the console, since you can do something like

bs = UA.Game.FindAllEntities(GetPlayer(), 10000, "beanstalk_sapling")
when testing (the variable "Game" is already preset; check code/debugtools.lua for all that's in there).
Link to comment
Share on other sites

@debugman18

I forgot to mention that I added a new line to modinfo.lua:

branch = "dev"
The idea is that when generating the release zip the modinfo would be changed to say

branch = "release"
instead (currently this is not being done, however).

Within the mod code, you can do

if TheMod:IsDevelopment() then    -- stuffelse    -- other stuffend
which returns true if branch is set to "dev" in modinfo.lua. I'm using this for things like automatic generation of prefab files in scripts/prefabs/ and compilation of our assets in asset_compilation.lua, which are only enabled for the "dev" branch. You can also do

local branch = TheMod:GetBranch()
which returns the branch in uppercase (so "DEV", for the development version).
Link to comment
Share on other sites

@debugman18

To avoid having to check all the time if IsDLCEnabled and REIGN_OF_GIANTS are defined, I'm now defining them (if they are not already defined) in code/modenv.lua. Remember that whatever is defined in modenv.lua is defined for all mod files, so by putting it there is propagates to the whole mod.

What I'm doing is check if the global variable IsDLCEnabled exists, and if not set it to the function which always returns false (Lambda.False). If REIGN_OF_GIANTS is not defined, I set it to false (as a dummy, meaningless value), simply to avoid a crash due to trying to access an undeclared global variable. So now you can just write

if IsDLCEnabled(REIGN_OF_GIANTS) then    -- stuffend
without having to do all the existence checks prior to that. I changed weather_machine.lua, magic_beans.lua and upmenuscreen.lua to simply do this test.

I'm also preimporting in modenv.lua a bunch of wicker stuff:

Lambda = wickerrequire "paradigms.functional"Logic = wickerrequire "lib.logic"Pred = wickerrequire "lib.predicates"Game = wickerrequire "game"Math = wickerrequire "math"SearchSpace = wickerrequire "lib.searchspace"Configurable = wickerrequire "adjectives.configurable"Debuggable = wickerrequire "adjectives.debuggable"
Link to comment
Share on other sites

@debugman18

To avoid having to check all the time if IsDLCEnabled and REIGN_OF_GIANTS are defined, I'm now defining them (if they are not already defined) in code/modenv.lua. Remember that whatever is defined in modenv.lua is defined for all mod files, so by putting it there is propagates to the whole mod.

What I'm doing is check if the global variable IsDLCEnabled exists, and if not set it to the function which always returns false (Lambda.False). If REIGN_OF_GIANTS is not defined, I set it to false (as a dummy, meaningless value), simply to avoid a crash due to trying to access an undeclared global variable. So now you can just write

if IsDLCEnabled(REIGN_OF_GIANTS) then    -- stuffend
without having to do all the existence checks prior to that. I changed weather_machine.lua and magic_beans.lua to simply do this test.

I'm also preimporting in modenv.lua a bunch of wicker stuff:

Lambda = wickerrequire "paradigms.functional"Logic = wickerrequire "lib.logic"Pred = wickerrequire "lib.predicates"Game = wickerrequire "game"Math = wickerrequire "math"SearchSpace = wickerrequire "lib.searchspace"Configurable = wickerrequire "adjectives.configurable"Debuggable = wickerrequire "adjectives.debuggable"

 

Noted.

 

I'm currently experimenting with the worldgen screen, trying to figure out why the background appears black on Windows, but not on Mac or Linux.

Link to comment
Share on other sites

@debugman18

If you could post a set piece generated by the current Tiled version I might be able to write a converter to the old version compatible with DS. An equivalent file with the set piece made in the old version would help, but I don't think it's absolutely necessary.

And by the way, did you manage to sort out the analogous problem with Spriter?

Link to comment
Share on other sites

@debugman18

If you could post a set piece generated by the current Tiled version I might be able to write a converter to the old version compatible with DS. An equivalent file with the set piece made in the old version would help, but I don't think it's absolutely necessary.

And by the way, did you manage to sort out the analogous problem with Spriter?

 

Well, I'm using0.9.1 of Tiled, which is the latest version. It seems to create setpieces properly. Here's a setpiece from that version anyway:

 

https://www.dropbox.com/s/mqkclb8fa84todo/latest_tiled.lua

 

I didn't know there was any incompatibility with Tiled.

 

As far as Spriter is concerned, I'm using b5, which seems to be working properly. (The black crystal animation was done through it.)

Link to comment
Share on other sites

Well, I'm using 0.9.1 of Tiled, which is the latest version. It seems to create setpieces properly. Here's a setpiece from that version anyway:

 

https://www.dropbox.com/s/mqkclb8fa84todo/latest_tiled.lua

 

I didn't know there was any incompatibility with Tiled.

 

As far as Spriter is concerned, I'm using b5, which seems to be working properly. (The black crystal animation was done through it.)

Oh, sorry then. I thought you had told me Tiled was having issues as well, but it's just Spriter then.

Link to comment
Share on other sites

@Mr. Tiddles

I read through your prefabs/stategraph/brain code, and good job, very well done. I just ask that you pleeease indent your code (and keep indendation consistent) :razz:.

I made the following tweaks:

I conditionally enabled the day cycle based spawning of gummy bears based on whether the world is on permadusk or not (using the logic I posted in Candyland). I disabled the light flickering task of the gummybear den when it goes to sleep (in the sense that the engine disables it): in the storm ram, we were having the issue that it was exploding RAM usage, and we found out this was due to it periodically spawning a "spark" prefab; the issue was that the spark prefab only despawns when its animation ends, and when the entity is asleep the animation never plays, so a huge amount of entities was piling up over time, and the same would happen here. I also made the build switch/rainbow puff/howling sequence for transitioning into the naughty (non-cuddly) mode only happen when a gummybear has been without a target for a whole second, since doing this whenever it switched targets made it very weak against many weak mobs, due to it being incapacitated for long periods of time.

Oh, and I made the checking for combat targets run in a considerably lower resolution. A hundred times per second is a bit... excessive. And I disabled it when the entity is asleep as well.

Link to comment
Share on other sites

@debugman18

I automated the change of the "branch" entry in modinfo.lua to "release" when generating a zip for packaging.

If you take a look at pkginfo.lua, you'll see the entry

--[[-- Receives the modinfo file as a table, to be modified.---- The resulting table is then (turned back into a file) placed in the zip.--]]modinfo_filter = function(modinfo)    modinfo.branch = "release"    return modinfoend,
The automatically (re)generated modinfo.lua looks like this:

name = "Up and Away"author = "The Fellowship of the Bean"version = "prealpha"id = "upandaway"branch = "release"description = "A massive mod that adds many new things to the traditional Don't Starve experience, including new items, new monsters, new food, new structures, new recipes, and more.\\Original concept by debugman18."forumthread = "/topic/26501-up-and-away-mod-collaboration-thread"api_version = 4icon_atlas = "favicon/upandaway.xml"icon = "upandaway.tex"
I'm preserving the order in which the modinfo entries are defined to keep it nice and readable.

Note that the actual modinfo.lua file in the git repo's directory is not touched (well, it is read, but not written to :razz:), the modinfo manipulation is done in memory and the resulting string is put directly into the zip.

Link to comment
Share on other sites

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.