Jump to content

[WIP] Speeder Upper


Recommended Posts

Brand spanking new to modding in Don't Starve, but I'll try not to ask questions that have already been answered to death.

 

The mod I'm currently working on (alpha version is attached) is supposed to add a console command "c_dayspeed()" which basically changes the day length (how many real-time minutes each in-game day lasts).

 

I'm having trouble figuring out which variables I need to declare and return in order to change the game's GLOBAL.TUNING variables having to do with time. Also having trouble getting anything involving an array variable to work in a function, even when they work just fine outside of functions.

 

Problematic code snippet:

--copied from data/scripts/tuningoverrides.lualocal tuning_backups = {} local function OverrideTuningVariables(tuning)     for k, v in pairs(tuning) do          tuning_backups[k] = TUNING[k]          TUNING[k] = v     endend local function ResetTuningVariables()     for k,v in pairs(tuning_backups) do          TUNING[k] = v     endend c_dayspeed = function(l_minutes)     local seg_time = l_minutes * 30 / 8     OverrideTuningVariables(TUNING.SEG_TIME = seg_time)end

Anybody want to point out what I'm doing wrong here? Also, is this kind of mod going to be possible (or practical given my skill set in LUA)?

alpha.zip

Link to comment
Share on other sites

Can't edit posts on this forum? I guess that's one excuse to bump a thread ...

 

Update:

 

I feel like I'm getting close to what I want to do, but I'm still confused about syntax:

 

--[[test function that "should" (if all goes well) add a working console command c_test(#) which sets how many seconds the gamewill wait before executing the autosave feature. I just want this to work as a sample code so I can build a bigger function to do all time related events except autosave. AutoSaving thegame is just the easiest alteration to notice.--]]local l_savedelay = 480 --default day length function c_test(l_newdelay)     l_newdelay = l_newdelay or 480     l_savedelay = l_newdelay     return {l_savedelay}end local TUNING_OVERRIDES = [TUNING.AUTOSAVE_INTERVAL = l_savedelay] return {OVERRIDES = TUNING_OVERRIDES}

 

^^ returns error message "Expected symbol near '[' " ... as I expected because that's the part of syntax I'm completely unfamiliar with. Can't figure out how to enclose the statement for the string TUNING_OVERRIDES which contains the "=" sign.

Link to comment
Share on other sites

Can't edit posts on this forum? I guess that's one excuse to bump a thread ...

 

Update:

 

I feel like I'm getting close to what I want to do, but I'm still confused about syntax:

--[[test function that "should" (if all goes well) add a working console command c_test(#) which sets how many seconds the gamewill wait before executing the autosave feature. I just want this to work as a sample code so I can build a bigger function to do all time related events except autosave. AutoSaving thegame is just the easiest alteration to notice.--]]local l_savedelay = 480 --default day length function c_test(l_newdelay)     l_newdelay = l_newdelay or 480     l_savedelay = l_newdelay     return {l_savedelay}end local TUNING_OVERRIDES = [TUNING.AUTOSAVE_INTERVAL = l_savedelay] return {OVERRIDES = TUNING_OVERRIDES}

^^ returns error message "Expected symbol near '[' " ... as I expected because that's the part of syntax I'm completely unfamiliar with. Can't figure out how to enclose the statement for the string TUNING_OVERRIDES which contains the "=" sign.

 

Change those [ ] to { }

Link to comment
Share on other sites

@debugman18:

 

I changed from { } to [ ] because of the error:

 

'}' expected near '='

 

I also tried ( ' ' ) ... which didn't give an error. It just didn't work. That's why I completely baffled about the syntax here.

Link to comment
Share on other sites

@debugman18:

 

I changed from { } to [ ] because of the error:

 

'}' expected near '='

 

I also tried ( ' ' ) ... which didn't give an error. It just didn't work. That's why I completely baffled about the syntax here.

 

I'm pretty sure that's because you're using the '=' syntax inside of the table "{ }". You should declare the value of the variable outside of its table, I think.

Link to comment
Share on other sites

back@debugman18: Can you post an example using the test code I provided? Not sure how that would look. Thanks for the help by the way.

 

Like this:

 

local TUNING.AUTOSAVE_INTERVAL = l_savedelay

 

local TUNING_OVERRIDES = {TUNING.AUTOSAVE_INTERVAL}
 
Although I don't know how to achieve completely what you're trying to do.
Link to comment
Share on other sites

function test(l_minutes)     local l_minutes = l_minutes or 8     TUNING.AUTOSAVE_INTERVAL = l_minutes * 60          --Need a way to delay the next command so this function can return variables first               TUNE()     return {               TUNING.AUTOSAVE_INTERVAL,               OVERRIDES = TUNING.AUTOSAVE_INTERVAL               }end

 

Could this work if I can find a way to use something like DoTaskInTime (don't have an inst declared for it) to have the script run TUNE() after all the variables are in check? I feel like I'm getting there, but still not sure if this will ever work (I've had dozens of failed prototypes already -- each more promising than this idea).

Link to comment
Share on other sites

function test(l_minutes)     local l_minutes = l_minutes or 8     TUNING.AUTOSAVE_INTERVAL = l_minutes * 60          --Need a way to delay the next command so this function can return variables first               TUNE()     return {               TUNING.AUTOSAVE_INTERVAL,               OVERRIDES = TUNING.AUTOSAVE_INTERVAL               }end

Could this work if I can find a way to use something like DoTaskInTime (don't have an inst declared for it) to have the script run TUNE() after all the variables are in check? I feel like I'm getting there, but still not sure if this will ever work (I've had dozens of failed prototypes already -- each more promising than this idea).

 

 

You could do inst:DoTaskInTime(seconds, function() tune end). You do need something to be running DoTaskInTime, I believe. Why not just do each function separately and in order?

 

So, for instance, make a function containing everything you want to do before TUNE runs, then run it, then run tune.

Link to comment
Share on other sites

I'd need help figuring that one out. I tried putting TUNE() in the function after the return{...}, but got an error saying it was expecting end to follow return{ }. If I put it outside the function, then it won't get called when the function is executed from the console, and you're right about me not being able to use inst:DoTaskInTime because I'm not using PostInit(function(inst)...end) ... there should be something I can throw in there to make that command wait while the function continues on ... or I should be able to get the function to set those GLOBAL variables without being forced to exit. Something easy I'm missing here ...

Link to comment
Share on other sites

I don't really understand what you're trying to do in a lot of the code you've posted, so it's hard to help (for example, why try to emulate tuning_override.lua? What does it do that you also want to do?).

Here's some code that would add a console command (console commands are just global functions) that would set SEG_TIME to the number of minutes passed to it or, if it's called with no parameters, would reset SEG_TIME to the default value:

local default_seg_time = TUNING.SEG_TIMEfunction c_dayspeed(l_minutes)     -- "condition and val_if_true or val_if_false" is Lua's version of the ternary operator     local seg_time = l_minutes and (l_minutes * 30 / 8) or default_seg_time     TUNING.SEG_TIME = seg_timeend
Link to comment
Share on other sites

The code I've been posting is just a test function (practice for the real deal) that should create a console command that will change the autosave interval to autosave every "l_minutes" minutes in-game. This way I can test the script quickly by going into the game and running the console command c_test(.1) to change the autosave interval from 8 minutes to 6 seconds. If the game doesn't save after waiting 6 seconds, it didn't work.

 

If I get that to work correctly, I can change the variable from TUNING.AUTOSAVE_INTERVAL to every other tuning var that uses a seg_time, total_day_time, or other time local variable. I have the mod up and running on Steam at the moment (in beta) as "Take your time" because it does work but isn't customizeable in-game. It just makes everything go 3 times slower hunger/day/season/perish-wise.

 

Played around with your script a bit (good to see you by the way):

 

local default_autosave_interval = TUNING.AUTOSAVE_INTERVAL function c_test(l_minutes)     local autosave_interval = l_minutes or default_autosave_interval     require('tuning') --[[ entered inside the function because TUNE() isn't recognized as               a function even though it works fine standalone in the console (didn't work anyways) --]]     TUNING.AUTOSAVE_INTERVAL = autosave_interval     TUNE() --[[ I think I need this to work in order to apply the changes.           Without it, I'm pretty sure the variable just sits there being orphaned. --]]end
Link to comment
Share on other sites

Calling Tune (not sure why you have it all caps, it's defined as Tune in tuning.lua) will just reset all tuning variables to their defaults. You don't want to do that.

For each variable, you need to see how it's used in the game code to be able to determine how you need to modify it. For example, TUNING.AUTOSAVE_INTERVAL is used in components/autosaver.lua and only gets referenced when the component is first created and whenever an autosave is actually performed. So, any changes you make to TUNING.AUTOSAVE_INTERVAL will only take effect after the next autosave. To have it take effect immediately, you'd want to do:

 

local default_autosave_interval = TUNING.AUTOSAVE_INTERVAL  function c_test(l_minutes)    local autosave_interval = l_minutes or default_autosave_interval    TUNING.AUTOSAVE_INTERVAL = autosave_interval    -- set the next save to be one interval length from now    -- alternatively you could call GetPlayer().components.autosaver:DoSave() to force a save    GetPlayer().components.autosaver.timeout = autosave_intervalend
Link to comment
Share on other sites

Thanks for that Squeek. It solved the c_test( ) function at least, but unfortunately did it in such a way that doesn't work as a template for the c_dayspeed( ) function. :hypnotized:

 

That TUNE( ) bit was a typo because I couldn't copy/paste into this silly reply box, and when I copy/pasted back from the box, I forgot that Tune( ) isn't all-caps. Then I got confused when I was getting "nil" errors for a global function that I knew existed.

 

I browsed around those script files some more to see where any of the other TUNING... variables fit in and haven't found a single useful one yet. So there should be a local "timeout" variable that I need to correct as well as the global _TIME variable for each one of these, and many (there are over 150 of the stinking things) of them may require a maths function to determine the appropriate timeout method. I guess I'll keep looking, but at least it's a start. Something that works. Cheers.

Link to comment
Share on other sites

Thanks for that Squeek. It solved the c_test( ) function at least, but unfortunately did it in such a way that doesn't work as a template for the c_dayspeed( ) function. :hypnotized:

Yes, as I was trying to get at, there's no way to make a 'template' function for overriding tuning variables. They are all used in different ways, so you have to figure out how they are used in order to make sure that your change will have the intended effect.

I browsed around those script files some more to see where any of the other TUNING... variables fit in and haven't found a single useful one yet. So there should be a local "timeout" variable that I need to correct as well as the global _TIME variable for each one of these, and many (there are over 150 of the stinking things) of them may require a maths function to determine the appropriate timeout method. I guess I'll keep looking, but at least it's a start. Something that works. Cheers.

The timeout variable is specific to the autosaver component. Most of the TUNING.*_TIME variables are used in components/clock.lua, but SEG_TIME is used all over the place.

To properly change the total day time, you'll have to overwrite all variables that depend on it.

A very basic start would be:

local function MultiplyTuningVariableBy(keypath, multiplier)    assert(type(keypath) == "string")    -- table.getfield and table.setfield are non-standard functions defined in util.lua    -- they allow for getting and setting child keys using a string    -- table.getfield(tbl, "a.b.c") would get the value of tbl["a"]["b"]["c"]    local cur_value = table.getfield(TUNING, keypath)    if cur_value ~= nil then        table.setfield(TUNING, keypath, cur_value*multiplier)    endendlocal tuning_variables_affected_by_total_day_length = {    "SEG_TIME", "TOTAL_DAY_TIME", "WILSON_HUNGER_RATE", "BLUEAMULET_FUEL",    -- etc, there are a ton that would need to be in this table, see tuning.lua}function c_dayspeed(new_day_length)    -- get the ratio of new:old day length    local day_length_ratio = new_day_length/TUNING.TOTAL_DAY_TIME    -- multiply all relevant variables by that ratio    for _,keypath in ipairs(tuning_variables_affected_by_total_day_length) do        MultiplyTuningVariableBy(keypath, day_length_ratio)    endend
But that's only the beginning. You'd now have to go through each and every one of the affected variables and see how it's used and check if you need to do anything further to make sure it'd work properly. For example, you'd probably want to do a dummy call to Clock:SetSegs to force it to update it's variables using the new SEG_TIME value.

local clock = GetClock()clock:SetSegs(clock:GetDaySegs(), clock:GetDuskSegs(), clock:GetNightSegs())
As you can probably tell, you've chosen a much more difficult task that you might have first thought. Day length was not written to be adjustable on-the-fly, and to allow it to be, you're going to have to modify a whole lot of stuff every time the day length changes.

If you don't already, I'd highly suggest using a text editor that has good find-in-files support because that's the best way to find all references to a variable in the Don't Starve code. Something like Notepad++ or Sublime Text would work.

Link to comment
Share on other sites

At least we're on the same page now. Sorry about my cross-eyed code analyzing; going on a 70+ hour work week. I'd be more than happy to take the back seat on this mod if anybody likes the idea and wants to run with it themselves. It looks like the script will be about 1000 lines long, but it should be doable.

 

I'm thinking the GLOBAL.TUNING variables can be abandoned altogether:

 

--partial script to show example of TUNING.WILSON_HUNGER_RATE by itselffunction dayspeed(l_minutes)     l_minutes = l_minutes or 24 --[[setting default to 24 minute day to reduce              confusion with "Take Your Time" mod --]]     local seg_time = l_minutes * 30 / 8 --[[ if set to game default (8 minutes),               seg_time should be 30 seconds --]]      --juicy bits follow; need to add an "if" statement to check player character is Wilson     GetPlayer().components.hunger:SetRate(75 / seg_time / 16) -- drop 75 hunger per 16 segs (day)end

 

What I like about this mod is the ability to speed up the game time rate rather than slow it down (hence the name "Speeder Upper"). It's worth trying out the "Take Your Time" mod attached below and setting the "l_minutes" (on line 9) from "24" to "4" just to see what the game is like at double time. I made it to day 24 before dying spectacularly (no hunger, no health, no sanity, no snivel gear in the dark of winter, no fuel for the campfire, and music-box hands coming for me). It really does add a new element of replayability to an already exhilarating game.

 

Cheers.

Take your time b111.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.

×
  • Create New...