koishi-plugin-ggcevo-game 1.3.16 → 1.3.17
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.js +375 -327
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -528,7 +528,7 @@ function apply(ctx, config) {
|
|
|
528
528
|
},
|
|
529
529
|
{
|
|
530
530
|
name: "暴击韵律",
|
|
531
|
-
effect: "
|
|
531
|
+
effect: "攻击暴击率+20%"
|
|
532
532
|
},
|
|
533
533
|
{
|
|
534
534
|
name: "酥手空空",
|
|
@@ -585,7 +585,7 @@ function apply(ctx, config) {
|
|
|
585
585
|
},
|
|
586
586
|
"冷适应": {
|
|
587
587
|
effect: 0,
|
|
588
|
-
description: "受到10
|
|
588
|
+
description: "受到10次寒冷伤害后,自身获得“惧热”标签,并且免疫寒冷伤害"
|
|
589
589
|
},
|
|
590
590
|
"感染空间站": {
|
|
591
591
|
effect: 0,
|
|
@@ -597,11 +597,11 @@ function apply(ctx, config) {
|
|
|
597
597
|
},
|
|
598
598
|
"霉菌滋生": {
|
|
599
599
|
effect: 0,
|
|
600
|
-
description: "
|
|
600
|
+
description: "受到攻击后,若“空间站哨枪塔”存活,则为其回复1%的最大生命值"
|
|
601
601
|
},
|
|
602
602
|
"岗哨机枪": {
|
|
603
603
|
effect: 0,
|
|
604
|
-
description: "
|
|
604
|
+
description: "受到10次攻击后,为存活的异形回复其10%的最大生命值(可重复触发)"
|
|
605
605
|
},
|
|
606
606
|
"结构装甲": {
|
|
607
607
|
effect: 0,
|
|
@@ -609,15 +609,15 @@ function apply(ctx, config) {
|
|
|
609
609
|
},
|
|
610
610
|
"吸血唾液": {
|
|
611
611
|
effect: 0,
|
|
612
|
-
description: "受到攻击将会获得一层“吸血”,每层“吸血”提供5
|
|
612
|
+
description: "受到攻击将会获得一层“吸血”,每层“吸血”提供5%的减伤(至多10层)"
|
|
613
613
|
},
|
|
614
614
|
"进食": {
|
|
615
615
|
effect: 0,
|
|
616
|
-
description: "
|
|
616
|
+
description: "当“吸血”达到10层后,下一次受到攻击将会消耗所有层数回复自身20%的最大生命值"
|
|
617
617
|
},
|
|
618
618
|
"嗜血狂暴": {
|
|
619
619
|
effect: 0,
|
|
620
|
-
description: "血量低于50
|
|
620
|
+
description: "血量低于50%时,每次受到攻击将会额外活到一层“吸血”,并且受到的伤害-20%"
|
|
621
621
|
},
|
|
622
622
|
"吐血": {
|
|
623
623
|
effect: 0,
|
|
@@ -1010,34 +1010,56 @@ function apply(ctx, config) {
|
|
|
1010
1010
|
]
|
|
1011
1011
|
}
|
|
1012
1012
|
];
|
|
1013
|
-
function
|
|
1014
|
-
let
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
if (
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
if (
|
|
1035
|
-
|
|
1036
|
-
|
|
1013
|
+
async function calculateTotalDamage(ctx2, session, equippedWeapon, targetBoss, options) {
|
|
1014
|
+
let effectMessage = [];
|
|
1015
|
+
const finalTags = options?.customTags || targetBoss.tags || [];
|
|
1016
|
+
const [profile] = await ctx2.database.get("sc2arcade_player", { userId: session.userId });
|
|
1017
|
+
const { regionId, realmId, profileId } = profile;
|
|
1018
|
+
const handle = `${regionId}-S2-${realmId}-${profileId}`;
|
|
1019
|
+
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
1020
|
+
const [weaponName, weaponData] = weaponConfigEntry;
|
|
1021
|
+
const baseDamage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
|
|
1022
|
+
let totalAdditive = 0;
|
|
1023
|
+
const tagAdditive = await calculateTagMultiplier(weaponData, finalTags, equippedWeapon);
|
|
1024
|
+
totalAdditive += tagAdditive;
|
|
1025
|
+
const { totalModAdd, hasCrit } = calculateModifiers(
|
|
1026
|
+
equippedWeapon,
|
|
1027
|
+
weaponName,
|
|
1028
|
+
await checkCritRhythm(ctx2, handle)
|
|
1029
|
+
);
|
|
1030
|
+
totalAdditive += totalModAdd;
|
|
1031
|
+
if (hasCrit) effectMessage.push("✨ 触发暴击!");
|
|
1032
|
+
const careerBonus = await calculateCareerAdditive(ctx2, handle, weaponData.type, weaponData.id);
|
|
1033
|
+
totalAdditive += careerBonus.value;
|
|
1034
|
+
if (careerBonus.message) effectMessage.push(careerBonus.message);
|
|
1035
|
+
const wishAdditive = await calculateWishAdditive(ctx2, handle, equippedWeapon);
|
|
1036
|
+
totalAdditive += wishAdditive.value;
|
|
1037
|
+
if (wishAdditive.message) effectMessage.push(wishAdditive.message);
|
|
1038
|
+
const [rankRecord] = await ctx2.database.get("ggcevo_rank", { handle, rankseason: config.rankseason });
|
|
1039
|
+
totalAdditive += calculateRankAdditive(rankRecord);
|
|
1040
|
+
let finalDamage = baseDamage * (1 + totalAdditive);
|
|
1041
|
+
const minDamage = baseDamage * 0.01;
|
|
1042
|
+
if (finalDamage < minDamage) {
|
|
1043
|
+
finalDamage = minDamage;
|
|
1044
|
+
effectMessage.push("⚠️ 触发保底机制:造成基础伤害的1%");
|
|
1037
1045
|
}
|
|
1038
|
-
return {
|
|
1046
|
+
return {
|
|
1047
|
+
damage: Math.round(finalDamage),
|
|
1048
|
+
hasCrit,
|
|
1049
|
+
effectMessage
|
|
1050
|
+
};
|
|
1039
1051
|
}
|
|
1040
|
-
__name(
|
|
1052
|
+
__name(calculateTotalDamage, "calculateTotalDamage");
|
|
1053
|
+
async function checkCritRhythm(ctx2, handle) {
|
|
1054
|
+
const [record] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1055
|
+
handle,
|
|
1056
|
+
wishname: "暴击韵律",
|
|
1057
|
+
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1058
|
+
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1059
|
+
});
|
|
1060
|
+
return !!record;
|
|
1061
|
+
}
|
|
1062
|
+
__name(checkCritRhythm, "checkCritRhythm");
|
|
1041
1063
|
async function calculateTagMultiplier(weaponData, tags, equippedWeapon) {
|
|
1042
1064
|
const MOD_EFFECTS = [
|
|
1043
1065
|
{ mod: "裂甲核心", tag: "重甲", value: 1.2 },
|
|
@@ -1054,135 +1076,118 @@ function apply(ctx, config) {
|
|
|
1054
1076
|
return totalAdditive;
|
|
1055
1077
|
}
|
|
1056
1078
|
__name(calculateTagMultiplier, "calculateTagMultiplier");
|
|
1057
|
-
function
|
|
1058
|
-
let
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1079
|
+
function calculateModifiers(equippedWeapon, weaponName, hasCritRhythm) {
|
|
1080
|
+
let totalModAdd = 0;
|
|
1081
|
+
let hasCrit = false;
|
|
1082
|
+
let crystalCrit = 0;
|
|
1083
|
+
let overloadCrit = 0;
|
|
1084
|
+
let rhythmCrit = 0;
|
|
1085
|
+
equippedWeapon.installedMods.forEach((mod) => {
|
|
1086
|
+
if (mod === "动能增幅") {
|
|
1087
|
+
totalModAdd += 0.2;
|
|
1088
|
+
}
|
|
1089
|
+
if (mod === "裂甲核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
1090
|
+
totalModAdd += 0.4;
|
|
1091
|
+
}
|
|
1092
|
+
if (mod === "棱镜水晶") {
|
|
1093
|
+
crystalCrit = 20;
|
|
1094
|
+
}
|
|
1095
|
+
if (mod === "棱镜超载核心" && weaponName === modConfig[mod].exclusiveTo) {
|
|
1096
|
+
overloadCrit = 80;
|
|
1097
|
+
}
|
|
1062
1098
|
});
|
|
1063
|
-
|
|
1099
|
+
rhythmCrit = hasCritRhythm ? 20 : 0;
|
|
1100
|
+
const totalCritRate = Math.min(
|
|
1101
|
+
crystalCrit + overloadCrit + rhythmCrit,
|
|
1102
|
+
100
|
|
1103
|
+
);
|
|
1104
|
+
if (totalCritRate > 0) {
|
|
1105
|
+
const roll = Math.random() * 100;
|
|
1106
|
+
if (roll <= totalCritRate) {
|
|
1107
|
+
hasCrit = true;
|
|
1108
|
+
totalModAdd += 1;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return { totalModAdd, hasCrit };
|
|
1064
1112
|
}
|
|
1065
|
-
__name(
|
|
1066
|
-
async function
|
|
1113
|
+
__name(calculateModifiers, "calculateModifiers");
|
|
1114
|
+
async function calculateCareerAdditive(ctx2, handle, weaponType, weaponId) {
|
|
1067
1115
|
const [careerData] = await ctx2.database.get("ggcevo_careers", { handle });
|
|
1068
|
-
|
|
1069
|
-
const faction = careerData?.group;
|
|
1116
|
+
let value = 0;
|
|
1070
1117
|
let message = "";
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
multiplier = 1.05;
|
|
1118
|
+
if (careerData?.career === "警卫长") {
|
|
1119
|
+
value += 0.05;
|
|
1074
1120
|
message = "⚔️ 职业加成:警卫长(攻击伤害+5%)";
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1121
|
+
}
|
|
1122
|
+
if (careerData?.career === "武器中士") {
|
|
1123
|
+
value += 0.15;
|
|
1077
1124
|
message = "⚔️ 职业加成:武器中士(攻击伤害+15%)";
|
|
1078
1125
|
}
|
|
1079
|
-
if (
|
|
1126
|
+
if (careerData?.career === "能量武器专家") {
|
|
1080
1127
|
if (weaponType === "能量武器") {
|
|
1081
|
-
|
|
1082
|
-
message = "
|
|
1083
|
-
} else {
|
|
1084
|
-
message = "⚠️ 能量武器专家:未装备能量武器,加成未生效";
|
|
1128
|
+
value += 0.2;
|
|
1129
|
+
message = "⚔️ 职业加成:能量武器专家(能量武器伤害+20%)";
|
|
1085
1130
|
}
|
|
1086
1131
|
}
|
|
1087
|
-
if (
|
|
1132
|
+
if (careerData?.career === "纵火狂") {
|
|
1088
1133
|
if (weaponType === "热能武器") {
|
|
1089
|
-
|
|
1090
|
-
message = "
|
|
1091
|
-
} else {
|
|
1092
|
-
message = "⚠️ 纵火狂:未装备热能武器,加成未生效";
|
|
1134
|
+
value += 0.2;
|
|
1135
|
+
message = "⚔️ 职业加成:纵火狂(热能武器伤害+20%)";
|
|
1093
1136
|
}
|
|
1094
1137
|
}
|
|
1095
|
-
if (
|
|
1138
|
+
if (careerData?.career === "猩红杀手") {
|
|
1096
1139
|
if (weaponId === 7) {
|
|
1097
|
-
|
|
1098
|
-
message = "
|
|
1099
|
-
} else {
|
|
1100
|
-
message = "⚠️ 猩红杀手:未装备侦查步枪,加成未生效";
|
|
1140
|
+
value += 0.15;
|
|
1141
|
+
message = "⚔️ 职业加成:猩红杀手(侦查步枪伤害+15%)";
|
|
1101
1142
|
}
|
|
1102
1143
|
}
|
|
1103
|
-
return {
|
|
1104
|
-
damage: currentDamage * multiplier,
|
|
1105
|
-
message: message || void 0
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
|
-
__name(calculateCareerBonus, "calculateCareerBonus");
|
|
1109
|
-
function calculateRankBonus(rankRecord) {
|
|
1110
|
-
if (!rankRecord || rankRecord.rank <= 0) return 0;
|
|
1111
|
-
return Math.floor(rankRecord.rank / 400) * 0.01;
|
|
1144
|
+
return { value, message };
|
|
1112
1145
|
}
|
|
1113
|
-
__name(
|
|
1114
|
-
async function
|
|
1115
|
-
let
|
|
1116
|
-
const
|
|
1117
|
-
const
|
|
1118
|
-
const [profile] = await ctx2.database.get("sc2arcade_player", { userId: session.userId });
|
|
1119
|
-
const { regionId, realmId, profileId } = profile;
|
|
1120
|
-
const handle = `${regionId}-S2-${realmId}-${profileId}`;
|
|
1121
|
-
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
1122
|
-
const [weaponName, weaponData] = weaponConfigEntry;
|
|
1123
|
-
const weaponType = weaponData.type;
|
|
1124
|
-
const weaponId = weaponData.id;
|
|
1125
|
-
let damage = weaponData.damage * (1 + 0.1 * equippedWeapon.level);
|
|
1126
|
-
const [critRhythmEffect] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1146
|
+
__name(calculateCareerAdditive, "calculateCareerAdditive");
|
|
1147
|
+
async function calculateWishAdditive(ctx2, handle, weapon) {
|
|
1148
|
+
let value = 0;
|
|
1149
|
+
const messages = [];
|
|
1150
|
+
const [sovereign] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1127
1151
|
handle,
|
|
1128
|
-
wishname: "
|
|
1152
|
+
wishname: "王权增幅",
|
|
1129
1153
|
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1130
1154
|
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1131
1155
|
});
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
damage *= 1 + totalModAdd;
|
|
1138
|
-
if (critRhythmEffect) {
|
|
1139
|
-
effectMessage.push("🎵 暴击韵律祈愿生效(武器暴击率+20%)");
|
|
1140
|
-
}
|
|
1141
|
-
const tagMultiplier = await calculateTagMultiplier(weaponData, finalTags, equippedWeapon);
|
|
1142
|
-
damage *= 1 + tagMultiplier;
|
|
1143
|
-
const passiveMultiplier = calculatePassiveEffects(finalPassives);
|
|
1144
|
-
damage *= 1 + passiveMultiplier;
|
|
1145
|
-
const { damage: careerDamage, message: careerMessage } = await calculateCareerBonus(
|
|
1146
|
-
ctx2,
|
|
1147
|
-
handle,
|
|
1148
|
-
damage,
|
|
1149
|
-
weaponType,
|
|
1150
|
-
// 新增参数
|
|
1151
|
-
weaponId
|
|
1152
|
-
);
|
|
1153
|
-
damage = careerDamage;
|
|
1154
|
-
if (careerMessage) effectMessage.push(careerMessage);
|
|
1155
|
-
const [sovereignEffect] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1156
|
+
if (sovereign) {
|
|
1157
|
+
value += 0.05;
|
|
1158
|
+
messages.push("👑 王权增幅(攻击伤害+5%)");
|
|
1159
|
+
}
|
|
1160
|
+
const [lament] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1156
1161
|
handle,
|
|
1157
|
-
wishname: "
|
|
1162
|
+
wishname: "悲鸣之锋",
|
|
1158
1163
|
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1159
1164
|
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1160
1165
|
});
|
|
1161
|
-
|
|
1166
|
+
if (lament) {
|
|
1167
|
+
const levelBonus = 0.1 * (weapon.level + 1);
|
|
1168
|
+
value += levelBonus;
|
|
1169
|
+
messages.push(`🗡️ 悲鸣之锋(攻击伤害+${Math.round(levelBonus * 100)}%)`);
|
|
1170
|
+
}
|
|
1171
|
+
const [critRhythm] = await ctx2.database.get("ggcevo_Wish_Record", {
|
|
1162
1172
|
handle,
|
|
1163
|
-
wishname: "
|
|
1173
|
+
wishname: "暴击韵律",
|
|
1164
1174
|
startTime: { $lte: /* @__PURE__ */ new Date() },
|
|
1165
1175
|
endTime: { $gte: /* @__PURE__ */ new Date() }
|
|
1166
1176
|
});
|
|
1167
|
-
if (
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1171
|
-
if (lamentEffect) {
|
|
1172
|
-
const levelBonus = 0.1 * (equippedWeapon.level + 1);
|
|
1173
|
-
damage *= 1 + levelBonus;
|
|
1174
|
-
effectMessage.push(`🗡️ 悲鸣之锋祈愿生效(基于武器等级,攻击伤害+${(levelBonus * 100).toFixed(0)}%)`);
|
|
1175
|
-
}
|
|
1176
|
-
const [rankRecord] = await ctx2.database.get("ggcevo_rank", { handle: session.handle, rankseason: config.rankseason });
|
|
1177
|
-
const rankBonus = calculateRankBonus(rankRecord);
|
|
1178
|
-
damage *= 1 + rankBonus;
|
|
1177
|
+
if (critRhythm) {
|
|
1178
|
+
messages.push("🎵 暴击韵律(攻击暴击率+20%)");
|
|
1179
|
+
}
|
|
1179
1180
|
return {
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
effectMessage
|
|
1181
|
+
value,
|
|
1182
|
+
message: messages.join(",")
|
|
1183
1183
|
};
|
|
1184
1184
|
}
|
|
1185
|
-
__name(
|
|
1185
|
+
__name(calculateWishAdditive, "calculateWishAdditive");
|
|
1186
|
+
function calculateRankAdditive(rankRecord) {
|
|
1187
|
+
if (!rankRecord || rankRecord.rank <= 0) return 0;
|
|
1188
|
+
return Math.floor(rankRecord.rank / 400) * 0.01;
|
|
1189
|
+
}
|
|
1190
|
+
__name(calculateRankAdditive, "calculateRankAdditive");
|
|
1186
1191
|
const initDefaultItems = {
|
|
1187
1192
|
"咕咕币": { id: 1, type: "抽奖道具", description: "用于进行抽奖" },
|
|
1188
1193
|
"兑换券": { id: 2, type: "兑换货币", description: "用于兑换赞助物品" },
|
|
@@ -1361,20 +1366,21 @@ function apply(ctx, config) {
|
|
|
1361
1366
|
}, 60 * 1e3);
|
|
1362
1367
|
const PassiveHandler = {
|
|
1363
1368
|
// 冰霜进化处理(免疫冰霜伤害)
|
|
1364
|
-
handleFrostEvolution: /* @__PURE__ */ __name(function(targetBoss, weaponName,
|
|
1369
|
+
handleFrostEvolution: /* @__PURE__ */ __name(function(targetBoss, weaponName, damage, maxHP) {
|
|
1365
1370
|
if (targetBoss.skills.includes("冰霜进化") && weaponName === "零度之下") {
|
|
1366
|
-
const healAmount =
|
|
1371
|
+
const healAmount = damage;
|
|
1367
1372
|
return {
|
|
1368
1373
|
updatedHP: Math.min(targetBoss.HP + healAmount, maxHP),
|
|
1369
1374
|
initialDamage: 0,
|
|
1370
|
-
|
|
1375
|
+
// 直接设置伤害为0
|
|
1376
|
+
messages: [`❄️ 【冰霜进化】生效:免疫冰霜伤害,${targetBoss.name}回复 ${healAmount} 生命值`]
|
|
1371
1377
|
};
|
|
1372
1378
|
}
|
|
1373
1379
|
return null;
|
|
1374
1380
|
}, "handleFrostEvolution"),
|
|
1375
1381
|
// 冰霜环绕处理(主宰专用)
|
|
1376
|
-
handleFrostSurround: /* @__PURE__ */ __name(async (ctx2, targetBoss, currentHP, maxHP
|
|
1377
|
-
if (
|
|
1382
|
+
handleFrostSurround: /* @__PURE__ */ __name(async (ctx2, targetBoss, currentHP, maxHP) => {
|
|
1383
|
+
if (!targetBoss.skills.includes("冰霜环绕") || currentHP <= 0 || // 新增血量必须大于0的判断
|
|
1378
1384
|
currentHP / maxHP > 0.3) {
|
|
1379
1385
|
return null;
|
|
1380
1386
|
}
|
|
@@ -1400,14 +1406,14 @@ function apply(ctx, config) {
|
|
|
1400
1406
|
updatedHP,
|
|
1401
1407
|
skillUpdates,
|
|
1402
1408
|
messages: [
|
|
1403
|
-
`❄️
|
|
1404
|
-
`🌪️
|
|
1409
|
+
`❄️ 【冰霜环绕】生效,${targetBoss.name}回复45%最大生命值(+${healAmount}HP)`,
|
|
1410
|
+
`🌪️ 警告!【寒霜地狱】降临,所有存活的异形获得30%减伤效果`
|
|
1405
1411
|
]
|
|
1406
1412
|
};
|
|
1407
1413
|
}, "handleFrostSurround"),
|
|
1408
1414
|
// 冰霜回复处理(子代专用)
|
|
1409
1415
|
handleFrostRecovery: /* @__PURE__ */ __name(async (ctx2, targetBoss, currentHP, maxHP, activeBosses, bossGroup) => {
|
|
1410
|
-
if (
|
|
1416
|
+
if (!targetBoss.skills.includes("冰霜回复") || currentHP <= 0 || // 新增血量必须大于0的判断
|
|
1411
1417
|
currentHP / maxHP > 0.3) {
|
|
1412
1418
|
return null;
|
|
1413
1419
|
}
|
|
@@ -1433,7 +1439,7 @@ function apply(ctx, config) {
|
|
|
1433
1439
|
remove: ["冰霜回复"]
|
|
1434
1440
|
}],
|
|
1435
1441
|
messages: [
|
|
1436
|
-
`❄️
|
|
1442
|
+
`❄️ 【冰霜回复】生效,${targetBoss.name}回复40%最大生命值(+${selfHeal}HP),${mainBoss.name}回复10%最大生命值(+${mainHeal}HP)`
|
|
1437
1443
|
]
|
|
1438
1444
|
};
|
|
1439
1445
|
}, "handleFrostRecovery"),
|
|
@@ -1452,24 +1458,25 @@ function apply(ctx, config) {
|
|
|
1452
1458
|
tags: newtags
|
|
1453
1459
|
});
|
|
1454
1460
|
return {
|
|
1455
|
-
messages: [`❄️
|
|
1461
|
+
messages: [`❄️ 【冷适应】生效,${targetBoss.name}获得「惧热」标签`]
|
|
1456
1462
|
};
|
|
1457
1463
|
}
|
|
1458
1464
|
return null;
|
|
1459
1465
|
}, "handleColdAdaptation"),
|
|
1460
|
-
//
|
|
1466
|
+
// 冷适应免疫处理
|
|
1461
1467
|
handleColdAdaptationImmunity: /* @__PURE__ */ __name(function(targetBoss, weaponName) {
|
|
1462
|
-
if (targetBoss.
|
|
1468
|
+
if (targetBoss.skills.includes("冷适应") && targetBoss.Skillcountpoints >= 10 && weaponName === "零度之下") {
|
|
1463
1469
|
return {
|
|
1464
1470
|
initialDamage: 0,
|
|
1465
|
-
|
|
1471
|
+
// 直接设置伤害为0
|
|
1472
|
+
messages: [`❄️ 【冷适应】生效:免疫寒冷伤害`]
|
|
1466
1473
|
};
|
|
1467
1474
|
}
|
|
1468
1475
|
return null;
|
|
1469
1476
|
}, "handleColdAdaptationImmunity"),
|
|
1470
1477
|
// 求生本能处理
|
|
1471
1478
|
handleSurvivalInstinct: /* @__PURE__ */ __name(function(targetBoss, currentHP, maxHP) {
|
|
1472
|
-
if (currentHP >
|
|
1479
|
+
if (currentHP > 0) return null;
|
|
1473
1480
|
let effect = null;
|
|
1474
1481
|
if (targetBoss.skills.includes("求生本能I")) {
|
|
1475
1482
|
effect = { heal: maxHP * 0.3, skill: "求生本能I" };
|
|
@@ -1479,28 +1486,21 @@ function apply(ctx, config) {
|
|
|
1479
1486
|
if (!effect) return null;
|
|
1480
1487
|
return {
|
|
1481
1488
|
updatedHP: effect.heal,
|
|
1482
|
-
messages: [
|
|
1489
|
+
messages: [`【${effect.skill}】生效,${targetBoss.name}瞬间回复${effect.heal}生命值!`],
|
|
1483
1490
|
skillUpdates: [{
|
|
1484
1491
|
name: targetBoss.name,
|
|
1485
1492
|
remove: [effect.skill]
|
|
1486
1493
|
}]
|
|
1487
1494
|
};
|
|
1488
1495
|
}, "handleSurvivalInstinct"),
|
|
1489
|
-
//
|
|
1490
|
-
handleInfectedStation: /* @__PURE__ */ __name(async (ctx2, targetBoss
|
|
1491
|
-
if (targetBoss.name !== "空间站感染虫" || !targetBoss.skills.includes("感染空间站"))
|
|
1492
|
-
|
|
1493
|
-
}
|
|
1494
|
-
const sentryConfig = bossGroup.minions.find((m) => m.name === "空间站哨枪塔");
|
|
1495
|
-
if (!sentryConfig) return null;
|
|
1496
|
-
const [sentryGun] = await ctx2.database.get("ggcevo_boss", {
|
|
1497
|
-
name: "空间站哨枪塔",
|
|
1498
|
-
isActive: true
|
|
1499
|
-
});
|
|
1496
|
+
// 感染空间站处理(返回减伤系数)
|
|
1497
|
+
handleInfectedStation: /* @__PURE__ */ __name(async (ctx2, targetBoss) => {
|
|
1498
|
+
if (targetBoss.name !== "空间站感染虫" || !targetBoss.skills.includes("感染空间站")) return null;
|
|
1499
|
+
const [sentryGun] = await ctx2.database.get("ggcevo_boss", { name: "空间站哨枪塔", isActive: true });
|
|
1500
1500
|
if (sentryGun) {
|
|
1501
|
-
const newDamage = Math.floor(initialDamage * 0.5);
|
|
1502
1501
|
return {
|
|
1503
|
-
|
|
1502
|
+
damageMultiplier: -0.5,
|
|
1503
|
+
// 50% 减伤
|
|
1504
1504
|
messages: ["🛡️ 【感染空间站】生效:空间站哨枪塔存活,受到的伤害减少50%"]
|
|
1505
1505
|
};
|
|
1506
1506
|
}
|
|
@@ -1533,23 +1533,18 @@ function apply(ctx, config) {
|
|
|
1533
1533
|
}, "handleMoldGrowth"),
|
|
1534
1534
|
// 岗哨机枪处理
|
|
1535
1535
|
handleSentryGun: /* @__PURE__ */ __name(async (ctx2, targetBoss, bossGroup) => {
|
|
1536
|
-
if (
|
|
1536
|
+
if (!targetBoss.skills.includes("岗哨机枪")) {
|
|
1537
1537
|
return null;
|
|
1538
1538
|
}
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
{ Skillcountpoints: newCount }
|
|
1544
|
-
);
|
|
1545
|
-
if (newCount >= 10) {
|
|
1539
|
+
const currentCount = targetBoss.Skillcountpoints || 0;
|
|
1540
|
+
const updates = [];
|
|
1541
|
+
let messages = [];
|
|
1542
|
+
if (currentCount === 10) {
|
|
1546
1543
|
const getMaxHP = /* @__PURE__ */ __name((name2) => {
|
|
1547
1544
|
if (name2 === "空间站感染虫") return bossGroup.main.maxHP;
|
|
1548
1545
|
const minion = bossGroup.minions.find((m) => m.name === name2);
|
|
1549
1546
|
return minion?.maxHP || 0;
|
|
1550
1547
|
}, "getMaxHP");
|
|
1551
|
-
const updates = [];
|
|
1552
|
-
const messages = [];
|
|
1553
1548
|
const [infectionBug] = await ctx2.database.get("ggcevo_boss", {
|
|
1554
1549
|
name: "空间站感染虫",
|
|
1555
1550
|
isActive: true
|
|
@@ -1564,7 +1559,7 @@ function apply(ctx, config) {
|
|
|
1564
1559
|
{ HP: Math.min(infectionBug.HP + heal, maxHP) }
|
|
1565
1560
|
)
|
|
1566
1561
|
);
|
|
1567
|
-
messages.push(
|
|
1562
|
+
messages.push(`空间站感染虫回复${heal}HP`);
|
|
1568
1563
|
}
|
|
1569
1564
|
const [mechaBug] = await ctx2.database.get("ggcevo_boss", {
|
|
1570
1565
|
name: "机械感染虫",
|
|
@@ -1591,150 +1586,193 @@ function apply(ctx, config) {
|
|
|
1591
1586
|
);
|
|
1592
1587
|
await Promise.all(updates);
|
|
1593
1588
|
return {
|
|
1594
|
-
messages: ["🔫
|
|
1589
|
+
messages: ["🔫 【岗哨机枪】生效:" + messages.join(",")]
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
const newCount = currentCount + 1;
|
|
1593
|
+
await ctx2.database.set(
|
|
1594
|
+
"ggcevo_boss",
|
|
1595
|
+
{ name: targetBoss.name },
|
|
1596
|
+
{ Skillcountpoints: newCount }
|
|
1597
|
+
);
|
|
1598
|
+
if (newCount === 10) {
|
|
1599
|
+
return {
|
|
1600
|
+
messages: ["🔫 【岗哨机枪】达到10层!下次攻击将清空层数并治疗所有存活的异形"]
|
|
1595
1601
|
};
|
|
1596
1602
|
}
|
|
1597
1603
|
return null;
|
|
1598
1604
|
}, "handleSentryGun"),
|
|
1599
|
-
//
|
|
1600
|
-
handleStructuralArmor: /* @__PURE__ */ __name((targetBoss,
|
|
1601
|
-
if (
|
|
1602
|
-
return null;
|
|
1603
|
-
}
|
|
1605
|
+
// 结构装甲处理(返回减伤系数)
|
|
1606
|
+
handleStructuralArmor: /* @__PURE__ */ __name((targetBoss, weaponData) => {
|
|
1607
|
+
if (!targetBoss.skills.includes("结构装甲")) return null;
|
|
1604
1608
|
let reduction = 0.2;
|
|
1605
1609
|
let msg = "常规武器减伤20%";
|
|
1606
1610
|
if (weaponData.type === "热能武器") {
|
|
1607
1611
|
reduction = 0.4;
|
|
1608
1612
|
msg = "热能武器减伤40%";
|
|
1609
1613
|
}
|
|
1610
|
-
const newDamage = Math.floor(initialDamage * (1 - reduction));
|
|
1611
1614
|
return {
|
|
1612
|
-
|
|
1615
|
+
damageMultiplier: -reduction,
|
|
1616
|
+
// 返回减伤系数
|
|
1613
1617
|
messages: [`🛡️ 【结构装甲】生效:${msg}`]
|
|
1614
1618
|
};
|
|
1615
1619
|
}, "handleStructuralArmor"),
|
|
1616
|
-
//
|
|
1617
|
-
handleBloodEffects: /* @__PURE__ */ __name(function(targetBoss,
|
|
1618
|
-
if (!targetBoss.skills.includes("吸血唾液"))
|
|
1619
|
-
return null;
|
|
1620
|
-
}
|
|
1621
|
-
let messages = [];
|
|
1622
|
-
let newDamage = initialDamage;
|
|
1620
|
+
// 吸血效果处理(返回综合系数)
|
|
1621
|
+
handleBloodEffects: /* @__PURE__ */ __name(function(targetBoss, currentHP, maxHP) {
|
|
1622
|
+
if (!targetBoss.skills.includes("吸血唾液") || !targetBoss.skills.includes("嗜血狂暴") || !targetBoss.skills.includes("吐血")) return null;
|
|
1623
1623
|
const bloodStacks = targetBoss.Skillcountpoints || 0;
|
|
1624
|
-
let
|
|
1624
|
+
let damageMultiplier = 0;
|
|
1625
|
+
const messages = [];
|
|
1625
1626
|
if (targetBoss.skills.includes("吸血唾液")) {
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
}
|
|
1627
|
+
const reduction = bloodStacks * 0.05;
|
|
1628
|
+
damageMultiplier -= reduction;
|
|
1629
|
+
messages.push(`🩸 【吸血唾液】生效:受到的伤害-${bloodStacks * 5}%`);
|
|
1630
1630
|
}
|
|
1631
1631
|
if (targetBoss.skills.includes("嗜血狂暴") && currentHP / maxHP < 0.5) {
|
|
1632
|
-
|
|
1633
|
-
messages.push(`🔥
|
|
1634
|
-
}
|
|
1635
|
-
if (totalReduction > 0) {
|
|
1636
|
-
newDamage = Math.floor(initialDamage * (1 - totalReduction));
|
|
1632
|
+
damageMultiplier -= 0.2;
|
|
1633
|
+
messages.push(`🔥 【嗜血狂暴】生效:血量低于50%,进入狂暴状态,受到的伤害-20%`);
|
|
1637
1634
|
}
|
|
1638
1635
|
if (targetBoss.skills.includes("吐血") && bloodStacks < 1) {
|
|
1639
|
-
|
|
1640
|
-
messages.push(`💔
|
|
1636
|
+
damageMultiplier += 0.1;
|
|
1637
|
+
messages.push(`💔 【吐血】生效:无“吸血”层数,受到的伤害+10%`);
|
|
1641
1638
|
}
|
|
1642
|
-
return
|
|
1639
|
+
return { damageMultiplier, messages };
|
|
1643
1640
|
}, "handleBloodEffects"),
|
|
1644
1641
|
handleBloodCount: /* @__PURE__ */ __name(async function(ctx2, targetBoss, currentHP, maxHP) {
|
|
1645
|
-
if (!targetBoss.skills.includes("吸血唾液")) {
|
|
1642
|
+
if (!targetBoss.skills.includes("吸血唾液") || !targetBoss.skills.includes("进食") || !targetBoss.skills.includes("嗜血狂暴")) {
|
|
1646
1643
|
return null;
|
|
1647
1644
|
}
|
|
1648
1645
|
let messages = [];
|
|
1649
1646
|
let updatedHP = currentHP;
|
|
1647
|
+
let newStacks;
|
|
1650
1648
|
const oldStacks = targetBoss.Skillcountpoints || 0;
|
|
1651
1649
|
if (oldStacks >= 10 && targetBoss.skills.includes("进食")) {
|
|
1652
1650
|
const heal = Math.floor(maxHP * 0.2);
|
|
1653
1651
|
updatedHP = Math.min(currentHP + heal, maxHP);
|
|
1654
1652
|
await ctx2.database.set("ggcevo_boss", { name: targetBoss.name }, { Skillcountpoints: 0 });
|
|
1655
|
-
messages.push(`🍽️
|
|
1653
|
+
messages.push(`🍽️ 【进食】生效:${targetBoss.name}回复20%最大生命值(+${heal}HP),“吸血”层数清零`);
|
|
1656
1654
|
return { updatedHP, messages };
|
|
1657
1655
|
}
|
|
1658
|
-
|
|
1656
|
+
if (targetBoss.skills.includes("吸血唾液")) {
|
|
1657
|
+
newStacks = oldStacks + 1;
|
|
1658
|
+
messages.push(`🩸 【吸血唾液】生效:获得1层“吸血”`);
|
|
1659
|
+
}
|
|
1659
1660
|
if (targetBoss.skills.includes("嗜血狂暴") && currentHP / maxHP < 0.5) {
|
|
1660
1661
|
newStacks += 1;
|
|
1661
|
-
messages.push(`🔥
|
|
1662
|
+
messages.push(`🔥 【嗜血狂暴】生效:额外获得1层“吸血”`);
|
|
1662
1663
|
}
|
|
1663
1664
|
newStacks = Math.min(newStacks, 10);
|
|
1664
1665
|
if (oldStacks < 10 && newStacks >= 10) {
|
|
1665
|
-
messages.push(`🩸
|
|
1666
|
+
messages.push(`🩸 “吸血”层数达到${newStacks},下次受到攻击将触发【进食】`);
|
|
1666
1667
|
}
|
|
1667
1668
|
await ctx2.database.set("ggcevo_boss", { name: targetBoss.name }, { Skillcountpoints: newStacks });
|
|
1668
1669
|
return { updatedHP, messages };
|
|
1669
1670
|
}, "handleBloodCount"),
|
|
1670
|
-
//
|
|
1671
|
-
handleGammaRadiation: /* @__PURE__ */ __name(async (ctx2, targetBoss,
|
|
1672
|
-
if (
|
|
1671
|
+
// 修改后的伽马枪辐射处理
|
|
1672
|
+
handleGammaRadiation: /* @__PURE__ */ __name(async (ctx2, targetBoss, weaponData) => {
|
|
1673
|
+
if (weaponData.name !== "伽马枪" || targetBoss.tags.includes("机械") || !targetBoss.tags.includes("生物")) {
|
|
1674
|
+
return null;
|
|
1675
|
+
}
|
|
1673
1676
|
const messages = [];
|
|
1674
|
-
const
|
|
1675
|
-
const
|
|
1676
|
-
const
|
|
1677
|
+
const hasRadiation = targetBoss.skills.includes("辐射");
|
|
1678
|
+
const currentLayers = targetBoss.Vulnerability || 0;
|
|
1679
|
+
const newSkills = hasRadiation ? targetBoss.skills : [...targetBoss.skills, "辐射"];
|
|
1680
|
+
const newLayers = hasRadiation ? Math.min(currentLayers + 1, 100) : 1;
|
|
1677
1681
|
let layerMsg;
|
|
1678
|
-
|
|
1679
|
-
|
|
1682
|
+
0;
|
|
1683
|
+
if (!hasRadiation) {
|
|
1684
|
+
layerMsg = `☢️ ${targetBoss.name} 获得【辐射】效果`;
|
|
1685
|
+
} else if (newLayers === currentLayers) {
|
|
1686
|
+
layerMsg = `☢️ 辐射层数已达上限(100层)`;
|
|
1680
1687
|
} else {
|
|
1681
|
-
|
|
1682
|
-
layerMsg = `☢️ 辐射层数已达上限(100层)`;
|
|
1683
|
-
} else {
|
|
1684
|
-
const addedLayers = newVulnerability - targetBoss.Vulnerability;
|
|
1685
|
-
layerMsg = `☢️ 辐射层数+${addedLayers}`;
|
|
1686
|
-
}
|
|
1688
|
+
layerMsg = `☢️ 辐射层数叠加至${newLayers}`;
|
|
1687
1689
|
}
|
|
1688
|
-
await ctx2.database.set(
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1690
|
+
await ctx2.database.set(
|
|
1691
|
+
"ggcevo_boss",
|
|
1692
|
+
{ name: targetBoss.name },
|
|
1693
|
+
{
|
|
1694
|
+
skills: Array.from(new Set(newSkills)),
|
|
1695
|
+
// 显式类型断言
|
|
1696
|
+
Vulnerability: newLayers
|
|
1697
|
+
}
|
|
1698
|
+
);
|
|
1699
|
+
messages.push(layerMsg);
|
|
1693
1700
|
return { messages };
|
|
1694
1701
|
}, "handleGammaRadiation"),
|
|
1695
|
-
//
|
|
1696
|
-
calculateRadiationDamage: /* @__PURE__ */ __name((targetBoss
|
|
1697
|
-
if (!targetBoss.skills.includes("辐射"))
|
|
1698
|
-
return {
|
|
1699
|
-
damage: baseDamage,
|
|
1700
|
-
messages: []
|
|
1701
|
-
};
|
|
1702
|
-
}
|
|
1702
|
+
// 伽马枪辐射计算(返回增伤系数)
|
|
1703
|
+
calculateRadiationDamage: /* @__PURE__ */ __name((targetBoss) => {
|
|
1704
|
+
if (!targetBoss.skills.includes("辐射")) return null;
|
|
1703
1705
|
const radiationLayers = targetBoss.Vulnerability || 0;
|
|
1704
|
-
const damageMultiplier = 1 + radiationLayers * 0.01;
|
|
1705
|
-
const amplifiedDamage = Math.floor(baseDamage * damageMultiplier);
|
|
1706
1706
|
return {
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
] : []
|
|
1707
|
+
damageMultiplier: radiationLayers * 0.01,
|
|
1708
|
+
// 每层1%增伤
|
|
1709
|
+
messages: radiationLayers > 0 ? [`☢️ 【辐射】生效:当前${radiationLayers}层辐射,受到的伤害+${radiationLayers}%`] : []
|
|
1711
1710
|
};
|
|
1712
1711
|
}, "calculateRadiationDamage"),
|
|
1713
|
-
//
|
|
1714
|
-
handlePassives: /* @__PURE__ */ __name(async function(ctx2, targetBoss, initialDamage, currentHP, maxHP, weaponName, weaponData,
|
|
1712
|
+
// 统一处理被动技能
|
|
1713
|
+
handlePassives: /* @__PURE__ */ __name(async function(ctx2, targetBoss, initialDamage, currentHP, maxHP, weaponName, weaponData, activeBosses, bossGroup) {
|
|
1715
1714
|
let messages = [];
|
|
1716
1715
|
let skillUpdates = [];
|
|
1716
|
+
let totalMultiplier = 0;
|
|
1717
|
+
const frostEvoResult = this.handleFrostEvolution(targetBoss, weaponName, initialDamage, maxHP);
|
|
1718
|
+
if (frostEvoResult) {
|
|
1719
|
+
return {
|
|
1720
|
+
currentHP: frostEvoResult.updatedHP,
|
|
1721
|
+
messages: frostEvoResult.messages,
|
|
1722
|
+
skillUpdates,
|
|
1723
|
+
initialDamage: 0
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
const coldImmunityResult = this.handleColdAdaptationImmunity(targetBoss, weaponName);
|
|
1727
|
+
if (coldImmunityResult) {
|
|
1728
|
+
return {
|
|
1729
|
+
currentHP,
|
|
1730
|
+
messages: coldImmunityResult.messages,
|
|
1731
|
+
skillUpdates,
|
|
1732
|
+
initialDamage: 0
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1717
1735
|
if (currentHP <= 0 && !targetBoss.skills.includes("求生本能I") && !targetBoss.skills.includes("求生本能II")) {
|
|
1718
1736
|
return { currentHP, messages: [], skillUpdates: [], initialDamage };
|
|
1719
1737
|
}
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1738
|
+
targetBoss.skills.forEach((skill) => {
|
|
1739
|
+
const config2 = passiveConfig[skill];
|
|
1740
|
+
if (config2 && config2.effect !== void 0 && config2.effect !== 0) {
|
|
1741
|
+
totalMultiplier += config2.effect;
|
|
1742
|
+
const effectPercent = Math.round(config2.effect * 100);
|
|
1743
|
+
messages.push(`📚 【${skill}】生效,受到的伤害${config2.effect > 0 ? "+" : ""}${effectPercent}%`);
|
|
1744
|
+
}
|
|
1745
|
+
});
|
|
1746
|
+
const infectionResult = await this.handleInfectedStation(ctx2, targetBoss);
|
|
1747
|
+
if (infectionResult) {
|
|
1748
|
+
totalMultiplier += infectionResult.damageMultiplier;
|
|
1749
|
+
messages.push(...infectionResult.messages);
|
|
1724
1750
|
}
|
|
1725
|
-
const
|
|
1726
|
-
if (
|
|
1727
|
-
|
|
1728
|
-
messages.push(...
|
|
1751
|
+
const armorResult = this.handleStructuralArmor(targetBoss, weaponData);
|
|
1752
|
+
if (armorResult) {
|
|
1753
|
+
totalMultiplier += armorResult.damageMultiplier;
|
|
1754
|
+
messages.push(...armorResult.messages);
|
|
1729
1755
|
}
|
|
1730
|
-
const
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1756
|
+
const bloodEffect = this.handleBloodEffects(targetBoss, currentHP, maxHP);
|
|
1757
|
+
if (bloodEffect) {
|
|
1758
|
+
totalMultiplier += bloodEffect.damageMultiplier;
|
|
1759
|
+
messages.push(...bloodEffect.messages);
|
|
1760
|
+
}
|
|
1761
|
+
const radiationCalc = this.calculateRadiationDamage(targetBoss);
|
|
1762
|
+
if (radiationCalc) {
|
|
1763
|
+
totalMultiplier += radiationCalc.damageMultiplier;
|
|
1764
|
+
messages.push(...radiationCalc.messages);
|
|
1765
|
+
}
|
|
1766
|
+
const originalMultiplier = totalMultiplier;
|
|
1767
|
+
totalMultiplier = Math.max(totalMultiplier, -0.99);
|
|
1768
|
+
if (originalMultiplier < -0.99) {
|
|
1769
|
+
messages.push(`⚠️ 减伤效果已达上限(99%)`);
|
|
1736
1770
|
}
|
|
1737
|
-
|
|
1771
|
+
let finalDamage = initialDamage * (1 + totalMultiplier);
|
|
1772
|
+
finalDamage = Math.floor(finalDamage);
|
|
1773
|
+
finalDamage = Math.max(finalDamage, 1);
|
|
1774
|
+
currentHP = targetBoss.HP - finalDamage;
|
|
1775
|
+
const frostSurroundResult = await this.handleFrostSurround(ctx2, targetBoss, currentHP, maxHP);
|
|
1738
1776
|
if (frostSurroundResult) {
|
|
1739
1777
|
currentHP = frostSurroundResult.updatedHP;
|
|
1740
1778
|
messages.push(...frostSurroundResult.messages);
|
|
@@ -1746,53 +1784,44 @@ function apply(ctx, config) {
|
|
|
1746
1784
|
messages.push(...frostRecoveryResult.messages);
|
|
1747
1785
|
skillUpdates.push(...frostRecoveryResult.skillUpdates);
|
|
1748
1786
|
}
|
|
1787
|
+
const moldResult = await this.handleMoldGrowth(ctx2, targetBoss, bossGroup);
|
|
1788
|
+
if (moldResult) {
|
|
1789
|
+
messages.push(...moldResult.messages);
|
|
1790
|
+
}
|
|
1791
|
+
const survivalResult = this.handleSurvivalInstinct(targetBoss, currentHP, maxHP);
|
|
1792
|
+
if (survivalResult) {
|
|
1793
|
+
currentHP = survivalResult.updatedHP;
|
|
1794
|
+
messages.push(...survivalResult.messages);
|
|
1795
|
+
skillUpdates.push(...survivalResult.skillUpdates);
|
|
1796
|
+
}
|
|
1749
1797
|
const coldAdaptResult = await this.handleColdAdaptation(ctx2, targetBoss, weaponName);
|
|
1750
1798
|
if (coldAdaptResult) {
|
|
1751
1799
|
messages.push(...coldAdaptResult.messages);
|
|
1752
1800
|
}
|
|
1753
|
-
const coldImmunityResult = this.handleColdAdaptationImmunity(targetBoss, weaponName);
|
|
1754
|
-
if (coldImmunityResult) {
|
|
1755
|
-
initialDamage = coldImmunityResult.initialDamage;
|
|
1756
|
-
currentHP = targetBoss.HP;
|
|
1757
|
-
messages.push(...coldImmunityResult.messages);
|
|
1758
|
-
return { currentHP, messages, skillUpdates, initialDamage };
|
|
1759
|
-
}
|
|
1760
1801
|
const bloodCountResult = await this.handleBloodCount(ctx2, targetBoss, currentHP, maxHP);
|
|
1761
1802
|
if (bloodCountResult) {
|
|
1762
1803
|
currentHP = bloodCountResult.updatedHP;
|
|
1763
1804
|
messages.push(...bloodCountResult.messages);
|
|
1764
1805
|
}
|
|
1765
|
-
const infectionResult = await this.handleInfectedStation(ctx2, targetBoss, initialDamage, bossGroup);
|
|
1766
|
-
if (infectionResult) {
|
|
1767
|
-
initialDamage = infectionResult.initialDamage;
|
|
1768
|
-
messages.push(...infectionResult.messages);
|
|
1769
|
-
}
|
|
1770
|
-
const armorResult = this.handleStructuralArmor(targetBoss, initialDamage, weaponData);
|
|
1771
|
-
if (armorResult) {
|
|
1772
|
-
initialDamage = armorResult.initialDamage;
|
|
1773
|
-
messages.push(...armorResult.messages);
|
|
1774
|
-
}
|
|
1775
1806
|
const sentryResult = await this.handleSentryGun(ctx2, targetBoss, bossGroup);
|
|
1776
1807
|
if (sentryResult) {
|
|
1777
1808
|
messages.push(...sentryResult.messages);
|
|
1778
1809
|
}
|
|
1779
|
-
const
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
const survivalResult = this.handleSurvivalInstinct(targetBoss, currentHP, maxHP);
|
|
1790
|
-
if (survivalResult) {
|
|
1791
|
-
currentHP = survivalResult.updatedHP;
|
|
1792
|
-
messages.push(...survivalResult.messages);
|
|
1793
|
-
skillUpdates.push(...survivalResult.skillUpdates);
|
|
1810
|
+
const gammaRadResult = await this.handleGammaRadiation(
|
|
1811
|
+
ctx2,
|
|
1812
|
+
targetBoss,
|
|
1813
|
+
weaponData
|
|
1814
|
+
// 传入武器数据对象
|
|
1815
|
+
);
|
|
1816
|
+
if (gammaRadResult) {
|
|
1817
|
+
messages.push(...gammaRadResult.messages);
|
|
1794
1818
|
}
|
|
1795
|
-
return {
|
|
1819
|
+
return {
|
|
1820
|
+
currentHP,
|
|
1821
|
+
messages,
|
|
1822
|
+
skillUpdates,
|
|
1823
|
+
initialDamage: finalDamage
|
|
1824
|
+
};
|
|
1796
1825
|
}, "handlePassives"),
|
|
1797
1826
|
// 应用技能更新到数据库
|
|
1798
1827
|
applySkillUpdates: /* @__PURE__ */ __name(async (ctx2, skillUpdates) => {
|
|
@@ -2347,6 +2376,23 @@ function apply(ctx, config) {
|
|
|
2347
2376
|
].join("\n");
|
|
2348
2377
|
}
|
|
2349
2378
|
__name(generateUpgradePriceList, "generateUpgradePriceList");
|
|
2379
|
+
const weaponConfigById = {};
|
|
2380
|
+
for (const key in weaponConfig) {
|
|
2381
|
+
weaponConfigById[weaponConfig[key].id] = weaponConfig[key];
|
|
2382
|
+
}
|
|
2383
|
+
async function calculateTotalPower(handle, baseRank) {
|
|
2384
|
+
const weapons = await ctx.database.get("ggcevo_equipment", { handle });
|
|
2385
|
+
let total = baseRank;
|
|
2386
|
+
for (const { weaponId, level, installedMods } of weapons) {
|
|
2387
|
+
const weapon = weaponConfigById[weaponId];
|
|
2388
|
+
if (!weapon) continue;
|
|
2389
|
+
total += weapon.damage * 100;
|
|
2390
|
+
total += level * 1e3;
|
|
2391
|
+
total += (installedMods?.length || 0) * 2e3;
|
|
2392
|
+
}
|
|
2393
|
+
return total;
|
|
2394
|
+
}
|
|
2395
|
+
__name(calculateTotalPower, "calculateTotalPower");
|
|
2350
2396
|
ctx.command("ggcevo/抽奖").action(async (argv) => {
|
|
2351
2397
|
const session = argv.session;
|
|
2352
2398
|
let winCount = 0;
|
|
@@ -3795,7 +3841,7 @@ ${achievementList.join("\n")}`;
|
|
|
3795
3841
|
ctx.command("ggcevo/pk [user]", "发起玩家对战").alias("挑战").action(async (argv, user) => {
|
|
3796
3842
|
try {
|
|
3797
3843
|
const session = argv.session;
|
|
3798
|
-
if (!user) return "
|
|
3844
|
+
if (!user) return "请输入“pk @指定pk玩家”。";
|
|
3799
3845
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
3800
3846
|
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
3801
3847
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
@@ -3818,6 +3864,8 @@ ${achievementList.join("\n")}`;
|
|
|
3818
3864
|
]);
|
|
3819
3865
|
const initiatorRank = initiatorData[0]?.rank || 0;
|
|
3820
3866
|
const targetRank = targetData[0]?.rank || 0;
|
|
3867
|
+
const initiatorPower = await calculateTotalPower(initiatorHandle, initiatorRank);
|
|
3868
|
+
const targetPower = await calculateTotalPower(targetHandle, targetRank);
|
|
3821
3869
|
const initiatorRankname = initiatorData[0]?.name || session.username;
|
|
3822
3870
|
const targetRankname = targetData[0]?.name || (targetUsername.name || targetUsername.user.name);
|
|
3823
3871
|
let initiatorPK = {
|
|
@@ -3895,9 +3943,9 @@ ${achievementList.join("\n")}`;
|
|
|
3895
3943
|
const targetGold = targetSign[0]?.totalRewards || 0;
|
|
3896
3944
|
if (initiatorGold < 100) return "发起者需要至少100金币才能发起挑战。";
|
|
3897
3945
|
if (targetGold < 100) return "对方金币不足100,无法应战。";
|
|
3898
|
-
const
|
|
3899
|
-
|
|
3900
|
-
|
|
3946
|
+
const powerDiff = initiatorPower - targetPower;
|
|
3947
|
+
let winRate = 50 + powerDiff / 20 * 0.01;
|
|
3948
|
+
winRate = Math.min(Math.max(winRate, 5), 95);
|
|
3901
3949
|
const isWin = Math.random() * 100 < winRate;
|
|
3902
3950
|
const stealPercentage = getRandomInt(1, 5);
|
|
3903
3951
|
const goldTransfer = Math.floor(
|
|
@@ -3965,13 +4013,13 @@ ${achievementList.join("\n")}`;
|
|
|
3965
4013
|
});
|
|
3966
4014
|
const result = [
|
|
3967
4015
|
`⚔️【对战结果】${isWin ? "胜利" : "失败"}`,
|
|
3968
|
-
`🏅 挑战者:${initiatorRankname}(
|
|
3969
|
-
`🛡️ 应战者:${targetRankname}(
|
|
4016
|
+
`🏅 挑战者:${initiatorRankname}(战斗力 ${initiatorRank})`,
|
|
4017
|
+
`🛡️ 应战者:${targetRankname}(战斗力 ${targetRank})`,
|
|
3970
4018
|
`📊 胜率预测:${winRate.toFixed(1)}%`,
|
|
3971
4019
|
`🎰 金币变动:${stealPercentage}%`
|
|
3972
4020
|
];
|
|
3973
4021
|
isWin ? result.push(`💰 您从对方的口袋里抢夺了${goldTransfer}枚金币`) : result.push(`💸 您从口袋里拿出了${goldTransfer}枚金币上交给对方`);
|
|
3974
|
-
initiatorCareer?.group === "辛迪加海盗" ? result.push(`🔴 海盗阵营奖励:获得1
|
|
4022
|
+
initiatorCareer?.group === "辛迪加海盗" ? result.push(`🔴 海盗阵营奖励:获得1枚红晶`) : "";
|
|
3975
4023
|
result.push(`📅 剩余挑战次数:${config.dailyPKLimit - (initiatorPK.todayCount + 1)}`);
|
|
3976
4024
|
return result.join("\n");
|
|
3977
4025
|
} catch (error) {
|
|
@@ -4105,7 +4153,7 @@ ${Object.keys(typeStats).join("、")}`;
|
|
|
4105
4153
|
});
|
|
4106
4154
|
return [
|
|
4107
4155
|
`🏪 咕咕武器库 - ${type} 🏪`,
|
|
4108
|
-
"使用“购买
|
|
4156
|
+
"使用“购买 武器名称”指令进行购买",
|
|
4109
4157
|
discountRate > 0 && `🔧 当前购买折扣:${discountRate}% (武器系统 Lv${techLevel})`,
|
|
4110
4158
|
"====================",
|
|
4111
4159
|
...items,
|
|
@@ -4146,7 +4194,7 @@ ${validTypes.join("、")}`;
|
|
|
4146
4194
|
].join("\n"));
|
|
4147
4195
|
return [
|
|
4148
4196
|
`💣 爆破装备库 - ${type} 💣`,
|
|
4149
|
-
"使用“购买
|
|
4197
|
+
"使用“购买 物品名称”指令进行购买",
|
|
4150
4198
|
"====================",
|
|
4151
4199
|
...items,
|
|
4152
4200
|
items.length === 0 ? "⚠️ 该分类下暂无可用物品" : ""
|
|
@@ -4300,7 +4348,7 @@ ${validTypes.join("、")}`;
|
|
|
4300
4348
|
].join("\n");
|
|
4301
4349
|
}));
|
|
4302
4350
|
return [
|
|
4303
|
-
|
|
4351
|
+
`🛡️ ${handle}当前拥有的武器`,
|
|
4304
4352
|
'使用"装备 武器名称"来装备武器',
|
|
4305
4353
|
"⚡表示当前装备武器",
|
|
4306
4354
|
"──────────────",
|
|
@@ -4481,6 +4529,11 @@ ${validTypes.join("、")}`;
|
|
|
4481
4529
|
ctx.command("ggcevo/攻击 <bossName>").usage("请输入要攻击的异形名称(例如:攻击 异齿猛兽 或 攻击 寒冰王蛇)").action(async (argv, bossName) => {
|
|
4482
4530
|
const session = argv.session;
|
|
4483
4531
|
let broadcastMessage = null;
|
|
4532
|
+
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
4533
|
+
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
4534
|
+
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
4535
|
+
const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
|
|
4536
|
+
if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
|
|
4484
4537
|
const getActiveBossNames = /* @__PURE__ */ __name(async () => {
|
|
4485
4538
|
const activeBosses2 = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
4486
4539
|
return activeBosses2.map((b) => b.name).join(",");
|
|
@@ -4499,11 +4552,6 @@ ${validTypes.join("、")}`;
|
|
|
4499
4552
|
return `当前没有找到名为 ${bossName} 的可攻击目标。
|
|
4500
4553
|
请攻击当前存活的异形:${activeNames || "无"}。`;
|
|
4501
4554
|
}
|
|
4502
|
-
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
4503
|
-
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
4504
|
-
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
4505
|
-
const existingEntries = await ctx.database.get("ggcevo_blacklist", { handle });
|
|
4506
|
-
if (existingEntries.length > 0) return "❌ 拒绝访问,您已被列入黑名单。";
|
|
4507
4555
|
const config2 = ctx.config;
|
|
4508
4556
|
const unlimitedBossAttack = config2.unlimitedBossAttack;
|
|
4509
4557
|
if (!unlimitedBossAttack) {
|
|
@@ -4526,17 +4574,17 @@ ${validTypes.join("、")}`;
|
|
|
4526
4574
|
if (!weaponData.isantiair && targetBoss.groupId === 5) {
|
|
4527
4575
|
return "您装备的武器无法攻击空中目标!";
|
|
4528
4576
|
}
|
|
4529
|
-
const { damage: baseDamage, hasCrit, effectMessage } = await calculateTotalDamage(ctx, session, equippedWeapon, targetBoss);
|
|
4530
4577
|
const activeBosses = await ctx.database.get("ggcevo_boss", { isActive: true });
|
|
4531
|
-
if (!activeBosses.length) return "
|
|
4578
|
+
if (!activeBosses.length) return "当前没有存活的异形,请等待下一轮刷新。";
|
|
4532
4579
|
const bossGroup = bossPool.find(
|
|
4533
4580
|
(g) => g.main.name === targetBoss.name || g.minions.some((m) => m.name === targetBoss.name)
|
|
4534
4581
|
);
|
|
4535
4582
|
if (!bossGroup) return "无法获取异形组配置。";
|
|
4536
4583
|
const maxHP = targetBoss.type === "主宰" ? bossGroup.main.maxHP : bossGroup.minions.find((m) => m.name === targetBoss.name)?.maxHP || 0;
|
|
4537
|
-
|
|
4584
|
+
const { damage, hasCrit, effectMessage } = await calculateTotalDamage(ctx, session, equippedWeapon, targetBoss);
|
|
4585
|
+
let initialDamage = Math.min(damage, targetBoss.HP);
|
|
4538
4586
|
let currentHP = targetBoss.HP - initialDamage;
|
|
4539
|
-
let
|
|
4587
|
+
let passiveMessages = [];
|
|
4540
4588
|
const passiveResult = await PassiveHandler.handlePassives(
|
|
4541
4589
|
ctx,
|
|
4542
4590
|
targetBoss,
|
|
@@ -4545,13 +4593,12 @@ ${validTypes.join("、")}`;
|
|
|
4545
4593
|
maxHP,
|
|
4546
4594
|
weaponName,
|
|
4547
4595
|
weaponData,
|
|
4548
|
-
baseDamage,
|
|
4549
4596
|
activeBosses,
|
|
4550
4597
|
bossGroup
|
|
4551
4598
|
);
|
|
4552
4599
|
currentHP = passiveResult.currentHP;
|
|
4553
4600
|
initialDamage = passiveResult.initialDamage;
|
|
4554
|
-
|
|
4601
|
+
passiveMessages.push(...passiveResult.messages);
|
|
4555
4602
|
if (passiveResult.skillUpdates.length > 0) {
|
|
4556
4603
|
await PassiveHandler.applySkillUpdates(ctx, passiveResult.skillUpdates);
|
|
4557
4604
|
}
|
|
@@ -4619,7 +4666,7 @@ ${validTypes.join("、")}`;
|
|
|
4619
4666
|
await ctx.database.set("ggcevo_boss", { name: mainBoss.name }, {
|
|
4620
4667
|
skills: [...mainBoss.skills, "孤立无援"]
|
|
4621
4668
|
});
|
|
4622
|
-
broadcastMessages.push("💥
|
|
4669
|
+
broadcastMessages.push("💥 机械感染虫已阵亡,空间站感染虫进入【孤立无援】状态,受到的伤害+20%!");
|
|
4623
4670
|
}
|
|
4624
4671
|
} else {
|
|
4625
4672
|
remainingMinions = await ctx.database.get("ggcevo_boss", {
|
|
@@ -4637,7 +4684,7 @@ ${validTypes.join("、")}`;
|
|
|
4637
4684
|
await ctx.database.set("ggcevo_boss", { name: mainBoss.name }, {
|
|
4638
4685
|
skills: [...mainBoss.skills, "孤立无援"]
|
|
4639
4686
|
});
|
|
4640
|
-
broadcastMessages.push(
|
|
4687
|
+
broadcastMessages.push(`💥 所有子代已阵亡,${mainBoss.name}进入【孤立无援】状态,受到的伤害+20%!`);
|
|
4641
4688
|
}
|
|
4642
4689
|
}
|
|
4643
4690
|
}
|
|
@@ -4669,7 +4716,7 @@ ${validTypes.join("、")}`;
|
|
|
4669
4716
|
handle,
|
|
4670
4717
|
redcrystal: (careerData?.redcrystal || 0) + 1
|
|
4671
4718
|
}], ["handle"]);
|
|
4672
|
-
redcrystalMessage = "🔴 清洁工职业加成:获得1
|
|
4719
|
+
redcrystalMessage = "🔴 清洁工职业加成:获得1枚红晶";
|
|
4673
4720
|
}
|
|
4674
4721
|
const finalReward = Math.round(initialDamage * careerMultiplier);
|
|
4675
4722
|
const [existingSign] = await ctx.database.get("ggcevo_sign", { handle });
|
|
@@ -4681,12 +4728,15 @@ ${validTypes.join("、")}`;
|
|
|
4681
4728
|
const resultMessage = [
|
|
4682
4729
|
`🔥 ${session.username} 使用武器 ${weaponName} 对 ${targetBoss.name} 发起攻击!`,
|
|
4683
4730
|
...effectMessage.length > 0 ? [
|
|
4684
|
-
|
|
4685
|
-
${effectMessage.join("\n")}`
|
|
4731
|
+
`⚡ 攻击效果:
|
|
4732
|
+
${effectMessage.map((m) => `▸ ${m}`).join("\n")}`
|
|
4733
|
+
] : [],
|
|
4734
|
+
// === 新增被动效果提示区域 ===
|
|
4735
|
+
...passiveMessages.length > 0 ? [
|
|
4736
|
+
`🛡️ 被动效果:
|
|
4737
|
+
${passiveMessages.map((m) => `▸ ${m}`).join("\n")}`
|
|
4686
4738
|
] : [],
|
|
4687
|
-
...healMessages,
|
|
4688
4739
|
`造成伤害:${initialDamage}${hasCrit ? "(✨ 暴击)" : ""}`,
|
|
4689
|
-
// 修改金币显示行
|
|
4690
4740
|
`获得金币:${finalReward}${careerMessage}`,
|
|
4691
4741
|
redcrystalMessage,
|
|
4692
4742
|
`目标剩余HP:${Math.max(currentHP, 0)}/${maxHP}`,
|
|
@@ -4699,12 +4749,11 @@ ${effectMessage.join("\n")}`
|
|
|
4699
4749
|
await ctx.broadcast(groupId, finalBroadcast);
|
|
4700
4750
|
}
|
|
4701
4751
|
});
|
|
4702
|
-
ctx.command("ggcevo/攻击假人").
|
|
4752
|
+
ctx.command("ggcevo/攻击假人").option("tags", "-t <tags:string> 添加BOSS标签(逗号分隔)").action(async (argv) => {
|
|
4703
4753
|
const session = argv.session;
|
|
4704
4754
|
const { options } = argv;
|
|
4705
4755
|
const parseList = /* @__PURE__ */ __name((str) => str ? str.split(",").map((s) => s.trim()).filter(Boolean) : [], "parseList");
|
|
4706
4756
|
const tags = parseList(options.tags);
|
|
4707
|
-
const passives = parseList(options.passives);
|
|
4708
4757
|
const [profile] = await ctx.database.get("sc2arcade_player", { userId: session.userId });
|
|
4709
4758
|
if (!profile) return "🔒 需要先绑定游戏句柄。";
|
|
4710
4759
|
const handle = `${profile.regionId}-S2-${profile.realmId}-${profile.profileId}`;
|
|
@@ -4720,8 +4769,6 @@ ${effectMessage.join("\n")}`
|
|
|
4720
4769
|
HP: Infinity,
|
|
4721
4770
|
type: "主宰",
|
|
4722
4771
|
groupId: 0,
|
|
4723
|
-
skills: passives || [],
|
|
4724
|
-
// 从选项获取被动
|
|
4725
4772
|
tags: tags || []
|
|
4726
4773
|
// 从选项获取标签
|
|
4727
4774
|
};
|
|
@@ -4733,21 +4780,22 @@ ${effectMessage.join("\n")}`
|
|
|
4733
4780
|
{
|
|
4734
4781
|
isTest: true,
|
|
4735
4782
|
// 标记为测试模式
|
|
4736
|
-
customTags: tags
|
|
4737
|
-
customPassives: passives
|
|
4783
|
+
customTags: tags
|
|
4738
4784
|
}
|
|
4739
4785
|
);
|
|
4740
4786
|
const weaponConfigEntry = Object.entries(weaponConfig).find(([_, c]) => c.id === equippedWeapon.weaponId);
|
|
4741
4787
|
const [weaponName] = weaponConfigEntry;
|
|
4742
4788
|
return [
|
|
4743
|
-
`🎯
|
|
4789
|
+
`🎯 攻击 ${dummyBoss.name}`,
|
|
4744
4790
|
`💥 使用武器:${weaponName}`,
|
|
4745
4791
|
options.tags?.length && `🏷️ 模拟标签:${tags.join(", ")}`,
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4792
|
+
...effectMessage.length ? [
|
|
4793
|
+
"⚡ 攻击效果:",
|
|
4794
|
+
...effectMessage.map((m) => `▸ ${m}`)
|
|
4795
|
+
// 这里添加符号
|
|
4796
|
+
] : [],
|
|
4797
|
+
`📊 理论伤害值:${damage}${hasCrit ? " (✨ 触发暴击)" : ""}`,
|
|
4798
|
+
"💡 提示:使用 -t 重甲,生物…… 添加测试标签"
|
|
4751
4799
|
].filter((line) => line).join("\n");
|
|
4752
4800
|
});
|
|
4753
4801
|
ctx.command("ggcevo/伤害榜 [page]", "查看当前主宰伤害排名").usage("输入 伤害榜 [页码] 查看对应页的排行榜,每页10条").action(async (_, page) => {
|
|
@@ -5182,9 +5230,9 @@ ${effectMessage.join("\n")}`
|
|
|
5182
5230
|
infoCard.push("", "〓 科技研发 〓", ...activeTechs);
|
|
5183
5231
|
}
|
|
5184
5232
|
}
|
|
5185
|
-
const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动PK获得(无论胜负)" : "💡
|
|
5233
|
+
const promptMessage = careerData.group === "辛迪加海盗" ? "💡 提示:红晶可通过主动PK获得(无论胜负)" : "💡 提示:使用「转职」指令可变更职业";
|
|
5186
5234
|
return [
|
|
5187
|
-
|
|
5235
|
+
`〓 ${handle}的职业档案 〓`,
|
|
5188
5236
|
...infoCard,
|
|
5189
5237
|
"〓═════════〓\n" + promptMessage
|
|
5190
5238
|
// 提示信息放在分隔线下方
|