Page 1 of 1

Custom assembling machine

Posted: Fri Aug 22, 2025 10:04 pm
by Pearlseverance
I made a custom assembling machine that is supposed to craft an item that utilizes control.lua to randomize the output using a "dummy" item.

I want the randomization result to be weighted, with a 95% chance of crafting one item, and a 5% chance of crafting the other.

The problem is, I cannot get the dummy item to be replaced by the expected resulting items. I did use Google for help, so I do not understand what is wrong with my code.
The other problem is I cannot make the machine itself to appear on the screen.. as in, the sprite doesn't show, or is invisible. The item being produced is fine, however.

I can send the data.lua and control.lua for debugging purposes.

Code: Select all

data:extend(
{
  {
    type = "item",
    name = "shape-triangle",
    icon = "__TriangleFactory__/graphics/icons/triangle-icon.png",
	icon_size = 64,
    subgroup = "raw-material", -- Or a new subgroup, or an existing one
    order = "z[shape-item]",
    stack_size = 99,
	pictures = {
	{size = 64, filename = "__TriangleFactory__/graphics/icons/triangle1.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/triangle2.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/triangle3.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/triangle4.png", scale = 0.5, mipmap_count = 1}
	}
  }
})
data:extend(
{
  {
    type = "item",
    name = "shape-circle",
    icon = "__TriangleFactory__/graphics/icons/circle-icon.png",
	icon_size = 64,
    subgroup = "raw-material", -- Or a new subgroup, or an existing one
    order = "z[shape-item]",
    stack_size = 99,
	pictures = {
	{size = 64, filename = "__TriangleFactory__/graphics/icons/circle1.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/circle2.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/circle3.png", scale = 0.5, mipmap_count = 1},
	{size = 64, filename = "__TriangleFactory__/graphics/icons/circle4.png", scale = 0.5, mipmap_count = 1}
	}
  }
})
data:extend(
{
  {
    type = "item",
    name = "placeholder-shape",
    icon = "__TriangleFactory__/graphics/icons/triangle-icon.png",
	icon_size = 64,
    subgroup = "raw-material", -- Or a new subgroup, or an existing one
    order = "z[shape-item]",
    stack_size = 1
  }
})
data:extend(
{
  {
    type = "item",
    name = "triangle-assembler-item",
    icon = "__base__/graphics/icons/assembling-machine-2.png",
	icon_size = 64,
    subgroup = "production-machine", -- Or a new subgroup, or an existing one
    order = "z[shape-item]",
    stack_size = 99,
	place_result = "triangle-assembler"
  }
})
-- Define a new recipe category
data:extend(
{
  {
    type = "recipe-category",
    name = "random-shape-crafting"
  }
})

data:extend(
{
  {
    type = "recipe-category",
    name = "trianglemaker-crafting"
  }
})

-- Define the custom assembling machine
data:extend(
{
  {
    type = "assembling-machine",
    name = "triangle-assembler",
    icon = "__base__/graphics/icons/assembling-machine-2.png",
    icon_size = 64,
    flags = {"placeable-neutral", "placeable-player", "player-creation"},
    minable = {hardness = 0.2, mining_time = 0.5, result = "triangle-assembler-item"},
    max_health = 300,
    corpse = "small-remnants",
    collision_box = {{-1.2, -1.2}, {1.2, 1.2}},
    selection_box = {{-1.5, -1.5}, {1.5, 1.5}},
    fast_replaceable_group = "assembling-machine",
    crafting_speed = 1.0,
    crafting_categories = {"random-shape-crafting"},
    energy_usage = "150kW",
    energy_source =
    {
      type = "electric",
      emissions = 0.05,
      usage_priority = "secondary-input"
    },
     animation = {
      layers = {
        {
          filename = "__TriangleFactory__/graphics/entity/triangle-assembler/triangle-assembler.png",
          width = 64,
          height = 64,
          frame_count = 1,
          shift = {0, 0}
        },
        {
          filename = "__TriangleFactory__/graphics/entity/triangle-assembler/triangle-assembler.png",
          tint = {r=0.0, g=0.0, b=0.0}, -- Change tint to show it's a special machine
          width = 64,
          height = 64,
          frame_count = 1,
          shift = {0, 0}
        }
      }
    },
    module_inventory_size = 2,
    working_visualisations = {
      {
        filename = "__TriangleFactory__/graphics/entity/triangle-assembler/triangle-assembler.png",
        width = 128,
        height = 128,
        frame_count = 4,
        line_length = 2,
        animation_speed = 1,
        shift = {0.2, 0.05}
      }
    },
    vehicle_impact_sound =  { filename = "__base__/sound/car-metal-impact.ogg", volume = 0.65 },
    open_sound = { filename = "__base__/sound/machine-open.ogg", volume = 0.85 },
    close_sound = { filename = "__base__/sound/machine-close.ogg", volume = 0.85 }
  }
 }
)

-- Define the recipe with a placeholder result
data:extend(
{
  {
    type = "recipe",
    name = "shape-recipe",
    category = "random-shape-crafting",
    ingredients = {
	{
      type = "item",
      name = "steel-plate",
      amount = 3
    },
    {
      type = "item",
      name = "copper-plate",
      amount = 3
    },
	},
    results = {
      {type= "item", name = "placeholder-shape", probability=1, amount_min=1, amount_max=1}
    },
    enabled = true,
	auto_recycle = false
  }
})
-- Shape Assembly recipe
data:extend(
{
  {
    type = "recipe",
    name = "triangle-assembler-recipe",
    category = "crafting",
	ingredients = {
	{
      type = "item",
      name = "steel-plate",
      amount = 4
    },
    {
      type = "item",
      name = "copper-plate",
      amount = 5
    },
	{
      type = "item",
      name = "electronic-circuit",
      amount = 3
    },
	{
      type = "item",
      name = "engine-unit",
      amount = 3
    },
	},
    results = {
      {type= "item", name = "triangle-assembler-item", probability=1, amount_min=1, amount_max=1}
    },
    enabled = true,
	auto_recycle = false
  }
})

Code: Select all

-- Store your weighted random outcomes in a global variable
global = {}
global.random_outcomes = {
  { name = "shape-triangle", count = 1, weight = 95 }, -- 95% chance
  { name = "shape-circle", count = 1, weight = 5 } -- 5% chance
}

-- The total weight is used to get a random number
global.total_weight = 0
for _, outcome in ipairs(global.random_outcomes) do
  global.total_weight = global.total_weight + outcome.weight
end

-- Function to pick a random item based on weights
local function get_random_item()
  local random_roll = math.random(1, global.total_weight)
  local cumulative_weight = 0
  
  for _, outcome in ipairs(global.random_outcomes) do
    cumulative_weight = cumulative_weight + outcome.weight
    if random_roll == 0 and progress == 0 then
        -- We can be sure a craft just finished
        
        -- Get the machine's output inventory
        local output_inventory = entity.get_output_inventory()

        if output_inventory then
          -- Get a random outcome
          local result = get_random_outcomes()
          
          -- Remove the placeholder item (if any) and insert the new item
          output_inventory.insert(result)
          
          -- Log the outcome for debugging
          game.print("Triangle Assembler created: " .. result.count .. " " .. result.name)
        end
      end
      
      data.last_progress = progress
    end
      -- Clean up invalid entities
      global.tracked_assemblers[unit_number] = nil
end

Re: Custom assembling machine

Posted: Fri Aug 22, 2025 10:24 pm
by eugenekay
Pearlseverance wrote: Fri Aug 22, 2025 10:04 pmI want the randomization result to be weighted, with a 95% chance of crafting one item, and a 5% chance of crafting the other.
That seems like an awful lot of custom Lua Control code. Is there a reason that the built-in probability factor of the ItemProductPrototype does not work for your use case?

For example, uranium-processing has a 0.7% chance to produce Uranium-235 vs Uranium-238:

Code: Select all

  {
    type = "recipe",
    name = "uranium-processing",
    energy_required = 12,
    enabled = false,
    auto_recycle = false,
    category = "centrifuging",
    ingredients = {{type = "item", name = "uranium-ore", amount = 10}},
    icon = "__base__/graphics/icons/uranium-processing.png",
    subgroup = "uranium-processing",
    order = "a[uranium-processing]-a[uranium-processing]",
    results =
    {
      {
        type = "item",
        name = "uranium-235",
        probability = 0.007,
        amount = 1
      },
      {
        type = "item",
        name = "uranium-238",
        probability = 0.993,
        amount = 1
      }
    },
    allow_productivity = true
  },
Good Luck!

Re: Custom assembling machine

Posted: Sat Aug 23, 2025 3:28 pm
by Pearlseverance
Like I said. I was too shy to ask for help on the forums before.... So I asked Google and it gave me a bunch of jank I suppose!

Thank you for the new insight.

Re: Custom assembling machine

Posted: Sat Aug 23, 2025 4:00 pm
by Pearlseverance
eugenekay wrote: Fri Aug 22, 2025 10:24 pm
Pearlseverance wrote: Fri Aug 22, 2025 10:04 pmI want the randomization result to be weighted, with a 95% chance of crafting one item, and a 5% chance of crafting the other.
That seems like an awful lot of custom Lua Control code. Is there a reason that the built-in probability factor of the ItemProductPrototype does not work for your use case?

For example, uranium-processing has a 0.7% chance to produce Uranium-235 vs Uranium-238:

Code: Select all

  {
    type = "recipe",
    name = "uranium-processing",
    energy_required = 12,
    enabled = false,
    auto_recycle = false,
    category = "centrifuging",
    ingredients = {{type = "item", name = "uranium-ore", amount = 10}},
    icon = "__base__/graphics/icons/uranium-processing.png",
    subgroup = "uranium-processing",
    order = "a[uranium-processing]-a[uranium-processing]",
    results =
    {
      {
        type = "item",
        name = "uranium-235",
        probability = 0.007,
        amount = 1
      },
      {
        type = "item",
        name = "uranium-238",
        probability = 0.993,
        amount = 1
      }
    },
    allow_productivity = true
  },
Good Luck!
This recipe code indeed works for me. I removed the control.lua and nearly everything is perfect now. I only now need to find out why my machine is invisible.

It is a 128x128 image split into four 64 pixel frames... Not actually sure how I am supposed to get the machine to show up in this instance, but I tried using my experience in modding other games to help me.

Re: Custom assembling machine

Posted: Sat Aug 23, 2025 4:38 pm
by Pearlseverance
I added the priority code and the missing "graphics_set = " line to the machine code and now the image shows up. Everything is good in the Triangle Factory now.

This can be marked as SOLVED!

Image