Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

Hello,

When using an altar or table, is there a way to randomly place items around the table (asset addon)? For instance, if I add three items, they all show in the center, all sort of through each other.

Thank you!
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Use :setSubtileOffset(x, y) to influence the placement of individual objects in a tile.

A way to do this for groups is to iterate through the items and randomly nudge them around.
Alternately the items could be placed in formations based upon how many items are present.
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

Isaac wrote: Mon Jun 10, 2024 1:14 am Use :setSubtileOffset(x, y) to influence the placement of individual objects in a tile.

A way to do this for groups is to iterate through the items and randomly nudge them around.
Alternately the items could be placed in formations based upon how many items are present.
Thank you for that. One last question, how do I define an item on a table or altar?

In my case, the item on the map is altar_1, and it contained items (fire_bomb, potion_healing, & potion_cure_poison). Each example I've seen would be something like this:

Code: Select all

altar_1:setSubtileOffset(x, y)
Would it be something like:

Code: Select all

altar_1(fire_bomb):setSubtileOffset(x, y)
altar_1(potion_healing):setSubtileOffset(x, y)
altar_1(potion_cure_poisonb):setSubtileOffset(x, y)
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
User avatar
7Soul
Posts: 209
Joined: Sun Oct 19, 2014 1:56 am
Location: Brazil

Re: Ask a simple question, get a simple answer

Post by 7Soul »

Altars and other such objects use the Surface Component to store items

I think something like this works:

Code: Select all

for item in altar_1.surface:contents() do
	if item.go.name == "fire_bomb" then
		item.go:setSubtileOffset(x,y)
	end
end
Join the LoG discord server: https://discord.gg/ArgAgNN :D

My Mods
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

7Soul wrote: Fri Jun 28, 2024 6:15 pm Altars and other such objects use the Surface Component to store items

I think something like this works:

Code: Select all

for item in altar_1.surface:contents() do
	if item.go.name == "fire_bomb" then
		item.go:setSubtileOffset(x,y)
	end
end
Oh, appreciate that. I finally got the script working for specific items on the floor, but hadn't tried tables, shelves, or altars. One thing I was attempting to do was to cover ALL items, but I've already run into issues with memory, heh.

What I have thus far:

Code: Select all

function setItemOffset()
        itemToFind = "fire_bomb_14", "fire_bomb_15"
        local item = findEntity(itemToFind)  -- Replace with your item's ID
        if item then
            -- Set specific offsets
            local offsetX = math.random(-3, 3) / 10
            local offsetY = math.random(-3, 3) / 10
            local offsetZ = math.random(-3, 3) / 10

        item:setSubtileOffset(offsetX, offsetY, offsetZ)
    else
        print("Cannot find ", itemToFind)

    end
end

-- Call the function to set the subtile offset for the item
setItemOffset()
Image

Evidently it doesn't like it when you use:

Code: Select all

function getAllItems()
    local allItems = {
        -- Armor
        "leather_cap", "leather_vest", "leather_pants", "leather_boots", "heavy_shield",
        "light_shield", "tower_shield", "wooden_shield", "round_shield", "loincloth",
        "loincloth_rags", "doublet", "peasant_tunic", "peasant_breeches", "peasant_shoes",
        "plate_cuirass", "plate_gauntlets", "plate_greaves", "plate_boots", "ring_greaves",
        "ring_cuirass", "ring_gauntlets", "ring_boots", "chitin_mail", "chitin_mask",
        "chitin_greaves", "chitin_boots", "chitin_gauntlets", "chitin_cuirass", "meteor_greaves",
        "meteor_cuirass", "meteor_gauntlets", "meteor_boots", "herder_cap", "herder_vest",
        "assassin_dagger", "assassin_cloak", "assassin_hood", "assassin_pants", "assassin_shoes",

        -- Consumables
        "healing_potion", "energy_potion", "poison_potion", "firebomb", "frostbomb",
        "shockbomb", "antivenom", "resurrection_potion", "speed_potion", "willpower_potion",
        "vitality_potion", "protection_potion", "strength_potion", "shield_potion", "mana_potion",
        "poison_bomb", "fire_bomb", "ice_bomb", "shock_bomb", "boiled_egg", "bread", "baked_bread",
        "fish", "grilled_fish", "meat", "grilled_meat", "salted_sausage", "mole_jerky", "cheese",
        "apple", "pear", "turtle_steak", "herder_cap", "herder_vest", "herder_breeches", 
        "herder_gloves", "herder_hood", "herder_cloak",

        -- Miscellaneous
        "torch", "rock", "scroll_fireburst", "scroll_fireball", "scroll_shock", "scroll_frostbolt",
        "scroll_poison_cloud", "scroll_frostburst", "scroll_invisibility", "scroll_lightning_bolt",
        "scroll_light", "scroll_darkness", "scroll_protection", "scroll_shield", "scroll_vitality",
        "scroll_energy", "scroll_healing", "scroll_mirror", "scroll_poison_shield", "scroll_fire_shield",
        "scroll_shock_shield", "scroll_frost_shield", "scroll_open", "scroll_teleport", "scroll_rejuvenation",
        "scroll_regen", "scroll_resurrect", "scroll_disintegrate", "scroll_summon", "scroll_cure", "scroll_fear",
        "scroll_stone", "scroll_air", "scroll_earth", "scroll_metal", "scroll_mind", "scroll_poison", 
        "scroll_spirit", "scroll_strength", "scroll_time", "scroll_water", "scroll_spellbook",
        "scroll_magic_missile", "scroll_protection", "scroll_mirror", "scroll_spell_healing", 
        "scroll_spell_protection", "scroll_spell_strength", "scroll_spell_energy", "scroll_spell_light",
        "scroll_spell_invisibility", "scroll_spell_lightning", "scroll_spell_fireball", "scroll_spell_frostbolt",
        "scroll_spell_shock", "scroll_spell_ice", "scroll_spell_earth", "scroll_spell_air", "scroll_spell_water",
        "scroll_spell_mind", "scroll_spell_metal", "scroll_spell_spirit", "scroll_spell_poison", 
        "scroll_spell_stone", "scroll_spell_strength", "scroll_spell_protection", "scroll_spell_energy",
        "scroll_spell_shield", "scroll_spell_poison_shield", "scroll_spell_fire_shield", "scroll_spell_shock_shield",
        "scroll_spell_frost_shield", "scroll_spell_invisibility", "scroll_spell_teleport", "scroll_spell_fear", 
        "scroll_spell_cure", "scroll_spell_regen", "scroll_spell_rejuvenation", "scroll_spell_resurrect", 
        "scroll_spell_disintegrate", "scroll_spell_summon", "scroll_spell_open", "scroll_spell_mirror",
        "scroll_spell_air", "scroll_spell_earth", "scroll_spell_energy", "scroll_spell_fire", "scroll_spell_frost",
        "scroll_spell_light", "scroll_spell_lightning", "scroll_spell_poison", "scroll_spell_shock", 
        "scroll_spell_stone", "scroll_spell_time", "scroll_spell_water", "crystal_shard_healing", 
        "crystal_shard_recharging", "crystal_shard_protection", "golden_orb", "blue_gem", "green_gem", 
        "red_gem", "key_iron", "key_bronze", "key_silver", "key_gold", "key_brass", "key_copper", 
        "key_skeleton", "compass", "shovel", "lock_pick", "rope", "map", "mortar_and_pestle", 
        "flute", "lyre", "crystal_flask", "tar_bead", "blooddrop_cap", "blackmoss", "mudwort", "slime_bell", 
        "crystal_flask", "potion_healing", "potion_energy", "potion_poison", "potion_speed", "potion_shield", 
        "potion_fire_shield", "potion_frost_shield", "potion_shock_shield", "potion_poison_shield", 
        "broadhead_arrow", "crossbow_quarrel",

        -- Weapons
        "dagger", "knife", "fist_dagger", "rapier", "short_sword", "cutlass", "serpent_blade", 
        "scimitar", "long_sword", "great_sword", "battle_axe", "hand_axe", "two_handed_axe", 
        "machete", "cleaver", "shuriken", "throwing_knife", "throwing_axe", "spear", "icefall_hammer", 
        "mace", "flail", "morning_star", "quarterstaff", "staff", "mage_staff", "necromancer_staff", 
        "fire_blade", "lightning_blade", "venom_edge", "bone_blade", "sky_pillar", "ancient_shuriken", 
        "lightning_bow", "longbow", "composite_bow", "crossbow", "hand_cannon", "musket"
    }
    return allItems
end
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

Still some work needed evidently...

Code: Select all

function randomizeItems()
    local offsetX = math.random(-3, 3) / 10
    local offsetY = math.random(-3, 3) / 10
    local offsetZ = math.random(-3, 3) / 10

    for item in tp_shop_counter_01_part02_1.surface:contents() do
		if item.go.name == "fjeld_warg_meat" then
			item.go:setSubtileOffset(offsetX,offsetY)
		end
	end

    for item in altar_1.surface:contents() do
    	if item.go.name == "fire_bomb" then
    		item.go:setSubtileOffset(offsetX,offsetY)
	    end
    end
end

-- Call the function to set the subtile offset for the item
randomizeItems()
Errors at line 7 and 14:
attempt to index local 'item' (a number value)
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
User avatar
7Soul
Posts: 209
Joined: Sun Oct 19, 2014 1:56 am
Location: Brazil

Re: Ask a simple question, get a simple answer

Post by 7Soul »

My bad it should be

Code: Select all

for _,item in altar_1.surface:contents() do
     --etc
end
Where _ is the index, and 'item' is the Item component
Join the LoG discord server: https://discord.gg/ArgAgNN :D

My Mods
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

7Soul wrote: Sat Jun 29, 2024 2:24 am My bad it should be

Code: Select all

for _,item in altar_1.surface:contents() do
     --etc
end
Where _ is the index, and 'item' is the Item component
Appreciate that.

I've added a entra line to see what the offset variables are and I see that the item is noted as table... is that expected?
Image

Code: Select all

function randomizeItems()
    local offsetX = math.random(-3, 3) / 10
    local offsetY = math.random(-3, 3) / 10
    local offsetZ = math.random(-3, 3) / 10
    local itemSurface = altar_1

    for _,item in altar_1.surface:contents() do
        if item.go.name == "fire_bomb" then
            item.go:setSubtileOffset(offsetX,offsetY)
            print("Item:", item, "on", itemSurface, "Offsets: ", "X:", offsetX, "Y:", offsetY, "Z:", offsetZ)
            end
    end
end
I plan on making itemSurface a table with all the surface names to make this at least manageable. "fire_bomb" will also be another table, items, in the end of items on the surfaces. At least, that is the thought.

Something like:

Code: Select all

function randomizeItems()
    local offsetX = math.random(-3, 3) / 10
    local offsetY = math.random(-3, 3) / 10
    local offsetZ = math.random(-3, 3) / 10
    local itemSurface = "altar_1", "shelf_1","table_1"
    local items = "fire_bomb","potion_healing","potion_cure_poison"

    for _,item in itemSurface.surface:contents() do
        if item.go.name == items then
            item.go:setSubtileOffset(offsetX,offsetY)
            print("Item:", item, "on", itemSurface, "Offsets: ", "X:", offsetX, "Y:", offsetY, "Z:", offsetZ)
            end
    end
end
I have yet to get it working though.
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
User avatar
The_Morlock
Posts: 25
Joined: Sun Jun 02, 2024 6:15 am

Re: Ask a simple question, get a simple answer

Post by The_Morlock »

While I was looking for something easier to manage, this at least works and it isn't all over the place with the naming. Explicit item and surface names... yeesh. I'll work a little more on this later on, but I at least have a level done.

Code: Select all

--
-- Script works with explicit item names and explicit surface names.
--

function clearOffset()
    local offsetX = nil
    local offsetY = nil
    local offsetZ = nil
end

function randomizeItems()
    local itemDetails = {
        {surface = altar_1,						item = "fire_bomb",				offsetX = math.random(-4, 4) / 5,	offsetY = math.random(-4, 4) / 5,	offsetZ = math.random(-4, 4) / 5},
        {surface = altar_1,						item = "potion_healing",		offsetX = math.random(-4, 4) / 5,	offsetY = math.random(-4, 4) / 5,	offsetZ = math.random(-4, 4) / 5},
        {surface = altar_1,						item = "potion_cure_poison",	offsetX = math.random(-4, 4) / 5,	offsetY = math.random(-4, 4) / 5,	offsetZ = math.random(-4, 4) / 5},
--      {surface = castle_alcove_4,				item = "steel_armband",			offsetX = 1.40,						offsetY = math.random(-3, 3) / 5,	offsetZ = math.random(-4, 4) / 5},
        {surface = tp_shop_counter_01_part02_1,	item = "fjeld_warg_meat",		offsetX = math.random(-4, 4) / 5,	offsetY = math.random(-4, 4) / 8,	offsetZ = math.random(-4, 4) / 5},
        {surface = tp_wall_shelf_01_1,			item = "potion_healing",		offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
        {surface = tp_wall_shelf_01_2,			item = "bread",					offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
		{surface = tp_wall_shelf_01_3,			item = "warg_meat",				offsetX = 1.40,						offsetY = math.random(-3, 3) / 5,	offsetZ = math.random(-4, 4) / 5},
        {surface = tp_wall_shelf_01_4,			item = "fjeld_warg_meat",		offsetX = 1.40,						offsetY = math.random(-3, 3) / 5,	offsetZ = math.random(-4, 4) / 5},
        {surface = tp_wall_shelf_01_5,			item = "potion_cure_disease",	offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
        {surface = tp_wall_shelf_01_5,			item = "scroll_disrupt",		offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
        {surface = tp_wall_shelf_01_6,			item = "potion_cure_poison",	offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
        {surface = tp_wall_shelf_01_6,			item = "scroll_fire_shield",	offsetX = -1.40,					offsetY = math.random(-3, 3) / 5,	offsetZ = nil},
        {surface = tp_wall_shelf_01_7,			item = "potion_resurrection",	offsetX = 0.5,						offsetY = math.random(-2.6, -2.6) / 2,	offsetZ = nil},
        {surface = tp_wall_shelf_01_7,			item = "crystal_shard_healing",	offsetX = 0.25,						offsetY = math.random(-2.75, -2.75) / 2,	offsetZ = nil}
    }

    for _, detail in ipairs(itemDetails) do
        local surface = detail.surface
        local itemName = detail.item
        local offsetX = detail.offsetX
        local offsetY = detail.offsetY
        local offsetZ = detail.offsetZ

        for _, item in surface.surface:contents() do
            if item.go.name == itemName then
                item.go:setSubtileOffset(offsetX, offsetY)
                if offsetZ then
                    print("Item:", itemName, "on", surface, "Offsets: ", "X:", offsetX, "Y:", offsetY, "Z:", offsetZ)
                else
                    print("Item:", itemName, "on", surface, "Offsets: ", "X:", offsetX, "Y:", offsetY)
                end
            end
        end
    end
end

clearOffset()
randomizeItems()
My Project(s): Grimstone Keep, a reimagining of the 1995 Interplay game, Stonekeep.
Discord: https://discord.gg/AfZVYHc8JX
Patreon: https://patreon.com/GrimstoneKeep
Facebook: https://www.facebook.com/profile.php?id=61565937875005
Hiker
Posts: 9
Joined: Sun Nov 19, 2023 1:43 pm

Re: Ask a simple question, get a simple answer

Post by Hiker »

I wonder if it’s possible to set random properties when defining objects? For example, immediately identify food with random nutrition? Clearly, we are talking about making each object random.
Post Reply