#Is it possible for me to remove the crafts from 4 mods and add all the items into a "Gacha" table?

21 messages · Page 1 of 1 (latest)

topaz cape
#

I have 4 plushie mods that I want to add into a gacha table that people use /gacha to use a coin item to randomly get a plushie. is this possible without addons?

minor isleBOT
#

Once your ticket has been resolved, please close it with </ticket close:1054771505520717835> command!

merry lantern
#

Yes, possible:

  • You can create custom commands
  • You can make the command consume an item from the inventory
  • You can make the command give a random plushie
topaz cape
#

I would love to have different teirs to it, like X plushies are more common than X

Like Teir 1, 2, 3, 4, 5 for lest to most common

merry lantern
#

For demonstration, I'll write a script that consumes gold ingots from inventory and gives a random tool. This will take a while BTW

topaz cape
#

It's okay I just need a example n work from there!

merry lantern
#

So far, I made these:

  • Command (refers to function inside global in startup scripts):
// Server script
ServerEvents.commandRegistry(event => {
  const { commands: Commands, arguments: Arguments } = event
  event.register(
    Commands.literal('gacha').executes(ctx => global.command(ctx))
  )
})
  • Startup script (so it can be quickly reloaded with /kubejs reload startup_scripts), includes weighted RNG that rolls rarity. The weightedRNG function is well typed with JSDoc annotation, so if you use VSCode or any other editor that supports TS you can see that you will get one of the keys of the object provided that has weights
#
/** @import { $CommandContext } from "com.mojang.brigadier.context.CommandContext" */
/** @import { $CommandSourceStack } from "net.minecraft.commands.CommandSourceStack") */

const weightedRNG = (() => {
  /** @type {Record<string, number>} */
  let _weights
  /** @type {[string, number][]} */
  let _entries
  /** @type {number} */
  let _raritySum
  /**
   * @template {Record<string, number>} T
   * @param {T} weights
   * @returns {keyof T}
   */
  return function weightedRNG(weights) {
    if (_weights == undefined || _weights !== weights) {
      _weights = weights
      _raritySum = Object.values(_weights).reduce((a, b) => a + b)
      _entries = Object.entries(_weights)
    }
    // An integer number between 1 and _raritySum, inclusive.
    let randomNumber = Utils.random.nextInt(_raritySum) + 1
    let index = -1
    while (randomNumber > 0) {
      index++
      randomNumber -= _entries[index][1]
    }
    return _entries[index][0]
  }
})()

/**
 *
 * @param {$CommandContext<$CommandSourceStack>} ctx
 * @returns {integer}
 */
global.command = ctx => {
  const { player } = ctx.source
  const rolledRarity = weightedRNG({
    common: 100,
    uncommon: 50,
    rare: 20,
    epic: 10,
    legendary: 2,
  })
  player.tell(rolledRarity)
  // const slot = player.inventory.find('minecraft:gold_ingot') // Find gold in inventory
  // if (slot == -1) return 0 // Return, if gold not found (`find` returns -1)
  // const coinStack = player.inventory.getStackInSlot(slot) // Get the item stack at that slot
  // coinStack.count--; // Reduce its size by 1
  // player.tell(slot)
  return 1
}
topaz cape
#

Ohhh okay I'm reading them rn

topaz cape
swift marlin
#

Right now it appears to be pure RNG, but weighted. No pity system, that wasn't specified in the requirements. What KonSola5's script currently does is when a player runs the command, it generates a rarity, and tells the player that rarity in their chat log. That's all. So you have a 100/182 chance of rolling common, 50/182 chance of uncommon, etc. but no guarantees of X rarity in N spins.

They started writing the code to deduct the gold ingot, but it looks like it wasn't working so they commented that out.

You would have to add persistant data to the player for that. Which is possible too.

merry lantern
#

Could also use Utils.lazy to make a function that memoizes its output, but didn't think of that

topaz cape
#

Okay I will start to make a script myself and see how well it works

#

with this example

merry lantern
#

player.give can give the player an item

#
player.give(item)
#

Where item is anything that can be a representation of an item stack

merry lantern
#

And since I made the weighted RNG return a string corresponding to rarity, you can specify possible outputs in a JS object with arrays as values:

const rewards = {
    common: ["minecraft:dirt", "minecraft:cobblestone"],
    uncommon: ["minecraft:iron_ingot", "minecraft:bone_block"],
    rare: ["minecraft:blaze_rod", "minecraft:lapis_block"],
    epic: ["minecraft:diamond", "minecraft:music_disc_relic", "minecraft:music_disc_stal"],
    legendary: ["minecraft:elytra", "minecraft:nether_star"],
}

const rarityRewards = rewards[rolledRarity];
player.give(rarityRewards[Utils.random.nextInt(rarityRewards.length)])