本篇教程由作者设定未经允许禁止转载。
需要KubeJS和LootJS: KubeJS Addon。
需要注意的是lootjs的修改通过Just Enough Resources是看不到的,需要用高级战利品信息显示才能看见,两个可以一起装,后者会覆盖前者的页面
本教程只记录了我的整合包里所用到的魂石,没有涉及到的在未来可能会添加(下一步是加植魔,但是要做完相关的其他内容才会来做这个),也可能不会(如机械动力以及枪相关附属等)
我一个人编写一个人测试,难免会有隐藏的bug,如果你有发现任何bug随时向我反馈
别忘了event.remove({ mod: 'mine_fargo' })
先列出目前添加的所有内容
| 魂石名称 | 获取方法 |
| 空白魂石 | 合成 |
| 矿物之魂 | 在植物魔法的台子上合成 |
| 煤炭魂石 | 挖矿概率获得 |
| 铜魂石 | 挖矿概率获得 |
| 青金石魂石 | 挖矿概率获得 |
| 铁魂石 | 挖矿概率获得 |
| 红石魂石 | 挖矿概率获得 |
| 金魂石 | 挖矿概率获得 |
| 绿宝石魂石 | 挖矿概率获得 |
| 钻石魂石 | 挖矿概率获得 |
| 下界合金魂石 | 挖矿概率获得 |
| 自然之魂 | |
| 冰雪魂石 | 在冰原或雪原等流浪者会刷新的地方用火焰附加/怒火击杀流浪者有1%的概率掉落 |
| 熔岩魂石 | 在细雪里(ticksFrozen>0)击杀烈焰人50%概率获得一个 |
| 蘑菇魂石 | 在蘑菇岛使用剪刀5%掉落 |
| 下界魂石 | 在下界,每着火5秒1%的概率触发一次掉落 |
| 末地魂石 | 吃紫颂果、右键末影珍珠每次分别有1%的概率掉落,上述两种行为每次都会积累得分,得分满100额外给一个 |
| 海洋魂石 | 每1000分得一个,分数来源:Score=(游泳距离 ×1.0)+(水面行走×0.5)+(水下行走 ×1.1)+(坐船×0.3) |
| 翠绿魂石 | 收获作物的时候1%概率获得 |
| 森林魂石 | 在森林、繁花森林、桦木森林、黑森林、丛林、稀疏丛林、竹林、樱花树林群系,当玩家每隔10秒,有1%在玩家脚下生成一个。累计30分钟额外掉落一个 |
| 生灵之魂 | “掠夺”附魔不会生效 |
| 狱灵魂石 | 击杀僵尸猪灵、猪灵、猪灵蛮兵有1%的概率掉落,100次独立保底一次 |
| 亡灵魂石 | 击杀亡灵生物1%掉落一个,100个保底,如果武器有亡灵杀手变成5%,此外凋灵固定掉一个 |
| 节肢魂石 | 击杀原版蜘蛛和洞穴蜘蛛1%掉落一个,100个保底,如果武器有节肢杀手变成5% |
| 动物魂石 | 击杀动物(同时有age和InLove数据值的生物)时1%掉落 |
| 水生魂石 | 击杀亡灵生物1%掉落一个,100个保底,如果武器有水生杀手变成5% |
| 飞翼魂石 | 杀100只幻翼掉一个 |
| 灾变之魂 | |
| 焰魔魂石 | 加入战利品表 |
| 利维坦魂石 | 加入战利品表 |
| 咒翼灵骸魂石 | 加入战利品表 |
| 末影守卫魂石 | 加入战利品表 |
| 远古遗魂魂石 | 加入战利品表 |
| 先驱者魂石 | 加入战利品表 |
| 下界合金巨兽魂石 | 加入战利品表 |
| 斯库拉魂石 | 加入战利品表 |
| 巨龙之魂 | |
| 龙骨魂石 | 所有龙有概率掉落 |
| 炎血魂石 | 龙骨魂石在冶炼炉浇筑火龙血 |
| 霜血魂石 | 龙骨魂石在冶炼炉浇筑冰龙血 |
| 霆血魂石 | 龙骨魂石在冶炼炉浇筑雷龙血 |
| 龙炎魂石 | 龙骨魂石在对应锻炉里 |
| 龙霜魂石 | 龙骨魂石在对应锻炉里 |
| 龙霆魂石 | 龙骨魂石在对应锻炉里 |
| 冰火之魂 | |
| 独眼巨人魂石 | 加入战利品表 |
| 蛇发女妖魂石 | 加入战利品表 |
| 海蟒魂石 | 加入战利品表 |
| 食人妖魂石 | 加入战利品表 |
| 海马魂石 | 加入战利品表 |
| 死亡蠕虫魂石 | 加入战利品表 |
| 塞壬魂石(模组特殊处理) | 加入战利品表 |
| 九头蛇魂石(模组特殊处理) | 加入战利品表 |
| 乐事魂石 | 进食时有概率获得 |
| 海王魂石 | 加到海王的战利品表里 |
| 超然之魂 | |
| 锚定魂石 | 任务兑换 |
| 磁铁魂石 | 任务兑换 捡起物品时0.1%概率获得,无保底 |
| 危险魂石 | 任务兑换 杀死任意生物有0.1%获得,无保底 |
| 替死魂石 | 任务兑换 在灵魂破碎状态且身上有灵魂窃取buff的时候击杀任意生物100%获得 |
| 金果魂石 | 任务兑换 每次吃(附魔)金苹果有(15%)5%概率获得,无保底 |
| 潮水魂石 | 任务兑换 身上有潮涌buff时,每三分钟获取一个 |
| 修复魂石 | 任务兑换 |
| 伊始之魂 | 一即全,全即一 |
kjs代码,都是服务端,可以直接放在一个文件里 ,我这里是图方便全放一起了,你大可不必如此
const CHANCE_SNOW = 0.01
const CHANCE_LAVA = 0.5
const CHANCE_MUSH = 0.01
const CHANCE_LUSH = 0.01
const CHANCE_GREEN = 0.01
const CHANCE_FOREST = 0.001
const CHANCE_NETHER = 0.01
const CHANCE_END = 0.01
const CHANCE_UNDEAD = 0.01
const CHANCE_SMITE = 0.01
const CHANCE_ARTHROPOD = 0.01
const CHANCE_ANIMAL = 0.01
const CHANCE_WATER = 0.01
const CHANCE_DRAGON = 0.1
const CHANCE_MAGNET = 0.001
const CHANCE_DANGER = 0.001
const CHANCE_GOLDEN_APPLE = 0.05
//矿物相关的内容直接使用了战利品表覆写,在data里覆盖了原版内容,在此不显示,可以改用lootjs实现
let MobType = Java.loadClass("net.minecraft.world.entity.MobType")
EntityEvents.death(event => {
let { entity, player, level, source } = event
if (source.getActual().type == "minecraft:player")
player = source.getActual()//为player重新赋值
else return
let weapon = player ? player.getMainHandItem() : null
var coldBiomes = [
'deep_cold_ocean',
'deep_frozen_ocean',
'frozen_peaks',
'frozen_ocean',
'frozen_river',
'grove',
'ice_spikes',
'snowy_beach',
'snowy_plains',
'snowy_slopes',
'snowy_taiga']
//冰雪魂石:在冰原或雪原等流浪者会刷新的地方用火焰附加/怒火击杀流浪者有1%的概率掉落
if (entity.type == "minecraft:stray")
//是player发起的攻击
if (player && weapon) {
//判定武器是否有对应附魔或者特性
if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:fiery") ||
weapon.getEnchantmentLevel("minecraft:fire_aspect") > 0))
//判定群系
if (coldBiomes.some((element) => element == level.getBiome(player.blockPosition()).unwrapKey().get().getPath()))
//概率
if (Math.random() < CHANCE_SNOW)
entity.block.popItem(Item.of("mine_fargo:snow_soul_stone"))
}
//熔岩魂石:在细雪里(ticksFrozen>0)击杀烈焰人50%概率获得一个
if (entity.type == "minecraft:blaze")
if (player && player.ticksFrozen > 0)
if (Math.random() < CHANCE_LAVA)
entity.block.popItem(Item.of("mine_fargo:lava_soul_stone"))
// player.setStatusMessage(event.entity.mobType == MobType.ILLAGER ? Text.red("ILLAGER") :
// event.entity.mobType == MobType.WATER ? Text.yellow("WATER") :
// event.entity.mobType == MobType.UNDEFINED ? Text.white("UNDEFINED") :
// event.entity.mobType == MobType.UNDEAD ? Text.red("UNDEAD") :
// event.entity.mobType == MobType.ARTHROPOD ? Text.yellow("ARTHROPOD") :
// Text.white("..."))
//狱灵魂石:击杀僵尸猪灵、猪灵、猪灵蛮兵有1%的概率掉落,100次独立保底一次
multipleKillCounterList(event, ["minecraft:zombified_piglin", "minecraft:piglin", "minecraft:piglin_brute"],
CHANCE_NETHER, "nether_count", "mine_fargo:nether_soul_stone", true)
//亡灵魂石:击杀亡灵生物1%掉落一个,100个保底,如果武器有亡灵杀手变成5%,此外凋灵固定掉一个
if (entity.mobType && entity.mobType == MobType.UNDEAD) {
let _CHANCE_SMITE = CHANCE_SMITE
if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:smite") ||
weapon.getEnchantmentLevel("minecraft:smite") > 0))
_CHANCE_SMITE *= 5
multipleKillCounterByMobType(event, MobType.UNDEAD, _CHANCE_SMITE, "undead_count", "mine_fargo:death_soul_stone", true)
if (entity.type == "minecraft:wither")
entity.block.popItem(Item.of("mine_fargo:death_soul_stone"))
}
//节肢魂石:击杀原版蜘蛛和洞穴蜘蛛1%掉落一个,100个保底,如果武器有节肢杀手变成5%
if (entity.type == 'minecraft:cave_spider' || entity.type == 'minecraft:spider') {
let _CHANCE_ARTHROPOD = CHANCE_ARTHROPOD
if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:bane_of_sssss") ||
weapon.getEnchantmentLevel("minecraft:bane_of_arthropods") > 0))
_CHANCE_ARTHROPOD *= 5
multipleKillCounterByMobType(event, MobType.ARTHROPOD, _CHANCE_ARTHROPOD, "arthropod_count", "mine_fargo:arthropod_soul_stone", true)
}
//动物魂石:击杀动物(同时有age和InLove数据值的生物)时1%掉落
if (entity.nbt.contains('Age') && entity.nbt.contains('InLove'))
if (player && Math.random() < CHANCE_ANIMAL) {
entity.block.popItem(Item.of("mine_fargo:animal_soul_stone"))
player.setStatusMessage(Text.green("动物之魂!"));
}
//水生魂石:击杀水生生物(原版水生生物,如果模组继承了对应值应该也算)1%掉落一个,100个保底,如果武器有水生杀手(匠魂的特性,原版没有对应附魔)变成5%
if (entity.mobType && entity.mobType == MobType.WATER) {
let _CHANCE_WATER = CHANCE_WATER
if ((weapon.hasTag('tconstruct:modifiable') && SimpleTCon.hasModifier(weapon, "tconstruct:antiaquatic")))
_CHANCE_WATER *= 5
multipleKillCounterByMobType(event, MobType.WATER, _CHANCE_WATER, "water_count", "mine_fargo:aquatic_soul_stone", true)
}
//飞翼魂石:每100只幻翼会掉一个
multipleKillCounter(event, 'minecraft:phantom', 100, "wings_count", 'mine_fargo:wing_soul_stone', true)
//龙骨魂石:所有龙死后有10%概率掉落(右键龙骨架不方便)
multipleKillCounterList(event, ["iceandfire:fire_dragon", "iceandfire:ice_dragon", "iceandfire:lightning_dragon"],
CHANCE_DRAGON, "dragon_count", "mine_fargo:dragon_bone_soul_stone", true)
})
//蘑菇魂石:在蘑菇岛使用剪刀5%掉落
ItemEvents.entityInteracted(event => {
let { item, player, level, target } = event
if (level.getBiome(player.blockPosition()).unwrapKey().get().getPath() == "mushroom_fields")
if (item.hasTag("forge:shears"))
if (Math.random() < CHANCE_MUSH)
target.block.popItem(Item.of("mine_fargo:mushroom_soul_stone"))
})
//乐事魂石:进食时有概率获得
ItemEvents.foodEaten(event => {
let { player } = event
if (Math.random() < CHANCE_LUSH) {
player.block.popItem(Item.of("mine_fargo:farmers_delight_soul_stone"))
player.setStatusMessage(Text.yellow("获得乐事魂石!"));
}
})
//末地魂石:吃紫颂果、右键末影珍珠每次分别有1%的概率掉落,上述两种行为每次都会积累得分,得分满100额外给一个
ItemEvents.foodEaten(event => {
let { item, player } = event
if (item.getId() == 'minecraft:chorus_fruit') {
if (Math.random() < CHANCE_END)
player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
//此处处理规避data中无内容的情况
let count = player.data.get("end_count")
if (isNaN(count)) count = 0;
count++;
if (count >= 100) {
player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
player.setStatusMessage(Text.white("额外的馈赠!"));
player.data.put("end_count", count -= 100)
}
player.data.put("end_count", count);
}
})
ItemEvents.rightClicked(event => {
let { item, player } = event
if (item.getId() == 'minecraft:ender_pearl') {
if (Math.random() < CHANCE_END)
player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
let count = player.data.get("end_count")
if (isNaN(count)) count = 0;
count++;
if (count >= 100) {
player.block.popItem(Item.of("mine_fargo:ender_soul_stone"))
player.setStatusMessage(Text.white("额外的馈赠!"));
player.data.put("end_count", count -= 100)
}
player.data.put("end_count", count);
}
})
//用于每分钟触发一次
let oceanTimer = 0
PlayerEvents.tick(event => {
let { player, server, level } = event
//下界魂石:在下界,每着火5秒触发一次掉落,1%的概率
if (player.level.dimension == "minecraft:the_nether") {
if (player.isOnFire()) {
let cooldownTicks = 100;
if (!player.data.get("nether_timer")) player.data.put("nether_timer", 0)
let nether_timer = player.data.get("nether_timer")
if (level.getTime() - nether_timer >= cooldownTicks) {
player.data.put("nether_timer", level.getTime())
if (Math.random() < CHANCE_NETHER)//已经将该物品设置为防火
{
player.block.popItem(Item.of("mine_fargo:nether_soul_stone"))
player.setStatusMessage(Text.gold("真金不怕火炼!"));
}
}
}
}
//简单的延时,每分钟触发一次
if (level.getTime() - oceanTimer >= 1200) {
oceanTimer = level.getTime()
//海洋魂石:每1000分得一个,分数来源:Score=(游泳距离 ×1.0)+(水面行走×0.5)+(水下行走 ×1.1)+(坐船×0.3)
let overworld = server.getLevel('minecraft:overworld')
//这里用了 FilesJS来读取存档里的数据文件,如果你的电脑由于任何原因不让访问这里就全失效
let uuid = player.getUuid()
let saveName = overworld.getServer().storageSource.getDimensionPath(overworld.getDimensionKey()).getFileName().toString();
let totalStats = FilesJS.readFile(`saves/${saveName}/stats/${uuid}.json`)
//粗糙的手动处理
let swiming = parseInt((totalStats.split("\"minecraft:swim_one_cm\":")[1] == undefined ? "0,"
: totalStats.split("\"minecraft:swim_one_cm\":")[1]).split(",")[0]) / 100
let walkOnWater = parseInt((totalStats.split("\"minecraft:walk_on_water_one_cm\":")[1] == undefined ? "0,"
: totalStats.split("\"minecraft:walk_on_water_one_cm\":")[1]).split(",")[0]) / 100
let walkUnderwater = parseInt((totalStats.split("\"minecraft:walk_under_water_one_cm\":")[1] == undefined ? "0,"
: totalStats.split("\"minecraft:walk_under_water_one_cm\":")[1]).split(",")[0]) / 100
let rideBoat = parseInt((totalStats.split("\"minecraft:boat_one_cm\":")[1] == undefined ? "0,"
: totalStats.split("\"minecraft:boat_one_cm\":")[1]).split(",")[0]) / 100
let finalScore = swiming + walkOnWater * 0.5 + walkUnderwater * 1.1 + rideBoat * 0.3
let data = player.persistentData;
//已经获得过的次数
if (!data.get("ocean_score_times")) data.putInt("ocean_score_times", 0)
let last_times = data.get("ocean_score_times")
if (finalScore > 1000 * last_times) {
let times = parseInt(finalScore / 1000)
let i = times - last_times
while (i > 0) {
player.block.popItem(Item.of("mine_fargo:ocean_soul_stone"))
i--
player.setStatusMessage(i);//放这里看不出来的
}
data.putInt("ocean_score_times", times)
}
}
})
//翠绿魂石:收获作物的时候1%概率获得
BlockEvents.broken(event => {
let { block, player } = event
if (block.hasTag('minecraft:crops') && Math.random() < CHANCE_GREEN) {
player.block.popItem(Item.of("mine_fargo:farmers_delight_soul_stone"))
player.setStatusMessage(Text.green("生生不息!"));
}
})
const FOREST_BIOME = ["forest", "flower_forest", "birch_forest", "dark_forest", "jungle", "sparse_jungle", "bamboo_jungle", "cherry_grove"];
//如果家建在这些群系(大概率是)会一直获得,一晚上掉落十多个
//森林魂石:在森林、繁花森林、桦木森林、黑森林、丛林、稀疏丛林、竹林、樱花树林群系,每隔10秒,有0.1%概率在玩家脚下生成一个。累计30分钟额外掉落一个
PlayerEvents.tick(event => {
let { player, level } = event;
let biome = level.getBiome(player.blockPosition()).unwrapKey().get().getPath()
// 检查是否在目标森林群系
let isInForest = FOREST_BIOME.some((element) => element == biome)
let data = player.data;
if (!data.get("forest_last_tick")) data.put("forest_last_tick", 0);
if (!data.get("forest_timer")) data.put("forest_timer", 0);//在森林内的时间,每10秒增加一次
let currentAge = level.getTime();
if (isInForest) {
// === 每10秒一次概率掉落 ===
let lastTick = data.get("forest_last_tick");
if (currentAge - lastTick >= 200) {
data.put("forest_last_tick", currentAge);
if (Math.random() < CHANCE_FOREST) {
// 掉落物品(在玩家位置生成)
player.block.popItem(Item.of("mine_fargo:forest_soul_stone"))
player.setStatusMessage(Text.green("自然的馈赠!"));
}
data.put("forest_timer", data.get("forest_timer") + 200);
}
}
else
data.put("forest_last_tick", currentAge);
// === 每30分钟固定掉落 ===
let last30minTick = data.get("forest_timer");
//player.setStatusMessage(last30minTick);
if (last30minTick >= 36000) {
data.put("forest_timer", data.get("forest_timer") - 36000);
player.block.popItem(Item.of("mine_fargo:forest_soul_stone"))
player.setStatusMessage(Text.gold("自然的恩赐!"));
}
});
//合成表修改,主要是龙相关内容
ServerEvents.recipes(event => {
const { tconstruct } = event.recipes;
//龙骨的忘记了下次更新的时候补
//龙血获取和浇筑,其中带有kubejs前缀的流体需要自行注册
tconstruct.melting(Fluid.of('kubejs:fire_dragon_blood', 500), 'iceandfire:fire_dragon_heart', 1000, 40);
tconstruct.melting(Fluid.of('kubejs:ice_dragon_blood', 500), 'iceandfire:ice_dragon_heart', 1000, 40);
tconstruct.melting(Fluid.of('kubejs:lightning_dragon_blood', 500), 'iceandfire:lightning_dragon_heart', 1000, 40);
tconstruct.melting(Fluid.of('kubejs:fire_dragon_blood', 100), 'iceandfire:fire_dragon_flesh', 1000, 40);
tconstruct.melting(Fluid.of('kubejs:ice_dragon_blood', 100), 'iceandfire:ice_dragon_flesh', 1000, 40);
tconstruct.melting(Fluid.of('kubejs:lightning_dragon_blood', 100), 'iceandfire:lightning_dragon_flesh', 1000, 40);
tconstruct.casting_table('iceandfire:fire_dragon_blood', Fluid.of('kubejs:fire_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);
tconstruct.casting_table('iceandfire:ice_dragon_blood', Fluid.of('kubejs:ice_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);
tconstruct.casting_table('iceandfire:lightning_dragon_blood', Fluid.of('kubejs:lightning_dragon_blood', 100), 'minecraft:glass_bottle', true, 20, true);
tconstruct.casting_table('mine_fargo:fire_dragon_blood_soul_stone', Fluid.of('kubejs:fire_dragon_blood', 500),
'mine_fargo:dragon_bone_soul_stone', true, 20, true);
tconstruct.casting_table('mine_fargo:ice_dragon_blood_soul_stone', Fluid.of('kubejs:ice_dragon_blood', 500),
'mine_fargo:dragon_bone_soul_stone', true, 20, true);
tconstruct.casting_table('mine_fargo:lightning_dragon_blood_soul_stone', Fluid.of('kubejs:lightning_dragon_blood', 500),
'mine_fargo:dragon_bone_soul_stone', true, 20, true);
dragonforge("fire", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:fire_dragon_blood', 'mine_fargo:fire_dragon_steel_soul_stone')
dragonforge("ice", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:ice_dragon_blood', 'mine_fargo:ice_dragon_steel_soul_stone')
dragonforge("lightning", 3600, 'mine_fargo:dragon_bone_soul_stone', 'iceandfire:lightning_dragon_blood', 'mine_fargo:lightning_dragon_steel_soul_stone')
/**
* 龙锻炉
* @param {string} dragonForgeType 类型(fire,ice,lightning)
* @param {number} tick 时间(20tick为1秒)
* @param {string} input 输入物品
* @param {string} blood 血(其实是个物品即可,即第二个物品)
* @param {string} output 输出物品
*/
function dragonforge(dragonForgeType, tick, input, blood, output) {
event.custom({
type: "iceandfire:dragonforge",
dragon_type: dragonForgeType,
cook_time: tick,
input: {
item: input
},
blood: {
item: blood
},
result: {
item: output
}
})
}
})
//修改战利品表
LootJS.modifiers(event => {
event.enableLogging()
//灾变的内容
event.addLootTableModifier("cataclysm:entities/ignis")
.addLoot(Item.of('mine_fargo:ignis_soul_stone'))
event.addLootTableModifier("cataclysm:entities/the_leviathan")
.addLoot(Item.of('mine_fargo:the_leviathan_soul_stone'))
event.addLootTableModifier("cataclysm:entities/maledictus")
.addLoot(Item.of('mine_fargo:maledictus_soul_stone'))
event.addLootTableModifier("cataclysm:entities/ender_guardian")
.addLoot(Item.of('mine_fargo:ender_guardian_soul_stone'))
event.addLootTableModifier("cataclysm:entities/ancient_remnant")
.addLoot(Item.of('mine_fargo:ancient_remnant_soul_stone'))
event.addLootTableModifier("cataclysm:entities/the_harbinger")
.addLoot(Item.of('mine_fargo:the_harbinger_soul_stone'))
event.addLootTableModifier("cataclysm:entities/netherite_monstrosity")
.addLoot(Item.of('mine_fargo:netherite_monstrosity_soul_stone'))
event.addLootTableModifier("cataclysm:entities/scylla")
.addLoot(Item.of('mine_fargo:scylla_soul_stone'))
// Ice and Fire 魂石掉落
event.addLootTableModifier("iceandfire:entities/hydra")
.addLoot(Item.of('mine_fargo:iaf_hydra_soul_stone'))
event.addLootTableModifier("iceandfire:entities/siren")
.addLoot(Item.of('mine_fargo:iaf_siren_soul_stone'))
event.addLootTableModifier("iceandfire:entities/cyclops")
.addLoot(Item.of('mine_fargo:cyclops_soul_stone'))
event.addLootTableModifier("iceandfire:entities/gorgon")
.addLoot(Item.of('mine_fargo:gorgon_soul_stone'))
event.addLootTableModifier("iceandfire:entities/sea_serpent")
.addLoot(Item.of('mine_fargo:sea_serpent_soul_stone'))
//食人妖3种变体
event.addLootTableModifier("iceandfire:entities/troll_forest")
.addLoot(Item.of('mine_fargo:troll_soul_stone'))
event.addLootTableModifier("iceandfire:entities/troll_frost")
.addLoot(Item.of('mine_fargo:troll_soul_stone'))
event.addLootTableModifier("iceandfire:entities/troll_mountain")
.addLoot(Item.of('mine_fargo:troll_soul_stone'))
event.addLootTableModifier("iceandfire:entities/hippocampus")
.addLoot(Item.of('mine_fargo:hippocampus_soul_stone'))
//死亡蠕虫3种变体
event.addLootTableModifier("iceandfire:entities/deathworm_red_giant")
.addLoot(Item.of('mine_fargo:death_worm_soul_stone'))
event.addLootTableModifier("iceandfire:entities/deathworm_tan_giant")
.addLoot(Item.of('mine_fargo:death_worm_soul_stone'))
event.addLootTableModifier("iceandfire:entities/deathworm_white_giant")
.addLoot(Item.of('mine_fargo:death_worm_soul_stone'))
//海王
event.addLootTableModifier("aquaculture:box/neptunes_bounty")
.addLoot(Item.of('mine_fargo:neptunium_soul_stone'))
})
//下面是超然之魂下属的魂石,所有这些魂石都可以去任务商店买,锚定魂石(不知道有什么用)和修复魂石(op)只能任务获取
//磁铁魂石:捡起物品时0.1%概率获得,无保底
//由于是检测背包变化,所以从任何gui里拿东西到背包也算
PlayerEvents.inventoryChanged(event => {
let { player } = event;
//这个概率还是可以的,一晚上出了三四个,感觉可以再低一点1
if (Math.random() < CHANCE_MAGNET) {
player.block.popItem(Item.of("mine_fargo:magnet_soul_stone"))
player.setStatusMessage(Text.blue("Mag").append(Text.red("net!")));
}
})
const EnigmaticItems = Java.loadClass("com.aizistral.enigmaticlegacy.registries.EnigmaticItems")
EntityEvents.death(event => {
let { player, source, entity } = event;
if (source.getActual().type == "minecraft:player")
player = source.getActual()//为player重新赋值
else return
//危险魂石:杀死任意生物有0.1%获得,无保底
if (Math.random() < CHANCE_DANGER) {
entity.block.popItem(Item.of("mine_fargo:hazard_soul_stone"))
player.setStatusMessage(Text.red("危险!"))
}
//替死魂石:在灵魂破碎状态(灵魂水晶不满)且身上有灵魂窃取buff的时候击杀任意生物100%获得
if (EnigmaticItems.SOUL_CRYSTAL.getLostCrystals(player) > 0 && player.hasEffect("alexsmobs:soulsteal")) {
entity.block.popItem(Item.of("mine_fargo:undying_soul_stone"))
}
})
//金果魂石:每次吃(附魔)金苹果有(15%)5%概率获得,无保底
ItemEvents.foodEaten(event => {
let { player } = event;
if (event.item.id == "minecraft:golden_apple") {
if (Math.random() < CHANCE_GOLDEN_APPLE) {
player.block.popItem(Item.of('mine_fargo:enchanted_golden_apple_soul_stone'))
player.setStatusMessage(Text.gold("金苹果!"))
}
}
if (event.item.id == "minecraft:enchanted_golden_apple") {
if (Math.random() < CHANCE_GOLDEN_APPLE * 3) {
player.block.popItem(Item.of('mine_fargo:enchanted_golden_apple_soul_stone'))
player.setStatusMessage(Text.gold("金苹果!"))
}
}
})
//潮水魂石:身上有潮涌buff时,每三分钟获取一个
PlayerEvents.tick(event => {
let { player, level } = event;
if (!player.data.get("conduit_timer")) player.data.put("conduit_timer", 0)//计数器,记录下一次应该获取潮水魂石的时间
let now = level.getTime()
if (player.hasEffect("minecraft:conduit_power")) {
let timer = player.data.get("conduit_timer")
if (timer == 0)//获取buff的第一刻
player.data.put("conduit_timer", now + 3600)
else if (now >= timer) {
player.block.popItem(Item.of("mine_fargo:water_soul_stone"))
player.data.put("conduit_timer", now + 3600)
player.setStatusMessage(Text.blue("潮涌!"))
}
}
else
player.data.put("conduit_timer", 0)
//初级的代码,效率低
// if (player.hasEffect("minecraft:conduit_power")) {
// //临时变量,记录上一次更新计时器的世界时间
// let timer = player.data.get("conduit_timer")
// timer++
// if (timer >= 3600) {
// player.block.popItem(Item.of("mine_fargo:water_soul_stone"))
// timer -= 3600
// }
// player.data.put("conduit_timer", timer)
// }
// else
// player.data.put("conduit_timer", 0)
})
//轮子,重复命名比较多,然后其实有没用到的,我以为我会用但是没有,没用到的写完之后就没更新了。因为名字都长得比较像所以也都没改
/**
* 重复击杀生物掉落指定物品(计数器持久化在 player.data 中)
* @param {Internal.LivingEntityDeathEventJS} event
* @param {string} target 生物ID,如 "minecraft:zombified_piglin"
* @param {number} times 每多少次掉落一个物品
* @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
* @param {string} item 掉落物品ID
* @param {boolean} prompt 是否显示当前计数
*/
function multipleKillCounter(event, target, times, key, item, prompt) {
let { entity, source, player } = event;
if (source.getActual().type == "minecraft:player")
player = source.getActual()//为player重新赋值
else player = null
if (entity.type !== target) return;
// 获取当前计数,若不存在则初始化为 0
let count = player.data.get(key);
if (isNaN(count)) count = 0;
count++;
// 显示计数(可选)
if (prompt) {
player.setStatusMessage(Text.green(`${key}: ${count}`));
}
// 检查是否达到掉落条件
if (count >= times) {
// 掉落物品
entity.block.popItem(Item.of(item));
// 减去对应次数,保留余数
count -= times;
}
// 将新计数写回 player.data
player.data.put(key, count);
}
/**
* 用于设置批量类型的生物击杀奖励
* @param {Internal.LivingEntityDeathEventJS} event
* @param {Internal.Player} player
* @param {string} target tag或者mod,不带#
* @param {number} times
* @param {string} key
* @param {string} item
* @param {boolean} prompt
* @param {boolean} tagOrMod true表示tag,false表示mod
*/
function multipleKillCounterTag(event, player, target, times, key, item, prompt, tagOrMod) {
let { entity } = event;
if (tagOrMod) {
//tag匹配模式,如果没有对应tag直接退出
if (!entity.hasTag(target))
return
} else {
//mod匹配模式,type是modid:name的格式
if (!entity.getType().startsWith(target))
return
}
// 获取当前计数,若不存在则初始化为 0
let count = player.data.get(key);
if (isNaN(count)) count = 0;
count++;
// 显示计数(可选)
if (prompt) {
player.setStatusMessage(Text.green(`${key}: ${count}`));
}
// 检查是否达到掉落条件
if (count >= times) {
// 掉落物品
entity.block.popItem(Item.of(item));
// 减去对应次数,保留余数
count -= times;
}
// 将新计数写回 player.data
player.data.put(key, count);
}
/**
* 玩家击杀指定列表中的生物有概率获取物品
* @param {Internal.LivingEntityDeathEventJS} event -
* @param {string[]} targetList 一个string数组,包含所有目标
* @param {number} chance 概率
* @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
* @param {string} item 物品id
* @param {boolean} guarantee 是否有保底(保底数字为1/chance)
* @returns
*/
function multipleKillCounterList(event, targetList, chance, key, item, guarantee) {
let { entity, source, player } = event;
if (source.getActual().type == "minecraft:player")
player = source.getActual()//为player重新赋值
else player = null
if (targetList.indexOf(entity.type) == -1) return;
if (Math.random() < chance)
player.block.popItem(Item.of(item))
// 获取当前计数,若不存在则初始化为 0
let count = player.data.get(key);
let times = 1 / chance;
if (isNaN(count)) count = 0;
count++;
// 检查是否达到掉落条件
if (guarantee && count >= times) {
// 掉落物品
entity.block.popItem(Item.of(item));
// 减去对应次数,保留余数
count -= times;
}
// 将新计数写回 player.data
player.data.put(key, count);
}
/**
* 玩家击杀怪物类型的生物有概率获取物品
* @param {Internal.LivingEntityDeathEventJS} event -
* @param {Internal.MobType} mobType 怪物类型
* @param {number} chance 概率
* @param {string} key 存储在 player.data 中的计数器键名,如 "nether_count"
* @param {string} item 物品id
* @param {boolean} guarantee 是否有保底(保底数字为1/chance)
* @returns
*/
function multipleKillCounterByMobType(event, mobType, chance, key, item, guarantee) {
let { entity, source, player } = event;
if (source.getActual().type == "minecraft:player")
player = source.getActual()//为player重新赋值
else player = null
if (entity.mobType !== mobType) return;
if (Math.random() < chance)
player.block.popItem(Item.of(item))
// 获取当前计数,若不存在则初始化为 0
let count = player.data.get(key);
let times = 1 / chance;
if (isNaN(count)) count = 0;
count++;
// 检查是否达到掉落条件
if (guarantee && count >= times) {
// 掉落物品
entity.block.popItem(Item.of(item));
// 减去对应次数,保留余数
count -= times;
}
// 将新计数写回 player.data
player.data.put(key, count);
}


