koishi-plugin-ggcevo-game 1.2.43 → 1.2.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +2 -0
- package/lib/index.js +496 -308
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -231,8 +231,10 @@ function apply(ctx, config) {
|
|
|
231
231
|
name: "string",
|
|
232
232
|
type: "string",
|
|
233
233
|
HP: "unsigned",
|
|
234
|
+
tags: { type: "list", initial: [] },
|
|
234
235
|
skills: { type: "list", initial: [] },
|
|
235
236
|
// 明确数组元素类型
|
|
237
|
+
Skillcountpoints: "unsigned",
|
|
236
238
|
groupId: "unsigned",
|
|
237
239
|
isActive: "boolean",
|
|
238
240
|
respawnTime: "timestamp"
|
|
@@ -412,11 +414,11 @@ function apply(ctx, config) {
|
|
|
412
414
|
rare: [
|
|
413
415
|
{
|
|
414
416
|
name: "悲鸣之锋",
|
|
415
|
-
effect: "
|
|
417
|
+
effect: "增加基于武器等级的伤害加成(0级为10%,每等级增加10%)"
|
|
416
418
|
},
|
|
417
419
|
{
|
|
418
420
|
name: "精灵双倍",
|
|
419
|
-
effect: "
|
|
421
|
+
effect: "下一次击败首领时可获得双倍奖励"
|
|
420
422
|
},
|
|
421
423
|
{
|
|
422
424
|
name: "喵喵财源",
|
|
@@ -510,7 +512,7 @@ function apply(ctx, config) {
|
|
|
510
512
|
{
|
|
511
513
|
professionName: "能量武器",
|
|
512
514
|
effectname: "",
|
|
513
|
-
effect: "能量武器攻击伤害+
|
|
515
|
+
effect: "能量武器攻击伤害+15%",
|
|
514
516
|
requirements: "",
|
|
515
517
|
description: "",
|
|
516
518
|
Jobtransfer: true
|
|
@@ -593,7 +595,7 @@ function apply(ctx, config) {
|
|
|
593
595
|
effect: 0.1,
|
|
594
596
|
description: "子代的防御薄弱,受到的伤害+10%"
|
|
595
597
|
},
|
|
596
|
-
"
|
|
598
|
+
"异形甲壳": {
|
|
597
599
|
effect: -0.2,
|
|
598
600
|
description: "拥有坚硬的生物甲壳,受到的伤害-20%"
|
|
599
601
|
},
|
|
@@ -603,7 +605,7 @@ function apply(ctx, config) {
|
|
|
603
605
|
},
|
|
604
606
|
"冰霜回复": {
|
|
605
607
|
effect: 0,
|
|
606
|
-
description: "血量降低到30
|
|
608
|
+
description: "血量降低到30%以下时触发,回复自身40%的最大生命值,并且回复主宰10%的最大生命值(触发后移除)"
|
|
607
609
|
},
|
|
608
610
|
"冰霜进化": {
|
|
609
611
|
effect: 0,
|
|
@@ -611,11 +613,31 @@ function apply(ctx, config) {
|
|
|
611
613
|
},
|
|
612
614
|
"冰霜环绕": {
|
|
613
615
|
effect: 0,
|
|
614
|
-
description: "血量降低到30%以下时触发,回复自身45
|
|
616
|
+
description: "血量降低到30%以下时触发,回复自身45%的最大生命值(触发后移除)"
|
|
615
617
|
},
|
|
616
618
|
"寒霜地狱": {
|
|
617
619
|
effect: -0.3,
|
|
618
620
|
description: "灾难的暴风雪降临,受到的伤害-30%"
|
|
621
|
+
},
|
|
622
|
+
"应激甲壳I": {
|
|
623
|
+
effect: -0.2,
|
|
624
|
+
description: "拥有自适应甲壳,受到的伤害-20%"
|
|
625
|
+
},
|
|
626
|
+
"应激甲壳II": {
|
|
627
|
+
effect: -0.25,
|
|
628
|
+
description: "拥有自适应甲壳,受到的伤害-25%"
|
|
629
|
+
},
|
|
630
|
+
"求生本能I": {
|
|
631
|
+
effect: 0,
|
|
632
|
+
description: "濒死时,畸变体会迅速回复30%的最大生命值(触发后移除)"
|
|
633
|
+
},
|
|
634
|
+
"求生本能II": {
|
|
635
|
+
effect: 0,
|
|
636
|
+
description: "濒死时,畸变体会迅速回复50%的最大生命值(触发后移除)"
|
|
637
|
+
},
|
|
638
|
+
"冷适应": {
|
|
639
|
+
effect: 0,
|
|
640
|
+
description: "受到10次寒冷伤害后,永久获得“惧热”标签,同时免疫寒冷伤害"
|
|
619
641
|
}
|
|
620
642
|
};
|
|
621
643
|
const bossPool = [
|
|
@@ -624,18 +646,18 @@ function apply(ctx, config) {
|
|
|
624
646
|
id: 1,
|
|
625
647
|
name: "异齿猛兽-首领",
|
|
626
648
|
type: "主宰",
|
|
627
|
-
maxHP:
|
|
649
|
+
maxHP: 12e3,
|
|
628
650
|
tags: ["重甲", "生物"],
|
|
629
|
-
passive: ["
|
|
651
|
+
passive: ["异形甲壳"]
|
|
630
652
|
// 明确类型
|
|
631
653
|
},
|
|
632
654
|
minions: [
|
|
633
655
|
{
|
|
634
656
|
name: "异齿猛兽",
|
|
635
657
|
type: "子代",
|
|
636
|
-
maxHP:
|
|
658
|
+
maxHP: 4e3,
|
|
637
659
|
tags: ["重甲", "生物"],
|
|
638
|
-
passive: ["弱化形态", "
|
|
660
|
+
passive: ["弱化形态", "异形甲壳"]
|
|
639
661
|
// 明确类型
|
|
640
662
|
}
|
|
641
663
|
]
|
|
@@ -645,7 +667,7 @@ function apply(ctx, config) {
|
|
|
645
667
|
id: 2,
|
|
646
668
|
name: "寒冰王蛇",
|
|
647
669
|
type: "主宰",
|
|
648
|
-
maxHP:
|
|
670
|
+
maxHP: 8500,
|
|
649
671
|
tags: ["重甲", "惧热", "生物"],
|
|
650
672
|
passive: ["冰霜环绕", "冰霜进化"]
|
|
651
673
|
// 明确类型
|
|
@@ -654,12 +676,41 @@ function apply(ctx, config) {
|
|
|
654
676
|
{
|
|
655
677
|
name: "冰蛇",
|
|
656
678
|
type: "子代",
|
|
657
|
-
maxHP:
|
|
679
|
+
maxHP: 2500,
|
|
658
680
|
tags: ["惧热", "生物"],
|
|
659
681
|
passive: ["弱化形态", "冰霜回复", "冰霜进化"]
|
|
660
682
|
// 明确类型
|
|
661
683
|
}
|
|
662
684
|
]
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
main: {
|
|
688
|
+
id: 3,
|
|
689
|
+
name: "莽兽",
|
|
690
|
+
type: "主宰",
|
|
691
|
+
maxHP: 8e3,
|
|
692
|
+
tags: ["重甲", "生物"],
|
|
693
|
+
passive: ["应激甲壳II", "求生本能II", "冷适应"]
|
|
694
|
+
// 明确类型
|
|
695
|
+
},
|
|
696
|
+
minions: [
|
|
697
|
+
{
|
|
698
|
+
name: "狂暴畸变体",
|
|
699
|
+
type: "子代",
|
|
700
|
+
maxHP: 2e3,
|
|
701
|
+
tags: ["重甲", "生物"],
|
|
702
|
+
passive: ["弱化形态", "应激甲壳I", "求生本能I", "冷适应"]
|
|
703
|
+
// 明确类型
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
name: "剧毒畸变体",
|
|
707
|
+
type: "子代",
|
|
708
|
+
maxHP: 2e3,
|
|
709
|
+
tags: ["重甲", "生物"],
|
|
710
|
+
passive: ["弱化形态", "应激甲壳I", "求生本能I", "冷适应"]
|
|
711
|
+
// 明确类型
|
|
712
|
+
}
|
|
713
|
+
]
|
|
663
714
|
}
|
|
664
715
|
];
|
|
665
716
|
function calculateModifiers(equippedWeapon, weaponName, hasCritRhythm) {
|
|
@@ -690,29 +741,25 @@ function apply(ctx, config) {
|
|
|
690
741
|
return { totalModAdd, hasCrit };
|
|
691
742
|
}
|
|
692
743
|
__name(calculateModifiers, "calculateModifiers");
|
|
693
|
-
function
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
744
|
+
async function calculateTagMultiplier(weaponData, bossName, equippedWeapon) {
|
|
745
|
+
const bossRecord = await ctx.database.get("ggcevo_boss", { name: bossName });
|
|
746
|
+
if (!bossRecord || !bossRecord.length) {
|
|
747
|
+
throw new Error(`未找到BOSS记录: ${bossName}`);
|
|
748
|
+
}
|
|
749
|
+
const bossTags = Array.isArray(bossRecord[0].tags) ? bossRecord[0].tags : JSON.parse(bossRecord[0].tags || "[]");
|
|
750
|
+
let totalAdditive = 0;
|
|
751
|
+
bossTags.forEach((tag) => {
|
|
752
|
+
let effectValue;
|
|
700
753
|
if (tag === "重甲" && equippedWeapon.installedMods.includes("裂甲核心")) {
|
|
701
754
|
effectValue = 1.2;
|
|
755
|
+
} else {
|
|
756
|
+
effectValue = weaponData.tagEffects?.[tag] ?? 1;
|
|
702
757
|
}
|
|
703
|
-
|
|
704
|
-
});
|
|
705
|
-
voidTags.forEach((tag) => {
|
|
706
|
-
const effectValue = weaponData.tagEffects?.[tag] ?? 1;
|
|
707
|
-
totalTagAdd += effectValue - 1;
|
|
708
|
-
});
|
|
709
|
-
typeTags.forEach((tag) => {
|
|
710
|
-
const effectValue = weaponData.tagEffects?.[tag] ?? 1;
|
|
711
|
-
totalTagAdd += effectValue - 1;
|
|
758
|
+
totalAdditive += effectValue - 1;
|
|
712
759
|
});
|
|
713
|
-
return
|
|
760
|
+
return totalAdditive;
|
|
714
761
|
}
|
|
715
|
-
__name(
|
|
762
|
+
__name(calculateTagMultiplier, "calculateTagMultiplier");
|
|
716
763
|
function calculatePassiveEffects(targetBoss) {
|
|
717
764
|
let passiveEffect = 0;
|
|
718
765
|
const effectivePassives = [...targetBoss.skills || []];
|
|
@@ -751,8 +798,8 @@ function apply(ctx, config) {
|
|
|
751
798
|
if (critRhythmEffect) {
|
|
752
799
|
effectMessage.push("🎵 暴击韵律祈愿生效(暴击率+20%)");
|
|
753
800
|
}
|
|
754
|
-
const targetBossConfig = targetBoss.
|
|
755
|
-
const tagMultiplier =
|
|
801
|
+
const targetBossConfig = targetBoss.name;
|
|
802
|
+
const tagMultiplier = await calculateTagMultiplier(weaponData, targetBossConfig, equippedWeapon);
|
|
756
803
|
damage *= 1 + tagMultiplier;
|
|
757
804
|
const passiveMultiplier = calculatePassiveEffects(targetBoss);
|
|
758
805
|
damage *= 1 + passiveMultiplier;
|
|
@@ -775,7 +822,7 @@ function apply(ctx, config) {
|
|
|
775
822
|
if (lamentEffect) {
|
|
776
823
|
const levelBonus = 0.1 * (equippedWeapon.level + 1);
|
|
777
824
|
damage *= 1 + levelBonus;
|
|
778
|
-
effectMessage.push(`🗡️ 悲鸣之锋祈愿生效(
|
|
825
|
+
effectMessage.push(`🗡️ 悲鸣之锋祈愿生效(基于武器等级,攻击伤害+${(levelBonus * 100).toFixed(0)}%)`);
|
|
779
826
|
}
|
|
780
827
|
const [rankRecord] = await ctx2.database.get("ggcevo_rank", { handle: session.handle, rankseason: config.rankseason });
|
|
781
828
|
const rankBonus = calculateRankBonus(rankRecord);
|
|
@@ -917,8 +964,9 @@ function apply(ctx, config) {
|
|
|
917
964
|
name: nextBossGroup.main.name,
|
|
918
965
|
type: nextBossGroup.main.type,
|
|
919
966
|
HP: nextBossGroup.main.maxHP,
|
|
967
|
+
tags: nextBossGroup.main.tags,
|
|
968
|
+
// 新增标签字段
|
|
920
969
|
skills: [...nextBossGroup.main.passive],
|
|
921
|
-
// 直接展开被动数组
|
|
922
970
|
groupId: nextBossGroup.main.id,
|
|
923
971
|
isActive: true,
|
|
924
972
|
respawnTime: /* @__PURE__ */ new Date()
|
|
@@ -928,8 +976,9 @@ function apply(ctx, config) {
|
|
|
928
976
|
name: minion.name,
|
|
929
977
|
type: minion.type,
|
|
930
978
|
HP: minion.maxHP,
|
|
979
|
+
tags: minion.tags,
|
|
980
|
+
// 新增标签字段
|
|
931
981
|
skills: [...minion.passive],
|
|
932
|
-
// 直接展开被动数组
|
|
933
982
|
groupId: mainBoss.groupId,
|
|
934
983
|
isActive: true,
|
|
935
984
|
respawnTime: /* @__PURE__ */ new Date()
|
|
@@ -959,6 +1008,347 @@ function apply(ctx, config) {
|
|
|
959
1008
|
await ctx.broadcast(config.groupId, `🔄 新的主宰已刷新,快去挑战吧!`);
|
|
960
1009
|
}
|
|
961
1010
|
}, 60 * 1e3);
|
|
1011
|
+
const PassiveHandler = {
|
|
1012
|
+
// 冰霜进化处理(免疫冰霜伤害)
|
|
1013
|
+
handleFrostEvolution: /* @__PURE__ */ __name(function(targetBoss, weaponName, baseDamage, currentHP, maxHP) {
|
|
1014
|
+
if (targetBoss.skills.includes("冰霜进化") && weaponName === "零度之下") {
|
|
1015
|
+
const healAmount = baseDamage;
|
|
1016
|
+
return {
|
|
1017
|
+
updatedHP: Math.min(targetBoss.HP + healAmount, maxHP),
|
|
1018
|
+
initialDamage: 0,
|
|
1019
|
+
messages: [`❄️ ${targetBoss.name} 触发【冰霜进化】免疫冰霜伤害!并且回复 ${healAmount} 生命值`]
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
return null;
|
|
1023
|
+
}, "handleFrostEvolution"),
|
|
1024
|
+
// 冰霜环绕处理(主宰专用)
|
|
1025
|
+
handleFrostSurround: /* @__PURE__ */ __name(async (ctx2, targetBoss, currentHP, maxHP, bossGroup) => {
|
|
1026
|
+
if (targetBoss.type !== "主宰" || !targetBoss.skills.includes("冰霜环绕") || currentHP <= 0 || // 新增血量必须大于0的判断
|
|
1027
|
+
currentHP / maxHP > 0.3) {
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
const healAmount = Math.floor(maxHP * 0.45);
|
|
1031
|
+
const updatedHP = Math.min(currentHP + healAmount, maxHP);
|
|
1032
|
+
const activeMinions = await ctx2.database.get("ggcevo_boss", {
|
|
1033
|
+
groupId: targetBoss.groupId,
|
|
1034
|
+
type: "子代",
|
|
1035
|
+
isActive: true
|
|
1036
|
+
});
|
|
1037
|
+
const skillUpdates = [
|
|
1038
|
+
{
|
|
1039
|
+
name: targetBoss.name,
|
|
1040
|
+
remove: ["冰霜环绕"],
|
|
1041
|
+
add: ["寒霜地狱"]
|
|
1042
|
+
},
|
|
1043
|
+
...activeMinions.map((m) => ({
|
|
1044
|
+
name: m.name,
|
|
1045
|
+
add: ["寒霜地狱"]
|
|
1046
|
+
}))
|
|
1047
|
+
];
|
|
1048
|
+
return {
|
|
1049
|
+
updatedHP,
|
|
1050
|
+
skillUpdates,
|
|
1051
|
+
messages: [
|
|
1052
|
+
`❄️ ${targetBoss.name} 触发【冰霜环绕】,自身回复45%最大生命值(+${healAmount}HP)`,
|
|
1053
|
+
`🌪️ 【寒霜地狱】降临!所有存活的主宰和存活的子代将获得30%减伤效果`
|
|
1054
|
+
]
|
|
1055
|
+
};
|
|
1056
|
+
}, "handleFrostSurround"),
|
|
1057
|
+
// 冰霜回复处理(子代专用)
|
|
1058
|
+
handleFrostRecovery: /* @__PURE__ */ __name(async (ctx2, targetBoss, currentHP, maxHP, activeBosses, bossGroup) => {
|
|
1059
|
+
if (targetBoss.type !== "子代" || !targetBoss.skills.includes("冰霜回复") || currentHP <= 0 || // 新增血量必须大于0的判断
|
|
1060
|
+
currentHP / maxHP > 0.3) {
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
const selfHeal = Math.floor(maxHP * 0.4);
|
|
1064
|
+
const updatedHP = Math.min(currentHP + selfHeal, maxHP);
|
|
1065
|
+
let mainHeal = 0;
|
|
1066
|
+
const mainBoss = activeBosses.find(
|
|
1067
|
+
(b) => b.groupId === targetBoss.groupId && b.type === "主宰"
|
|
1068
|
+
);
|
|
1069
|
+
if (mainBoss) {
|
|
1070
|
+
const mainMaxHP = bossGroup.main.maxHP;
|
|
1071
|
+
mainHeal = Math.floor(mainMaxHP * 0.1);
|
|
1072
|
+
await ctx2.database.set(
|
|
1073
|
+
"ggcevo_boss",
|
|
1074
|
+
{ name: mainBoss.name },
|
|
1075
|
+
{ HP: Math.min(mainBoss.HP + mainHeal, mainMaxHP) }
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
return {
|
|
1079
|
+
updatedHP,
|
|
1080
|
+
skillUpdates: [{
|
|
1081
|
+
name: targetBoss.name,
|
|
1082
|
+
remove: ["冰霜回复"]
|
|
1083
|
+
}],
|
|
1084
|
+
messages: [
|
|
1085
|
+
`❄️ ${targetBoss.name} 触发【冰霜回复】,自身回复40%最大生命值(+${selfHeal}HP),主宰回复10%最大生命值(+${mainHeal}HP)`
|
|
1086
|
+
]
|
|
1087
|
+
};
|
|
1088
|
+
}, "handleFrostRecovery"),
|
|
1089
|
+
// 冷适应计数处理
|
|
1090
|
+
handleColdAdaptation: /* @__PURE__ */ __name(async function(ctx2, targetBoss, weaponName) {
|
|
1091
|
+
if (weaponName !== "零度之下" || !targetBoss.skills.includes("冷适应") || targetBoss.label.includes("惧热")) {
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
const newCount = (targetBoss.Skillcountpoints || 0) + 1;
|
|
1095
|
+
await ctx2.database.set("ggcevo_boss", { name: targetBoss.name }, {
|
|
1096
|
+
Skillcountpoints: newCount
|
|
1097
|
+
});
|
|
1098
|
+
if (newCount >= 10 && !targetBoss.label.includes("惧热")) {
|
|
1099
|
+
const newLabels = [.../* @__PURE__ */ new Set([...targetBoss.label, "惧热"])];
|
|
1100
|
+
await ctx2.database.set("ggcevo_boss", { name: targetBoss.name }, {
|
|
1101
|
+
tags: newLabels
|
|
1102
|
+
});
|
|
1103
|
+
return {
|
|
1104
|
+
messages: [`❄️ ${targetBoss.name} 触发【冷适应】,永久获得「惧热」标签并免疫寒冷伤害!`]
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
return null;
|
|
1108
|
+
}, "handleColdAdaptation"),
|
|
1109
|
+
// 新增冷适应免疫处理函数(模仿冰霜进化)
|
|
1110
|
+
handleColdAdaptationImmunity: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
1111
|
+
if (targetBoss.type === "主宰" && targetBoss.name === "莽兽" && targetBoss.skills.includes("冷适应") && targetBoss.Skillcountpoints >= 10 && weaponName === "零度之下") {
|
|
1112
|
+
return {
|
|
1113
|
+
initialDamage: 0,
|
|
1114
|
+
messages: [`❄️ ${targetBoss.name} 触发【冷适应】免疫寒冷伤害!`]
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
return null;
|
|
1118
|
+
}, "handleColdAdaptationImmunity"),
|
|
1119
|
+
// 求生本能处理
|
|
1120
|
+
handleSurvivalInstinct: /* @__PURE__ */ __name(function(targetBoss, currentHP, maxHP) {
|
|
1121
|
+
if (currentHP > 0) return null;
|
|
1122
|
+
let effect = null;
|
|
1123
|
+
if (targetBoss.skills.includes("求生本能I")) {
|
|
1124
|
+
effect = { heal: maxHP * 0.3, skill: "求生本能I" };
|
|
1125
|
+
} else if (targetBoss.skills.includes("求生本能II")) {
|
|
1126
|
+
effect = { heal: maxHP * 0.5, skill: "求生本能II" };
|
|
1127
|
+
}
|
|
1128
|
+
if (!effect) return null;
|
|
1129
|
+
return {
|
|
1130
|
+
updatedHP: effect.heal,
|
|
1131
|
+
messages: [`${targetBoss.name} 触发【${effect.skill}】,瞬间回复${effect.heal}生命值!`],
|
|
1132
|
+
skillUpdates: [{
|
|
1133
|
+
name: targetBoss.name,
|
|
1134
|
+
remove: [effect.skill]
|
|
1135
|
+
}]
|
|
1136
|
+
};
|
|
1137
|
+
}, "handleSurvivalInstinct"),
|
|
1138
|
+
// 统一处理被动技能(关键修复部分)
|
|
1139
|
+
handlePassives: /* @__PURE__ */ __name(async function(ctx2, targetBoss, initialDamage, currentHP, maxHP, weaponName, baseDamage, activeBosses, bossGroup) {
|
|
1140
|
+
let messages = [];
|
|
1141
|
+
let skillUpdates = [];
|
|
1142
|
+
if (currentHP <= 0) {
|
|
1143
|
+
return { currentHP, messages: [], skillUpdates: [] };
|
|
1144
|
+
}
|
|
1145
|
+
const frostEvoResult = this.handleFrostEvolution(targetBoss, weaponName, baseDamage, currentHP, maxHP);
|
|
1146
|
+
if (frostEvoResult) {
|
|
1147
|
+
initialDamage = frostEvoResult.initialDamage;
|
|
1148
|
+
currentHP = frostEvoResult.updatedHP;
|
|
1149
|
+
messages.push(...frostEvoResult.messages);
|
|
1150
|
+
return { currentHP, messages, skillUpdates, initialDamage };
|
|
1151
|
+
}
|
|
1152
|
+
const frostSurroundResult = await this.handleFrostSurround(ctx2, targetBoss, currentHP, maxHP, bossGroup);
|
|
1153
|
+
if (frostSurroundResult) {
|
|
1154
|
+
currentHP = frostSurroundResult.updatedHP;
|
|
1155
|
+
messages.push(...frostSurroundResult.messages);
|
|
1156
|
+
skillUpdates.push(...frostSurroundResult.skillUpdates);
|
|
1157
|
+
}
|
|
1158
|
+
const frostRecoveryResult = await this.handleFrostRecovery(ctx2, targetBoss, currentHP, maxHP, activeBosses, bossGroup);
|
|
1159
|
+
if (frostRecoveryResult) {
|
|
1160
|
+
currentHP = frostRecoveryResult.updatedHP;
|
|
1161
|
+
messages.push(...frostRecoveryResult.messages);
|
|
1162
|
+
skillUpdates.push(...frostRecoveryResult.skillUpdates);
|
|
1163
|
+
}
|
|
1164
|
+
const coldAdaptResult = await this.handleColdAdaptation(ctx2, targetBoss, weaponName);
|
|
1165
|
+
if (coldAdaptResult) {
|
|
1166
|
+
messages.push(...coldAdaptResult.messages);
|
|
1167
|
+
}
|
|
1168
|
+
const coldImmunityResult = this.handleColdAdaptationImmunity(targetBoss, weaponName);
|
|
1169
|
+
if (coldImmunityResult) {
|
|
1170
|
+
initialDamage = coldImmunityResult.initialDamage;
|
|
1171
|
+
currentHP = targetBoss.HP;
|
|
1172
|
+
messages.push(...coldImmunityResult.messages);
|
|
1173
|
+
return { currentHP, messages, skillUpdates, initialDamage };
|
|
1174
|
+
}
|
|
1175
|
+
const survivalResult = this.handleSurvivalInstinct(targetBoss, currentHP, maxHP);
|
|
1176
|
+
if (survivalResult) {
|
|
1177
|
+
currentHP = survivalResult.updatedHP;
|
|
1178
|
+
messages.push(...survivalResult.messages);
|
|
1179
|
+
skillUpdates.push(...survivalResult.skillUpdates);
|
|
1180
|
+
}
|
|
1181
|
+
return { currentHP, messages, skillUpdates, initialDamage };
|
|
1182
|
+
}, "handlePassives"),
|
|
1183
|
+
// 应用技能更新到数据库
|
|
1184
|
+
applySkillUpdates: /* @__PURE__ */ __name(async (ctx2, skillUpdates) => {
|
|
1185
|
+
const updates = skillUpdates.map(async (update) => {
|
|
1186
|
+
const boss = await ctx2.database.get("ggcevo_boss", { name: update.name });
|
|
1187
|
+
const originalSkills = boss[0]?.skills || [];
|
|
1188
|
+
const newSkills = [
|
|
1189
|
+
...originalSkills.filter((s) => !update.remove?.includes(s)),
|
|
1190
|
+
...update.add || []
|
|
1191
|
+
];
|
|
1192
|
+
return ctx2.database.set(
|
|
1193
|
+
"ggcevo_boss",
|
|
1194
|
+
{ name: update.name },
|
|
1195
|
+
{ skills: [...new Set(newSkills)] }
|
|
1196
|
+
// 去重
|
|
1197
|
+
);
|
|
1198
|
+
});
|
|
1199
|
+
await Promise.all(updates);
|
|
1200
|
+
}, "applySkillUpdates")
|
|
1201
|
+
};
|
|
1202
|
+
async function handleBossDefeatRewards(ctx2, targetBoss, session) {
|
|
1203
|
+
const damageRecords = await ctx2.database.select("ggcevo_boss_damage").where({
|
|
1204
|
+
bossGroupId: targetBoss.groupId,
|
|
1205
|
+
totalDamage: { $gt: 0 }
|
|
1206
|
+
}).orderBy("totalDamage", "desc").execute();
|
|
1207
|
+
const rewardMessages = [];
|
|
1208
|
+
const broadcastMessages = [];
|
|
1209
|
+
const rewardMap = /* @__PURE__ */ new Map();
|
|
1210
|
+
const updatePromises = [];
|
|
1211
|
+
if (damageRecords.length > 0) {
|
|
1212
|
+
const top20 = damageRecords.slice(0, 20);
|
|
1213
|
+
top20.forEach((record, index) => {
|
|
1214
|
+
const rank = index + 1;
|
|
1215
|
+
let guguCoins, gold;
|
|
1216
|
+
switch (true) {
|
|
1217
|
+
case rank === 1:
|
|
1218
|
+
guguCoins = 30;
|
|
1219
|
+
gold = 2e3;
|
|
1220
|
+
break;
|
|
1221
|
+
case rank === 2:
|
|
1222
|
+
guguCoins = 25;
|
|
1223
|
+
gold = 1750;
|
|
1224
|
+
break;
|
|
1225
|
+
case rank === 3:
|
|
1226
|
+
guguCoins = 20;
|
|
1227
|
+
gold = 1500;
|
|
1228
|
+
break;
|
|
1229
|
+
case rank <= 10:
|
|
1230
|
+
guguCoins = 15;
|
|
1231
|
+
gold = 1e3;
|
|
1232
|
+
break;
|
|
1233
|
+
default:
|
|
1234
|
+
guguCoins = 10;
|
|
1235
|
+
gold = 500;
|
|
1236
|
+
}
|
|
1237
|
+
const key = record.handle;
|
|
1238
|
+
rewardMap.set(key, {
|
|
1239
|
+
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + guguCoins,
|
|
1240
|
+
gold: (rewardMap.get(key)?.gold || 0) + gold,
|
|
1241
|
+
playerName: record.playerName
|
|
1242
|
+
});
|
|
1243
|
+
rewardMessages.push(
|
|
1244
|
+
`${rank}. ${record.playerName}`,
|
|
1245
|
+
` 获得奖励: ${guguCoins} 咕咕币 + ${gold} 金币`
|
|
1246
|
+
);
|
|
1247
|
+
});
|
|
1248
|
+
const others = damageRecords.slice(20);
|
|
1249
|
+
if (others.length > 0) {
|
|
1250
|
+
others.forEach((record) => {
|
|
1251
|
+
const key = record.handle;
|
|
1252
|
+
rewardMap.set(key, {
|
|
1253
|
+
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + 3,
|
|
1254
|
+
gold: (rewardMap.get(key)?.gold || 0) + 200,
|
|
1255
|
+
playerName: record.playerName
|
|
1256
|
+
});
|
|
1257
|
+
});
|
|
1258
|
+
rewardMessages.push(`其他参与者各获得: 3 咕咕币 + 200 金币`);
|
|
1259
|
+
}
|
|
1260
|
+
const doubleRewardPlayers = await handleDoubleRewards(ctx2, damageRecords, rewardMap);
|
|
1261
|
+
await applyDoubleRewards(ctx2, doubleRewardPlayers, rewardMap, rewardMessages);
|
|
1262
|
+
await updateRewardRecords(ctx2, rewardMap, updatePromises);
|
|
1263
|
+
}
|
|
1264
|
+
broadcastMessages.push(
|
|
1265
|
+
`🎯 主宰 ${targetBoss.name} 已被 ${session.username} 击破!`,
|
|
1266
|
+
`所有子代已消失,下一个主宰将在1小时后重生`,
|
|
1267
|
+
"",
|
|
1268
|
+
"🏆 伤害排行榜奖励:",
|
|
1269
|
+
...rewardMessages
|
|
1270
|
+
);
|
|
1271
|
+
return { rewardMessages };
|
|
1272
|
+
}
|
|
1273
|
+
__name(handleBossDefeatRewards, "handleBossDefeatRewards");
|
|
1274
|
+
async function handleDoubleRewards(ctx2, damageRecords, rewardMap) {
|
|
1275
|
+
const doubleRewardPlayers = /* @__PURE__ */ new Map();
|
|
1276
|
+
for (const record of damageRecords) {
|
|
1277
|
+
const [elfEffect] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1278
|
+
handle: record.handle,
|
|
1279
|
+
wishname: "精灵双倍",
|
|
1280
|
+
isused: false,
|
|
1281
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1282
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1283
|
+
});
|
|
1284
|
+
if (elfEffect) {
|
|
1285
|
+
doubleRewardPlayers.set(record.handle, {
|
|
1286
|
+
effect: elfEffect,
|
|
1287
|
+
originalReward: {
|
|
1288
|
+
guguCoins: rewardMap.get(record.handle)?.guguCoins || 0,
|
|
1289
|
+
gold: rewardMap.get(record.handle)?.gold || 0
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
return doubleRewardPlayers;
|
|
1295
|
+
}
|
|
1296
|
+
__name(handleDoubleRewards, "handleDoubleRewards");
|
|
1297
|
+
async function applyDoubleRewards(ctx2, doubleRewardPlayers, rewardMap, rewardMessages) {
|
|
1298
|
+
if (doubleRewardPlayers.size > 0) {
|
|
1299
|
+
await ctx2.database.withTransaction(async () => {
|
|
1300
|
+
for (const [handle, data] of doubleRewardPlayers) {
|
|
1301
|
+
const reward = rewardMap.get(handle);
|
|
1302
|
+
reward.guguCoins = data.originalReward.guguCoins * 2;
|
|
1303
|
+
reward.gold = data.originalReward.gold * 2;
|
|
1304
|
+
await ctx2.database.set(
|
|
1305
|
+
"ggcevo_Wish_Record",
|
|
1306
|
+
{ id: data.effect.id },
|
|
1307
|
+
{ isused: true }
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
rewardMessages.forEach((msg, index) => {
|
|
1312
|
+
const match = msg.match(/(\d+\.) (.+?) 获得奖励/);
|
|
1313
|
+
if (match) {
|
|
1314
|
+
const playerName = match[2];
|
|
1315
|
+
const targetHandle = [...rewardMap.keys()].find(
|
|
1316
|
+
(key) => rewardMap.get(key).playerName === playerName
|
|
1317
|
+
);
|
|
1318
|
+
if (targetHandle && doubleRewardPlayers.has(targetHandle)) {
|
|
1319
|
+
rewardMessages[index] = `${match[1]} ${playerName} 🧚 获得双倍奖励: ${rewardMap.get(targetHandle).guguCoins} 咕咕币 + ${rewardMap.get(targetHandle).gold} 金币(精灵双倍祈愿生效)`;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
__name(applyDoubleRewards, "applyDoubleRewards");
|
|
1326
|
+
async function updateRewardRecords(ctx2, rewardMap, updatePromises) {
|
|
1327
|
+
for (const [handle, reward] of rewardMap) {
|
|
1328
|
+
const signPromise = (async () => {
|
|
1329
|
+
const [existingSign] = await ctx2.database.get("ggcevo_sign", { handle });
|
|
1330
|
+
await ctx2.database.upsert("ggcevo_sign", [{
|
|
1331
|
+
handle,
|
|
1332
|
+
totalRewards: existingSign?.totalRewards + reward.gold
|
|
1333
|
+
}], ["handle"]);
|
|
1334
|
+
})();
|
|
1335
|
+
updatePromises.push(signPromise);
|
|
1336
|
+
const backpackPromise = (async () => {
|
|
1337
|
+
const [existingItem] = await ctx2.database.get("ggcevo_backpack", {
|
|
1338
|
+
handle,
|
|
1339
|
+
itemId: 1
|
|
1340
|
+
});
|
|
1341
|
+
await ctx2.database.upsert("ggcevo_backpack", [{
|
|
1342
|
+
handle,
|
|
1343
|
+
itemId: 1,
|
|
1344
|
+
quantity: existingItem?.quantity + reward.guguCoins
|
|
1345
|
+
}], ["handle", "itemId"]);
|
|
1346
|
+
})();
|
|
1347
|
+
updatePromises.push(backpackPromise);
|
|
1348
|
+
}
|
|
1349
|
+
await Promise.all(updatePromises);
|
|
1350
|
+
}
|
|
1351
|
+
__name(updateRewardRecords, "updateRewardRecords");
|
|
962
1352
|
ctx.command("ggcevo/抽奖").action(async (argv) => {
|
|
963
1353
|
const session = argv.session;
|
|
964
1354
|
let winCount = 0;
|
|
@@ -1930,6 +2320,12 @@ ${itemDetails.join("\n")}`;
|
|
|
1930
2320
|
}
|
|
1931
2321
|
qualityGroups[quality].push(`${itemName}${quantityText}`);
|
|
1932
2322
|
}
|
|
2323
|
+
const couponCostMap = {
|
|
2324
|
+
t3: 3,
|
|
2325
|
+
t2: 4,
|
|
2326
|
+
t1: 5,
|
|
2327
|
+
t0: 6
|
|
2328
|
+
};
|
|
1933
2329
|
const order = ["t0", "t1", "t2", "t3"];
|
|
1934
2330
|
let message = "请在30秒内输入可兑换物品名称(显示格式:物品名 [剩余/总量]):\n";
|
|
1935
2331
|
message += "注意:限量物品将在赛季更新时补货,限定物品[史蒂夫]除外。\n";
|
|
@@ -1937,7 +2333,7 @@ ${itemDetails.join("\n")}`;
|
|
|
1937
2333
|
const items = qualityGroups[quality] || [];
|
|
1938
2334
|
if (!items.length) continue;
|
|
1939
2335
|
message += `
|
|
1940
|
-
[${quality.toUpperCase()}]
|
|
2336
|
+
[${quality.toUpperCase()}](${couponCostMap[quality]}张兑换券)
|
|
1941
2337
|
${items.join("、")}
|
|
1942
2338
|
`;
|
|
1943
2339
|
}
|
|
@@ -2510,7 +2906,7 @@ ${achievementList.join("\n")}`;
|
|
|
2510
2906
|
pageNum < totalPages ? `输入 pk榜 ${pageNum + 1} 查看下一页` : "已是最后一页"
|
|
2511
2907
|
].join("\n");
|
|
2512
2908
|
});
|
|
2513
|
-
ctx.command("ggcevo/切换pk状态", "切换玩家对战状态").alias("切换pk").action(async ({ session }) => {
|
|
2909
|
+
ctx.command("ggcevo/切换pk状态", "切换玩家对战状态").alias("切换pk", "pk状态").action(async ({ session }) => {
|
|
2514
2910
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
2515
2911
|
if (!profile) return "您暂未绑定句柄。";
|
|
2516
2912
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
@@ -2556,7 +2952,7 @@ ${achievementList.join("\n")}`;
|
|
|
2556
2952
|
day: "2-digit"
|
|
2557
2953
|
})}`;
|
|
2558
2954
|
});
|
|
2559
|
-
ctx.command("ggcevo/武器库 [type]").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async (
|
|
2955
|
+
ctx.command("ggcevo/武器库 [type]").alias("武器商店", "武器商城", "武器商场").usage("输入“武器库”查看类型,或“武器库 类型”查看详细武器信息").action(async (_, type) => {
|
|
2560
2956
|
const typeStats = Object.values(weaponConfig).reduce((stats, weapon) => {
|
|
2561
2957
|
stats[weapon.type] = (stats[weapon.type] || 0) + 1;
|
|
2562
2958
|
return stats;
|
|
@@ -2575,7 +2971,7 @@ ${achievementList.join("\n")}`;
|
|
|
2575
2971
|
return `无效武器类型,可用类型:
|
|
2576
2972
|
${validTypes.join("、")}`;
|
|
2577
2973
|
}
|
|
2578
|
-
const items = Object.entries(weaponConfig).filter(([
|
|
2974
|
+
const items = Object.entries(weaponConfig).filter(([_2, config2]) => config2.type === normalizedType).map(([name2, config2]) => {
|
|
2579
2975
|
const tagEffectsDesc = config2.tagEffects ? Object.entries(config2.tagEffects).map(([tag, multiplier]) => `▸ 对${tag}目标造成${(multiplier * 100).toFixed(0)}%伤害`).join("\n") : "▸ 无特殊加成效果";
|
|
2580
2976
|
return [
|
|
2581
2977
|
`【${name2}】`,
|
|
@@ -2778,7 +3174,7 @@ ${validTypes.join("、")}`;
|
|
|
2778
3174
|
return `${message}
|
|
2779
3175
|
当前等级:${newLevel},伤害:${baseDamage},可用改装槽:${slots}个。`;
|
|
2780
3176
|
});
|
|
2781
|
-
ctx.command("ggcevo/改装 <weapon> [mod]", "安装武器模块").alias("改装武器", "改造", "改造武器").action(async ({ session }, weapon, mod) => {
|
|
3177
|
+
ctx.command("ggcevo/改装 <weapon> [mod]", "安装武器模块").alias("改装武器", "改造", "改造武器", "武器改装", "武器改造").action(async ({ session }, weapon, mod) => {
|
|
2782
3178
|
const isValidWeapon = weapon && weaponConfig[weapon]?.id !== void 0;
|
|
2783
3179
|
const generateModList = /* @__PURE__ */ __name(() => {
|
|
2784
3180
|
if (!isValidWeapon) {
|
|
@@ -2813,7 +3209,7 @@ ${validTypes.join("、")}`;
|
|
|
2813
3209
|
handle,
|
|
2814
3210
|
weaponId: weaponConfig[weapon].id
|
|
2815
3211
|
});
|
|
2816
|
-
if (!equipment) return "
|
|
3212
|
+
if (!equipment) return "尚未获得该武器。";
|
|
2817
3213
|
const modInfo = modConfig[mod];
|
|
2818
3214
|
if (modInfo.isExclusive) {
|
|
2819
3215
|
if (modInfo.exclusiveTo !== weapon) {
|
|
@@ -2852,21 +3248,15 @@ ${validTypes.join("、")}`;
|
|
|
2852
3248
|
`剩余金币:${signInfo.totalRewards - modInfo.cost}`
|
|
2853
3249
|
].join("\n\n");
|
|
2854
3250
|
});
|
|
2855
|
-
ctx.command("ggcevo/攻击 <
|
|
3251
|
+
ctx.command("ggcevo/攻击 <bossName>").usage("请输入要攻击的BOSS名称(例如:攻击 异齿猛兽 或 攻击 寒冰王蛇)").action(async (argv, bossName) => {
|
|
2856
3252
|
const session = argv.session;
|
|
2857
3253
|
let broadcastMessage = null;
|
|
2858
|
-
const
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
};
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
if (aliases.includes(targetType)) {
|
|
2865
|
-
normalizedTarget = key;
|
|
2866
|
-
break;
|
|
2867
|
-
}
|
|
2868
|
-
}
|
|
2869
|
-
if (!normalizedTarget) return "请指定正确的攻击目标:主宰/zz 或 子代/zd";
|
|
3254
|
+
const [targetBoss] = await ctx.database.get("ggcevo_boss", {
|
|
3255
|
+
name: bossName,
|
|
3256
|
+
isActive: true
|
|
3257
|
+
});
|
|
3258
|
+
if (!bossName) return `请选择你要攻击的目标,请使用"主宰信息"查看`;
|
|
3259
|
+
if (!targetBoss) return `当前没有找到名为 ${bossName} 的可攻击目标,请使用"主宰信息"查看`;
|
|
2870
3260
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
2871
3261
|
if (!profile) return "您暂未绑定句柄。";
|
|
2872
3262
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
@@ -2889,115 +3279,50 @@ ${validTypes.join("、")}`;
|
|
|
2889
3279
|
equipped: true
|
|
2890
3280
|
});
|
|
2891
3281
|
if (!equippedWeapon) return "请先装备武器再攻击。";
|
|
2892
|
-
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
2893
|
-
if (!activeBosses.length) return "当前没有存活的主宰。";
|
|
2894
|
-
const targetBoss = normalizedTarget === "主宰" ? activeBosses.find((b) => b.type === "主宰") : activeBosses.find((b) => b.type === "子代");
|
|
2895
|
-
if (!targetBoss) return `当前没有可攻击的${normalizedTarget === "主宰" ? "主宰" : "子代"}。`;
|
|
2896
3282
|
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
2897
3283
|
const [weaponName, weaponData] = weaponConfigEntry;
|
|
2898
3284
|
const { damage: baseDamage, hasCrit, effectMessage } = await calculateTotalDamage(ctx, session, equippedWeapon, targetBoss);
|
|
2899
|
-
const
|
|
3285
|
+
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
3286
|
+
if (!activeBosses.length) return "当前没有存活的主宰。";
|
|
3287
|
+
const bossGroup = bossPool.find(
|
|
3288
|
+
(g) => g.main.name === targetBoss.name || g.minions.some((m) => m.name === targetBoss.name)
|
|
3289
|
+
);
|
|
2900
3290
|
if (!bossGroup) return "无法获取BOSS组配置。";
|
|
2901
3291
|
const maxHP = targetBoss.type === "主宰" ? bossGroup.main.maxHP : bossGroup.minions.find((m) => m.name === targetBoss.name)?.maxHP || 0;
|
|
2902
3292
|
let initialDamage = Math.min(baseDamage, targetBoss.HP);
|
|
2903
3293
|
let currentHP = targetBoss.HP - initialDamage;
|
|
2904
3294
|
let healMessages = [];
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
currentHP
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
type: "子代",
|
|
2922
|
-
isActive: true
|
|
2923
|
-
});
|
|
2924
|
-
const updates = [
|
|
2925
|
-
// 更新主宰
|
|
2926
|
-
{
|
|
2927
|
-
name: targetBoss.name,
|
|
2928
|
-
skills: [
|
|
2929
|
-
...targetBoss.skills.filter((s) => s !== "冰霜环绕"),
|
|
2930
|
-
"寒霜地狱"
|
|
2931
|
-
]
|
|
2932
|
-
// 明确类型
|
|
2933
|
-
},
|
|
2934
|
-
// 更新所有存活子代
|
|
2935
|
-
...activeMinions.map((minion) => ({
|
|
2936
|
-
name: minion.name,
|
|
2937
|
-
skills: [
|
|
2938
|
-
...minion.skills,
|
|
2939
|
-
"寒霜地狱"
|
|
2940
|
-
// 明确字面量类型
|
|
2941
|
-
]
|
|
2942
|
-
}))
|
|
2943
|
-
];
|
|
2944
|
-
updates.forEach((update) => {
|
|
2945
|
-
globalSkillUpdates.set(update.name, update.skills);
|
|
2946
|
-
});
|
|
2947
|
-
await ctx.database.upsert("ggcevo_boss", updates, ["name"]);
|
|
2948
|
-
healMessages.push(
|
|
2949
|
-
`❄️ ${targetBoss.name} 触发【冰霜环绕】,自身回复45%最大生命值(+${healAmount}HP)`,
|
|
2950
|
-
`🌪️ 【寒霜地狱】降临!所有存活的主宰和子代将获得30%减伤效果`
|
|
2951
|
-
);
|
|
2952
|
-
}
|
|
2953
|
-
if (targetBoss.type === "子代" && targetBoss.skills.includes("冰霜回复") && hpPercentage <= 0.3) {
|
|
2954
|
-
let mainHeal;
|
|
2955
|
-
const selfHeal = Math.floor(maxHP * 0.2);
|
|
2956
|
-
currentHP = Math.min(currentHP + selfHeal, maxHP);
|
|
2957
|
-
const mainBoss = activeBosses.find(
|
|
2958
|
-
(b) => b.groupId === targetBoss.groupId && b.type === "主宰"
|
|
2959
|
-
);
|
|
2960
|
-
if (mainBoss) {
|
|
2961
|
-
const mainMaxHP = bossGroup.main.maxHP;
|
|
2962
|
-
mainHeal = Math.floor(mainMaxHP * 0.2);
|
|
2963
|
-
const mainNewHP = Math.min(mainBoss.HP + mainHeal, mainMaxHP);
|
|
2964
|
-
await ctx.database.set(
|
|
2965
|
-
"ggcevo_boss",
|
|
2966
|
-
{ name: mainBoss.name },
|
|
2967
|
-
{ HP: mainNewHP }
|
|
2968
|
-
);
|
|
2969
|
-
}
|
|
2970
|
-
triggeredSkills.push("冰霜回复");
|
|
2971
|
-
healMessages.push(`❄️ ${targetBoss.name} 触发【冰霜回复】,自身回复20%最大生命值(+${selfHeal}HP),主宰回复20%最大生命值(+${mainHeal}HP)`);
|
|
2972
|
-
}
|
|
3295
|
+
const passiveResult = await PassiveHandler.handlePassives(
|
|
3296
|
+
ctx,
|
|
3297
|
+
targetBoss,
|
|
3298
|
+
initialDamage,
|
|
3299
|
+
currentHP,
|
|
3300
|
+
maxHP,
|
|
3301
|
+
weaponName,
|
|
3302
|
+
baseDamage,
|
|
3303
|
+
activeBosses,
|
|
3304
|
+
bossGroup
|
|
3305
|
+
);
|
|
3306
|
+
currentHP = passiveResult.currentHP;
|
|
3307
|
+
initialDamage = passiveResult.initialDamage;
|
|
3308
|
+
healMessages.push(...passiveResult.messages);
|
|
3309
|
+
if (passiveResult.skillUpdates.length > 0) {
|
|
3310
|
+
await PassiveHandler.applySkillUpdates(ctx, passiveResult.skillUpdates);
|
|
2973
3311
|
}
|
|
2974
3312
|
const isDefeated = currentHP <= 0;
|
|
2975
3313
|
const [existingRecord] = await ctx.database.get("ggcevo_boss_damage", {
|
|
2976
3314
|
handle,
|
|
2977
3315
|
bossGroupId: targetBoss.groupId
|
|
2978
3316
|
});
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
lastattackDate: /* @__PURE__ */ new Date()
|
|
2989
|
-
});
|
|
2990
|
-
} else {
|
|
2991
|
-
await ctx.database.create("ggcevo_boss_damage", {
|
|
2992
|
-
handle,
|
|
2993
|
-
playerName: session.username,
|
|
2994
|
-
bossGroupId: targetBoss.groupId,
|
|
2995
|
-
totalDamage: initialDamage,
|
|
2996
|
-
// 改为实际伤害
|
|
2997
|
-
attackCount: 1,
|
|
2998
|
-
lastattackDate: /* @__PURE__ */ new Date()
|
|
2999
|
-
});
|
|
3000
|
-
}
|
|
3317
|
+
await ctx.database.upsert("ggcevo_boss_damage", [{
|
|
3318
|
+
handle,
|
|
3319
|
+
bossGroupId: targetBoss.groupId,
|
|
3320
|
+
playerName: session.username,
|
|
3321
|
+
totalDamage: (existingRecord?.totalDamage || 0) + initialDamage,
|
|
3322
|
+
// 改为实际伤害
|
|
3323
|
+
attackCount: (existingRecord?.attackCount || 0) + 1,
|
|
3324
|
+
lastattackDate: /* @__PURE__ */ new Date()
|
|
3325
|
+
}], ["handle"]);
|
|
3001
3326
|
if (isDefeated) {
|
|
3002
3327
|
if (targetBoss.type === "主宰") {
|
|
3003
3328
|
await ctx.database.set(
|
|
@@ -3015,143 +3340,7 @@ ${validTypes.join("、")}`;
|
|
|
3015
3340
|
{ name: targetBoss.name },
|
|
3016
3341
|
{ respawnTime }
|
|
3017
3342
|
);
|
|
3018
|
-
const
|
|
3019
|
-
bossGroupId: targetBoss.groupId,
|
|
3020
|
-
totalDamage: { $gt: 0 }
|
|
3021
|
-
// 新增过滤条件
|
|
3022
|
-
}).orderBy("totalDamage", "desc").execute();
|
|
3023
|
-
let rewardMessages = [];
|
|
3024
|
-
const updatePromises = [];
|
|
3025
|
-
const rewardMap = /* @__PURE__ */ new Map();
|
|
3026
|
-
if (damageRecords.length > 0) {
|
|
3027
|
-
const top20 = damageRecords.slice(0, 20);
|
|
3028
|
-
top20.forEach((record, index) => {
|
|
3029
|
-
const rank = index + 1;
|
|
3030
|
-
let guguCoins, gold;
|
|
3031
|
-
if (rank === 1) {
|
|
3032
|
-
guguCoins = 30;
|
|
3033
|
-
gold = 2e3;
|
|
3034
|
-
} else if (rank === 2) {
|
|
3035
|
-
guguCoins = 25;
|
|
3036
|
-
gold = 1750;
|
|
3037
|
-
} else if (rank === 3) {
|
|
3038
|
-
guguCoins = 20;
|
|
3039
|
-
gold = 1500;
|
|
3040
|
-
} else if (rank <= 10) {
|
|
3041
|
-
guguCoins = 15;
|
|
3042
|
-
gold = 1e3;
|
|
3043
|
-
} else {
|
|
3044
|
-
guguCoins = 10;
|
|
3045
|
-
gold = 500;
|
|
3046
|
-
}
|
|
3047
|
-
const key = record.handle;
|
|
3048
|
-
rewardMap.set(key, {
|
|
3049
|
-
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + guguCoins,
|
|
3050
|
-
gold: (rewardMap.get(key)?.gold || 0) + gold,
|
|
3051
|
-
playerName: record.playerName
|
|
3052
|
-
});
|
|
3053
|
-
rewardMessages.push(
|
|
3054
|
-
`${rank}. ${record.playerName}`,
|
|
3055
|
-
` 获得奖励: ${guguCoins} 咕咕币 + ${gold} 金币`
|
|
3056
|
-
);
|
|
3057
|
-
});
|
|
3058
|
-
const others = damageRecords.slice(20);
|
|
3059
|
-
if (others.length > 0) {
|
|
3060
|
-
others.forEach((record) => {
|
|
3061
|
-
const key = record.handle;
|
|
3062
|
-
rewardMap.set(key, {
|
|
3063
|
-
guguCoins: (rewardMap.get(key)?.guguCoins || 0) + 3,
|
|
3064
|
-
gold: (rewardMap.get(key)?.gold || 0) + 200,
|
|
3065
|
-
playerName: record.playerName
|
|
3066
|
-
});
|
|
3067
|
-
});
|
|
3068
|
-
rewardMessages.push(`其他参与者各获得: 3 咕咕币 + 200 金币`);
|
|
3069
|
-
}
|
|
3070
|
-
const doubleRewardPlayers = /* @__PURE__ */ new Map();
|
|
3071
|
-
for (const record of damageRecords) {
|
|
3072
|
-
const [elfEffect] = await ctx.database.get("ggcevo_Wish_Record", {
|
|
3073
|
-
handle: record.handle,
|
|
3074
|
-
wishname: "精灵双倍",
|
|
3075
|
-
isused: false,
|
|
3076
|
-
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
3077
|
-
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
3078
|
-
});
|
|
3079
|
-
if (elfEffect) {
|
|
3080
|
-
doubleRewardPlayers.set(record.handle, {
|
|
3081
|
-
effect: elfEffect,
|
|
3082
|
-
originalReward: {
|
|
3083
|
-
guguCoins: rewardMap.get(record.handle)?.guguCoins || 0,
|
|
3084
|
-
gold: rewardMap.get(record.handle)?.gold || 0
|
|
3085
|
-
}
|
|
3086
|
-
});
|
|
3087
|
-
}
|
|
3088
|
-
}
|
|
3089
|
-
if (doubleRewardPlayers.size > 0) {
|
|
3090
|
-
await ctx.database.withTransaction(async () => {
|
|
3091
|
-
for (const [handle2, data] of doubleRewardPlayers) {
|
|
3092
|
-
const reward = rewardMap.get(handle2);
|
|
3093
|
-
reward.guguCoins = data.originalReward.guguCoins * 2;
|
|
3094
|
-
reward.gold = data.originalReward.gold * 2;
|
|
3095
|
-
await ctx.database.set(
|
|
3096
|
-
"ggcevo_Wish_Record",
|
|
3097
|
-
{ id: data.effect.id },
|
|
3098
|
-
{ isused: true }
|
|
3099
|
-
);
|
|
3100
|
-
}
|
|
3101
|
-
});
|
|
3102
|
-
rewardMessages = rewardMessages.map((msg) => {
|
|
3103
|
-
const match = msg.match(/(\d+\.) (.+?) 获得奖励/);
|
|
3104
|
-
if (match) {
|
|
3105
|
-
const playerName = match[2];
|
|
3106
|
-
const targetHandle = [...rewardMap.keys()].find(
|
|
3107
|
-
(key) => rewardMap.get(key).playerName === playerName
|
|
3108
|
-
);
|
|
3109
|
-
if (targetHandle && doubleRewardPlayers.has(targetHandle)) {
|
|
3110
|
-
return `${match[1]} ${playerName} 🧚 获得奖励: ${rewardMap.get(targetHandle).guguCoins} 咕咕币 + ${rewardMap.get(targetHandle).gold} 金币 (双倍生效)`;
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
return msg;
|
|
3114
|
-
});
|
|
3115
|
-
}
|
|
3116
|
-
for (const [handle2, reward] of rewardMap) {
|
|
3117
|
-
const signPromise = (async () => {
|
|
3118
|
-
const [existingSign2] = await ctx.database.get("ggcevo_sign", { handle: handle2 });
|
|
3119
|
-
if (existingSign2) {
|
|
3120
|
-
await ctx.database.set("ggcevo_sign", { handle: handle2 }, {
|
|
3121
|
-
totalRewards: existingSign2.totalRewards + reward.gold
|
|
3122
|
-
});
|
|
3123
|
-
} else {
|
|
3124
|
-
await ctx.database.create("ggcevo_sign", {
|
|
3125
|
-
handle: handle2,
|
|
3126
|
-
totalRewards: reward.gold
|
|
3127
|
-
});
|
|
3128
|
-
}
|
|
3129
|
-
})();
|
|
3130
|
-
updatePromises.push(signPromise);
|
|
3131
|
-
const backpackPromise = (async () => {
|
|
3132
|
-
const [existingItem] = await ctx.database.get("ggcevo_backpack", {
|
|
3133
|
-
handle: handle2,
|
|
3134
|
-
itemId: 1
|
|
3135
|
-
});
|
|
3136
|
-
if (existingItem) {
|
|
3137
|
-
await ctx.database.set("ggcevo_backpack", {
|
|
3138
|
-
handle: handle2,
|
|
3139
|
-
itemId: 1
|
|
3140
|
-
}, {
|
|
3141
|
-
quantity: existingItem.quantity + reward.guguCoins
|
|
3142
|
-
});
|
|
3143
|
-
} else {
|
|
3144
|
-
await ctx.database.create("ggcevo_backpack", {
|
|
3145
|
-
handle: handle2,
|
|
3146
|
-
itemId: 1,
|
|
3147
|
-
quantity: reward.guguCoins
|
|
3148
|
-
});
|
|
3149
|
-
}
|
|
3150
|
-
})();
|
|
3151
|
-
updatePromises.push(backpackPromise);
|
|
3152
|
-
}
|
|
3153
|
-
await Promise.all(updatePromises);
|
|
3154
|
-
}
|
|
3343
|
+
const { rewardMessages } = await handleBossDefeatRewards(ctx, targetBoss, session);
|
|
3155
3344
|
await ctx.database.remove("ggcevo_boss_damage", {
|
|
3156
3345
|
bossGroupId: targetBoss.groupId
|
|
3157
3346
|
});
|
|
@@ -3196,13 +3385,11 @@ ${validTypes.join("、")}`;
|
|
|
3196
3385
|
broadcastMessage = broadcastMessages;
|
|
3197
3386
|
}
|
|
3198
3387
|
} else {
|
|
3199
|
-
const finalSkills = globalSkillUpdates.get(targetBoss.name) || targetBoss.skills.filter((s) => !triggeredSkills.includes(s));
|
|
3200
3388
|
await ctx.database.set(
|
|
3201
3389
|
"ggcevo_boss",
|
|
3202
3390
|
{ name: targetBoss.name },
|
|
3203
3391
|
{
|
|
3204
|
-
HP: Math.max(currentHP, 0)
|
|
3205
|
-
skills: finalSkills
|
|
3392
|
+
HP: Math.max(currentHP, 0)
|
|
3206
3393
|
}
|
|
3207
3394
|
);
|
|
3208
3395
|
}
|
|
@@ -3224,15 +3411,11 @@ ${validTypes.join("、")}`;
|
|
|
3224
3411
|
...effectMessage.length > 0 ? [
|
|
3225
3412
|
`💫 祈愿效果:${effectMessage.join(" | ")}`
|
|
3226
3413
|
] : [],
|
|
3227
|
-
//
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
...healMessages
|
|
3233
|
-
],
|
|
3234
|
-
// 金币奖励显示逻辑优化
|
|
3235
|
-
`获得金币:${targetBoss.skills.includes("冰霜进化") && weaponName === "零度之下" ? 0 : initialDamage}`,
|
|
3414
|
+
// 直接显示伤害数值和附加效果
|
|
3415
|
+
`造成伤害:${initialDamage}${hasCrit ? "(✨ 暴击)" : ""}`,
|
|
3416
|
+
...healMessages,
|
|
3417
|
+
// 简化后的金币奖励显示
|
|
3418
|
+
`获得金币:${initialDamage}`,
|
|
3236
3419
|
`目标剩余HP:${Math.max(currentHP, 0)}/${maxHP}`,
|
|
3237
3420
|
isDefeated ? `🎉 恭喜,您成功击败 ${targetBoss.name}!` : ""
|
|
3238
3421
|
].filter((line) => line).join("\n");
|
|
@@ -3282,33 +3465,36 @@ ${validTypes.join("、")}`;
|
|
|
3282
3465
|
const bossGroup = bossPool.find((group) => group.main.name === mainBoss.name);
|
|
3283
3466
|
if (!bossGroup) return "BOSS配置数据异常,请联系管理员";
|
|
3284
3467
|
const mainBossHpBar = createHpBar(mainBoss.HP, bossGroup.main.maxHP);
|
|
3285
|
-
const mainPassives = mainBoss.skills.map((p) => `${p}:${passiveConfig[p].description}`);
|
|
3286
3468
|
const result = [
|
|
3287
3469
|
`🔴 主宰:${mainBoss.name}`,
|
|
3288
3470
|
`${mainBossHpBar} (${mainBoss.HP}/${bossGroup.main.maxHP})`,
|
|
3289
|
-
`标签:${
|
|
3471
|
+
`标签:${mainBoss.tags?.join("、") || "无"}`,
|
|
3472
|
+
// 从数据库label字段获取
|
|
3290
3473
|
"被动:",
|
|
3291
|
-
...
|
|
3474
|
+
...mainBoss.skills.map((p) => `${p}:${passiveConfig[p]?.description}`) || ["无"]
|
|
3292
3475
|
];
|
|
3293
3476
|
if (minions.length > 0) {
|
|
3294
3477
|
result.push("\n🟠 子代:");
|
|
3295
3478
|
for (const minion of minions) {
|
|
3296
3479
|
const minionConfig = bossGroup.minions.find((m) => m.name === minion.name);
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3480
|
+
const minionHpBar = createHpBar(
|
|
3481
|
+
minion.HP,
|
|
3482
|
+
minionConfig?.maxHP || 1e3
|
|
3483
|
+
// 后备值防止报错
|
|
3484
|
+
);
|
|
3300
3485
|
result.push(
|
|
3301
3486
|
`${minion.name}`,
|
|
3302
|
-
`${minionHpBar} (${minion.HP}/${minionConfig
|
|
3303
|
-
`标签:${
|
|
3487
|
+
`${minionHpBar} (${minion.HP}/${minionConfig?.maxHP || "未知"})`,
|
|
3488
|
+
`标签:${minion.tags?.join("、") || "无"}`,
|
|
3489
|
+
// 从数据库获取
|
|
3304
3490
|
"被动:",
|
|
3305
|
-
...
|
|
3491
|
+
...minion.skills.map((p) => `${p}:${passiveConfig[p]?.description}`) || ["无"]
|
|
3306
3492
|
);
|
|
3307
3493
|
}
|
|
3308
3494
|
}
|
|
3309
3495
|
return result.join("\n");
|
|
3310
3496
|
});
|
|
3311
|
-
ctx.command("ggcevo/初始化主宰 <groupid:number>", "初始化指定主宰组", { authority: 3 }).alias("初始化zz").action(async (
|
|
3497
|
+
ctx.command("ggcevo/初始化主宰 <groupid:number>", "初始化指定主宰组", { authority: 3 }).alias("初始化zz").action(async (_, groupid) => {
|
|
3312
3498
|
if (!groupid) groupid = 1;
|
|
3313
3499
|
const bossConfig = bossPool.find((g) => g.main.id === groupid);
|
|
3314
3500
|
if (!bossConfig) {
|
|
@@ -3319,6 +3505,7 @@ ${validTypes.join("、")}`;
|
|
|
3319
3505
|
name: bossConfig.main.name,
|
|
3320
3506
|
type: "主宰",
|
|
3321
3507
|
HP: bossConfig.main.maxHP,
|
|
3508
|
+
tags: bossConfig.main.tags,
|
|
3322
3509
|
skills: [...bossConfig.main.passive],
|
|
3323
3510
|
groupId: groupid,
|
|
3324
3511
|
isActive: true,
|
|
@@ -3329,6 +3516,7 @@ ${validTypes.join("、")}`;
|
|
|
3329
3516
|
name: minion.name,
|
|
3330
3517
|
type: "子代",
|
|
3331
3518
|
HP: minion.maxHP,
|
|
3519
|
+
tags: bossConfig.main.tags,
|
|
3332
3520
|
skills: [...minion.passive],
|
|
3333
3521
|
groupId: groupid,
|
|
3334
3522
|
isActive: true,
|