add first patch
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
console.info("[SOCIETY] gnomeInteraction.js loaded");
|
||||
|
||||
ItemEvents.entityInteracted((e) => {
|
||||
const { hand, player, item, level, target, server } = e;
|
||||
if (player.isFake() || player.isCrouching()) return;
|
||||
if (hand == "OFF_HAND") return;
|
||||
if (target.type !== "minecraft:villager") return;
|
||||
if (hand == "MAIN_HAND") {
|
||||
if (item.id === "oreganized:silver_ingot") {
|
||||
const { x, y, z } = target;
|
||||
server.runCommandSilent(`playsound trials:breeze_idle block @a ${x} ${y} ${z} 0.2 1`);
|
||||
let reward = player.level.createEntity("minecraft:item");
|
||||
reward.x = player.x;
|
||||
reward.y = player.y;
|
||||
reward.z = player.z;
|
||||
reward.item = Item.of(`2x society:fairy_dust`);
|
||||
reward.spawn();
|
||||
if (!player.isCreative()) item.shrink(1);
|
||||
} else {
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} gnome_unique_chatter_${Math.floor(Math.random() * 3)}`);
|
||||
}
|
||||
e.cancel()
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,219 @@
|
||||
console.info("[SOCIETY] npcInteraction.js loaded");
|
||||
// These lengths are formed from generateNpcDialog.js
|
||||
const dialogLengths = {
|
||||
banker: { chatterLengths: [15.0, 20.0, 13.0, 9.0, 11.0, 18.0], giftResponseLengths: { loved: 9.0, liked: 8.0, neutral: 8.0, disliked: 12.0, hated: 16.0 } },
|
||||
blacksmith: { chatterLengths: [16.0, 10.0, 13.0, 12.0, 11.0, 14.0], giftResponseLengths: { loved: 8.0, liked: 9.0, neutral: 8.0, disliked: 8.0, hated: 10.0 } },
|
||||
carpenter: { chatterLengths: [11.0, 10.0, 13.0, 9.0, 9.0, 15.0], giftResponseLengths: { loved: 6.0, liked: 7.0, neutral: 8.0, disliked: 10.0, hated: 10.0 } },
|
||||
fisher: { chatterLengths: [11.0, 9.0, 10.0, 10.0, 10.0, 11.0], giftResponseLengths: { loved: 7.0, liked: 6.0, neutral: 9.0, disliked: 7.0, hated: 7.0 } },
|
||||
librarian: { chatterLengths: [5.0, 5.0, 5.0, 5.0, 5.0, 6.0], giftResponseLengths: { loved: 5.0, liked: 5.0, neutral: 5.0, disliked: 5.0, hated: 5.0 } },
|
||||
market: { chatterLengths: [18.0, 14.0, 9.0, 16.0, 14.0, 14.0], giftResponseLengths: { loved: 10.0, liked: 8.0, neutral: 17.0, disliked: 12.0, hated: 13.0 } },
|
||||
shepherd: { chatterLengths: [15.0, 14.0, 13.0, 12.0, 14.0, 17.0], giftResponseLengths: { loved: 9.0, liked: 10.0, neutral: 8.0, disliked: 8.0, hated: 11.0 } },
|
||||
trader: { chatterLengths: [7.0, 5.0, 5.0, 7.0, 7.0, 6.0], giftResponseLengths: { loved: 5.0, liked: 5.0, neutral: 5.0, disliked: 5.0, hated: 5.0 } },
|
||||
wise_oak: { chatterLengths: [7.0, 5.0, 5.0, 5.0, 5.0, 8.0], giftResponseLengths: { loved: 0.0, liked: 0.0, neutral: 0.0, disliked: 0.0, hated: 0.0 } },
|
||||
witch: { chatterLengths: [7.0, 5.0, 6.0, 8.0, 6.0, 5.0], giftResponseLengths: { loved: 5.0, liked: 5.0, neutral: 5.0, disliked: 5.0, hated: 6.0 } },
|
||||
}
|
||||
const maxGifts = {
|
||||
banker: "society:slouching_towards_artistry",
|
||||
blacksmith: Item.of('justhammers:iron_hammer', "{Damage:0,RepairCost:0,display:{Name:'{\"text\":\"§6Aiden\\'s Hammer\"}'}}").enchant('minecraft:efficiency', 5).enchant('minecraft:fortune', 3),
|
||||
carpenter: Item.of('portable_blueprints:worn_blueprint', '{Damage:1,allow_nbt:1,altezza:0,blueprint_name:"blockapedia",buildAnyway:0b,display:{Name:\'{"italic":false,"color":"#FFFF00","text":"Blueprint: Blockapedia"}\'},free_build:1,inventari_blocco_selezionati:"",lunghezzaX:0,lunghezzaZ:0,mirrowX:0b,mirrowY:0b,mirrowZ:0b,nome:"blockapedia",owner:"worn",owner_name:"Ace (Built by Mimsy)",remaining_uses:1,rotateValue:0s,skipObstructionBlock:0b,visualizeBuild:1b,wasHolding:1b,worn_set:1b}'),
|
||||
fisher: "society:heart_of_neptunium",
|
||||
market: "society:universal_methods_of_farming",
|
||||
shepherd: Item.of('2x wildernature:penguin_spawn_egg'),
|
||||
librarian: 'society:debt_caverns',
|
||||
trader: "",
|
||||
witch: "society:auto_petter",
|
||||
}
|
||||
|
||||
const getNpcKey = (customName) => {
|
||||
const startIndex = customName.indexOf("dialog.npc.");
|
||||
const endIndex = customName.indexOf(".name");
|
||||
|
||||
if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
|
||||
console.log("[SOCIETY] WARNING: NPC has no custom name!")
|
||||
return;
|
||||
}
|
||||
|
||||
return customName.substring(startIndex + "dialog.npc.".length, endIndex);
|
||||
}
|
||||
const npcIds = ["easy_npc:humanoid", "easy_npc:humanoid_slim"];
|
||||
|
||||
const handleNpc = (e, npcId, level, server, target, player, item) => {
|
||||
let day = global.getDay(level);
|
||||
if (!player.persistentData.npcData) player.persistentData.npcData = {}
|
||||
let npcData = player.persistentData.npcData[npcId];
|
||||
if (!npcData) {
|
||||
if (!player.stages.has(`invited_${npcId}`)) {
|
||||
player.stages.add(`invited_${npcId}`)
|
||||
}
|
||||
player.persistentData.npcData[npcId] = {
|
||||
friendship: -1,
|
||||
dayLastChatted: -1,
|
||||
dayLastGifted: -4,
|
||||
maxGifted: false
|
||||
}
|
||||
} else if (Number(npcData.friendship) == -1) {
|
||||
npcData.friendship = 5
|
||||
server.runCommandSilent(
|
||||
`dialog ${player.getUuid()} show ${player.username} ${npcId}_intro`
|
||||
);
|
||||
} else if (!npcData.maxGifted && Number(npcData.friendship) >= 500) {
|
||||
if (npcId.equals("banker") && player.stages.has("slouching_towards_artistry")) {
|
||||
player.give(Item.of("2x waystones:waystone"))
|
||||
server.runCommandSilent(`dialog ${player.username} show ${player.username} banker_unique__gift_read`);
|
||||
} else if (npcId.equals("market") && player.stages.has("universal_methods_of_farming")) {
|
||||
player.give(Item.of("16x society:sparkpod_seed"))
|
||||
server.runCommandSilent(`dialog ${player.username} show ${player.username} market_unique_five_gift_read`);
|
||||
} else if (npcId.equals("librarian") && player.stages.has("debt_caverns")) {
|
||||
player.give(Item.of('botania:diva_charm'))
|
||||
player.give(Item.of('botania:mana_ring', '{mana:500000}'))
|
||||
server.runCommandSilent(`dialog ${player.username} show ${player.username} librarian_unique_five_gift_read`);
|
||||
} else if (npcId.equals("trader")) {
|
||||
player.stages.add("trader_clothing")
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} ${npcId}_unique_five_gift`);
|
||||
} else {
|
||||
player.give(maxGifts[npcId])
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} ${npcId}_unique_five_gift`);
|
||||
}
|
||||
npcData.maxGifted = true
|
||||
} else {
|
||||
// Carpenter has two shops so it always needs dialog to choose between the two.
|
||||
let dialogNumber;
|
||||
if (player.isCrouching() && item.hasTag("society:villager_gift")) {
|
||||
if (npcId === "wise_oak") {
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} wise_oak_unique_no_gifting`);
|
||||
server.runCommandSilent(`playsound stardew_fishing:fish_escape block @a ${target.x} ${target.y} ${target.z}`);
|
||||
server.runCommandSilent(`playsound species:item.wicked_swapper.teleport block @a ${target.x} ${target.y} ${target.z}`);
|
||||
level.spawnParticles(
|
||||
"mysticaloaktree:wind",
|
||||
true,
|
||||
target.x,
|
||||
target.y + 1.5,
|
||||
target.z,
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
25,
|
||||
0.001
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (day > npcData.dayLastGifted + 3 || npcData.dayLastGifted - day > 1) {
|
||||
let giftValue = global.getVillagerGiftResult(npcId, item.id);
|
||||
dialogNumber = Math.floor(Math.random() * dialogLengths[npcId].giftResponseLengths[giftValue]);
|
||||
let friendshipModification = 0;
|
||||
switch (giftValue) {
|
||||
case "hated":
|
||||
friendshipModification = -30;
|
||||
break;
|
||||
case "disliked":
|
||||
friendshipModification = -15;
|
||||
break;
|
||||
case "loved":
|
||||
friendshipModification = 40;
|
||||
break;
|
||||
case "liked":
|
||||
friendshipModification = 25;
|
||||
break;
|
||||
case "neutral":
|
||||
default:
|
||||
friendshipModification = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
npcData.friendship = npcData.friendship + friendshipModification;
|
||||
npcData.dayLastGifted = day
|
||||
server.runCommandSilent(`playsound stardew_fishing:complete block @a ${target.x} ${target.y} ${target.z}`);
|
||||
server.runCommandSilent(`playsound species:item.wicked_swapper.teleport block @a ${target.x} ${target.y} ${target.z}`);
|
||||
level.spawnParticles(
|
||||
"supplementaries:confetti",
|
||||
true,
|
||||
target.x,
|
||||
target.y + 1.5,
|
||||
target.z,
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
25,
|
||||
0.001
|
||||
);
|
||||
let delay = 0;
|
||||
if (item.isEdible()) delay = 20
|
||||
if (!player.isCreative()) item.shrink(1);
|
||||
server.scheduleInTicks(delay, () => {
|
||||
server.runCommandSilent(
|
||||
`dialog ${player.getUuid()} show ${player.username} ${npcId}_gift_${giftValue}_${dialogNumber}`
|
||||
);
|
||||
});
|
||||
if (Math.random() < 0.01) {
|
||||
let newGolem = level.createEntity(Math.random() < 0.5 ? "golemoverhaul:barrel_golem" : "golemoverhaul:hay_golem");
|
||||
newGolem.setX(target.getX() + 8);
|
||||
newGolem.setY(target.getY() + 2);
|
||||
newGolem.setZ(target.getZ() + -8);
|
||||
newGolem.spawn();
|
||||
}
|
||||
} else {
|
||||
player.tell(Text.translatable("society.npc.gifted_too_soon").gold())
|
||||
}
|
||||
} else {
|
||||
if (global.compareDay(day, npcData.dayLastChatted, 1)) {
|
||||
let hearts = Math.floor(npcData.friendship / 100);
|
||||
dialogNumber = Math.floor(Math.random() * (dialogLengths[npcId].chatterLengths[hearts]));
|
||||
|
||||
server.runCommandSilent(
|
||||
`dialog ${player.getUuid()} show ${player.username} ${npcId}_chatter_friendship${hearts}_${dialogNumber}`
|
||||
);
|
||||
npcData.dayLastChatted = day
|
||||
if (npcData.friendship + 5 > 500) {
|
||||
npcData.friendship = 500
|
||||
} else {
|
||||
if (npcId === "wise_oak") npcData.friendship = npcData.friendship + 15
|
||||
npcData.friendship = npcData.friendship + 5
|
||||
|
||||
}
|
||||
} else {
|
||||
if (npcId === "carpenter") {
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} carpenter_choice_dialog_need_to_buy`);
|
||||
} else if (npcId === "librarian" && global.isLateSeason(level)) {
|
||||
server.runCommandSilent(`dialog ${player.getUuid()} show ${player.username} librarian_choice_dialog_book_fair`);
|
||||
} else if (npcId === "wise_oak") {
|
||||
if (Number(npcData.friendship) >= 500) {
|
||||
player.tell("opening shop")
|
||||
server.runCommandSilent(`openshop ${player.username} wise_oak`)
|
||||
}
|
||||
} else {
|
||||
server.runCommandSilent(`openshop ${player.username} ${npcId}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (npcId === "wise_oak") {
|
||||
if (['society:tapper', 'society:auto_tapper'].includes(item.id)) {
|
||||
npcData.friendship = 0;
|
||||
}
|
||||
} else {
|
||||
e.cancel()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ItemEvents.entityInteracted((e) => {
|
||||
const { hand, player, item, level, target, server } = e;
|
||||
if (player.isFake()) return;
|
||||
if (hand == "OFF_HAND") return;
|
||||
if (item.id == 'easy_npc_config_ui:easy_npc_wand') return;
|
||||
if (!npcIds.includes(target.type)) return;
|
||||
if (hand == "MAIN_HAND") {
|
||||
let npcId = getNpcKey(target.nbt.CustomName.toString())
|
||||
handleNpc(e, npcId, level, server, target, player, item)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
BlockEvents.rightClicked("mysticaloaktree:wise_oak", (e) => {
|
||||
const { hand, player, block, level, server, item } = e;
|
||||
if (player.isFake()) return;
|
||||
if (hand == "OFF_HAND") return;
|
||||
if (hand == "MAIN_HAND") {
|
||||
handleNpc(e, "wise_oak", level, server, block, player, item)
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
console.info("[SOCIETY] npcInvite.js loaded");
|
||||
|
||||
ItemEvents.rightClicked("society:invitation", (e) => {
|
||||
const { server, player, item } = e;
|
||||
if (player.isFake()) e.cancel();
|
||||
const inviteNbt = player.getHeldItem("main_hand").getNbt();
|
||||
|
||||
if (inviteNbt) {
|
||||
let id = inviteNbt.get("type").id
|
||||
let baseId = id.substring(8, id.length);
|
||||
server.scheduleInTicks(0, () => {
|
||||
server.scheduleInTicks(1, () => {
|
||||
player.give(Item.of("society:villager_home", `{type:"${baseId}"}`))
|
||||
});
|
||||
});
|
||||
if (!player.stages.has(`invited_${baseId}`)) {
|
||||
player.stages.add(`invited_${baseId}`)
|
||||
player.tell(Text.translatable("society.invitation.place_home").green());
|
||||
if (baseId === "market") {
|
||||
player.tell(Text.translatable("society.new_villager.message").green());
|
||||
}
|
||||
}
|
||||
if (!player.isCreative()) item.count--;
|
||||
server.runCommandSilent(
|
||||
`playsound stardew_fishing:complete block @a ${player.x} ${player.y} ${player.z}`
|
||||
);
|
||||
} else {
|
||||
player.tell("Something went wrong! Tell Chakyl")
|
||||
}
|
||||
global.addItemCooldown(player, item, 4);
|
||||
});
|
||||
@@ -0,0 +1,161 @@
|
||||
console.info("[SOCIETY] villagerMechanics.js loaded");
|
||||
|
||||
const npcMap = new Map([
|
||||
["carpenter", "humanoid/carpenter"],
|
||||
["market", "humanoid/market"],
|
||||
["blacksmith", "humanoid/blacksmith"],
|
||||
["shepherd", "humanoid_slim/shepherd"],
|
||||
["fisher", "humanoid_slim/fisher"],
|
||||
["banker", "humanoid_slim/banker"],
|
||||
["librarian", "humanoid_slim/librarian"],
|
||||
["witch", "humanoid_slim/witch"],
|
||||
["trader", "humanoid/trader"]
|
||||
]);
|
||||
const getBoundNpc = (level, block, boundNpc) => {
|
||||
let nearbyNPCs = level.getLevel()
|
||||
.getServer()
|
||||
.getEntities()
|
||||
.filter((entityType) => entityType.type === "easy_npc:humanoid" || entityType.type === "easy_npc:humanoid_slim");
|
||||
let foundNpc = -1;
|
||||
nearbyNPCs.forEach((e) => {
|
||||
if (e.getUuid().toString() === boundNpc) {
|
||||
foundNpc = e;
|
||||
}
|
||||
});
|
||||
return foundNpc;
|
||||
};
|
||||
|
||||
BlockEvents.placed("society:villager_home", (e) => {
|
||||
const { player, block, level, server } = e;
|
||||
if (player.isFake()) e.cancel();
|
||||
const homeNbt = player.getHeldItem("main_hand").getNbt();
|
||||
let nbt = block.getEntityData();
|
||||
const { x, y, z } = block;
|
||||
if (homeNbt) {
|
||||
let villagerType = homeNbt.getString("type");
|
||||
let day = global.getDay(level);
|
||||
if (!player.persistentData.npcData) player.persistentData.npcData = {}
|
||||
let npcData = player.persistentData.npcData[villagerType];
|
||||
if (!npcData) {
|
||||
player.persistentData.npcData[villagerType] = {
|
||||
friendship: -1,
|
||||
dayLastChatted: -1,
|
||||
dayLastGifted: -4,
|
||||
dayLastPlaced: -10,
|
||||
maxGifted: false,
|
||||
}
|
||||
npcData = player.persistentData.npcData[villagerType];
|
||||
}
|
||||
if (!npcData.dayLastPlaced) npcData.dayLastPlaced = -10
|
||||
if (day > Number(npcData.dayLastPlaced) + 10 || Number(npcData.dayLastPlaced) - day > 1) {
|
||||
let nearbyNPCs = level
|
||||
.getEntitiesWithin(AABB.ofBlock(block).inflate(4))
|
||||
.filter((entityType) => entityType.type === "easy_npc:humanoid" || entityType.type === "easy_npc:humanoid_slim");
|
||||
|
||||
if (player && nearbyNPCs.length == 0) {
|
||||
server.runCommandSilent(
|
||||
`execute in ${level.dimension} run easy_npc preset import_new custom easy_npc:preset/${npcMap.get(
|
||||
String(villagerType)
|
||||
)}.npc.nbt ${x} ${y + 0.25} ${z}`
|
||||
);
|
||||
nearbyNPCs = level
|
||||
.getEntitiesWithin(AABB.ofBlock(block).inflate(2))
|
||||
.filter((entityType) => entityType.type === "easy_npc:humanoid" || entityType.type === "easy_npc:humanoid_slim");
|
||||
|
||||
level.spawnParticles(
|
||||
"ribbits:spell",
|
||||
true,
|
||||
nearbyNPCs[0].x,
|
||||
nearbyNPCs[0].y + 1.5,
|
||||
nearbyNPCs[0].z,
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
20,
|
||||
0.05
|
||||
);
|
||||
server.runCommandSilent(
|
||||
`playsound botania:starcaller block @a ${player.x} ${player.y} ${player.z}`
|
||||
);
|
||||
server.runCommandSilent(`easy_npc navigation set home ${nearbyNPCs[0].getUuid()} ${x} ${y + 0.25} ${z}`)
|
||||
nbt.merge({
|
||||
data: {
|
||||
type: villagerType,
|
||||
boundNpc: nearbyNPCs[0].getUuid().toString(),
|
||||
placer: player.getUuid().toString(),
|
||||
},
|
||||
});
|
||||
global.setBlockEntityData(block, nbt)
|
||||
player.tell(
|
||||
Text.translatable(
|
||||
"society.villager_home.moved_in",
|
||||
Text.translatable(`dialog.npc.${villagerType}.name`).gold()
|
||||
)
|
||||
);
|
||||
npcData.dayLastPlaced = day
|
||||
} else {
|
||||
player.tell(Text.translatable("society.villager_home.too_close").red());
|
||||
player.inventoryMenu.broadcastFullState();
|
||||
e.cancel();
|
||||
}
|
||||
} else {
|
||||
player.tell(Text.translatable("society.villager_home.recently_moved_in").red());
|
||||
player.inventoryMenu.broadcastFullState();
|
||||
e.cancel();
|
||||
}
|
||||
} else {
|
||||
player.tell(Text.translatable("society.villager_home.error").red());
|
||||
player.inventoryMenu.broadcastFullState();
|
||||
e.cancel();
|
||||
}
|
||||
});
|
||||
BlockEvents.broken("society:villager_home", (e) => {
|
||||
const { block, player, level, server } = e;
|
||||
let nbt = block.getEntityData();
|
||||
const { type, placer, boundNpc } = nbt.data;
|
||||
if (player.getUuid().toString() !== placer && placer != -1 && !player.isCreative()) {
|
||||
player.tell(
|
||||
Text.translatable(
|
||||
"society.villager_home.not_invited_by_you",
|
||||
Text.translatable(`dialog.npc.${type}.name`).gold()
|
||||
).red()
|
||||
);
|
||||
e.cancel();
|
||||
}
|
||||
|
||||
let foundNpc = getBoundNpc(level, block, boundNpc);
|
||||
if (foundNpc != -1) {
|
||||
foundNpc.setRemoved("unloaded_to_chunk");
|
||||
level.spawnParticles(
|
||||
"windswept:feather_cloak",
|
||||
true,
|
||||
foundNpc.x,
|
||||
foundNpc.y + 1.5,
|
||||
foundNpc.z,
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
0.2 * rnd(1, 2),
|
||||
20,
|
||||
0.05
|
||||
);
|
||||
server.runCommandSilent(
|
||||
`playsound windswept:block.pinecone.note block @a ${player.x} ${player.y} ${player.z}`
|
||||
);
|
||||
player.tell(
|
||||
Text.translatable(
|
||||
"society.villager_home.moved_out",
|
||||
Text.translatable(`dialog.npc.${type}.name`).gold()
|
||||
)
|
||||
);
|
||||
block.popItem(Item.of(block.id, `{type:${type}}`));
|
||||
player.persistentData.npcData[type].dayLastPlaced = -10
|
||||
} else {
|
||||
if (!(type == undefined || placer == undefined || boundNpc == undefined)) {
|
||||
if (!player.isCreative()) {
|
||||
e.cancel();
|
||||
} else {
|
||||
player.tell("Unbound villager to home! If the villager still exists, run /easy_npc delete @e")
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user