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.

CarlZalph

Some Mod API QoL additions

Recommended Posts

CarlZalph    4964

Entities that have data on the C-side are hard to get at.  Animation, Tags, etc.

I propose some LUA proxy functions to output the appropriate datums being hidden but are exposed using the ent.entity:GetDebugString().

 

Currently to get a networked entity ID, useful for uniquely identifying an entity as a client, a table of tags, an animation, or an animation frame number you have to use the GetDebugString function.

It's not efficient and could be done more directly without having to dump a blob of data to parse.

 

ent.Network:GetID() -> Returns either the number index or a string holding the unique identifier.  It's not used anywhere else in the code base but it is useful for client mods to keep track of unique entities.  Having it as a number or string doesn't matter.

ent.AnimState:GetAnimation() -> Returns the currently playing animation string if it is, else nil.

ent.AnimState:GetAnimationFrame() -> Returns the currently playing animation's frame number if it is playing an animation, else nil.

ent.entity:GetTags() / ent:GetTags() -> Returns a table of all of the entity's tags that it has, or an empty table if there are none.

Share this post


Link to post
Share on other sites
Hornete    8931

I'd like to see a AnimState:SetRotation function too. It works exactly like Transform:SetRotation but it doesnt affect the physics of the entity and other such things. It's purely visual.

Share this post


Link to post
Share on other sites
CarlZalph    4964
11 hours ago, VampireMonkey said:

Here's another one, add "params" in "containers.lua" to the containers table in the same file so it can be easily accessed

Aye that's a good one, I had to do this for one of mine:

Spoiler

local FindFirstUpValueRecursive = nil
FindFirstUpValueRecursive = function(func, varname, checked)
    local i = 1
    local n, v = debug.getupvalue(func, i)
    while v ~= nil
    do
        if n == varname
        then
            return v
        end
        if type(v) == "function" and checked[v] == nil
        then
            checked[v] = true
            return FindFirstUpValueRecursive(v, varname, checked)
        end
        i = i + 1
        n, v = debug.getupvalue(func, i)
    end
end

local Containers = require("containers")
local params = FindFirstUpValueRecursive(Containers.widgetsetup, "params", {})

..And hope that another mod that's hooking the thing doesn't use a local var called "params" too.

I wonder if we could compile a list of these 'private' vars that there could be a pass done to make them no longer 'private' since it really makes it harder for modding.

Like there's 81 components that have the private-public system in place, most of them from carry-overs from DS.  But there are a bundle of DST-exclusive ones that also follow this backwards system.

Doing this would inevitably break all mods currently using upvalues to try to find these 'private' vars, but the upvalue method is already prone to breaking if Klei ever edited any of the functions being used as a basis anyway.

Could preserve the mods by having a dummy local variable point to the new ones:

-- Old
local b = {}
local bobs = "your uncle"
b.a = function(self, ...)
    print(bobs)
end
return b

-- New
local b = {}
local bobs = "your uncle"
b.bobs = bobs -- "public" accessor for mods
b.a = function(self, ...)
    local bobs = bobs -- Dummy for upvalue
    print(self.bobs) -- Use new interface
end
return b

 

 

To add to the list:

A real keybind picker for mods to use instead of the usual "scroll through a list of user-defined keys" with the mod config menu.  Mods that define the available keys are not the same between mods, some support F# keys and others do not for example.  Having a central means to let mods have a bind menu popup in the config would stop the inconsistencies while adding easier functionality.

Share this post


Link to post
Share on other sites
Hornete    8931

That reminds me. Could we get a fix for the overridebuild variable for Modded Crockpot Dishes please? Sadly the game prioritises using the recipe name of a dish as the build rather than the overridebuild variable assigned to the recipe. So overridebuild is essentially useless for modders to use. I'd like to see a fix for this.
 

Spoiler

local function SetProductSymbol(inst, product, overridebuild)
    local recipe = cooking.GetRecipe(inst.prefab, product)
    local potlevel = recipe ~= nil and recipe.potlevel or nil
    local build = overridebuild or (recipe ~= nil and recipe.overridebuild) or "cook_pot_food" --This line should be changed to the line under
   -- local build =  (recipe ~= nil and recipe.overridebuild) or overridebuild or "cook_pot_food"
    local overridesymbol = (recipe ~= nil and recipe.overridesymbolname) or product

    if potlevel == "high" then
        inst.AnimState:Show("swap_high")
        inst.AnimState:Hide("swap_mid")
        inst.AnimState:Hide("swap_low")
    elseif potlevel == "low" then
        inst.AnimState:Hide("swap_high")
        inst.AnimState:Hide("swap_mid")
        inst.AnimState:Show("swap_low")
    else
        inst.AnimState:Hide("swap_high")
        inst.AnimState:Show("swap_mid")
        inst.AnimState:Hide("swap_low")
    end

    inst.AnimState:OverrideSymbol("swap_cooked", build, overridesymbol)
end

local function ShowProduct(inst)
    if not inst:HasTag("burnt") then
        local product = inst.components.stewer.product
        SetProductSymbol(inst, product, IsModCookingProduct(inst.prefab, product) and product or nil) --Product name is assigned as build if crockpot dish is modded
    end
end

 

 

Share this post


Link to post
Share on other sites
VampireMonkey    176

Very pleased to see my suggestion getting added so damn quickly! :D

Here's some stuff that would be nice to be exposed a bit easierly:
pigbrain.lua has a whole bunch of local variables that could be moved to the tuning file, probably like for example : TUNING.PIG.MIN_FOLLOW_DIST

mermbrain.lua has alot of similar local variables

Actually looking at the various brain files, alot of them have local variables so maybe having a special tuningbrains.lua would be better, then accessed something like: TUNING.BRAINS.PIG.MIN_FOLLOW_DIST


Adding a "AddPlayerOnSave" & "AddPlayerOnLoad" to add custom data to the player on save/load so we don't have to override the player's onsave/onload method in "AddPlayerPostInit" to add custom data.

"AddComponentAction" doesn't allow multiple entries from the same mod to the same component action
 doing this twice will cause the first entry to get overridden by the last, allowing only 1 entry to be added per mod for each component action.

AddComponentAction("USEITEM", "fuel", function (inst, doer, target, actions)

Say i want to add many different actions that can be toggled on/off in the mod config menu, this forces me to put them all in the same method call.
Which makes the code slightly harder to manage when you keep adding more toggleable features.

Updating to Lua 5.4 would be nice too.

Share this post


Link to post
Share on other sites
VampireMonkey    176
Some way to suppress this line in modindex.lua at line 392
print( "Overriding mod " .. actual_modname .. "'s option " .. option .. " with value " .. tostring(override) )
 

If your mod has alot of config options the logs will get spammed.
or just make it print how many options were overridden.
something like this :

actual_modname .. " : Overrode " .. numoptions .. " of " .. total_numoptions .. " options."


Dunno if this is currently possible but some way to get the default config value of a config option.
We have "GetModConfigData", having a "GetModConfigDataAll" to get the entire thing with name, label, hover, options and ofcourse default, would be nice.

Share this post


Link to post
Share on other sites
VampireMonkey    176

When using "AddComponentAction" it would be nice to be able to pass modifiers like shift, ctrl, alt, we can use right click which is nice but it isn't enough!

Also being able to override any existing action would be nice too.

Share this post


Link to post
Share on other sites
penguin0616    1037
On 2/13/2021 at 5:03 PM, CarlZalph said:

Currently to get a networked entity ID, useful for uniquely identifying an entity as a client, a table of tags, an animation, or an animation frame number you have to use the GetDebugString function.

It's not efficient and could be done more directly without having to dump a blob of data to parse.

 

ent.Network:GetID() -> Returns either the number index or a string holding the unique identifier.  It's not used anywhere else in the code base but it is useful for client mods to keep track of unique entities.  Having it as a number or string doesn't matter.

 

On 2/13/2021 at 5:03 PM, CarlZalph said:

ent.AnimState:GetAnimationFrame() -> Returns the currently playing animation's frame number if it is playing an animation, else nil.

 

 

Looks like we got AnimState:GetCurrentAnimationFrame() and Network:GetNetworkID()

Share this post


Link to post
Share on other sites