#Add tooltip based on enchantments on items

26 messages · Page 1 of 1 (latest)

tiny garden
#

Hello! I'm trying to figure out how I could add some kind of dynamic tooltip which changes based on the highest enchantment level that a tool has.

For example, if my sword has sharpness 5 and looting 3, I want to only take into consideration the sharpness 5, and add a tooltip related to that value, like this:

-ATN: 30

I already know how I could only get the highest enchantment, but I'm still uncertain on how to do the dynamic tooltip. I would like for it to look like the attached screenshot, but I can manage the formatting, I just would like some guidance when it comes to the dynamic thing.

For the time being, I have a client_script which add other regular tooltips based on a dictionary, which goes like this:

import weaponList from 'sds_requirements.js';
import armorList from 'sds_requirements.js';

const itemList = Object.assign(weaponList, armorList);

ItemEvents.modifyTooltips(event => {
    for (const [item, requirements] of Object.entries(itemList)) {
        event.add(item, '')
        //event.add(weapon, Text.gray('Stat requirements:'))
        let reqEND = 0;
        let reqSTR = 0;
        let reqDEX = 0;
        for (const [stat, statValue] of Object.entries(requirements)) {
            switch (stat) {
                case ('kubejs:sds_endurance'):
                    reqEND = statValue
                    break;
                case ('kubejs:sds_strength'):
                    reqSTR = statValue
                    break;
                case ('kubejs:sds_dexterity'):
                    reqDEX = statValue
                    break;
            }
        }

        event.modify(item, {shift: false}, tooltip => {
            tooltip.add(
                Text.gray('Req: ')
                .append(Text.darkGray(reqEND > 0 ? `(${reqEND}) ` : ''))
                .append(Text.darkRed(reqSTR > 0 ? `(${reqSTR}) ` : ''))
                .append(Text.gold(reqDEX > 0 ? `(${reqDEX}) ` : ''))
            )
        });
        event.modify(item, {shift: true}, tooltip => {
            tooltip.add(Text.gray('Stat requirements:'));
            if (reqEND > 0) tooltip.add(Text.darkGray(`- END: ${reqEND}`));
            if (reqSTR > 0) tooltip.add(Text.darkRed(`- STR: ${reqSTR}`));
            if (reqDEX > 0) tooltip.add(Text.gold(`- DEX: ${reqDEX}`));
        });
    }

});
chrome hatchBOT
#

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

tiny garden
#

I believe in this case I should use this one, but I'm unsure on if this works dynamically, since it's in the client_scripts

I would like the player to have an easy time figuring out the requirement that the enchanted item has

fringe whale
#

Amazing documentation, who can guess what the "string" is supposed to represent?

#

Ah, ok, it's probably a "key" for the tooltip.dynamic

#

In ItemEvents.dynamicTooltip's event, you have access to event.item

#

Which is the ItemStack you are currently hovering over

tiny garden
#

Oh sick! I will test that out

tiny garden
#

Okay, I was able to pull it off by using the event.item

#

Here's my code in case anyone wants to take a peek/use it

import {weaponList, armorList, witherLevelArmorReq, witherLevelWeaponReq} from 'sds_requirements.js';


const itemList = Object.assign(weaponList, armorList);


function extractNumbers(text) {
    let digits = [];
    
    for (let i = 0; i < text.length; i++) {
        let character = text.charAt(i);
        if (character >= '0' && character <= '9') {
            digits[digits.length] = character;
        }
    }
    
    return digits.join('');
}

function getHighestDigit(text) {
    var highest = -1;
    var len = text.length;
    
    for (var i = 0; i < len; i++) {
        var character = text.charAt(i);
        
        if (character >= '0' && character <= '9') {
            var digit = character - '0';
            
            if (digit > highest) {
                highest = digit;
                
                if (highest === 9) {
                    return 9; 
                }
            }
        }
    }
    
    return highest; 
}


ItemEvents.modifyTooltips(event => {
    for (const [item, requirements] of Object.entries(itemList)) {
        event.add(item, '')
        let reqEND = requirements['kubejs:sds_endurance'] || 0;
        let reqSTR = requirements['kubejs:sds_strength'] || 0;
        let reqDEX = requirements['kubejs:sds_dexterity'] || 0;

        if (reqEND || reqSTR || reqDEX) {
            event.modify(item, {shift: false}, tooltip => {
                tooltip.add(
                    Text.gray('Req: ')
                    .append(Text.darkGray(reqEND > 0 ? `(${reqEND}) ` : ''))
                    .append(Text.darkRed(reqSTR > 0 ? `(${reqSTR}) ` : ''))
                    .append(Text.gold(reqDEX > 0 ? `(${reqDEX}) ` : ''))
                )
            });
            event.modify(item, {shift: true}, tooltip => {
                tooltip.add(Text.gray('Stat requirements:'));
                if (reqEND > 0) tooltip.add(Text.darkGray(`- END: ${reqEND}`));
                if (reqSTR > 0) tooltip.add(Text.darkRed(`- STR: ${reqSTR}`));
                if (reqDEX > 0) tooltip.add(Text.gold(`- DEX: ${reqDEX}`));
            });
        }
    }

})

ItemEvents.modifyTooltips(event => {
    event.modifyAll({shift: false}, tooltip => {
        tooltip.dynamic('enchantment_off')
    })

    event.modifyAll({shift: true}, tooltip => {
        tooltip.dynamic('enchantment_on')
    })

})

ItemEvents.dynamicTooltips('enchantment_off', event => {
    if (String(event.item.enchantments).includes("enchantments={}")) return;

    const witherLevel = getHighestDigit(String(extractNumbers(String(event.item.enchantments))))
    if (witherLevel <= 0) return;
    
    let reqATN;
    const itemTags = String(event.item.getTags())
    if (itemTags.includes('c:armors')  || itemTags.includes('minecraft:enchantable/armor')) reqATN = witherLevelArmorReq[witherLevel]
    else reqATN = witherLevelWeaponReq[witherLevel]
    if (!reqATN) return;

    event.add('')
    event.add(
        Text.gray('Unq req: ')
        .append(Text.blue(reqATN > 0 ? `(${reqATN}) ` : ''))
    )

})

ItemEvents.dynamicTooltips('enchantment_on', event => {
    if (String(event.item.enchantments).includes("enchantments={}")) return;
    
    const witherLevel = getHighestDigit(String(extractNumbers(String(event.item.enchantments))))
    if (witherLevel <= 0) return;
    
    let reqATN;
    const itemTags = String(event.item.getTags())
    if (itemTags.includes('c:armors')  || itemTags.includes('minecraft:enchantable/armor')) reqATN = witherLevelArmorReq[witherLevel]
    else reqATN = witherLevelWeaponReq[witherLevel]
    if (!reqATN) return;

    event.add('')
    event.add(Text.gray('Unique stat requirements:'));
    if (reqATN > 0) event.add(Text.blue(`- ATN: ${reqATN}`));

})
#

had to add the segment for unique requirements to add these enchanted item requirements, that way any item that can be enchanted can have those reqs too

fringe whale
tiny garden
#

what 😭

tiny garden
fringe whale
#

You can imagine loading KubeJS scripts as concatenating all scripts into one big script, then running that big script

#

You can use // priority: 100 (or any other number) to control which scripts load first and which load next

tiny garden
#

oh hell nah

#

so the only local scope would be inside functions i assume

fringe whale
#

You can simulate "modules" by making an object in global scope and using an IIFE to assign to it:

const sdsRequirements = (() => {
  return {
    weaponList = [],
    armorList = [],
    // ...
  }
})()
#

Bonus points for being able to hide internal functions that way

tiny garden
#

i see i see, thanks for the info, cuz i did notice some weird stuff going around, like being unable to modify const variables that assigned elsewhere

fringe whale
#

Then you definitely want to put your scripts in IIFEs

#
(() => {
  // ...
})()

This is IIFE

#

You declare a function, that gets immediately called