Jump to content

[Q] Resource calculator?


Recommended Posts

Hi all.

Has anyone seen/made a tool to calculate total resources required to build a base or some other "built" area? I've been playing with creative mode and would like to start building in my main world, but I would need at least ballpark figures for all the primary resources (ie. rocks, grass and logs, not cut stone, rope and boards).

Link to comment
https://forums.kleientertainment.com/forums/topic/77870-q-resource-calculator/
Share on other sites

On 4/17/2017 at 5:55 PM, myxal said:

Hi all.

Has anyone seen/made a tool to calculate total resources required to build a base or some other "built" area? I've been playing with creative mode and would like to start building in my main world, but I would need at least ballpark figures for all the primary resources (ie. rocks, grass and logs, not cut stone, rope and boards).

Personally I use my own customcommands.lua file and insert this in it:

local GroundTiles = require("worldtiledefs")
local function cz_buildlist_internal(materials, recipe, onlybase, multiplier)
    multiplier = math.ceil(multiplier / recipe.numtogive)
    for _,v in pairs(recipe.ingredients)
    do
        local prefab = v.type
        if onlybase and AllRecipes[prefab] ~= nil
        then
            cz_buildlist_internal(materials, AllRecipes[prefab], onlybase, v.amount * multiplier)
        else
            materials[prefab] = (materials[prefab] or 0) + v.amount * multiplier
        end
    end
end
function cz_buildlist(radius, onlybase, turfs)
    if ThePlayer == nil
    then
        return
    end
    radius = radius or 25.0
    local x, y, z = ThePlayer.Transform:GetWorldPosition()
    local ents = TheSim:FindEntities(x, y, z, radius, nil, {"INLIMBO", "FX", "DECOR", "player"})
    local materials = {}
    local ents_uncraftable = {}
    local ents_counts = {}
    for _,v in pairs(ents)
    do
        local prefab = v.prefab
        local entity_count = 1
        if Prefabs[prefab.."_item"]
        then
            prefab = prefab.."_item"
        end
        if Prefabs["dug_"..prefab]
        then
            prefab = "dug_"..prefab
        end
        if prefab:sub(1,7)=="winter_" and prefab:sub(-4)=="tree"
        then
            prefab = "winter_treestand"
        end
        if prefab:sub(1,5)=="wall_" and v.AnimState
        then
            local wall_values = {}
            wall_values["broken"] = 1
            wall_values["onequarter"] = 1
            wall_values["half"] = 1
            wall_values["threequarter"] = 2
            wall_values["fullA"] = 4
            wall_values["fullB"] = 4
            wall_values["fullC"] = 4
            for k,v2 in pairs(wall_values)
            do
                if v.AnimState:IsCurrentAnimation(k)
                then
                    entity_count = v2
                    break
                end
            end
        end
        ents_counts[prefab] = (ents_counts[prefab] or 0) + entity_count
    end
    for k,v in pairs(ents_counts)
    do
        local recipe = AllRecipes[k]
        if recipe ~= nil
        then
            cz_buildlist_internal(materials, recipe, onlybase, v)
        else
            ents_uncraftable[k] = (ents_uncraftable[k] or 0) + 1
        end
    end
    if turfs and TheWorld and TheWorld.Map
    then
        local turfs_out = {}
        local map = TheWorld.Map
        local xt, zt = map:GetTileCoordsAtPoint(x, y, z)
        local rt = radius/4.0
        for i=-rt,rt
        do
            for j=-rt,rt
            do
                local t = map:GetTile(xt+i, zt+j)
                local tt = GroundTiles.turf[t]
                if tt
                then
                    local prefab = "turf_"..tt.name
                    local recipe = AllRecipes[prefab]
                    if onlybase and recipe ~= nil
                    then
                        cz_buildlist_internal(materials, recipe, onlybase, 1.0)
                    else
                        ents_uncraftable[prefab] = (ents_uncraftable[prefab] or 0) + 1
                    end
                end
            end
        end
    end
    print("__Materials Required__")
    for k,v in pairs(materials)
    do
        print(k, v)
    end
    print("~~Uncraftables Below~~")
    for k,v in pairs(ents_uncraftable)
    do
        print(k, v)
    end
    print("^^Materials Required^^")
end

Then in the client-side console:

cz_buildlist(radius, onlybase, turfs)

Radius is a float, onlybase and turfs are booleans.

Example: cz_buildlist(14.0, false, true)

@CarlZalph

Hmm, when counting only base materials, the amount of direct materials (eg. boards) is ignored. For example, when counting direct materials, a single chest will show correctly 3 boards. But when counting base, it will show 4 logs instead of 12.

EDIT: Fixed!

local function cz_buildlist_internal(materials, recipe, onlybase, upperamount)
    for _,v in pairs(recipe.ingredients)
    do
        local prefab = v.type
        if onlybase and AllRecipes[prefab] ~= nil
        then
            cz_buildlist_internal(materials, AllRecipes[prefab], onlybase, v.amount)
        else
            materials[prefab] = (materials[prefab] or 0) + (v.amount * upperamount or 1)
        end
    end
end
function cz_buildlist(radius, onlybase)
    if ThePlayer == nil
    then
        return
    end
    local x, y, z = ThePlayer.Transform:GetWorldPosition()
    local ents = TheSim:FindEntities(x, y, z, radius or 25.0, nil, {"INLIMBO", "FX", "DECOR", "NOCLICK", "player"})
    local materials = {}
    for _,v in pairs(ents)
    do
        local recipe = AllRecipes[v.prefab]
        if recipe ~= nil
        then
            cz_buildlist_internal(materials, recipe, onlybase, 1)
        end
    end
    print("__Materials Required__")
    for k,v in pairs(materials)
    do
        print(k, v)
    end
    print("^^Materials Required^^")
end

EDIT: More issues noticed:

  • Walls, fences and gates are not counted at all
  • Mini signs are overcounted (each is counted as 1 board, when in reality 1 board crafts 4 of them)
1 hour ago, myxal said:

EDIT: More issues noticed:

  • Walls, fences and gates are not counted at all
  • Mini signs are overcounted (each is counted as 1 board, when in reality 1 board crafts 4 of them)

Try what's in the post now, I believe they're fixed.

3 hours ago, CarlZalph said:

Try what's in the post now, I believe they're fixed.

Awesome. The base central area I prototyped is pretty much done (it isn't too fancy :) ), except the turfs, and 1 anomaly - a festive tree planter will not reveal its materials after a tree is planted in it. (I guess the prefab changes from the planter to the "festive tree" itself?).

From testing though, I have found that walls' health is not factored in. Example - to place and max out 2 thulecite wall columns, I need to craft 2 sets of wall segments (8 are required in total; there are options to also max out the wall with thulecite fragments and/or thulecite, but using wall segments appears to be the cheapest method).

Perhaps more experienced players/knowledgeable wiki readers may weigh in if there's a trick to saving resources when building a particular kind of wall, but when using wall segments. all wall types start at 50% of max health, with each segment increasing health by 16.66..%

15 minutes ago, myxal said:

Awesome. The base central area I prototyped is pretty much done (it isn't too fancy :) ), except the turfs, and 1 anomaly - a festive tree planter will not reveal its materials after a tree is planted in it. (I guess the prefab changes from the planter to the "festive tree" itself?).

From testing though, I have found that walls' health is not factored in. Example - to place and max out 2 thulecite wall columns, I need to craft 2 sets of wall segments (8 are required in total; there are options to also max out the wall with thulecite fragments and/or thulecite, but using wall segments appears to be the cheapest method).

Perhaps more experienced players/knowledgeable wiki readers may weigh in if there's a trick to saving resources when building a particular kind of wall, but when using wall segments. all wall types start at 50% of max health, with each segment increasing health by 16.66..%

The walls would be a bit of a kludge for detection- would need to check the currently playing animation and use the minimum resources required to make it.

The festive tree one also would be another kludge in that once it becomes a winterized tree the prefab switches to another set, I'll check it out a bit later for if any pattern in the prefab names to use (like a prefix of "winter_" from glancing).

4 minutes ago, CarlZalph said:

The walls would be a bit of a kludge for detection- would need to check the currently playing animation and use the minimum resources required to make it.

IMHO, trying to go for "the cheapest way to build up a wall" would be a wasted effort, since the "value" of a particular resource isn't objectively universal - it's determined by resources on stock, playstyle and available "facilities". Fire hounds burned down my twig farm? No way am I building up wood walls with twigs. Collected 800 grass from gekko farm? Will build up with grass alone to save twigs and time. Etc...

Point being, translating wall health simply into segments used would be definitely enough for me.

12 hours ago, CarlZalph said:

The walls would be a bit of a kludge for detection- would need to check the currently playing animation and use the minimum resources required to make it.

The festive tree one also would be another kludge in that once it becomes a winterized tree the prefab switches to another set, I'll check it out a bit later for if any pattern in the prefab names to use (like a prefix of "winter_" from glancing).

Thanks, will check it in the evening.

BTW, can you also do a check, if for a given enitity's prefab, a "dug_..." prefab exists? That should allow counting of diggables (saplings, grass, berry bushes...). 

@CarlZalph

What works: Wall and turf counting, planted festive trees.

Issue: Diggables are ignored. (They don't have any recipe, so the internal function never gets called on them?) I fixed it by putting diggables into a separate list, if there's no recipe (there's a mod that allows crafting plants).

And speaking or recipes, I imagined the turfs would be handled through recipe filter, but instead all are listed, even the non-craftable ones :) I'm not entirely sure what's the right thing to do here...

--- /Users/user1/Documents/Klei/DoNotStarveTogether/customcommands.lua.old	2017-04-19 20:41:11.000000000 +0200
+++ /Users/user1/Documents/Klei/DoNotStarveTogether/customcommands.lua	2017-04-19 21:22:24.000000000 +0200
@@ -21,6 +21,7 @@
     local x, y, z = ThePlayer.Transform:GetWorldPosition()
     local ents = TheSim:FindEntities(x, y, z, radius, nil, {"INLIMBO", "FX", "DECOR", "NOCLICK", "player"})
     local materials = {}
+    local diggables = {}
     local ents_counts = {}
     for _,v in pairs(ents)
     do
@@ -33,6 +34,11 @@
         if Prefabs["dug_"..prefab]
         then
             prefab = "dug_"..prefab
+            local recipe = AllRecipes[prefab]
+            if recipe == nil
+            then
+              diggables[prefab] = (diggables[prefab] or 0) + entity_count
+            end
         end
         if prefab:sub(1,7)=="winter_" and prefab:sub(-4)=="tree"
         then
@@ -99,4 +105,10 @@
         print(k, v)
     end
     print("^^Materials Required^^")
-end
\ No newline at end of file
+    print("__Diggables Planted__")
+    for k,v in pairs(diggables)
+    do
+        print(k, v)
+    end
+    print("^^Diggables Planted^^")
+end

 

@CarlZalphRegarding turfs - I've seen players using some non-craftable turfs in the base purely for the aesthetics, that's why I'm hesitant to outright ignore non-craftable turfs. I'm thinking maybe you could implements the recipe filter for turfs, and the main function could take an extra argument - a list of prefabs (anything), that would be counted in the separate list, and not included in the materials list - that way, players could count arbitrary objects in the design ("How many glommer goop to surround the Ocuvigil?"), as well as exclude a particular prefab from the materials total ("How many resources do i need for this if I put the wooden floor later"?)

Offtopic: LOL, the forum won't do syntax highlighting for lua source, but will do it for lua patches, WTF? :D 

EDIT: This should do the trick: (Also, nightmarefuel is added to materials list even when onlybase=true. NOBODY farms dark petals. )

local GroundTiles = require("worldtiledefs")
local function cz_buildlist_internal(materials, recipe, onlybase, multiplier)
    multiplier = math.ceil(multiplier / recipe.numtogive)
    for _,v in pairs(recipe.ingredients)
    do
        local prefab = v.type
        if onlybase and AllRecipes[prefab] ~= nil and prefab ~= "nightmarefuel"
        then
            cz_buildlist_internal(materials, AllRecipes[prefab], onlybase, v.amount * multiplier)
        else
            materials[prefab] = (materials[prefab] or 0) + v.amount * multiplier
        end
    end
end
function cz_buildlist(radius, onlybase, turfs, excludes)
    local exc_trans = {}
    if excludes ~= nil
    then
      for _,v in pairs(excludes)
      do
        exc_trans[v] = true;
      end
    end
    if ThePlayer == nil
    then
        return
    end
    radius = radius or 25.0
    local x, y, z = ThePlayer.Transform:GetWorldPosition()
    local ents = TheSim:FindEntities(x, y, z, radius, nil, {"INLIMBO", "FX", "DECOR", "NOCLICK", "player"})
    local materials = {}
    local noncrafts = {}
    local ents_counts = {}
    for _,v in pairs(ents)
    do
        local prefab = v.prefab
        local entity_count = 1
        if Prefabs[prefab.."_item"]
        then
            prefab = prefab.."_item"
        end
        if Prefabs["dug_"..prefab]
        then
            prefab = "dug_"..prefab
            if AllRecipes[prefab] == nil
            then
              noncrafts[prefab] = (noncrafts[prefab] or 0) + entity_count
            end
        end
        if prefab:sub(1,7)=="winter_" and prefab:sub(-4)=="tree"
        then
            prefab = "winter_treestand"
        end
        if prefab:sub(1,5)=="wall_" and v.AnimState
        then
            local wall_values = {}
            wall_values["broken"] = 1
            wall_values["onequarter"] = 1
            wall_values["half"] = 1
            wall_values["threequarter"] = 2
            wall_values["fullA"] = 4
            wall_values["fullB"] = 4
            wall_values["fullC"] = 4
            for k,v2 in pairs(wall_values)
            do
                if v.AnimState:IsCurrentAnimation(k)
                then
                    entity_count = v2
                    break
                end
            end
        end
        ents_counts[prefab] = (ents_counts[prefab] or 0) + entity_count
    end
    for k,v in pairs(ents_counts)
    do
      local recipe = AllRecipes[k]
      if excludes ~= nil and exc_trans[k]
      then
        noncrafts[k] = (noncrafts[k] or 0) + v
      else
        if recipe ~= nil
        then
          cz_buildlist_internal(materials, recipe, onlybase, v)
        end
      end
    end
    if turfs and TheWorld and TheWorld.Map
    then
        local turfs_out = {}
        local map = TheWorld.Map
        local xt, zt = map:GetTileCoordsAtPoint(x, y, z)
        local rt = radius/4.0
        for i=-rt,rt
        do
            for j=-rt,rt
            do
                local t = map:GetTile(xt+i, zt+j)
                local tt = GroundTiles.turf[t]
                if tt
                then
                    local prefab = "turf_"..tt.name
                    local recipe = AllRecipes[prefab]
                    if onlybase and recipe ~= nil and not exc_trans[prefab]
                    then
                        cz_buildlist_internal(materials, recipe, onlybase, 1.0)
                    else
                        noncrafts[prefab] = (noncrafts[prefab] or 0) + 1
                    end
                end
            end
        end
    end
    print("__Materials Required__")
    for k,v in pairs(materials)
    do
        print(k, v)
    end
    print("^^Materials Required^^")
    print("__Non-craftables__")
    for k,v in pairs(noncrafts)
    do
        print(k, v)
    end
    print("^^Non-craftables^^")
end

Usage:

cz_buildlist(30.0,true,true,{"treasurechest","goldnugget"})

2 hours ago, myxal said:

@CarlZalph

Issue: Diggables are ignored. (They don't have any recipe, so the internal function never gets called on them?)

Fixed.

2 hours ago, myxal said:

This should do the trick: (Also, nightmarefuel is added to materials list even when onlybase=true. NOBODY farms dark petals. )

cz_buildlist(30.0,true,true,{"treasurechest","goldnugget"})

I worry about feature bloat for this function to be honest.

Too many different ways to view the same data and to filter them.

 

But I have put in the second list of 'uncraftables' at the bottom of the original material list in mine.

Reason for the turfs that can't be crafted to be taken into consideration is that the person running the command explicitly stated they wanted turfs outputted and so all turfs are to be outputted- can't know if the person wanted uncrafts or not without having yet another parameter.

21 hours ago, CarlZalph said:

Fixed.

I worry about feature bloat for this function to be honest.

Too many different ways to view the same data and to filter them.

Fair enough. I'll keep the 4-argument one as it allows me to exclude stuff that I'm not sure about building immediately or is already built when preparing for rebuilds.

I went on to prototype the farm area and noticed a minor issue - farms (I built the improved ones) are not counted if there's a crop on them (either growing or ready to be harvested).

35 minutes ago, myxal said:

I went on to prototype the farm area and noticed a minor issue - farms (I built the improved ones) are not counted if there's a crop on them (either growing or ready to be harvested).

Fixed by removing the "NOCLICK" tag from the initial entity scan.

This'll populate more entities in the uncraftable section, but it'll catch farms that have things on them.

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...