DFHack / dfhack

Memory hacking library for Dwarf Fortress and a set of tools that use it
Other
1.87k stars 475 forks source link

Make crystal glass more common #3883

Open quietust opened 1 year ago

quietust commented 1 year ago

Back in the 2D versions of Dwarf Fortress, rock crystals were virtually guaranteed to occur in every embark, though they were somewhat rare. Once Toady implemented proper geology, however, they became so scarce as to be virtually nonexistent (to the point that he had to alter the Strange Mood code so dwarves would not demand crystal glass until you actually crafted some of it yourself).

There are several ways this can be improved:

  1. Before embarking, modify the world's geological regions so that at least one layer contains Rock Crystal inclusions.
  2. At any time, find all Gem-trading entities and add Rough Rock Crystals to their list of "miscellaneous" trade goods (i.e. the list which contains things like lye, potash, and pearlash).

Open issues:

  1. When adding an inclusion to a geological layer, determine whether the "frequency" value (currently world_geo_layer.vein_unk_38) is absolute or relative. If it's absolute, we can probably add it to every stone layer, otherwise we should just pick one layer which has at least a few small clusters (to avoid ending up with unusually large numbers of them).
  2. If possible, we might try hooking into worldgen (by interposing the relevant viewscreen) so the geology can be altered immediately after it's been initialized and before any civilizations get created, so that their resources will be updated accordingly. In this way, we could also add Rough Rock Crystals as a trade good to every entity which has Cut Rock Crystals rather than having to examine their flags.
  3. Rather than explicitly dealing with Rock Crystals, we should use any inorganic material having the [CRYSTAL_GLASSABLE] flag.
quietust commented 1 year ago

Extremely preliminary script for improvement 1:

local gems = {}

-- Find all crystal-glassable gem types
for i,v in pairs(df.global.world.raws.inorganics) do
    if v.material.flags.CRYSTAL_GLASSABLE then
        table.insert(gems, i)
    end
end

-- Iterate across all geological regions
for _,v in pairs(df.global.world.world_data.geo_biomes) do
    -- Examine all layers within each region
    for _,w in pairs(v.layers) do
        -- For now, only accept standard Stone layer types
        -- (SEDIMENTARY+METAMORPHIC+IGNEOUS_INTRUSIVE+IGNEOUS_EXTRUSIVE)
        if w.type >= 1 and w.type <= 4 then
            local have_glassable = false
            -- Check if we have any glassable gems already
            for _,x in pairs(w.vein_mat) do
                for _,y in pairs(gems) do
                    if x == y then
                        have_glassable = true
                    end
                end
            end
            if not have_glassable then
                -- We didn't find any, so let's add one
                w.vein_mat:insert('#', gems[math.random(1, #gems)])
                w.vein_nested_in:insert('#', -1)
                w.vein_type:insert('#', 3) -- CLUSTER_SMALL
                w.vein_unk_38:insert('#', 1) -- supposed to be frequency, seemingly ignored
            end
        end
    end
end