import { ItemStack, Player } from "@minecraft/server"; import { randomInteger, ascendingSort } from "lazuli-common"; import { giveItem, withPercentChance } from "lazuli-utils"; /** * Define a gift item. * @category Need Registry */ export class GiftItem { constructor( /** * Identifier of the type of items for the stack. If a namespace is not specified, 'minecraft:' is assumed. */ readonly typeId: string, /** * Rewards of the gift. */ public reward: RewardType ) {} /** * Registry the gift. * @deprecated Use `Register.giftRegistry()` to registry the gift. */ protected register(): void { console.warn("[Lazuli] The register method was deprecated!"); } /** * Give reward to a player. * @param player */ giveReward(player: Player): void { if (this.reward.items) { const ITEMS = this.reward.items; ITEMS.forEach((item) => { giveItem(player, item); }); } if (this.reward.exp) { player.addExperience(this.reward.exp); } if (this.reward.level) { player.addExperience(this.reward.level); } player.playSound("random.levelup"); } } /** * A Percent-Driven random reward gift. * @category Need Registry */ export class PercentGiftItem extends GiftItem { constructor( /** * Identifier of the type of items for the stack. If a namespace is not specified, 'minecraft:' is assumed. */ readonly typeId: string, /** * The probability of give reward when use the gift, should be a percentage (0~1). */ public chance: number, /** * Rewards of the gift. */ public reward: RewardType ) { super(typeId, reward); } /** * Give reward to a player. * @param player */ giveReward(player: Player): void { withPercentChance({ chance: this.chance, event: () => { if (this.reward.items) { const ITEMS = this.reward.items; ITEMS.forEach((item) => { giveItem(player, item); }); } if (this.reward.exp) { player.addExperience(this.reward.exp); } if (this.reward.level) { player.addExperience(this.reward.level); } player.playSound("random.levelup"); }, }); } } /** * A Weight-Driven random reward gift. * @category Need Registry */ export class WeightGiftItem { constructor( /** * Identifier of the type of items for the stack. If a namespace is not specified, 'minecraft:' is assumed. */ readonly typeId: string, /** * Data of the gift, including its reward and weight. */ public data: RewardWeightData[] ) {} /** * Registry the gift. * @deprecated Use `Register.giftRegistry()` to registry the gift. */ protected register(): void { console.warn("[Lazuli] The register method was deprecated!"); } /** * Give reward to a player. * @param player */ giveReward(player: Player): void { let weightArr: number[] = []; this.data.forEach((data) => { weightArr.push(data.weight); }); const totalWeight = this.data.reduce( (accumulator, currentValue) => accumulator + currentValue.weight, 0 ); let random = randomInteger(totalWeight, 1); weightArr.push(random); ascendingSort(weightArr); let index = weightArr.indexOf(random); if (this.data[index].reward.items) { // @ts-ignore this.data[index].reward.items.forEach((item) => { giveItem(player, item); }); } if (this.data[index].reward.exp) { // @ts-ignore player.addExperience(this.data[index].reward.exp); } if (this.data[index].reward.level) { // @ts-ignore player.addLevels(this.data[index].reward.level); } player.playSound("random.levelup"); } } /** * Types of gift reward. */ export interface RewardType { /** * Player will get these items when the quest is finished. */ items?: ItemStack[]; /** * The specific level will be given to the player. */ level?: number; /** * The specific point will be given to the player. */ exp?: number; } /** * Data of the gift, including its reward and weight. */ export interface RewardWeightData { /** * Reward of the gift. */ reward: RewardType; /** * Weight of giving this reward. */ weight: number; }