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.
Files changed (2) hide show
  1. package/lib/index.js +375 -327
  2. 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: "攻击时,暴击率+20%"
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: "自身每受到1次攻击,若“空间站哨枪塔”存活,则为其回复1%的最大生命值"
600
+ description: "受到攻击后,若“空间站哨枪塔”存活,则为其回复1%的最大生命值"
601
601
  },
602
602
  "岗哨机枪": {
603
603
  effect: 0,
604
- description: "自己的职责为“保护感染虫”,受到10次攻击后,为存活的机械感染虫和主宰回复10%的最大生命值(可重复触发)"
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%的减伤,至多10层"
612
+ description: "受到攻击将会获得一层“吸血”,每层“吸血”提供5%的减伤(至多10层)"
613
613
  },
614
614
  "进食": {
615
615
  effect: 0,
616
- description: "当“吸血”层数达到10层后,下一次受到攻击,将会消耗所有层数回复自身20%的最大生命值"
616
+ description: "当“吸血”达到10层后,下一次受到攻击将会消耗所有层数回复自身20%的最大生命值"
617
617
  },
618
618
  "嗜血狂暴": {
619
619
  effect: 0,
620
- description: "血量低于50%时,每次受到攻击将会额外叠加一层吸血唾液,并且受到的伤害-20%"
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 calculateModifiers(equippedWeapon, weaponName, hasCritRhythm) {
1014
- let totalModAdd = 0;
1015
- let hasCrit = false;
1016
- let hasCrystal = false;
1017
- let hasOverload = false;
1018
- equippedWeapon.installedMods.forEach((mod) => {
1019
- if (mod === "动能增幅") {
1020
- totalModAdd += 0.2;
1021
- }
1022
- if (mod === "裂甲核心" && weaponName === modConfig[mod].exclusiveTo) {
1023
- totalModAdd += 0.4;
1024
- }
1025
- if (mod === "棱镜水晶") hasCrystal = true;
1026
- if (mod === "棱镜超载核心" && weaponName === modConfig[mod].exclusiveTo) {
1027
- hasOverload = true;
1028
- }
1029
- });
1030
- let totalCritRate = (hasCrystal ? 20 : 0) + (hasOverload ? 80 : 0);
1031
- if (hasCritRhythm) {
1032
- totalCritRate = Math.min(totalCritRate + 20, 100);
1033
- }
1034
- if (totalCritRate > 0 && Math.random() < totalCritRate / 100) {
1035
- hasCrit = true;
1036
- totalModAdd += 1;
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 { totalModAdd, hasCrit };
1046
+ return {
1047
+ damage: Math.round(finalDamage),
1048
+ hasCrit,
1049
+ effectMessage
1050
+ };
1039
1051
  }
1040
- __name(calculateModifiers, "calculateModifiers");
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 calculatePassiveEffects(passives) {
1058
- let passiveEffect = 0;
1059
- passives.forEach((passive) => {
1060
- const effect = passiveConfig[passive]?.effect || 0;
1061
- passiveEffect += effect;
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
- return passiveEffect;
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(calculatePassiveEffects, "calculatePassiveEffects");
1066
- async function calculateCareerBonus(ctx2, handle, currentDamage, weaponType, weaponId) {
1113
+ __name(calculateModifiers, "calculateModifiers");
1114
+ async function calculateCareerAdditive(ctx2, handle, weaponType, weaponId) {
1067
1115
  const [careerData] = await ctx2.database.get("ggcevo_careers", { handle });
1068
- const career = careerData?.career;
1069
- const faction = careerData?.group;
1116
+ let value = 0;
1070
1117
  let message = "";
1071
- let multiplier = 1;
1072
- if (career === "警卫长") {
1073
- multiplier = 1.05;
1118
+ if (careerData?.career === "警卫长") {
1119
+ value += 0.05;
1074
1120
  message = "⚔️ 职业加成:警卫长(攻击伤害+5%)";
1075
- } else if (career === "武器中士") {
1076
- multiplier = 1.15;
1121
+ }
1122
+ if (careerData?.career === "武器中士") {
1123
+ value += 0.15;
1077
1124
  message = "⚔️ 职业加成:武器中士(攻击伤害+15%)";
1078
1125
  }
1079
- if (faction === "辛迪加海盗" && career === "能量武器专家") {
1126
+ if (careerData?.career === "能量武器专家") {
1080
1127
  if (weaponType === "能量武器") {
1081
- multiplier *= 1.2;
1082
- message = " 职业加成:能量武器专家(能量武器伤害+20%)";
1083
- } else {
1084
- message = "⚠️ 能量武器专家:未装备能量武器,加成未生效";
1128
+ value += 0.2;
1129
+ message = "⚔️ 职业加成:能量武器专家(能量武器伤害+20%)";
1085
1130
  }
1086
1131
  }
1087
- if (faction === "辛迪加海盗" && career === "纵火狂") {
1132
+ if (careerData?.career === "纵火狂") {
1088
1133
  if (weaponType === "热能武器") {
1089
- multiplier *= 1.2;
1090
- message = " 职业加成:纵火狂(热能武器伤害+20%)";
1091
- } else {
1092
- message = "⚠️ 纵火狂:未装备热能武器,加成未生效";
1134
+ value += 0.2;
1135
+ message = "⚔️ 职业加成:纵火狂(热能武器伤害+20%)";
1093
1136
  }
1094
1137
  }
1095
- if (faction === "辛迪加海盗" && career === "猩红杀手") {
1138
+ if (careerData?.career === "猩红杀手") {
1096
1139
  if (weaponId === 7) {
1097
- multiplier *= 1.15;
1098
- message = " 职业加成:猩红杀手(侦查步枪伤害+15%)";
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(calculateRankBonus, "calculateRankBonus");
1114
- async function calculateTotalDamage(ctx2, session, equippedWeapon, targetBoss, options) {
1115
- let effectMessage = [];
1116
- const finalTags = options?.customTags || targetBoss.tags || [];
1117
- const finalPassives = options?.customPassives || targetBoss.skills || [];
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
- const { totalModAdd, hasCrit } = calculateModifiers(
1133
- equippedWeapon,
1134
- weaponName,
1135
- !!critRhythmEffect
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
- const [lamentEffect] = await ctx2.database.get("ggcevo_Wish_Record", {
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 (sovereignEffect) {
1168
- damage *= 1.05;
1169
- effectMessage.push(`👑 王权增幅祈愿生效(攻击伤害+5%)`);
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
- damage: Math.round(damage),
1181
- hasCrit,
1182
- effectMessage
1181
+ value,
1182
+ message: messages.join(",")
1183
1183
  };
1184
1184
  }
1185
- __name(calculateTotalDamage, "calculateTotalDamage");
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, baseDamage, currentHP, maxHP) {
1369
+ handleFrostEvolution: /* @__PURE__ */ __name(function(targetBoss, weaponName, damage, maxHP) {
1365
1370
  if (targetBoss.skills.includes("冰霜进化") && weaponName === "零度之下") {
1366
- const healAmount = baseDamage;
1371
+ const healAmount = damage;
1367
1372
  return {
1368
1373
  updatedHP: Math.min(targetBoss.HP + healAmount, maxHP),
1369
1374
  initialDamage: 0,
1370
- messages: [`❄️ ${targetBoss.name} 触发【冰霜进化】免疫冰霜伤害!并且回复 ${healAmount} 生命值`]
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, bossGroup) => {
1377
- if (targetBoss.type !== "主宰" || !targetBoss.skills.includes("冰霜环绕") || currentHP <= 0 || // 新增血量必须大于0的判断
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
- `❄️ ${targetBoss.name} 触发【冰霜环绕】,自身回复45%最大生命值(+${healAmount}HP)`,
1404
- `🌪️ 【寒霜地狱】降临!主宰和所有存活的子代将获得30%减伤效果`
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 (targetBoss.type !== "子代" || !targetBoss.skills.includes("冰霜回复") || currentHP <= 0 || // 新增血量必须大于0的判断
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
- `❄️ ${targetBoss.name} 触发【冰霜回复】,自身回复40%最大生命值(+${selfHeal}HP),主宰回复10%最大生命值(+${mainHeal}HP)`
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: [`❄️ ${targetBoss.name} 触发【冷适应】,永久获得「惧热」标签并免疫寒冷伤害!`]
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.type === "主宰" && targetBoss.name === "莽兽" && targetBoss.skills.includes("冷适应") && targetBoss.Skillcountpoints >= 10 && weaponName === "零度之下") {
1468
+ if (targetBoss.skills.includes("冷适应") && targetBoss.Skillcountpoints >= 10 && weaponName === "零度之下") {
1463
1469
  return {
1464
1470
  initialDamage: 0,
1465
- messages: [`❄️ ${targetBoss.name} 触发【冷适应】免疫寒冷伤害!`]
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 > 1) return null;
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: [`${targetBoss.name} 触发【${effect.skill}】,瞬间回复${effect.heal}生命值!`],
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, initialDamage, bossGroup) => {
1491
- if (targetBoss.name !== "空间站感染虫" || !targetBoss.skills.includes("感染空间站")) {
1492
- return null;
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
- initialDamage: newDamage,
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 (targetBoss.name !== "空间站哨枪塔" || !targetBoss.skills.includes("岗哨机枪")) {
1536
+ if (!targetBoss.skills.includes("岗哨机枪")) {
1537
1537
  return null;
1538
1538
  }
1539
- const newCount = (targetBoss.Skillcountpoints || 0) + 1;
1540
- await ctx2.database.set(
1541
- "ggcevo_boss",
1542
- { name: targetBoss.name },
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(`主宰回复${heal}HP`);
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: ["🔫 【岗哨机枪】触发:" + messages.join(",")]
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, initialDamage, weaponData) => {
1601
- if (targetBoss.name !== "空间站哨枪塔" || !targetBoss.skills.includes("结构装甲")) {
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
- initialDamage: newDamage,
1615
+ damageMultiplier: -reduction,
1616
+ // 返回减伤系数
1613
1617
  messages: [`🛡️ 【结构装甲】生效:${msg}`]
1614
1618
  };
1615
1619
  }, "handleStructuralArmor"),
1616
- // 处理吸血相关效果(加法减伤 + 独立增伤)
1617
- handleBloodEffects: /* @__PURE__ */ __name(function(targetBoss, initialDamage, currentHP, maxHP) {
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 totalReduction = 0;
1624
+ let damageMultiplier = 0;
1625
+ const messages = [];
1625
1626
  if (targetBoss.skills.includes("吸血唾液")) {
1626
- totalReduction += bloodStacks * 0.05;
1627
- if (bloodStacks > 0) {
1628
- messages.push(`🩸 【吸血唾液】技能生效:受到的伤害-${bloodStacks * 5}%`);
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
- totalReduction += 0.2;
1633
- messages.push(`🔥 【嗜血狂暴】技能生效:血量低于50%,进入狂暴状态,受到的伤害-20%`);
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
- newDamage = Math.floor(newDamage * 1.1);
1640
- messages.push(`💔 【吐血】技能生效:无“吸血”层数,受到的伤害+10%`);
1636
+ damageMultiplier += 0.1;
1637
+ messages.push(`💔 【吐血】生效:无“吸血”层数,受到的伤害+10%`);
1641
1638
  }
1642
- return newDamage !== initialDamage ? { initialDamage: newDamage, messages } : null;
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(`🍽️ 【进食】技能生效:自身回复20%最大生命值(+${heal}HP),“吸血”层数清零`);
1653
+ messages.push(`🍽️ 【进食】生效:${targetBoss.name}回复20%最大生命值(+${heal}HP),“吸血”层数清零`);
1656
1654
  return { updatedHP, messages };
1657
1655
  }
1658
- let newStacks = oldStacks + 1;
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(`🔥 【嗜血狂暴】技能生效:额外叠加1层“吸血”`);
1662
+ messages.push(`🔥 【嗜血狂暴】生效:额外获得1层“吸血”`);
1662
1663
  }
1663
1664
  newStacks = Math.min(newStacks, 10);
1664
1665
  if (oldStacks < 10 && newStacks >= 10) {
1665
- messages.push(`🩸 吸血层数达到${newStacks},下次攻击将触发【进食】!`);
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, weaponName) => {
1672
- if (weaponName !== "伽马枪") return null;
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 isNewRadiation = !targetBoss.skills.includes("辐射");
1675
- const newSkills = isNewRadiation ? [...targetBoss.skills, "辐射"] : targetBoss.skills;
1676
- const newVulnerability = isNewRadiation ? 1 : Math.min(targetBoss.Vulnerability + 1, 100);
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
- if (isNewRadiation) {
1679
- layerMsg = `☢️ 获得【辐射】效果`;
1682
+ 0;
1683
+ if (!hasRadiation) {
1684
+ layerMsg = `☢️ ${targetBoss.name} 获得【辐射】效果`;
1685
+ } else if (newLayers === currentLayers) {
1686
+ layerMsg = `☢️ 辐射层数已达上限(100层)`;
1680
1687
  } else {
1681
- if (newVulnerability === targetBoss.Vulnerability) {
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("ggcevo_boss", { name: targetBoss.name }, {
1689
- skills: newSkills,
1690
- Vulnerability: newVulnerability
1691
- });
1692
- messages.push(`${targetBoss.name} ${layerMsg}`);
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, baseDamage) => {
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
- damage: amplifiedDamage,
1708
- messages: radiationLayers > 0 ? [
1709
- `☢️ 【辐射】效果触发:当前${radiationLayers}层辐射,受到的伤害+${radiationLayers}%`
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, baseDamage, activeBosses, bossGroup) {
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
- const radiationCalc = this.calculateRadiationDamage(targetBoss, initialDamage);
1721
- if (radiationCalc.messages.length > 0) {
1722
- messages.push(...radiationCalc.messages);
1723
- initialDamage = radiationCalc.damage;
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 bloodEffectResult = this.handleBloodEffects(targetBoss, initialDamage, currentHP, maxHP);
1726
- if (bloodEffectResult) {
1727
- initialDamage = bloodEffectResult.initialDamage;
1728
- messages.push(...bloodEffectResult.messages);
1751
+ const armorResult = this.handleStructuralArmor(targetBoss, weaponData);
1752
+ if (armorResult) {
1753
+ totalMultiplier += armorResult.damageMultiplier;
1754
+ messages.push(...armorResult.messages);
1729
1755
  }
1730
- const frostEvoResult = this.handleFrostEvolution(targetBoss, weaponName, baseDamage, currentHP, maxHP);
1731
- if (frostEvoResult) {
1732
- initialDamage = frostEvoResult.initialDamage;
1733
- currentHP = frostEvoResult.updatedHP;
1734
- messages.push(...frostEvoResult.messages);
1735
- return { currentHP, messages, skillUpdates, initialDamage };
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
- const frostSurroundResult = await this.handleFrostSurround(ctx2, targetBoss, currentHP, maxHP, bossGroup);
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 moldResult = await this.handleMoldGrowth(ctx2, targetBoss, bossGroup);
1780
- if (moldResult) {
1781
- messages.push(...moldResult.messages);
1782
- }
1783
- if (weaponName === "伽马枪" && targetBoss.tags.includes("生物") && !targetBoss.tags.includes("机械")) {
1784
- const radiationResult = await this.handleGammaRadiation(ctx2, targetBoss, weaponName);
1785
- if (radiationResult) {
1786
- messages.push(...radiationResult.messages);
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 { currentHP, messages, skillUpdates, initialDamage };
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 "缺少参数,请输入“pk @指定pk玩家”。";
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 rankDiff = initiatorRank - targetRank;
3899
- const clampedDiff = Math.min(Math.max(rankDiff, -1e4), 1e4);
3900
- const winRate = Math.min(Math.max(50 + clampedDiff * 5e-3, 5), 95);
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}(积分 ${initiatorRank})`,
3969
- `🛡️ 应战者:${targetRankname}(积分 ${targetRank})`,
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 "当前没有存活的异形,请等待1小时后刷新。";
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
- let initialDamage = Math.min(baseDamage, targetBoss.HP);
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 healMessages = [];
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
- healMessages.push(...passiveResult.messages);
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("💥 机械感染虫被消灭,空间站感染虫进入【孤立无援】状态,受到的伤害+20%!");
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("💥 所有子代已阵亡,主宰进入【孤立无援】状态,受到的伤害+20%!");
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/攻击假人").usage("测试当前装备武器的伤害,可添加标签和被动\n用法:攻击假人 [--标签 标签1 标签2] [--被动 被动1 被动2]").option("tags", "-t <tags:string> 添加BOSS标签(逗号分隔)").option("passives", "-p <passives:string> 添加BOSS被动(逗号分隔)").action(async (argv) => {
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
- `🎯 测试攻击 ${dummyBoss.name}`,
4789
+ `🎯 攻击 ${dummyBoss.name}`,
4744
4790
  `💥 使用武器:${weaponName}`,
4745
4791
  options.tags?.length && `🏷️ 模拟标签:${tags.join(", ")}`,
4746
- options.passives?.length && `🛡️ 模拟被动:${passives.join(", ")}`,
4747
- `📊 理论伤害值:${damage}`,
4748
- hasCrit ? "✨ 触发暴击" : "",
4749
- ...effectMessage,
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
  // 提示信息放在分隔线下方
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ggcevo-game",
3
3
  "description": "《星际争霸2》咕咕虫-evolved地图的专属游戏助手插件,集成天梯排行、抽奖系统、签到福利、兑换商城等丰富功能。",
4
- "version": "1.3.16",
4
+ "version": "1.3.17",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [